From b65f49fd69eeee827312f846e464f02848a9c1d2 Mon Sep 17 00:00:00 2001 From: Patrick McDonagh Date: Fri, 15 Apr 2016 18:00:21 -0500 Subject: [PATCH] Moved micro800 and tag modules to their own repos, included submodules --- .gitmodules | 8 + .remote-sync.json | 14 +- micro800 | 1 + python/mysql_cfg.pickle => mysql_cfg.pickle | 0 ..._mysql_config.py => pickle_mysql_config.py | 0 python/micro800.py | 94 -- python/pycomm.log | 1 - python/pycomm_micro/__init__.py | 1 - python/pycomm_micro/__init__.pyc | Bin 192 -> 0 bytes python/pycomm_micro/ab_comm/__init__.py | 2 - python/pycomm_micro/ab_comm/__init__.pyc | Bin 231 -> 0 bytes python/pycomm_micro/ab_comm/clx.py | 847 ------------------ python/pycomm_micro/ab_comm/clx.pyc | Bin 24375 -> 0 bytes python/pycomm_micro/ab_comm/slc.py | 446 --------- python/pycomm_micro/ab_comm/slc.pyc | Bin 12028 -> 0 bytes python/pycomm_micro/cip/__init__.py | 1 - python/pycomm_micro/cip/__init__.pyc | Bin 196 -> 0 bytes python/pycomm_micro/cip/cip_base.py | 827 ----------------- python/pycomm_micro/cip/cip_base.pyc | Bin 27697 -> 0 bytes python/pycomm_micro/cip/cip_const.py | 482 ---------- python/pycomm_micro/cip/cip_const.pyc | Bin 10710 -> 0 bytes python/pycomm_micro/common.py | 32 - python/pycomm_micro/common.pyc | Bin 1297 -> 0 bytes python/tag_mysql.py | 91 -- python/tag_sqlite.py | 85 -- tag | 1 + .../tagserver_MySQL.py => tagserver_MySQL.py | 0 ...tagserver_SQLite.py => tagserver_SQLite.py | 0 28 files changed, 15 insertions(+), 2918 deletions(-) create mode 100644 .gitmodules create mode 160000 micro800 rename python/mysql_cfg.pickle => mysql_cfg.pickle (100%) rename python/pickle_mysql_config.py => pickle_mysql_config.py (100%) delete mode 100644 python/micro800.py delete mode 100644 python/pycomm.log delete mode 100644 python/pycomm_micro/__init__.py delete mode 100644 python/pycomm_micro/__init__.pyc delete mode 100644 python/pycomm_micro/ab_comm/__init__.py delete mode 100644 python/pycomm_micro/ab_comm/__init__.pyc delete mode 100644 python/pycomm_micro/ab_comm/clx.py delete mode 100644 python/pycomm_micro/ab_comm/clx.pyc delete mode 100644 python/pycomm_micro/ab_comm/slc.py delete mode 100644 python/pycomm_micro/ab_comm/slc.pyc delete mode 100644 python/pycomm_micro/cip/__init__.py delete mode 100644 python/pycomm_micro/cip/__init__.pyc delete mode 100644 python/pycomm_micro/cip/cip_base.py delete mode 100644 python/pycomm_micro/cip/cip_base.pyc delete mode 100644 python/pycomm_micro/cip/cip_const.py delete mode 100644 python/pycomm_micro/cip/cip_const.pyc delete mode 100644 python/pycomm_micro/common.py delete mode 100644 python/pycomm_micro/common.pyc delete mode 100644 python/tag_mysql.py delete mode 100644 python/tag_sqlite.py create mode 160000 tag rename python/tagserver_MySQL.py => tagserver_MySQL.py (100%) rename python/tagserver_SQLite.py => tagserver_SQLite.py (100%) diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f556536 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,8 @@ +[submodule "tag"] + path = tag +[submodule "tag"] + url = http://patrickjmcd@bitbucket.poconsole.net/scm/poconsole/tag.git +[submodule "micro800"] + path = micro800 +[submodule "micro800"] + url = http://patrickjmcd@bitbucket.poconsole.net/scm/poconsole/micro800.git diff --git a/.remote-sync.json b/.remote-sync.json index 7f03967..c88f4b3 100644 --- a/.remote-sync.json +++ b/.remote-sync.json @@ -1,14 +1,10 @@ { - "transport": "scp", - "uploadOnSave": true, + "transport": "ftp", + "uploadOnSave": false, + "useAtomicWrites": false, "deleteLocal": false, - "hostname": "10.10.10.6", - "port": "22", - "target": "/home/pi/tagserver/", "ignore": [ ".remote-sync.json", ".git/**" - ], - "username": "pi", - "password": "raspberry" -} + ] +} \ No newline at end of file diff --git a/micro800 b/micro800 new file mode 160000 index 0000000..9fc9018 --- /dev/null +++ b/micro800 @@ -0,0 +1 @@ +Subproject commit 9fc901887c0b7a347b6c1779e68f3e8249dfc6ba diff --git a/python/mysql_cfg.pickle b/mysql_cfg.pickle similarity index 100% rename from python/mysql_cfg.pickle rename to mysql_cfg.pickle diff --git a/python/pickle_mysql_config.py b/pickle_mysql_config.py similarity index 100% rename from python/pickle_mysql_config.py rename to pickle_mysql_config.py diff --git a/python/micro800.py b/python/micro800.py deleted file mode 100644 index 5807eaa..0000000 --- a/python/micro800.py +++ /dev/null @@ -1,94 +0,0 @@ -from pycomm_micro.ab_comm.clx import Driver as u800Driver -import logging -import sys - - -def readMicroTag(addr, tag): - logging.basicConfig( - filename="u800Driver.log", - format="%(levelname)-10s %(asctime)s %(message)s", - level=logging.DEBUG - ) - c = u800Driver() - - if c.open(addr): - try: - v = c.read_tag(tag) - # print(v) - return v - except Exception as e: - err = c.get_status() - c.close() - print err - pass - c.close() - -def getTagType(addr, tag): - logging.basicConfig( - filename="u800Driver.log", - format="%(levelname)-10s %(asctime)s %(message)s", - level=logging.DEBUG - ) - c = u800Driver() - - if c.open(addr): - try: - return c.read_tag(tag)[1] - except Exception as e: - err = c.get_status() - c.close() - print err - pass - c.close() - -def writeMicroTag(addr, tag, val): - logging.basicConfig( - filename="u800Driver.log", - format="%(levelname)-10s %(asctime)s %(message)s", - level=logging.DEBUG - ) - c = u800Driver() - - if c.open(addr): - try: - #typ = getTagType(addr, tag) - cv = c.read_tag(tag) - wt = c.write_tag(tag, val, cv[1]) - # print(wt) - return wt - except Exception as e: - err = c.get_status() - c.close() - print err - pass - c.close() - - -def readMicroTagList(addr, tList): - logging.basicConfig( - filename="u800Driver.log", - format="%(levelname)-10s %(asctime)s %(message)s", - level=logging.DEBUG - ) - c = u800Driver() - - if c.open(addr): - vals = [] - try: - for t in tList: - v = c.read_tag(t) - vals.append({"tag":t,"val":v[0], "type":v[1]}) - # print(v) - # print("{0} - {1}".format(t, v)) - except Exception as e: - err = c.get_status() - c.close() - print err - pass - c.close() - return vals -if __name__ == '__main__': - if len(sys.argv) > 2: - print(readMicroTag(sys.argv[1], sys.argv[2])) - else: - print ("Did not pass a target and tag name.") diff --git a/python/pycomm.log b/python/pycomm.log deleted file mode 100644 index 7363b30..0000000 --- a/python/pycomm.log +++ /dev/null @@ -1 +0,0 @@ -pycomm.cip.cip_base WARNING 2016-04-07 16:14:59,861 (5, 'forward_close returned False') diff --git a/python/pycomm_micro/__init__.py b/python/pycomm_micro/__init__.py deleted file mode 100644 index 8c1f233..0000000 --- a/python/pycomm_micro/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'agostino' diff --git a/python/pycomm_micro/__init__.pyc b/python/pycomm_micro/__init__.pyc deleted file mode 100644 index bc5fab50c91c527deb86cdfad8b663c628f13a23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmYLCO9}!p6zk|l20Vcmn3cVNh&x@0Ai8k#D4jA^?T7YNm_vCvy?`kQK1f1Hc$t3Y z?c()5Yw^1Vx&d+v>V>#~8*%I=usj2)A!N2b?7Ld!S|d`0uOSh2aNrBQbBal%@C6iqfJthROq3+oE|_YA~-PLyvO`7 zd>ao)T!wsqc36#{_w>EZ)G z8l!E!*2d`?CHW)n(6VDxA+nCAV8rceg=8D$!T|f;b}Vs??Yj!B8}OdPBD}R=jR>Cc cGi1jAj57&ffkXMLrS-CJ)rz8y`KJ;608R%y6#xJL diff --git a/python/pycomm_micro/ab_comm/clx.py b/python/pycomm_micro/ab_comm/clx.py deleted file mode 100644 index 0ba1586..0000000 --- a/python/pycomm_micro/ab_comm/clx.py +++ /dev/null @@ -1,847 +0,0 @@ -# -*- coding: utf-8 -*- -# -# clx.py - Ethernet/IP Client for Rockwell PLCs -# -# -# Copyright (c) 2014 Agostino Ruscito -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -from pycomm_micro.cip.cip_base import * -from pycomm_micro.common import setup_logger -import logging - - -class Driver(Base): - """ - This Ethernet/IP client is based on Rockwell specification. Please refer to the link below for details. - - http://literature.rockwellautomation.com/idc/groups/literature/documents/pm/1756-pm020_-en-p.pdf - - The following services have been implemented: - - Read Tag Service (0x4c) - - Read Tag Fragment Service (0x52) - - Write Tag Service (0x4d) - - Write Tag Fragment Service (0x53) - - Multiple Service Packet (0x0a) - - The client has been successfully tested with the following PLCs: - - CompactLogix 5330ERM - - CompactLogix 5370 - - ControlLogix 5572 and 1756-EN2T Module - -""" - def __init__(self, debug=False, filename=None): - if debug: - super(Driver, self).__init__(setup_logger('ab_comm.clx', logging.DEBUG, filename)) - else: - super(Driver, self).__init__(setup_logger('ab_comm.clx', logging.INFO, filename)) - - self._buffer = {} - self._get_template_in_progress = False - self.__version__ = '0.2' - - def get_last_tag_read(self): - """ Return the last tag read by a multi request read - - :return: A tuple (tag name, value, type) - """ - return self._last_tag_read - - def get_last_tag_write(self): - """ Return the last tag write by a multi request write - - :return: A tuple (tag name, 'GOOD') if the write was successful otherwise (tag name, 'BAD') - """ - return self._last_tag_write - - def _parse_instance_attribute_list(self, start_tag_ptr, status): - """ extract the tags list from the message received - - :param start_tag_ptr: The point in the message string where the tag list begin - :param status: The status of the message receives - """ - tags_returned = self._reply[start_tag_ptr:] - tags_returned_length = len(tags_returned) - idx = 0 - instance = 0 - count = 0 - try: - while idx < tags_returned_length: - instance = unpack_dint(tags_returned[idx:idx+4]) - idx += 4 - tag_length = unpack_uint(tags_returned[idx:idx+2]) - idx += 2 - tag_name = tags_returned[idx:idx+tag_length] - idx += tag_length - symbol_type = unpack_uint(tags_returned[idx:idx+2]) - idx += 2 - count += 1 - self._tag_list.append({'instance_id': instance, - 'tag_name': tag_name, - 'symbol_type': symbol_type}) - except Exception as e: - raise DataError(e) - - if status == SUCCESS: - self._last_instance = -1 - elif status == 0x06: - self._last_instance = instance + 1 - else: - self._status = (1, 'unknown status during _parse_tag_list') - self._last_instance = -1 - - def _parse_structure_makeup_attributes(self, start_tag_ptr, status): - """ extract the tags list from the message received - - :param start_tag_ptr: The point in the message string where the tag list begin - :param status: The status of the message receives - """ - self._buffer = {} - - if status != SUCCESS: - self._buffer['Error'] = status - return - - attribute = self._reply[start_tag_ptr:] - idx = 4 - try: - if unpack_uint(attribute[idx:idx + 2]) == SUCCESS: - idx += 2 - self._buffer['object_definition_size'] = unpack_dint(attribute[idx:idx + 4]) - else: - self._buffer['Error'] = 'object_definition Error' - return - - idx += 6 - if unpack_uint(attribute[idx:idx + 2]) == SUCCESS: - idx += 2 - self._buffer['structure_size'] = unpack_dint(attribute[idx:idx + 4]) - else: - self._buffer['Error'] = 'structure Error' - return - - idx += 6 - if unpack_uint(attribute[idx:idx + 2]) == SUCCESS: - idx += 2 - self._buffer['member_count'] = unpack_uint(attribute[idx:idx + 2]) - else: - self._buffer['Error'] = 'member_count Error' - return - - idx += 4 - if unpack_uint(attribute[idx:idx + 2]) == SUCCESS: - idx += 2 - self._buffer['structure_handle'] = unpack_uint(attribute[idx:idx + 2]) - else: - self._buffer['Error'] = 'structure_handle Error' - return - - return self._buffer - - except Exception as e: - raise DataError(e) - - def _parse_template(self, start_tag_ptr, status): - """ extract the tags list from the message received - - :param start_tag_ptr: The point in the message string where the tag list begin - :param status: The status of the message receives - """ - tags_returned = self._reply[start_tag_ptr:] - bytes_received = len(tags_returned) - - self._buffer += tags_returned - - if status == SUCCESS: - self._get_template_in_progress = False - - elif status == 0x06: - self._byte_offset += bytes_received - else: - self._status = (1, 'unknown status {0} during _parse_template'.format(status)) - self.logger.warning(self._status) - self._last_instance = -1 - - def _parse_fragment(self, start_ptr, status): - """ parse the fragment returned by a fragment service. - - :param start_ptr: Where the fragment start within the replay - :param status: status field used to decide if keep parsing or stop - """ - try: - data_type = unpack_uint(self._reply[start_ptr:start_ptr+2]) - fragment_returned = self._reply[start_ptr+2:] - except Exception as e: - raise DataError(e) - - fragment_returned_length = len(fragment_returned) - idx = 0 - - while idx < fragment_returned_length: - try: - typ = I_DATA_TYPE[data_type] - value = UNPACK_DATA_FUNCTION[typ](fragment_returned[idx:idx+DATA_FUNCTION_SIZE[typ]]) - idx += DATA_FUNCTION_SIZE[typ] - except Exception as e: - raise DataError(e) - self._tag_list.append((self._last_position, value)) - self._last_position += 1 - - if status == SUCCESS: - self._byte_offset = -1 - elif status == 0x06: - self._byte_offset += fragment_returned_length - else: - self._status = (2, 'unknown status during _parse_fragment') - self._byte_offset = -1 - - def _parse_multiple_request_read(self, tags): - """ parse the message received from a multi request read: - - For each tag parsed, the information extracted includes the tag name, the value read and the data type. - Those information are appended to the tag list as tuple - - :return: the tag list - """ - offset = 50 - position = 50 - try: - number_of_service_replies = unpack_uint(self._reply[offset:offset+2]) - tag_list = [] - for index in range(number_of_service_replies): - position += 2 - start = offset + unpack_uint(self._reply[position:position+2]) - general_status = unpack_usint(self._reply[start+2:start+3]) - - if general_status == 0: - data_type = unpack_uint(self._reply[start+4:start+6]) - value_begin = start + 6 - value_end = value_begin + DATA_FUNCTION_SIZE[I_DATA_TYPE[data_type]] - value = self._reply[value_begin:value_end] - self._last_tag_read = (tags[index], UNPACK_DATA_FUNCTION[I_DATA_TYPE[data_type]](value), - I_DATA_TYPE[data_type]) - else: - self._last_tag_read = (tags[index], None, None) - - tag_list.append(self._last_tag_read) - - return tag_list - except Exception as e: - raise DataError(e) - - def _parse_multiple_request_write(self, tags): - """ parse the message received from a multi request writ: - - For each tag parsed, the information extracted includes the tag name and the status of the writing. - Those information are appended to the tag list as tuple - - :return: the tag list - """ - offset = 50 - position = 50 - try: - number_of_service_replies = unpack_uint(self._reply[offset:offset+2]) - tag_list = [] - for index in range(number_of_service_replies): - position += 2 - start = offset + unpack_uint(self._reply[position:position+2]) - general_status = unpack_usint(self._reply[start+2:start+3]) - - if general_status == 0: - self._last_tag_write = (tags[index] + ('GOOD',)) - else: - self._last_tag_write = (tags[index] + ('BAD',)) - - tag_list.append(self._last_tag_write) - return tag_list - except Exception as e: - raise DataError(e) - - def _check_reply(self): - """ check the replayed message for error - - """ - self._more_packets_available = False - try: - if self._reply is None: - self._status = (3, '%s without reply' % REPLAY_INFO[unpack_dint(self._message[:2])]) - return False - # Get the type of command - typ = unpack_uint(self._reply[:2]) - - # Encapsulation status check - if unpack_dint(self._reply[8:12]) != SUCCESS: - self._status = (3, "{0} reply status:{1}".format(REPLAY_INFO[typ], - SERVICE_STATUS[unpack_dint(self._reply[8:12])])) - return False - - # Command Specific Status check - if typ == unpack_uint(ENCAPSULATION_COMMAND["send_rr_data"]): - status = unpack_usint(self._reply[42:43]) - if status != SUCCESS: - self._status = (3, "send_rr_data reply:{0} - Extend status:{1}".format( - SERVICE_STATUS[status], get_extended_status(self._reply, 42))) - return False - else: - return True - elif typ == unpack_uint(ENCAPSULATION_COMMAND["send_unit_data"]): - status = unpack_usint(self._reply[48:49]) - if unpack_usint(self._reply[46:47]) == I_TAG_SERVICES_REPLY["Read Tag Fragmented"]: - self._parse_fragment(50, status) - return True - if unpack_usint(self._reply[46:47]) == I_TAG_SERVICES_REPLY["Get Instance Attributes List"]: - self._parse_instance_attribute_list(50, status) - return True - if unpack_usint(self._reply[46:47]) == I_TAG_SERVICES_REPLY["Get Attributes"]: - self._parse_structure_makeup_attributes(50, status) - return True - if unpack_usint(self._reply[46:47]) == I_TAG_SERVICES_REPLY["Read Template"] and \ - self._get_template_in_progress: - self._parse_template(50, status) - return True - if status == 0x06: - self._status = (3, "Insufficient Packet Space") - self._more_packets_available = True - elif status != SUCCESS: - self._status = (3, "send_unit_data reply:{0} - Extend status:{1}".format( - SERVICE_STATUS[status], get_extended_status(self._reply, 48))) - return False - else: - return True - - return True - except Exception as e: - raise DataError(e) - - def read_tag(self, tag): - """ read tag from a connected plc - - Possible combination can be passed to this method: - - ('Counts') a single tag name - - (['ControlWord']) a list with one tag or many - - (['parts', 'ControlWord', 'Counts']) - - At the moment there is not a strong validation for the argument passed. The user should verify - the correctness of the format passed. - - :return: None is returned in case of error otherwise the tag list is returned - """ - multi_requests = False - if isinstance(tag, list): - multi_requests = True - - if not self._target_is_connected: - if not self.forward_open(): - self._status = (6, "Target did not connected. read_tag will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. read_tag will not be executed.") - # multi_requests = False - if multi_requests: - rp_list = [] - for t in tag: - rp = create_tag_rp(t, multi_requests=True) - if rp is None: - self._status = (6, "Cannot create tag {0} request packet. read_tag will not be executed.".format(tag)) - raise DataError("Cannot create tag {0} request packet. read_tag will not be executed.".format(tag)) - else: - rp_list.append(chr(TAG_SERVICES_REQUEST['Read Tag']) + rp + pack_uint(1)) - message_request = build_multiple_service(rp_list, Base._get_sequence()) - - else: - rp = create_tag_rp(tag) - if rp is None: - self._status = (6, "Cannot create tag {0} request packet. read_tag will not be executed.".format(tag)) - return None - else: - # Creating the Message Request Packet - message_request = [ - pack_uint(Base._get_sequence()), - chr(TAG_SERVICES_REQUEST['Read Tag']), # the Request Service - chr(len(rp) / 2), # the Request Path Size length in word - rp, # the request path - pack_uint(1) - ] - - if self.send_unit_data( - build_common_packet_format( - DATA_ITEM['Connected'], - ''.join(message_request), - ADDRESS_ITEM['Connection Based'], - addr_data=self._target_cid, - )) is None: - raise DataError("send_unit_data returned not valid data") - - if multi_requests: - return self._parse_multiple_request_read(tag) - else: - # Get the data type - data_type = unpack_uint(self._reply[50:52]) - # print I_DATA_TYPE[data_type] - try: - return UNPACK_DATA_FUNCTION[I_DATA_TYPE[data_type]](self._reply[52:]), I_DATA_TYPE[data_type] - except Exception as e: - raise DataError(e) - - def read_array(self, tag, counts): - """ read array of atomic data type from a connected plc - - At the moment there is not a strong validation for the argument passed. The user should verify - the correctness of the format passed. - - :param tag: the name of the tag to read - :param counts: the number of element to read - :return: None is returned in case of error otherwise the tag list is returned - """ - if not self._target_is_connected: - if not self.forward_open(): - self._status = (7, "Target did not connected. read_tag will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. read_tag will not be executed.") - - self._byte_offset = 0 - self._last_position = 0 - - self._tag_list = [] - while self._byte_offset != -1: - rp = create_tag_rp(tag) - if rp is None: - self._status = (7, "Cannot create tag {0} request packet. read_tag will not be executed.".format(tag)) - return None - else: - # Creating the Message Request Packet - message_request = [ - pack_uint(Base._get_sequence()), - chr(TAG_SERVICES_REQUEST["Read Tag Fragmented"]), # the Request Service - chr(len(rp) / 2), # the Request Path Size length in word - rp, # the request path - pack_uint(counts), - pack_dint(self._byte_offset) - ] - - if self.send_unit_data( - build_common_packet_format( - DATA_ITEM['Connected'], - ''.join(message_request), - ADDRESS_ITEM['Connection Based'], - addr_data=self._target_cid, - )) is None: - raise DataError("send_unit_data returned not valid data") - - return self._tag_list - - def write_tag(self, tag, value=None, typ=None): - """ write tag/tags from a connected plc - - Possible combination can be passed to this method: - - ('tag name', Value, data type) as single parameters or inside a tuple - - ([('tag name', Value, data type), ('tag name2', Value, data type)]) as array of tuples - - At the moment there is not a strong validation for the argument passed. The user should verify - the correctness of the format passed. - - The type accepted are: - - BOOL - - SINT - - INT' - - DINT - - REAL - - LINT - - BYTE - - WORD - - DWORD - - LWORD - - :param tag: tag name, or an array of tuple containing (tag name, value, data type) - :param value: the value to write or none if tag is an array of tuple or a tuple - :param typ: the type of the tag to write or none if tag is an array of tuple or a tuple - :return: None is returned in case of error otherwise the tag list is returned - """ - multi_requests = False - if isinstance(tag, list): - multi_requests = True - - if not self._target_is_connected: - if not self.forward_open(): - self._status = (8, "Target did not connected. write_tag will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. write_tag will not be executed.") - - if multi_requests: - rp_list = [] - tag_to_remove = [] - idx = 0 - for name, value, typ in tag: - # Create the request path to wrap the tag name - rp = create_tag_rp(name, multi_requests=True) - if rp is None: - self._status = (8, "Cannot create tag{0} req. packet. write_tag will not be executed".format(tag)) - return None - else: - try: # Trying to add the rp to the request path list - val = PACK_DATA_FUNCTION[typ](value) - rp_list.append( - chr(TAG_SERVICES_REQUEST['Write Tag']) - + rp - + pack_uint(S_DATA_TYPE[typ]) - + pack_uint(1) - + val - ) - idx += 1 - except (LookupError, struct.error) as e: - self._status = (8, "Tag:{0} type:{1} removed from write list. Error:{2}.".format(name, typ, e)) - - # The tag in idx position need to be removed from the rp list because has some kind of error - tag_to_remove.append(idx) - - # Remove the tags that have not been inserted in the request path list - for position in tag_to_remove: - del tag[position] - # Create the message request - message_request = build_multiple_service(rp_list, Base._get_sequence()) - - else: - if isinstance(tag, tuple): - name, value, typ = tag - else: - name = tag - - rp = create_tag_rp(name) - if rp is None: - self._status = (8, "Cannot create tag {0} request packet. write_tag will not be executed.".format(tag)) - self.logger.warning(self._status) - return None - else: - # Creating the Message Request Packet - message_request = [ - pack_uint(Base._get_sequence()), - chr(TAG_SERVICES_REQUEST["Write Tag"]), # the Request Service - chr(len(rp) / 2), # the Request Path Size length in word - rp, # the request path - pack_uint(S_DATA_TYPE[typ]), # data type - pack_uint(1), # Add the number of tag to write - PACK_DATA_FUNCTION[typ](value) - ] - - ret_val = self.send_unit_data( - build_common_packet_format( - DATA_ITEM['Connected'], - ''.join(message_request), - ADDRESS_ITEM['Connection Based'], - addr_data=self._target_cid, - ) - ) - - if multi_requests: - return self._parse_multiple_request_write(tag) - else: - if ret_val is None: - raise DataError("send_unit_data returned not valid data") - return ret_val - - def write_array(self, tag, data_type, values): - """ write array of atomic data type from a connected plc - - At the moment there is not a strong validation for the argument passed. The user should verify - the correctness of the format passed. - - :param tag: the name of the tag to read - :param data_type: the type of tag to write - :param values: the array of values to write - """ - if not isinstance(values, list): - self._status = (9, "A list of tags must be passed to write_array.") - self.logger.warning(self._status) - raise DataError("A list of tags must be passed to write_array.") - - if not self._target_is_connected: - if not self.forward_open(): - self._status = (9, "Target did not connected. write_array will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. write_array will not be executed.") - - array_of_values = "" - byte_size = 0 - byte_offset = 0 - - for i, value in enumerate(values): - array_of_values += PACK_DATA_FUNCTION[data_type](value) - byte_size += DATA_FUNCTION_SIZE[data_type] - - if byte_size >= 450 or i == len(values)-1: - # create the message and send the fragment - rp = create_tag_rp(tag) - if rp is None: - self._status = (9, "Cannot create tag {0} request packet. \ - write_array will not be executed.".format(tag)) - return None - else: - # Creating the Message Request Packet - message_request = [ - pack_uint(Base._get_sequence()), - chr(TAG_SERVICES_REQUEST["Write Tag Fragmented"]), # the Request Service - chr(len(rp) / 2), # the Request Path Size length in word - rp, # the request path - pack_uint(S_DATA_TYPE[data_type]), # Data type to write - pack_uint(len(values)), # Number of elements to write - pack_dint(byte_offset), - array_of_values # Fragment of elements to write - ] - byte_offset += byte_size - - if self.send_unit_data( - build_common_packet_format( - DATA_ITEM['Connected'], - ''.join(message_request), - ADDRESS_ITEM['Connection Based'], - addr_data=self._target_cid, - )) is None: - raise DataError("send_unit_data returned not valid data") - array_of_values = "" - byte_size = 0 - - def _get_instance_attribute_list_service(self): - """ Step 1: Finding user-created controller scope tags in a Logix5000 controller - - This service returns instance IDs for each created instance of the symbol class, along with a list - of the attribute data associated with the requested attribute - """ - try: - if not self._target_is_connected: - if not self.forward_open(): - self._status = (10, "Target did not connected. get_tag_list will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. get_tag_list will not be executed.") - - self._last_instance = 0 - - self._get_template_in_progress = True - while self._last_instance != -1: - - # Creating the Message Request Packet - - message_request = [ - pack_uint(Base._get_sequence()), - chr(TAG_SERVICES_REQUEST['Get Instance Attributes List']), # STEP 1 - # the Request Path Size length in word - chr(3), - # Request Path ( 20 6B 25 00 Instance ) - CLASS_ID["8-bit"], # Class id = 20 from spec 0x20 - CLASS_CODE["Symbol Object"], # Logical segment: Symbolic Object 0x6B - INSTANCE_ID["16-bit"], # Instance Segment: 16 Bit instance 0x25 - '\x00', - pack_uint(self._last_instance), # The instance - # Request Data - pack_uint(2), # Number of attributes to retrieve - pack_uint(1), # Attribute 1: Symbol name - pack_uint(2) # Attribute 2: Symbol type - ] - - if self.send_unit_data( - build_common_packet_format( - DATA_ITEM['Connected'], - ''.join(message_request), - ADDRESS_ITEM['Connection Based'], - addr_data=self._target_cid, - )) is None: - raise DataError("send_unit_data returned not valid data") - - self._get_template_in_progress = False - - except Exception as e: - raise DataError(e) - - def _get_structure_makeup(self, instance_id): - """ - get the structure makeup for a specific structure - """ - if not self._target_is_connected: - if not self.forward_open(): - self._status = (10, "Target did not connected. get_tag_list will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. get_tag_list will not be executed.") - - message_request = [ - pack_uint(self._get_sequence()), - chr(TAG_SERVICES_REQUEST['Get Attributes']), - chr(3), # Request Path ( 20 6B 25 00 Instance ) - CLASS_ID["8-bit"], # Class id = 20 from spec 0x20 - CLASS_CODE["Template Object"], # Logical segment: Template Object 0x6C - INSTANCE_ID["16-bit"], # Instance Segment: 16 Bit instance 0x25 - '\x00', - pack_uint(instance_id), - pack_uint(4), # Number of attributes - pack_uint(4), # Template Object Definition Size UDINT - pack_uint(5), # Template Structure Size UDINT - pack_uint(2), # Template Member Count UINT - pack_uint(1) # Structure Handle We can use this to read and write UINT - ] - - if self.send_unit_data( - build_common_packet_format(DATA_ITEM['Connected'], - ''.join(message_request), ADDRESS_ITEM['Connection Based'], - addr_data=self._target_cid,)) is None: - raise DataError("send_unit_data returned not valid data") - - return self._buffer - - def _read_template(self, instance_id, object_definition_size): - """ get a list of the tags in the plc - - """ - if not self._target_is_connected: - if not self.forward_open(): - self._status = (10, "Target did not connected. get_tag_list will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. get_tag_list will not be executed.") - - self._byte_offset = 0 - self._buffer = "" - self._get_template_in_progress = True - - try: - while self._get_template_in_progress: - - # Creating the Message Request Packet - - message_request = [ - pack_uint(self._get_sequence()), - chr(TAG_SERVICES_REQUEST['Read Template']), - chr(3), # Request Path ( 20 6B 25 00 Instance ) - CLASS_ID["8-bit"], # Class id = 20 from spec 0x20 - CLASS_CODE["Template Object"], # Logical segment: Template Object 0x6C - INSTANCE_ID["16-bit"], # Instance Segment: 16 Bit instance 0x25 - '\x00', - pack_uint(instance_id), - pack_dint(self._byte_offset), # Offset - pack_uint(((object_definition_size * 4)-23) - self._byte_offset) - ] - - if not self.send_unit_data( - build_common_packet_format(DATA_ITEM['Connected'], ''.join(message_request), - ADDRESS_ITEM['Connection Based'], addr_data=self._target_cid,)): - raise DataError("send_unit_data returned not valid data") - - self._get_template_in_progress = False - return self._buffer - - except Exception as e: - raise DataError(e) - - def _isolating_user_tag(self): - try: - lst = self._tag_list - self._tag_list = [] - for tag in lst: - if tag['tag_name'].find(':') != -1 or tag['tag_name'].find('__') != -1: - continue - if tag['symbol_type'] & 0b0001000000000000: - continue - dimension = tag['symbol_type'] & 0b0110000000000000 >> 13 - template_instance_id = tag['symbol_type'] & 0b0000111111111111 - - if tag['symbol_type'] & 0b1000000000000000 : - tag_type = 'struct' - data_type = 'user-created' - self._tag_list.append({'instance_id': tag['instance_id'], - 'template_instance_id': template_instance_id, - 'tag_name': tag['tag_name'], - 'dim': dimension, - 'tag_type': tag_type, - 'data_type': data_type, - 'template': {}, - 'udt': {}}) - else: - tag_type = 'atomic' - data_type = I_DATA_TYPE[template_instance_id] - self._tag_list.append({'instance_id': tag['instance_id'], - 'tag_name': tag['tag_name'], - 'dim': dimension, - 'tag_type': tag_type, - 'data_type': data_type}) - except Exception as e: - raise DataError(e) - - def _parse_udt_raw(self, tag): - try: - buff = self._read_template(tag['template_instance_id'], tag['template']['object_definition_size']) - member_count = tag['template']['member_count'] - names = buff.split('\00') - lst = [] - - tag['udt']['name'] = 'Not an user defined structure' - for name in names: - if len(name) > 1: - - if name.find(';') != -1: - tag['udt']['name'] = name[:name.find(';')] - elif name.find('ZZZZZZZZZZ') != -1: - continue - elif name.isalpha(): - lst.append(name) - else: - continue - tag['udt']['internal_tags'] = lst - - type_list = [] - - for i in xrange(member_count): - # skip member 1 - - if i != 0: - array_size = unpack_uint(buff[:2]) - try: - data_type = I_DATA_TYPE[unpack_uint(buff[2:4])] - except Exception: - data_type = "None" - - offset = unpack_dint(buff[4:8]) - type_list.append((array_size, data_type, offset)) - - buff = buff[8:] - - tag['udt']['data_type'] = type_list - except Exception as e: - raise DataError(e) - - def get_tag_list(self): - self._tag_list = [] - # Step 1 - self._get_instance_attribute_list_service() - - # Step 2 - self._isolating_user_tag() - - # Step 3 - for tag in self._tag_list: - if tag['tag_type'] == 'struct': - tag['template'] = self._get_structure_makeup(tag['template_instance_id']) - - for idx, tag in enumerate(self._tag_list): - # print (tag) - if tag['tag_type'] == 'struct': - self._parse_udt_raw(tag) - - # Step 4 - - return self._tag_list - - - - diff --git a/python/pycomm_micro/ab_comm/clx.pyc b/python/pycomm_micro/ab_comm/clx.pyc deleted file mode 100644 index 53c8acfe0d1503ac73dbf5c926e4b749c78b465a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24375 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 C@f7#~ diff --git a/python/pycomm_micro/ab_comm/slc.py b/python/pycomm_micro/ab_comm/slc.py deleted file mode 100644 index bfdb243..0000000 --- a/python/pycomm_micro/ab_comm/slc.py +++ /dev/null @@ -1,446 +0,0 @@ -# -*- coding: utf-8 -*- -# -# clx.py - Ethernet/IP Client for Rockwell PLCs -# -# -# Copyright (c) 2014 Agostino Ruscito -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -from pycomm_micro.cip.cip_base import * -from pycomm_micro.common import setup_logger -import re -import logging -import math - - -def parse_tag(tag): - t = re.search(r"(?P[CT])(?P\d{1,3})" - r"(:)(?P\d{1,3})" - r"(.)(?PACC|PRE|EN|DN|TT|CU|CD|DN|OV|UN|UA)", tag, flags=re.IGNORECASE) - if t: - if (1 <= int(t.group('file_number')) <= 255) \ - and (0 <= int(t.group('element_number')) <= 255): - return True, t.group(0), {'file_type': t.group('file_type').upper(), - 'file_number': t.group('file_number'), - 'element_number': t.group('element_number'), - 'sub_element': PCCC_CT[t.group('sub_element').upper()], - 'read_func': '\xa2', - 'write_func': '\xab', - 'address_field': 3} - - t = re.search(r"(?P[FBN])(?P\d{1,3})" - r"(:)(?P\d{1,3})" - r"(/(?P\d{1,2}))?", - tag, flags=re.IGNORECASE) - if t: - if t.group('sub_element') is not None: - if (1 <= int(t.group('file_number')) <= 255) \ - and (0 <= int(t.group('element_number')) <= 255) \ - and (0 <= int(t.group('sub_element')) <= 15): - - return True, t.group(0), {'file_type': t.group('file_type').upper(), - 'file_number': t.group('file_number'), - 'element_number': t.group('element_number'), - 'sub_element': t.group('sub_element'), - 'read_func': '\xa2', - 'write_func': '\xab', - 'address_field': 3} - else: - if (1 <= int(t.group('file_number')) <= 255) \ - and (0 <= int(t.group('element_number')) <= 255): - - return True, t.group(0), {'file_type': t.group('file_type').upper(), - 'file_number': t.group('file_number'), - 'element_number': t.group('element_number'), - 'sub_element': t.group('sub_element'), - 'read_func': '\xa2', - 'write_func': '\xab', - 'address_field': 2} - - t = re.search(r"(?P[IO])(:)(?P\d{1,3})" - r"(.)(?P\d{1,3})" - r"(/(?P\d{1,2}))?", tag, flags=re.IGNORECASE) - if t: - if t.group('sub_element') is not None: - if (0 <= int(t.group('file_number')) <= 255) \ - and (0 <= int(t.group('element_number')) <= 255) \ - and (0 <= int(t.group('sub_element')) <= 15): - - return True, t.group(0), {'file_type': t.group('file_type').upper(), - 'file_number': t.group('file_number'), - 'element_number': t.group('element_number'), - 'sub_element': t.group('sub_element'), - 'read_func': '\xa2', - 'write_func': '\xab', - 'address_field': 3} - else: - if (0 <= int(t.group('file_number')) <= 255) \ - and (0 <= int(t.group('element_number')) <= 255): - - return True, t.group(0), {'file_type': t.group('file_type').upper(), - 'file_number': t.group('file_number'), - 'element_number': t.group('element_number'), - 'read_func': '\xa2', - 'write_func': '\xab', - 'address_field': 2} - - t = re.search(r"(?PS)" - r"(:)(?P\d{1,3})" - r"(/(?P\d{1,2}))?", tag, flags=re.IGNORECASE) - if t: - if t.group('sub_element') is not None: - if (0 <= int(t.group('element_number')) <= 255) \ - and (0 <= int(t.group('sub_element')) <= 15): - return True, t.group(0), {'file_type': t.group('file_type').upper(), - 'file_number': '2', - 'element_number': t.group('element_number'), - 'sub_element': t.group('sub_element'), - 'read_func': '\xa2', - 'write_func': '\xab', - 'address_field': 3} - else: - if 0 <= int(t.group('element_number')) <= 255: - return True, t.group(0), {'file_type': t.group('file_type').upper(), - 'file_number': '2', - 'element_number': t.group('element_number'), - 'read_func': '\xa2', - 'write_func': '\xab', - 'address_field': 2} - - t = re.search(r"(?PB)(?P\d{1,3})" - r"(/)(?P\d{1,4})", - tag, flags=re.IGNORECASE) - if t: - if (1 <= int(t.group('file_number')) <= 255) \ - and (0 <= int(t.group('element_number')) <= 4095): - bit_position = int(t.group('element_number')) - element_number = bit_position / 16 - sub_element = bit_position - (element_number * 16) - return True, t.group(0), {'file_type': t.group('file_type').upper(), - 'file_number': t.group('file_number'), - 'element_number': element_number, - 'sub_element': sub_element, - 'read_func': '\xa2', - 'write_func': '\xab', - 'address_field': 3} - - return False, tag - - -class Driver(Base): - """ - SLC/PLC_5 Implementation - """ - def __init__(self, debug=False, filename=None): - if debug: - super(Driver, self).__init__(setup_logger('ab_comm.slc', logging.DEBUG, filename)) - else: - super(Driver, self).__init__(setup_logger('ab_comm.slc', logging.INFO, filename)) - - self.__version__ = '0.1' - self._last_sequence = 0 - - def _check_reply(self): - """ - check the replayed message for error - """ - self._more_packets_available = False - try: - if self._reply is None: - self._status = (3, '%s without reply' % REPLAY_INFO[unpack_dint(self._message[:2])]) - return False - # Get the type of command - typ = unpack_uint(self._reply[:2]) - - # Encapsulation status check - if unpack_dint(self._reply[8:12]) != SUCCESS: - self._status = (3, "{0} reply status:{1}".format(REPLAY_INFO[typ], - SERVICE_STATUS[unpack_dint(self._reply[8:12])])) - return False - - # Command Specific Status check - if typ == unpack_uint(ENCAPSULATION_COMMAND["send_rr_data"]): - status = unpack_usint(self._reply[42:43]) - if status != SUCCESS: - self._status = (3, "send_rr_data reply:{0} - Extend status:{1}".format( - SERVICE_STATUS[status], get_extended_status(self._reply, 42))) - return False - else: - return True - - elif typ == unpack_uint(ENCAPSULATION_COMMAND["send_unit_data"]): - status = unpack_usint(self._reply[48:49]) - if unpack_usint(self._reply[46:47]) == I_TAG_SERVICES_REPLY["Read Tag Fragmented"]: - self._parse_fragment(50, status) - return True - if unpack_usint(self._reply[46:47]) == I_TAG_SERVICES_REPLY["Get Instance Attributes List"]: - self._parse_tag_list(50, status) - return True - if status == 0x06: - self._status = (3, "Insufficient Packet Space") - self._more_packets_available = True - elif status != SUCCESS: - self._status = (3, "send_unit_data reply:{0} - Extend status:{1}".format( - SERVICE_STATUS[status], get_extended_status(self._reply, 48))) - return False - else: - return True - - return True - except Exception as e: - raise DataError(e) - - def read_tag(self, tag, n=1): - """ read tag from a connected plc - - Possible combination can be passed to this method: - print c.read_tag('F8:0', 3) return a list of 3 registers starting from F8:0 - print c.read_tag('F8:0') return one value - - It is possible to read status bit - - :return: None is returned in case of error - """ - res = parse_tag(tag) - if not res[0]: - self._status = (1000, "Error parsing the tag passed to read_tag({0},{1})".format(tag, n)) - self.logger.warning(self._status) - raise DataError("Error parsing the tag passed to read_tag({0},{1})".format(tag, n)) - - bit_read = False - bit_position = 0 - sub_element = 0 - if int(res[2]['address_field'] == 3): - bit_read = True - bit_position = int(res[2]['sub_element']) - - if not self._target_is_connected: - if not self.forward_open(): - self._status = (5, "Target did not connected. read_tag will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. read_tag will not be executed.") - - data_size = PCCC_DATA_SIZE[res[2]['file_type']] - - # Creating the Message Request Packet - self._last_sequence = pack_uint(Base._get_sequence()) - - message_request = [ - self._last_sequence, - '\x4b', - '\x02', - CLASS_ID["8-bit"], - PATH["PCCC"], - '\x07', - self.attribs['vid'], - self.attribs['vsn'], - '\x0f', - '\x00', - self._last_sequence[1], - self._last_sequence[0], - res[2]['read_func'], - pack_usint(data_size * n), - pack_usint(int(res[2]['file_number'])), - PCCC_DATA_TYPE[res[2]['file_type']], - pack_usint(int(res[2]['element_number'])), - pack_usint(sub_element) - ] - - self.logger.debug("SLC read_tag({0},{1})".format(tag, n)) - if self.send_unit_data( - build_common_packet_format( - DATA_ITEM['Connected'], - ''.join(message_request), - ADDRESS_ITEM['Connection Based'], - addr_data=self._target_cid,)): - sts = int(unpack_usint(self._reply[58])) - try: - if sts != 0: - sts_txt = PCCC_ERROR_CODE[sts] - self._status = (1000, "Error({0}) returned from read_tag({1},{2})".format(sts_txt, tag, n)) - self.logger.warning(self._status) - raise DataError("Error({0}) returned from read_tag({1},{2})".format(sts_txt, tag, n)) - - new_value = 61 - if bit_read: - if res[2]['file_type'] == 'T' or res[2]['file_type'] == 'C': - if bit_position == PCCC_CT['PRE']: - return UNPACK_PCCC_DATA_FUNCTION[res[2]['file_type']]( - self._reply[new_value+2:new_value+2+data_size]) - elif bit_position == PCCC_CT['ACC']: - return UNPACK_PCCC_DATA_FUNCTION[res[2]['file_type']]( - self._reply[new_value+4:new_value+4+data_size]) - - tag_value = UNPACK_PCCC_DATA_FUNCTION[res[2]['file_type']]( - self._reply[new_value:new_value+data_size]) - return get_bit(tag_value, bit_position) - - else: - values_list = [] - while len(self._reply[new_value:]) >= data_size: - values_list.append( - UNPACK_PCCC_DATA_FUNCTION[res[2]['file_type']](self._reply[new_value:new_value+data_size]) - ) - new_value = new_value+data_size - - if len(values_list) > 1: - return values_list - else: - return values_list[0] - - except Exception as e: - self._status = (1000, "Error({0}) parsing the data returned from read_tag({1},{2})".format(e, tag, n)) - self.logger.warning(self._status) - raise DataError("Error({0}) parsing the data returned from read_tag({1},{2})".format(e, tag, n)) - else: - raise DataError("send_unit_data returned not valid data") - - def write_tag(self, tag, value): - """ write tag from a connected plc - - Possible combination can be passed to this method: - c.write_tag('N7:0', [-30, 32767, -32767]) - c.write_tag('N7:0', 21) - c.read_tag('N7:0', 10) - - It is not possible to write status bit - - :return: None is returned in case of error - """ - res = parse_tag(tag) - if not res[0]: - self._status = (1000, "Error parsing the tag passed to read_tag({0},{1})".format(tag, value)) - self.logger.warning(self._status) - raise DataError("Error parsing the tag passed to read_tag({0},{1})".format(tag, value)) - - if isinstance(value, list) and int(res[2]['address_field'] == 3): - self._status = (1000, "Function's parameters error. read_tag({0},{1})".format(tag, value)) - self.logger.warning(self._status) - raise DataError("Function's parameters error. read_tag({0},{1})".format(tag, value)) - - if isinstance(value, list) and int(res[2]['address_field'] == 3): - self._status = (1000, "Function's parameters error. read_tag({0},{1})".format(tag, value)) - self.logger.warning(self._status) - raise DataError("Function's parameters error. read_tag({0},{1})".format(tag, value)) - - bit_field = False - bit_position = 0 - sub_element = 0 - if int(res[2]['address_field'] == 3): - bit_field = True - bit_position = int(res[2]['sub_element']) - values_list = '' - else: - values_list = '\xff\xff' - - multi_requests = False - if isinstance(value, list): - multi_requests = True - - if not self._target_is_connected: - if not self.forward_open(): - self._status = (1000, "Target did not connected. write_tag will not be executed.") - self.logger.warning(self._status) - raise Error("Target did not connected. write_tag will not be executed.") - - try: - n = 0 - if multi_requests: - data_size = PCCC_DATA_SIZE[res[2]['file_type']] - for v in value: - values_list += PACK_PCCC_DATA_FUNCTION[res[2]['file_type']](v) - n += 1 - else: - n = 1 - if bit_field: - data_size = 2 - - if (res[2]['file_type'] == 'T' or res[2]['file_type'] == 'C') \ - and (bit_position == PCCC_CT['PRE'] or bit_position == PCCC_CT['ACC']): - sub_element = bit_position - values_list = '\xff\xff' + PACK_PCCC_DATA_FUNCTION[res[2]['file_type']](value) - else: - sub_element = 0 - if value > 0: - values_list = pack_uint(math.pow(2, bit_position)) + pack_uint(math.pow(2, bit_position)) - else: - values_list = pack_uint(math.pow(2, bit_position)) + pack_uint(0) - - else: - values_list += PACK_PCCC_DATA_FUNCTION[res[2]['file_type']](value) - data_size = PCCC_DATA_SIZE[res[2]['file_type']] - - except Exception as e: - self._status = (1000, "Error({0}) packing the values to write to the" - "SLC write_tag({1},{2})".format(e, tag, value)) - self.logger.warning(self._status) - raise DataError("Error({0}) packing the values to write to the " - "SLC write_tag({1},{2})".format(e, tag, value)) - - data_to_write = values_list - - # Creating the Message Request Packet - self._last_sequence = pack_uint(Base._get_sequence()) - - message_request = [ - self._last_sequence, - '\x4b', - '\x02', - CLASS_ID["8-bit"], - PATH["PCCC"], - '\x07', - self.attribs['vid'], - self.attribs['vsn'], - '\x0f', - '\x00', - self._last_sequence[1], - self._last_sequence[0], - res[2]['write_func'], - pack_usint(data_size * n), - pack_usint(int(res[2]['file_number'])), - PCCC_DATA_TYPE[res[2]['file_type']], - pack_usint(int(res[2]['element_number'])), - pack_usint(sub_element) - ] - - self.logger.debug("SLC write_tag({0},{1})".format(tag, value)) - if self.send_unit_data( - build_common_packet_format( - DATA_ITEM['Connected'], - ''.join(message_request) + data_to_write, - ADDRESS_ITEM['Connection Based'], - addr_data=self._target_cid,)): - sts = int(unpack_usint(self._reply[58])) - try: - if sts != 0: - sts_txt = PCCC_ERROR_CODE[sts] - self._status = (1000, "Error({0}) returned from SLC write_tag({1},{2})".format(sts_txt, tag, value)) - self.logger.warning(self._status) - raise DataError("Error({0}) returned from SLC write_tag({1},{2})".format(sts_txt, tag, value)) - - return True - except Exception as e: - self._status = (1000, "Error({0}) parsing the data returned from " - "SLC write_tag({1},{2})".format(e, tag, value)) - self.logger.warning(self._status) - raise DataError("Error({0}) parsing the data returned from " - "SLC write_tag({1},{2})".format(e, tag, value)) - else: - raise DataError("send_unit_data returned not valid data") \ No newline at end of file diff --git a/python/pycomm_micro/ab_comm/slc.pyc b/python/pycomm_micro/ab_comm/slc.pyc deleted file mode 100644 index 2500bf4b9ce2277a1b5eed65bb1b4996872265a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12028 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 EUrE9-3;+NC diff --git a/python/pycomm_micro/cip/cip_base.py b/python/pycomm_micro/cip/cip_base.py deleted file mode 100644 index 36999e1..0000000 --- a/python/pycomm_micro/cip/cip_base.py +++ /dev/null @@ -1,827 +0,0 @@ -# -*- coding: utf-8 -*- -# -# cip_base.py - A set of classes methods and structures used to implement Ethernet/IP -# -# -# Copyright (c) 2014 Agostino Ruscito -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -import struct -import socket - -from os import getpid -from pycomm_micro.cip.cip_const import * -from pycomm_micro.common import PycommError - - -class CommError(PycommError): - pass - - -class DataError(PycommError): - pass - - -def pack_sint(n): - return struct.pack('b', n) - - -def pack_usint(n): - return struct.pack('B', n) - - -def pack_int(n): - """pack 16 bit into 2 bytes little endian""" - return struct.pack(')^40~Qc3J&leP0B zPL)%6zg%%P-}m*scLpG}G!+iH0H>#Kci(=TK7G!2PIrU(|GI1F(1-u!?TSf$^7wuY zpXgP@0{nAK&6tZ>+%Xp&rRPj7XEyTYV%|6`mp8ROv&>kZsr8$U0dsKxIsGOaFl%^a zz`SqFd&azTanJ;VY3hzFb%zNGe7IOJ!H^@mS!MfRFtOp!4Y>{Dc)3HB?p-vkE~IbecuMaE5VP?3Wsm{4TGRCk#W zy?Vr);@2U3p+|@Dh5j7D7drYVzR;hzEJWLHtz{@ z>f$4&y4!^4Hyc2&*#NrA2GCJ9fDy0(^p*|a>q&f}%WMZ7W;^IE+rjH>2k)^Rlw>=| zV>^dT75$!6JN!aB!Bc97UuY+IS`F|EH3!eAN|r>GEP^VThbo!JDi53LkYQ(!qZxcX zYrm%K*9rUe9KO)m=kbN^ox~UV^@7cN(SE&zx{jzW^pJJoi*@0Pb>WM3;fr;Fz^n@- zWnG{p>p~vu!WZj$)C8wAc}Gp~NfUg^ybr#0P4N9nJZ8ejOmJF>kCVfLPn+P3c|T_^ zenO8gE9(gpyrS|?n&4Fv%$ndeK8lAylxgLGEN4ylv{-y5%YKH{lqQQ&dTV4s=zw2kgWbZN8F*w`qxT8&m*!1GM{RKbIO_`+Fyq8$iAEEdOjrAcN@ z<`Be8_WgQ!BlP`vNDmv0pk2eGErlebSo9WRC(cJ~6E$E|AR>XnU3aN^Cd-rDq+ z+8fOiad{ot?}n`t&CU37qmD23&)=w4T8$HxYLg#-wH$?0%}o#D!aR;o#EuL&8o+Eh zE^9b{+yQufc-iYm(ChAUDxSnA>28IT<%h$VVfrY7*qAHe4#(WYwC6CP9NR+7a;ui$ ztR{+E?MfW8>&^-Yj@7wJD2|V3<_oFA0O5Ep9xvSOKMNJL&q`SHqhml*W#&Iol!+KCH*H!tM%MW9u zq^m}X-o22GGj|WubkE~_^I?pWtYc>s1N~Gs(EP_5=nI&|bV6VJ=n1Vp)PV*V=quSk z?`cLUC);(B%e~|9Tre_fw`{w1r%_4 z+&*34#bX^dwQLzZp4EG2#koZgUAFv7_IzlBAaF!qrt1I61zV}~v}P#uR4gAQxk=nzxDtkoLj?SlOQ%04RXEBBumpSlwk z+aewqp{StB9p_n#1VUme#hS9A#RaFro}O{Q2i5tz`^3fdbrM>vjZk4)BNn>;=CfIxrJqQh2NB3=NaLmJ+CY#&8B%? zae7{P^NKNVKFvG(&T>%|tSox7Dm0tL=Cjy&)@2F9-c(sdm24phZ-Jqr%L-={mK46O za9W|Ka8co$j4DnId#&kv5fRMYEyvt=lJhuw>8QDt<6L4UAqnu_&7679;lEF!)U{n^ z1(^wO16lyFNW33D{oE@jZ`=|V7Ytu(v^L7I=+$Ti;s-r!MC&%O9Sg8lF86R+>5FN$ zz{0+admr2!{zG<|bTrO@v&%W+cxMo=kj6~SDDxFOV5A@hMtLhQD)lMsH#a^n!oa!X zfMTCBKbSMO2F$HNb2D#RE2J2y2QuP?yxAw(p`JYJfmC6BAM?QlHwQE7qI|!B{!ZX~+$lH{&ahH;<#s!o zdk!_5`|scZvySxu4&YjF%=j_PqGbk~%rs`@Y!<%vkxMYgm{dg|2wUG&+|iu2I(70b zzTB78i;1-*trhs^6ZT5#=U4ysl9o^Y0nNUoLrI+j-6gSOQUb?qPMBbaxsn&h!R`cO zPGCHxmHJ-OhiSe#WLke{9LK?4O6fviz*A(Lg)aGnM^mNju#$*yIXaA>cq4|hEDYRI zT#nn3TdIC8bkEnX)*ILB5zGJZbGIV*4h5^=AGh9sCTN9GSdS-JrS}K}*6ST%AU338 zE?!tJF3kEfi?hX2OeUXiG_JOr@)A#S;w)n_7RBXOEcQbTU5fW1F-*GY+cda8KNrU2 znQa+8Zv15j!eRE(mz`VSW-u@02ue#fp)@#^4EiM|LNXy_VxKwaqBx$mlm(w2 zg@n5~pw{};S|6FoR@z;buY=>VDy>w!($8HCwBTTE@By+im3+>PLu_sK(wMomgX;zP zH+QJ;wQoSeVc&1S9BBPfk_BFbyF9yuaqs8XE^}ohNgBVk)6}s!*p-Bon>(>$$<5J^ zB5-E_U*pilMvUu)*VKqrSP-b$dVw@^YJQGZIvQ6A}fFD zS%5B-!6OC0^QZVc$IUN|hiNaIWSaE!!ld?Bw9K3E)q6$cOXsXr>j4O7Of9T?Gfd^H z917A|m6agHS-fBEcItEriM9jRtu z#OhRMAh$oaFE^eW$qnQVIK%l}&KN#>azoB&j-YE8zk3|yIQ!EuKawACp2&?jLM#X;NRKi{I_Y!zBMMp|RGAeLDx zc2UeNyEAi3?nW3z<@IpNow*#s>;E?KR0yBjWD}|G$*GekpQ260qER!fRM)DNvaBlA z(F)hXR#>mtMJa%&)wdw$vRK(N^(A!JqjOM7SnQOv?8lqU5Hbl2ZM%~4Ys=;&+}rX4 z?AfYZT-^v8?O6J_huV}t;iF0XX?Vn=gD7J9hn-RU4ne6NaCYSo!}pL?r&~B|4zEyi z0#8BY8gmsKGfAwDtz3evbke1HY^v}SSdv%@|EOI>RT2|6QI;A21^rm zY%d{OU~9#&7@*&zsgsQCnfQ~a5*YM`Zy>&GvDr(XF+T|F#A<4oBLjk>SvN2)X&Uyd zKGrqbEEV}|L^}VIsQub+nUyYujRm4X+XBwDDW}UMiN-Mj=O_r9*i$XxP(Za3CaOq` z*wFwHW#&1{Vy*}N30oF?atngg7{C;B2P01wl6K?qc5;h$tAIZB34zm~>;xv}n0?1~#^ zFTLXs-GQqpX=U~#FC(s0y*v(7mslxaa#|_kbz8CU8kPc$-p_C?BnI&JJ4sb23yX%Y z3?_XUGMn!ZATq&XAIM}VMu4}8iSb*&W*7l5(Xcso3y2Gt6-XEg(&p5fC?e4<;&H`U2E4XlKRo*M!OcctD)NlSfhtk?@7TV z@*7~SSu1ba+_I}0GYFXQlzSTlR9mpp0>53a#uE0KZW^-s>@=DxZ=|WG)#h5eR!dV7 zl!%7cT8#~5FU`-W;^bB0qtos(04J9n^%_$+3JeI4BiK@SvxznuiQ3zAt7{)I7C7K$ zT`1HQZ*IA0Yp{6rG<0m%P@58}TDQHH@5=qGJBjvPo{Bnd-IvE*YB`rG@u}nPq;T;^ zWV@FvR3_fm&s^QD;K&n4WpT5BwVJ(N1(h(wuI30XkGl+?QkSbI!3h>Qa{)`03kz~| z9gAE^Z!9j(3K^cAp0x+aBEl#pYol0JIr1i{yJc$&jke15^-%VAOsDSb^zyX-`uT;K z<+;TLzchC-5t+U+mfu+_dX&YIz~>j1rf1%=Iq56jJZq=So}{?(Y7EK<)HRUMyTOMY z2vS#YJb?#zpjN|{-&jip956JHK5Q5kCFJCsS)t1vXo2nZunxCXEivu|Q8-f;qELAV zOZ%(gI-G$VwtWUadynC%$AY_S?NV?jK)pu6&1p5m^i7T9GX`LC$T~qOdT;EfeLO zgt%oKU_%FOarPDm1F0JTh4{1YHMz%FJDErt<1IuWo#A+32q7xB0yc>uczx&%Ji>^F zKu%DReFk7h1OgZ#&=2zL3E<>(oV2}Mj2c~}(FssazwXa16qlv3ON-z$sQ2RZIq^D+ zNwY%{C%`j(WLBdY>#?*r@AFmELIbO`=)YAgE=|wRy= zX*X^EEDMopmm5Gxj5Kljw0D&AzJMnF0x3ok8Z3@SKr_ifK^hV*Bizs7flvZ|SGc&2 zc2UsMuAU;E8#jo5Gjx9ynC~x|%~#VGWa^>7QIM4QM&u<@sdMarG6|{C8jAJ-1m(@j zwMn^D!RefrKbOu+S{T_E@L9nd$u5cp5mEM8rtg{&ceT~H8rG+@B0Wxw_md0=Rz-BG zWX*~uNpf7;#m*!rNp_fKPb(pA#FUfpx2Es+a?*YV9r!s;+CfANq}mvy+Pl(HN_~DxfaCuV|ax|*zNOYB?{*cMomtjG{db(!Pd+-I1!k9&Sk%|`Nhs$V!%j8 z?m^gMkXD>j`7{&w`JOB{L0hgLbOHXwU!@-jtKo`pC_oudCwz!H5@QWNKwuh31f#Ie zhS&+d3ke7en)p0{ssT&&K%l&G?KF4I_M52owT4Ci~>F14V-Lloz?Ptm0Hvu_{ zo*;qTZ^8lAev+j45^D4Q1e@WcdSXI~Rml`=%g~i28DF{Fu3wGBmUe#*%?DERz&$>& zY%GRWv5roc=N=4V!rn<6brrn{tM7)tME+G%3IE!iq!DoOQE~Br^Efnh0p`^{=xOjX zJC}aM&wG$Sttct}9x?;&u&~I2J-x`4ZO2+`M4@s-x89A=`wE);4GxX^!8lgJkU4aW z-ur3BD04loVeiWf_)4coirw#RJnsXvL5nn^-*X^0++P?N-aR~iJ5AYD2ndTFq7U(u z*htal#%iM`=$AR#I#!U)rQzTKA6yTCyi0JLbz2s;h&5o6;_!VpDpmN@WmA<2{I^;X z({3y%50x30q28faxxd9daGr4}ufn4t+ai6_0&|Ox$p{wosOudP-*4*1WJHTbyQuWd zj0*}90%u{SR8UYq>Vy#bFz21 zaFfX1;le#8dxr}*hU^_KTqLr0xNz^u-r>USCVPhqd!zOa*CXj2u0!b^uEV_a#72+s z+7lzVA#_-gqXf!FKpBfcNGE>s_-M_)0eTVYS~UjD@F;Nx7C#bwsFxAtLJ_4YbWtEn zxPlSTQBuPfSY`^`D02V#@FCbN(9T9cI2+lOmf20^$hSt=LqkdS33r*--w( zWV2a{P};*!E*zyGHpVWC%nM!4X|@`10|yga+)#?JIIEw>#;lZHt68n?{VNc3UqmC? zhp@PbYHSq_eE3c3q3~y=*>%N?nrnPTl~z>* zm*MZ%%25n^3cLDr&eFKkSs(Zh=$q{-lQ|j2S!Scr3X@Hl$S=QJuGY${wXmx=dqS6! zwhnD8OuF8x#&$a-^)(ElIvjLrRaYac%ZYc?f6^I>pm*Y2O8Q%r-f|-VP>*2Ct$^b# zcm3^u0-z;Rs^lpNEiw$`6P6z276kGZkV2!w`#ORLfln+45Gwlq|IHMXwG~oXt1gql z*k6Re<7tQSM$%Un7M9Y=yBcoxZa$JF1y%=>Z1}!|wi9?I8~{hUL}?bc2>P3hJ%*s?{l~ho{qO7QKgq~XW@A5rht1s`(!ab?-vgrtCL65YW3+lR z4}={Q-xmAGGuT-x9!J*mK?NaB3vf~fIj9|Il0JmpaI4+hDv*RmO|1vF64+VzjL@d< z?_%#sNppv#z}0I}1X$`S_YbzSljcAIit2|1=^^1Ij49!Xh$G)0?dm%_#t%EBJYQ(Xwfuni-WOCp|JZ1x@)8ZH(`-mH{tCk~F9NvN)ZQ)Xws>(%&j>RN&wlPKuO+DP1@NRDdT9himix|_Z)Q->vV zOvgHEC78a7*1f;M0H3ZkET+2O#*6ni(Z&IiQmYq-P4>bao~_=DpiiQhRR|D9z@QWK z(^=oN6}Q6N4zO@?T7$+nwpu_rZj6CM8yg^Ghc46Z!r~H6DK-Gxa6`E4UPmb&(Fj4& z5GOV2*j}na)t6%=;-7^(v@wGas}{Z#Y%O6k3kHPe(Hfd%S&z+lInDu@IIr1jZ&u9N+K#y78 z`{!u#G0qL;is_%|%nKLX3_dz0Zs%o-T>5q7JrF=)#V95jV)W^*6`6{n@0pGg(RAV5 zXSekgj~y+13lDz`W@ix`m4eJ=3@%Q{nN72)bC+;bV=V-I<{0u|Yy!WRR<3PAm*XTP zba~r2IQZ|tO$Xg#B{Om_z{d%^Q<9@O`Z09FoyWf1TmV5_jk8t6MNn(tOp+B&SU|{L z+r;e;oEna+I;$;}UpSJUE}Cp%T1}#bWbFYgu*@FFq?F7aZW8*oxp-6SsQM~8 zsl$jmtmpj;JbJ&)fa}Hk9R${NN&J4^KV$OO7?4NpnL=7A#T%7S7Krtb7LnA2W`3TJ z_}JjS3&C%p=I6)}``88++7Nz+0cFOV9WVgKImVFc>yo866 zx$QcGu)fQ;5d7Wg)*e~m0Kgoqh9ifJbk zR5&gC^myWb5lv{~&tn%;Q?EJLGUthZpbKV9J+ukkjs9vvvy&^|dsF(m=;Qnyru445 zDf(NSjW5Yw!WrscYaUWGcM~mL*6`|9C%3&rqgN6WHj+4kt_z?5F}0aO0cLaw6l3 z$(AHw@Xj+85zq$iAZ>j|2UB=JHc7_Sq@#c!I2Z^B@&O=7pWPtUf$#KqLti>Ezs89< z%LCV%m@ZkA+BvR8&D{$kOwx$LPo_6>*Qz%lwd`U0<5&j)_`gzX6Zmt=6XQS`Vga4X z*HJa(T2C-QjgE=&Km-Ij)m$gh>YT*yA4s5*fw0rE#H>N-D=VBrUK% zK*VB_7LMEtoRpF+2%CXZMLM)Jfz`JirhqH>iZ+_WG6`lOgh5`yZz+%wXc2tDg`)%k z;|dWF@Hdjpjw{$t0sr-5SKsb}*e>ieSFo*u^O@LFv5v0pawv*_su!3D`yl8N_FC96 zyl4kCq9WMpvRn7j=P_#B$XN$ArO$ZxXn73J4Nrzx9sw+B9c;~GW+EDf=QPS&| zal23M7`bB7ns84jnnKZ)a!XsG$Fz3Rj%@MXbiJ}L$-M>3=N-Hys5Qb2@jhXC2Xxs> zf?s3WFC&oA8-%OvbzL0v&N74gMa$#5?M-LTwbw@RzeCHLTo=0C*I#f3;hdjv4&wxj zMeP&LQ%VDB=L$hl!~Gnskn>0(GeQ5@>!VL{FOp1VmqsQCF*?ikI=KQ8fMt2m87w)0 zaq9^iuekRHgAP_4tTwwsSUVWJfa{<(hV#=&Y-bkZB{pp5VF}vAy);Vao`+g%jAdy|OQ6`t--H zK;+ndaf6F?Cfg5m&z0-An$(Ku{au7tE4_i}{Z%A*e~rN}G5G5U^%s|l3-$(Li}?`)KreDLNWZwS zP_&1%;ryF^11Gc6Yb|nTEO~Q_IQjmLydukU=ZcHxm;L3rnYT*z{uiaH4t%G1=g!YB z&n?Z*6+M9u?bvoTvNY{YpDW^;q;^J^z3GM0(xSKQ>uQbCx(f5yxc6 z<0Sq$9TC$warx3K@{$fyzsAykj{(J?_p1zw2s-w)lvej7`Z!e9J9}GQ>~8L-DAHd? zm(1V@c3MaBd4z+>Zyv6gg2X#TJfHSqkBOgrZZL04;aVjAV%iwW_2H9=ek~-_8vP-H zn-G89q91p&GSM%wXOAc*qF>5@QnerA6r!IR0HU8yI&+hVepU+U4^@!F64{S5-f@O9 zfZ)doj;@+^b!viq-YxmOCza0vM$`Z!cx_auN2n+f^ND=^9r71@FIirKFt3Vd0eFM|}*A5Y+G98(`xVs91JcM!+0_c&Mdu$%)RACTI#i%lP$ z`I$B#?~+HNcMxp8kPr~t!t~yQm@rr&Gv#U#{>4FYoF7*PKrya|(0yX>AS@?4IIvMA zW>fbG|8x*1DOyC3LCxe60$rwAS_WP5C#z+2)*FdauVZqq@ec)MZ$yuw&S$s$xF!4r z7k5k2vkUf*3TYkuKHl(tfPrkjzs=asFzEO@K&#|9%+Dj%JDsoHp#R318A3azKM$jA z9H*;ppPdWH-aOfvo%h7*emY0kMu9TrwCKcaGGE=3Q@Y#acxa(RRvgNMe>U01$dW(C z{2WEKU31}j#hD_mLv_zjGC7)vFQd4{X4~fKAxsYUTqs?#$=U0;oE&lo`8iuURA8h% zihgJ|e?)OeAY9DdVOmeq{79zDUiUyr{C!?Hm#p;(LBty#IXE71O$3q&m1Q|ObA~m` zrIb{-N!-P9I;UG=HvYB@JWhBWJE|XIJ>rkVz@7OEm~z&NDs113rF% z!PgngFrY_74jHQm|A>zr2IAbwCj&1947R49oPO=G{}L`k9^wt_!{~reiWw{bxZ^k_ zE}0bo-S-Nr57C!-2NCciczts*VYHU~4m>@HiN}nR3$mMNFX>TSm*(}E)`C(czmu1` zffd-PUd8S= zRy|iSB)2^^1UZoIdfP+j)-x|A*YG=_PITcqco2xf%V97ta>R7Y8jO>_*(fSGgX*U2=kBB4r`cu7YTP<<5qAFb4ttjDro`)Ttqlw;ztm4|FV=5aqu0$EMl=Dt_Nw;saX*8D3?>+`N$(JY!wilvILg3faE!tCArO|o!=DrQ zQ!MZ&S%9@Ae{o=GW@cvVpB;$Dk*n8l&$IghKfsDU!$9j6%Od&HGP2h;`S@cDK49<* z2%x?}xYaB0L+X-7k9k1i^NjuPcU~dAqF+ORKMA0}T{N0M(08D(z+YUA!-u~E$ur|N y2jVaFNNxWf>ig)tLFc1#hv4PfUK2{+Ikm4aI6PK3GJIxa|M20$Gh?R;!~YKwz)r&e diff --git a/python/pycomm_micro/cip/cip_const.py b/python/pycomm_micro/cip/cip_const.py deleted file mode 100644 index 3bf959f..0000000 --- a/python/pycomm_micro/cip/cip_const.py +++ /dev/null @@ -1,482 +0,0 @@ -# -*- coding: utf-8 -*- -# -# cip_const.py - A set of structures and constants used to implement the Ethernet/IP protocol -# -# -# Copyright (c) 2014 Agostino Ruscito -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -ELEMENT_ID = { - "8-bit": '\x28', - "16-bit": '\x29', - "32-bit": '\x2a' -} - -CLASS_ID = { - "8-bit": '\x20', - "16-bit": '\x21', -} - -INSTANCE_ID = { - "8-bit": '\x24', - "16-bit": '\x25' -} - -ATTRIBUTE_ID = { - "8-bit": '\x30', - "16-bit": '\x31' -} - -# Path are combined as: -# CLASS_ID + PATHS -# For example PCCC path is CLASS_ID["8-bit"]+PATH["PCCC"] -> 0x20, 0x67, 0x24, 0x01. -PATH = { - 'Connection Manager': '\x06\x24\x01', - 'Router': '\x02\x24\x01', - 'Backplane Data Type': '\x66\x24\x01', - 'PCCC': '\x67\x24\x01', - 'DHCP Channel A': '\xa6\x24\x01\x01\x2c\x01', - 'DHCP Channel B': '\xa6\x24\x01\x02\x2c\x01' -} - -ENCAPSULATION_COMMAND = { # Volume 2: 2-3.2 Command Field UINT 2 byte - "nop": '\x00\x00', - "list_targets": '\x01\x00', - "list_services": '\x04\x00', - "list_identity": '\x63\x00', - "list_interfaces": '\x64\x00', - "register_session": '\x65\x00', - "unregister_session": '\x66\x00', - "send_rr_data": '\x6F\x00', - "send_unit_data": '\x70\x00' -} - -""" -When a tag is created, an instance of the Symbol Object (Class ID 0x6B) is created -inside the controller. - -When a UDT is created, an instance of the Template object (Class ID 0x6C) is -created to hold information about the structure makeup. -""" -CLASS_CODE = { - "Message Router": '\x02', # Volume 1: 5-1 - "Symbol Object": '\x6b', - "Template Object": '\x6c', - "Connection Manager": '\x06' # Volume 1: 3-5 -} - -CONNECTION_MANAGER_INSTANCE = { - 'Open Request': '\x01', - 'Open Format Rejected': '\x02', - 'Open Resource Rejected': '\x03', - 'Open Other Rejected': '\x04', - 'Close Request': '\x05', - 'Close Format Request': '\x06', - 'Close Other Request': '\x07', - 'Connection Timeout': '\x08' -} - -TAG_SERVICES_REQUEST = { - "Read Tag": 0x4c, - "Read Tag Fragmented": 0x52, - "Write Tag": 0x4d, - "Write Tag Fragmented": 0x53, - "Read Modify Write Tag": 0x4e, - "Multiple Service Packet": 0x0a, - "Get Instance Attributes List": 0x55, - "Get Attributes": 0x03, - "Read Template": 0x4c, -} - -TAG_SERVICES_REPLY = { - 0xcc: "Read Tag", - 0xd2: "Read Tag Fragmented", - 0xcd: "Write Tag", - 0xd3: "Write Tag Fragmented", - 0xce: "Read Modify Write Tag", - 0x8a: "Multiple Service Packet", - 0xd5: "Get Instance Attributes List", - 0x83: "Get Attributes", - 0xcc: "Read Template" -} - - -I_TAG_SERVICES_REPLY = { - "Read Tag": 0xcc, - "Read Tag Fragmented": 0xd2, - "Write Tag": 0xcd, - "Write Tag Fragmented": 0xd3, - "Read Modify Write Tag": 0xce, - "Multiple Service Packet": 0x8a, - "Get Instance Attributes List": 0xd5, - "Get Attributes": 0x83, - "Read Template": 0xcc -} - - -""" -EtherNet/IP Encapsulation Error Codes - -Standard CIP Encapsulation Error returned in the cip message header -""" -STATUS = { - 0x0000: "Success", - 0x0001: "The sender issued an invalid or unsupported encapsulation command", - 0x0002: "Insufficient memory", - 0x0003: "Poorly formed or incorrect data in the data portion", - 0x0064: "An originator used an invalid session handle when sending an encapsulation message to the target", - 0x0065: "The target received a message of invalid length", - 0x0069: "Unsupported Protocol Version" -} - -""" -MSG Error Codes: - -The following error codes have been taken from: - -Rockwell Automation Publication -1756-RM003P-EN-P - December 2014 -""" -SERVICE_STATUS = { - 0x01: "Connection failure (see extended status)", - 0x02: "Insufficient resource", - 0x03: "Invalid value", - 0x04: "IOI syntax error. A syntax error was detected decoding the Request Path (see extended status)", - 0x05: "Destination unknown, class unsupported, instance \nundefined or structure element undefined (see extended status)", - 0x06: "Insufficient Packet Space", - 0x07: "Connection lost", - 0x08: "Service not supported", - 0x09: "Error in data segment or invalid attribute value", - 0x0A: "Attribute list error", - 0x0B: "State already exist", - 0x0C: "Object state conflict", - 0x0D: "Object already exist", - 0x0E: "Attribute not settable", - 0x0F: "Permission denied", - 0x10: "Device state conflict", - 0x11: "Reply data too large", - 0x12: "Fragmentation of a primitive value", - 0x13: "Insufficient command data", - 0x14: "Attribute not supported", - 0x15: "Too much data", - 0x1A: "Bridge request too large", - 0x1B: "Bridge response too large", - 0x1C: "Attribute list shortage", - 0x1D: "Invalid attribute list", - 0x1E: "Request service error", - 0x1F: "Connection related failure (see extended status)", - 0x22: "Invalid reply received", - 0x25: "Key segment error", - 0x26: "Invalid IOI error", - 0x27: "Unexpected attribute in list", - 0x28: "DeviceNet error - invalid member ID", - 0x29: "DeviceNet error - member not settable", - 0xD1: "Module not in run state", - 0xFB: "Message port not supported", - 0xFC: "Message unsupported data type", - 0xFD: "Message uninitialized", - 0xFE: "Message timeout", - 0xff: "General Error (see extended status)" -} - -EXTEND_CODES = { - 0x01: { - 0x0100: "Connection in use", - 0x0103: "Transport not supported", - 0x0106: "Ownership conflict", - 0x0107: "Connection not found", - 0x0108: "Invalid connection type", - 0x0109: "Invalid connection size", - 0x0110: "Module not configured", - 0x0111: "EPR not supported", - 0x0114: "Wrong module", - 0x0115: "Wrong device type", - 0x0116: "Wrong revision", - 0x0118: "Invalid configuration format", - 0x011A: "Application out of connections", - 0x0203: "Connection timeout", - 0x0204: "Unconnected message timeout", - 0x0205: "Unconnected send parameter error", - 0x0206: "Message too large", - 0x0301: "No buffer memory", - 0x0302: "Bandwidth not available", - 0x0303: "No screeners available", - 0x0305: "Signature match", - 0x0311: "Port not available", - 0x0312: "Link address not available", - 0x0315: "Invalid segment type", - 0x0317: "Connection not scheduled" - }, - 0x04: { - 0x0000: "Extended status out of memory", - 0x0001: "Extended status out of instances" - }, - 0x05: { - 0x0000: "Extended status out of memory", - 0x0001: "Extended status out of instances" - }, - 0x1F: { - 0x0203: "Connection timeout" - }, - 0xff: { - 0x7: "Wrong data type", - 0x2001: "Excessive IOI", - 0x2002: "Bad parameter value", - 0x2018: "Semaphore reject", - 0x201B: "Size too small", - 0x201C: "Invalid size", - 0x2100: "Privilege failure", - 0x2101: "Invalid keyswitch position", - 0x2102: "Password invalid", - 0x2103: "No password issued", - 0x2104: "Address out of range", - 0x2105: "Address and how many out of range", - 0x2106: "Data in use", - 0x2107: "Type is invalid or not supported", - 0x2108: "Controller in upload or download mode", - 0x2109: "Attempt to change number of array dimensions", - 0x210A: "Invalid symbol name", - 0x210B: "Symbol does not exist", - 0x210E: "Search failed", - 0x210F: "Task cannot start", - 0x2110: "Unable to write", - 0x2111: "Unable to read", - 0x2112: "Shared routine not editable", - 0x2113: "Controller in faulted mode", - 0x2114: "Run mode inhibited" - - } -} -DATA_ITEM = { - 'Connected': '\xb1\x00', - 'Unconnected': '\xb2\x00' -} - -ADDRESS_ITEM = { - 'Connection Based': '\xa1\x00', - 'Null': '\x00\x00', - 'UCMM': '\x00\x00' -} - -UCMM = { - 'Interface Handle': 0, - 'Item Count': 2, - 'Address Type ID': 0, - 'Address Length': 0, - 'Data Type ID': 0x00b2 -} - -CONNECTION_SIZE = { - 'Backplane': '\x03', # CLX - 'Direct Network': '\x02' -} - -HEADER_SIZE = 24 -EXTENDED_SYMBOL = '\x91' -BOOL_ONE = 0xff -REQUEST_SERVICE = 0 -REQUEST_PATH_SIZE = 1 -REQUEST_PATH = 2 -SUCCESS = 0 -INSUFFICIENT_PACKETS = 6 -OFFSET_MESSAGE_REQUEST = 40 - - -FORWARD_CLOSE = '\x4e' -UNCONNECTED_SEND = '\x52' -FORWARD_OPEN = '\x54' -LARGE_FORWARD_OPEN = '\x5b' -GET_CONNECTION_DATA = '\x56' -SEARCH_CONNECTION_DATA = '\x57' -GET_CONNECTION_OWNER = '\x5a' -MR_SERVICE_SIZE = 2 - -PADDING_BYTE = '\x00' -PRIORITY = '\x0a' -TIMEOUT_TICKS = '\x05' -TIMEOUT_MULTIPLIER = '\x01' -TRANSPORT_CLASS = '\xa3' - -CONNECTION_PARAMETER = { - 'PLC5': 0x4302, - 'SLC500': 0x4302, - 'CNET': 0x4320, - 'DHP': 0x4302, - 'Default': 0x43f8, -} - -""" -Atomic Data Type: - - Bit = Bool - Bit array = DWORD (32-bit boolean aray) - 8-bit integer = SINT -16-bit integer = UINT -32-bit integer = DINT - 32-bit float = REAL -64-bit integer = LINT - -From Rockwell Automation Publication 1756-PM020C-EN-P November 2012: -When reading a BOOL tag, the values returned for 0 and 1 are 0 and 0xff, respectively. -""" - -S_DATA_TYPE = { - 'BOOL': 0xc1, - 'SINT': 0xc2, # Signed 8-bit integer - 'INT': 0xc3, # Signed 16-bit integer - 'DINT': 0xc4, # Signed 32-bit integer - 'LINT': 0xc5, # Signed 64-bit integer - 'USINT': 0xc6, # Unsigned 8-bit integer - 'UINT': 0xc7, # Unsigned 16-bit integer - 'UDINT': 0xc8, # Unsigned 32-bit integer - 'ULINT': 0xc9, # Unsigned 64-bit integer - 'REAL': 0xca, # 32-bit floating point - 'LREAL': 0xcb, # 64-bit floating point - 'STIME': 0xcc, # Synchronous time - 'DATE': 0xcd, - 'TIME_OF_DAY': 0xce, - 'DATE_AND_TIME': 0xcf, - 'STRING': 0xd0, # character string (1 byte per character) - 'BYTE': 0xd1, # byte string 8-bits - 'WORD': 0xd2, # byte string 16-bits - 'DWORD': 0xd3, # byte string 32-bits - 'LWORD': 0xd4, # byte string 64-bits - 'STRING2': 0xd5, # character string (2 byte per character) - 'FTIME': 0xd6, # Duration high resolution - 'LTIME': 0xd7, # Duration long - 'ITIME': 0xd8, # Duration short - 'STRINGN': 0xd9, # character string (n byte per character) - 'SHORT_STRING': 0xda, # character string (1 byte per character, 1 byte length indicator) - 'TIME': 0xdb, # Duration in milliseconds - 'EPATH': 0xdc, # CIP Path segment - 'ENGUNIT': 0xdd, # Engineering Units - 'STRINGI': 0xde # International character string -} - -I_DATA_TYPE = { - 0xc1: 'BOOL', - 0xc2: 'SINT', # Signed 8-bit integer - 0xc3: 'INT', # Signed 16-bit integer - 0xc4: 'DINT', # Signed 32-bit integer - 0xc5: 'LINT', # Signed 64-bit integer - 0xc6: 'USINT', # Unsigned 8-bit integer - 0xc7: 'UINT', # Unsigned 16-bit integer - 0xc8: 'UDINT', # Unsigned 32-bit integer - 0xc9: 'ULINT', # Unsigned 64-bit integer - 0xca: 'REAL', # 32-bit floating point - 0xcb: 'LREAL', # 64-bit floating point - 0xcc: 'STIME', # Synchronous time - 0xcd: 'DATE', - 0xce: 'TIME_OF_DAY', - 0xcf: 'DATE_AND_TIME', - 0xd0: 'STRING', # character string (1 byte per character) - 0xd1: 'BYTE', # byte string 8-bits - 0xd2: 'WORD', # byte string 16-bits - 0xd3: 'DWORD', # byte string 32-bits - 0xd4: 'LWORD', # byte string 64-bits - 0xd5: 'STRING2', # character string (2 byte per character) - 0xd6: 'FTIME', # Duration high resolution - 0xd7: 'LTIME', # Duration long - 0xd8: 'ITIME', # Duration short - 0xd9: 'STRINGN', # character string (n byte per character) - 0xda: 'SHORT_STRING', # character string (1 byte per character, 1 byte length indicator) - 0xdb: 'TIME', # Duration in milliseconds - 0xdc: 'EPATH', # CIP Path segment - 0xdd: 'ENGUNIT', # Engineering Units - 0xde: 'STRINGI' # International character string -} - -REPLAY_INFO = { - 0x4e: 'FORWARD_CLOSE (4E,00)', - 0x52: 'UNCONNECTED_SEND (52,00)', - 0x54: 'FORWARD_OPEN (54,00)', - 0x6f: 'send_rr_data (6F,00)', - 0x70: 'send_unit_data (70,00)', - 0x00: 'nop', - 0x01: 'list_targets', - 0x04: 'list_services', - 0x63: 'list_identity', - 0x64: 'list_interfaces', - 0x65: 'register_session', - 0x66: 'unregister_session', -} - -PCCC_DATA_TYPE = { - 'N': '\x89', - 'B': '\x85', - 'T': '\x86', - 'C': '\x87', - 'S': '\x84', - 'F': '\x8a', - 'ST': '\x8d', - 'A': '\x8e', - 'R': '\x88', - 'O': '\x8b', - 'I': '\x8c' -} - -PCCC_DATA_SIZE = { - 'N': 2, - 'B': 2, - 'T': 6, - 'C': 6, - 'S': 2, - 'F': 4, - 'ST': 84, - 'A': 2, - 'R': 6, - 'O': 2, - 'I': 2 -} - -PCCC_CT = { - 'PRE': 1, - 'ACC': 2, - 'EN': 15, - 'TT': 14, - 'DN': 13, - 'CU': 15, - 'CD': 14, - 'OV': 12, - 'UN': 11, - 'UA': 10 -} - -PCCC_ERROR_CODE = { - -2: "Not Acknowledged (NAK)", - -3: "No Reponse, Check COM Settings", - -4: "Unknown Message from DataLink Layer", - -5: "Invalid Address", - -6: "Could Not Open Com Port", - -7: "No data specified to data link layer", - -8: "No data returned from PLC", - -20: "No Data Returned", - 16: "Illegal Command or Format, Address may not exist or not enough elements in data file", - 32: "PLC Has a Problem and Will Not Communicate", - 48: "Remote Node Host is Missing, Disconnected, or Shut Down", - 64: "Host Could Not Complete Function Due To Hardware Fault", - 80: "Addressing problem or Memory Protect Rungs", - 96: "Function not allows due to command protection selection", - 112: "Processor is in Program mode", - 128: "Compatibility mode file missing or communication zone problem", - 144: "Remote node cannot buffer command", - 240: "Error code in EXT STS Byte" -} \ No newline at end of file diff --git a/python/pycomm_micro/cip/cip_const.pyc b/python/pycomm_micro/cip/cip_const.pyc deleted file mode 100644 index ced24b97b43a3728c20fbaeacb199f72b53d86b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10710 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 I^wRbHFWVf!+yDRo diff --git a/python/pycomm_micro/common.py b/python/pycomm_micro/common.py deleted file mode 100644 index f44819c..0000000 --- a/python/pycomm_micro/common.py +++ /dev/null @@ -1,32 +0,0 @@ -__author__ = 'Agostino Ruscito' -__version__ = "1.0.7" -__date__ = "08 03 2015" -import logging - - -logging.basicConfig( - filename="pycomm.log", - filemode='w', - level=logging.INFO, - format="%(name)-13s %(levelname)-10s %(asctime)s %(message)s", - # propagate=0, -) - -LOGGER = logging.getLogger('pycomm') - - -class PycommError(Exception): - pass - - -def setup_logger(name, level, filename=None): - log = logging.getLogger('pycomm.'+name) - log.setLevel(level) - if filename: - fh = logging.FileHandler(filename, mode='w') - fh.setFormatter(logging.Formatter("%(levelname)-10s %(asctime)s %(message)s")) - log.addHandler(fh) - log.propagate = False - - return log - diff --git a/python/pycomm_micro/common.pyc b/python/pycomm_micro/common.pyc deleted file mode 100644 index 26cab345ffcbde9445f36b5f32a1d0b1b726a4d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1297 zcmb_b%Wl&^6ulF>d9*1-Aj*PGHkHhRCZ!-)AOuuNi&UkRE0D;>GMn$YrV;r@VQ&Os#62vpEWkgU@U8dZ9+ND zrmBc@yqxwEj^RQT#w#d13BXfO193G*5vPhG z%N<4$%AHLiUVAxLCZ-S4{bE#Qx@ByuEcr3X6WKjbMKzC(XL;GRaSHR9s=DRep6UV@ z4gl^eQ&ZO8)-amX^q*yNtZr*|v9zwO>MFe@YOUR9e& z<^C-akHxyEizi|ece@sFt4q+uGXSOn26-G&1Pqx>7m%Aymgp&pLT=u9e2-0*?CD~h zrLN1*!@*I=Pu)Lpc(lLY58Xui=ZPvULOIYm-=Qv4$VJ_C@3?y$0T=!5`agQlf1u%X Tb+ld=ZLj6-mT34J-lqQ#fuk#p diff --git a/python/tag_mysql.py b/python/tag_mysql.py deleted file mode 100644 index 9a7bcee..0000000 --- a/python/tag_mysql.py +++ /dev/null @@ -1,91 +0,0 @@ -#! /usr/bin/python - -from datetime import datetime -import time -import mysql.connector as mysqlcon -from pycomm.ab_comm.clx import Driver as ClxDriver -import micro800 as u800 -import traceback -import pickle - -with open('/root/tag-server/python/mysql_cfg.pickle', 'rb') as cfgFile: - mysql_cfg = pickle.load(cfgFile) - con = mysqlcon.connect(**mysql_cfg) - - - -def readTag(addr, tag): - time.sleep(0.01) - c = ClxDriver() - if c.open(addr): - try: - v = c.read_tag(tag) - # print(v) - return v - except Exception: - print("ERROR RETRIEVING TAG: {}".format(tag)) - err = c.get_status() - c.close() - print traceback.print_exc() - pass - c.close() - -class Tag(): - global readTag, con - - def __init__(self, name, tag, db_id, data_type, change_threshold, guarantee_sec, mapFn=None, device_type='CLX', ip_address='192.168.1.10'): - self.name = str(name) - self.tag = str(tag) - self.data_type = str(data_type) - self.value = None - self.last_value = None - self.guarantee_sec = guarantee_sec - self.chg_threshold = change_threshold - self.last_send_time = 0 - self.mapFn = mapFn - self.device_type = device_type - self.readFn = readTag - self.db_id = db_id - if self.device_type == "u800": - self.readFn = u800.readTag - self.ip_address = ip_address - - def read(self, forceSend): - writeToDB = False - if self.tag: - v = self.readFn(self.ip_address, self.tag) - if v: - val = v[0] - if self.data_type == 'BOOL' or self.data_type == 'STRING': - if self.mapFn: - val = self.mapFn[val] - if (self.last_send_time == 0) or (self.value is None) or not (self.value == val) or ((time.time() - self.last_send_time) > self.guarantee_sec) or (forceSend == True): - self.last_value = self.value - self.value = val - writeToDB = True - else: - writeToDB = False - else: - if (self.last_send_time == 0) or (self.value is None) or (abs(self.value - val) > self.chg_threshold) or ((time.time() - self.last_send_time) > self.guarantee_sec) or (forceSend == True): - self.last_value = self.value - self.value = val - writeToDB = True - else: - writeToDB = False - if forceSend == False: - writeToDB = False - if writeToDB: - self.sendToDB() - return self.value - - def sendToDB(self): - # TODO: Datetime - query = "INSERT INTO poconsole.tag_vals (dtime, tagID, val) VALUES ('{}', '{}', {})".format(time.strftime('%Y-%m-%d %H:%M:%S'), self.db_id, self.value) - self.last_send_time = time.time() - print query - # TODO: CHECK ON THIS LOGIC -- with con: - con.connect() - cur = con.cursor() - cur.execute(query) - con.commit() - cur.close() diff --git a/python/tag_sqlite.py b/python/tag_sqlite.py deleted file mode 100644 index 457cd94..0000000 --- a/python/tag_sqlite.py +++ /dev/null @@ -1,85 +0,0 @@ -#! /usr/bin/python -from datetime import datetime -import time -import sqlite3 as lite -from pycomm.ab_comm.clx import Driver as ClxDriver -import micro800 as u800 -import traceback -import pickle - -con = lite.connect("/mnt/usb/data.db") -# con = lite.connect("/Users/patrickjmcd/Desktop/data.db") - - -def readTag(addr, tag): - time.sleep(0.01) - c = ClxDriver() - if c.open(addr): - try: - v = c.read_tag(tag) - return v - except Exception: - print("ERROR RETRIEVING TAG: {} at {}".format(tag, addr)) - err = c.get_status() - c.close() - print err - pass - c.close() - -class Tag(): - global readTag, con - - def __init__(self, name, tag, db_id, data_type, change_threshold, guarantee_sec, mapFn=None, device_type='CLX', ip_address='192.168.1.10'): - self.name = name - self.tag = tag - self.data_type = data_type - self.value = None - self.last_value = None - self.guarantee_sec = guarantee_sec - self.chg_threshold = change_threshold - self.last_send_time = 0 - self.mapFn = mapFn - self.device_type = device_type - self.readFn = readTag - self.db_id = db_id - if self.device_type == "u800": - self.readFn = u800.readTag - self.ip_address = ip_address - - def read(self, forceSend): - writeToDB = False - if self.tag: - v = self.readFn(str(self.ip_address), str(self.tag)) - if v: - val = v[0] - if self.data_type == 'BOOL' or self.data_type == 'STRING': - if self.mapFn: - val = self.mapFn[val] - if (self.last_send_time == 0) or (self.value is None) or not (self.value == val) or ((time.time() - self.last_send_time) > self.guarantee_sec) or (forceSend == True): - self.last_value = self.value - self.value = val - writeToDB = True - else: - writeToDB = False - else: - if (self.last_send_time == 0) or (self.value is None) or (abs(self.value - v[0]) > self.chg_threshold) or ((time.time() - self.last_send_time) > self.guarantee_sec) or (forceSend == True): - self.last_value = self.value - self.value = v[0] - writeToDB = True - else: - writeToDB = False - if forceSend == False: - writeToDB = False - if writeToDB: - self.sendToDB() - return self.value - - def sendToDB(self): - query = "INSERT INTO tag_vals (dtime, tagID, val) VALUES ({}, '{}', {})".format(time.time(), self.db_id, self.value) - self.last_send_time = time.time() - print query - with con: - cur = con.cursor() - cur.execute(query) - con.commit() - cur.close() diff --git a/tag b/tag new file mode 160000 index 0000000..95388b0 --- /dev/null +++ b/tag @@ -0,0 +1 @@ +Subproject commit 95388b02b9b2497e73ad39d4534d3d942bf90913 diff --git a/python/tagserver_MySQL.py b/tagserver_MySQL.py similarity index 100% rename from python/tagserver_MySQL.py rename to tagserver_MySQL.py diff --git a/python/tagserver_SQLite.py b/tagserver_SQLite.py similarity index 100% rename from python/tagserver_SQLite.py rename to tagserver_SQLite.py