From 604d21c012a0e25fc078b83e5b9cc4a68fce8b8b Mon Sep 17 00:00:00 2001 From: Patrick McDonagh Date: Tue, 9 May 2017 15:24:04 -0500 Subject: [PATCH] Removes pycomm-helper and pycomm folders --- .gitmodules | 0 daq_sample/pycomm-master/.travis.yml | 12 - daq_sample/pycomm-master/CHANGES | 39 - daq_sample/pycomm-master/LICENSE | 22 - daq_sample/pycomm-master/MANIFEST.in | 1 - daq_sample/pycomm-master/README.rst | 171 ---- .../pycomm-master/examples/test_clx_comm.py | 42 - .../pycomm-master/examples/test_slc_only.py | 72 -- daq_sample/pycomm-master/pycomm/__init__.py | 1 - .../pycomm-master/pycomm/ab_comm/__init__.py | 2 - .../pycomm-master/pycomm/ab_comm/clx.py | 873 ------------------ .../pycomm-master/pycomm/ab_comm/slc.py | 574 ------------ .../pycomm-master/pycomm/cip/__init__.py | 1 - .../pycomm-master/pycomm/cip/cip_base.py | 864 ----------------- .../pycomm-master/pycomm/cip/cip_const.py | 483 ---------- daq_sample/pycomm-master/pycomm/common.py | 8 - daq_sample/pycomm-master/setup.py | 37 - daq_sample/pycomm_helper | 1 - 18 files changed, 3203 deletions(-) delete mode 100644 .gitmodules delete mode 100755 daq_sample/pycomm-master/.travis.yml delete mode 100755 daq_sample/pycomm-master/CHANGES delete mode 100755 daq_sample/pycomm-master/LICENSE delete mode 100755 daq_sample/pycomm-master/MANIFEST.in delete mode 100755 daq_sample/pycomm-master/README.rst delete mode 100755 daq_sample/pycomm-master/examples/test_clx_comm.py delete mode 100755 daq_sample/pycomm-master/examples/test_slc_only.py delete mode 100755 daq_sample/pycomm-master/pycomm/__init__.py delete mode 100755 daq_sample/pycomm-master/pycomm/ab_comm/__init__.py delete mode 100755 daq_sample/pycomm-master/pycomm/ab_comm/clx.py delete mode 100755 daq_sample/pycomm-master/pycomm/ab_comm/slc.py delete mode 100755 daq_sample/pycomm-master/pycomm/cip/__init__.py delete mode 100755 daq_sample/pycomm-master/pycomm/cip/cip_base.py delete mode 100755 daq_sample/pycomm-master/pycomm/cip/cip_const.py delete mode 100755 daq_sample/pycomm-master/pycomm/common.py delete mode 100755 daq_sample/pycomm-master/setup.py delete mode 160000 daq_sample/pycomm_helper diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29..0000000 diff --git a/daq_sample/pycomm-master/.travis.yml b/daq_sample/pycomm-master/.travis.yml deleted file mode 100755 index ba8ac2d..0000000 --- a/daq_sample/pycomm-master/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: python - -python: -- "2.6" -- "2.7" -- "3.2" -- "3.3" -- "3.4" - -install: python setup.py install - -script: nosetests \ No newline at end of file diff --git a/daq_sample/pycomm-master/CHANGES b/daq_sample/pycomm-master/CHANGES deleted file mode 100755 index 5754287..0000000 --- a/daq_sample/pycomm-master/CHANGES +++ /dev/null @@ -1,39 +0,0 @@ -CHANGES -======= - -1.0.8 ------ -Number 0001: -handling of raw values (hex) added to functions read_array and write_array: handling of raw values can be switched -on/off with additional parameter - -Number 0002: -is a bugfix when reading the tag_list from a PLC. If one tag is of datatype bool and it is part of a bool -array within an SINT, the tag type value contains also the bit position. - -Number 0003: -code is always logging into a file (pycomm.log) into working path. Code changed, so that it is possible to configure -the logging from the main application. - - - -1.0.6 ------ - -- Pypi posting - -1.0.0 ------ - -- Add support for SLC and PLC/05 plc - -0.2.0 ---- - -- Add CIP support class -- Add support for ControlLogix PLC - -0.1 ---- - -- Initial release. \ No newline at end of file diff --git a/daq_sample/pycomm-master/LICENSE b/daq_sample/pycomm-master/LICENSE deleted file mode 100755 index 62fcb0b..0000000 --- a/daq_sample/pycomm-master/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -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. - diff --git a/daq_sample/pycomm-master/MANIFEST.in b/daq_sample/pycomm-master/MANIFEST.in deleted file mode 100755 index 9561fb1..0000000 --- a/daq_sample/pycomm-master/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include README.rst diff --git a/daq_sample/pycomm-master/README.rst b/daq_sample/pycomm-master/README.rst deleted file mode 100755 index 0eed45b..0000000 --- a/daq_sample/pycomm-master/README.rst +++ /dev/null @@ -1,171 +0,0 @@ -pycomm -====== -pycomm is a package that includes a collection of modules used to communicate with PLCs. -At the moment the first module in the package is ab_comm. - -Test -~~~~ -The library is currently test on Python 2.6, 2.7. - -.. image:: https://travis-ci.org/ruscito/pycomm.svg?branch=master - :target: https://travis-ci.org/ruscito/pycomm - -Setup -~~~~~ -The package can be installed from - -GitHub: -:: - - git clone https://github.com/ruscito/pycomm.git - cd pycomm - sudo python setup.py install - - -PyPi: -:: - pip install pycomm - -ab_comm -~~~~~~~ -ab_comm is a module that contains a set of classes used to interface Rockwell PLCs using Ethernet/IP protocol. -The "clx" class can be used to communicate with Compactlogix, Controllogix PLCs -The "slc" can be used to communicate with Micrologix or SLC PLCs - -I tried to followCIP specifications volume 1 and 2 as well as `Rockwell Automation Publication 1756-PM020-EN-P - November 2012`_ . - -.. _Rockwell Automation Publication 1756-PM020-EN-P - November 2012: http://literature.rockwellautomation.com/idc/groups/literature/documents/pm/1756-pm020_-en-p.pdf - -See the following snippet for communication with a Controllogix PLC: - -:: - - from pycomm.ab_comm.clx import Driver as ClxDriver - import logging - - - if __name__ == '__main__': - logging.basicConfig( - filename="ClxDriver.log", - format="%(levelname)-10s %(asctime)s %(message)s", - level=logging.DEBUG - ) - c = ClxDriver() - - if c.open('172.16.2.161'): - - print(c.read_tag(['ControlWord'])) - print(c.read_tag(['parts', 'ControlWord', 'Counts'])) - - print(c.write_tag('Counts', -26, 'INT')) - print(c.write_tag(('Counts', 26, 'INT'))) - print(c.write_tag([('Counts', 26, 'INT')])) - print(c.write_tag([('Counts', -26, 'INT'), ('ControlWord', -30, 'DINT'), ('parts', 31, 'DINT')])) - - # To read an array - r_array = c.read_array("TotalCount", 1750) - for tag in r_array: - print (tag) - - # reset tha array to all 0 - w_array = [] - for i in xrange(1750): - w_array.append(0) - c.write_array("TotalCount", "SINT", w_array) - - c.close() - - - - -See the following snippet for communication with a Micrologix PLC: - - -:: - - from pycomm.ab_comm.slc import Driver as SlcDriver - import logging - - - if __name__ == '__main__': - logging.basicConfig( - filename="SlcDriver.log", - format="%(levelname)-10s %(asctime)s %(message)s", - level=logging.DEBUG - ) - c = SlcDriver() - if c.open('172.16.2.160'): - - print c.read_tag('S:1/5') - print c.read_tag('S:60', 2) - - print c.write_tag('N7:0', [-30, 32767, -32767]) - print c.write_tag('N7:0', 21) - print c.read_tag('N7:0', 10) - - print c.write_tag('F8:0', [3.1, 4.95, -32.89]) - print c.write_tag('F8:0', 21) - print c.read_tag('F8:0', 3) - - print c.write_tag('B3:100', [23, -1, 4, 9]) - print c.write_tag('B3:100', 21) - print c.read_tag('B3:100', 4) - - print c.write_tag('T4:3.PRE', 431) - print c.read_tag('T4:3.PRE') - print c.write_tag('C5:0.PRE', 501) - print c.read_tag('C5:0.PRE') - print c.write_tag('T4:3.ACC', 432) - print c.read_tag('T4:3.ACC') - print c.write_tag('C5:0.ACC', 502) - print c.read_tag('C5:0.ACC') - - c.write_tag('T4:2.EN', 0) - c.write_tag('T4:2.TT', 0) - c.write_tag('T4:2.DN', 0) - print c.read_tag('T4:2.EN', 1) - print c.read_tag('T4:2.TT', 1) - print c.read_tag('T4:2.DN',) - - c.write_tag('C5:0.CU', 1) - c.write_tag('C5:0.CD', 0) - c.write_tag('C5:0.DN', 1) - c.write_tag('C5:0.OV', 0) - c.write_tag('C5:0.UN', 1) - c.write_tag('C5:0.UA', 0) - print c.read_tag('C5:0.CU') - print c.read_tag('C5:0.CD') - print c.read_tag('C5:0.DN') - print c.read_tag('C5:0.OV') - print c.read_tag('C5:0.UN') - print c.read_tag('C5:0.UA') - - c.write_tag('B3:100', 1) - print c.read_tag('B3:100') - - c.write_tag('B3/3955', 1) - print c.read_tag('B3/3955') - - c.write_tag('N7:0/2', 1) - print c.read_tag('N7:0/2') - - print c.write_tag('O:0.0/4', 1) - print c.read_tag('O:0.0/4') - - c.close() - - -The Future -~~~~~~~~~~ -This package is under development. -The modules _ab_comm.clx_ and _ab_comm.slc_ are completed at moment but other drivers will be added in the future. - -Thanks -~~~~~~ -Thanks to patrickjmcd_ for the help with the Direct Connections and thanks in advance to anyone for feedback and suggestions. - -.. _patrickjmcd: https://github.com/patrickjmcd - -License -~~~~~~~ -pycomm is distributed under the MIT License \ No newline at end of file diff --git a/daq_sample/pycomm-master/examples/test_clx_comm.py b/daq_sample/pycomm-master/examples/test_clx_comm.py deleted file mode 100755 index cd8c37d..0000000 --- a/daq_sample/pycomm-master/examples/test_clx_comm.py +++ /dev/null @@ -1,42 +0,0 @@ -from pycomm.ab_comm.clx import Driver as ClxDriver -import logging - -from time import sleep - - -if __name__ == '__main__': - - logging.basicConfig( - filename="ClxDriver.log", - format="%(levelname)-10s %(asctime)s %(message)s", - level=logging.DEBUG - ) - c = ClxDriver() - - print c['port'] - print c.__version__ - - - if c.open('172.16.2.161'): - while 1: - try: - print(c.read_tag(['ControlWord'])) - print(c.read_tag(['parts', 'ControlWord', 'Counts'])) - - print(c.write_tag('Counts', -26, 'INT')) - print(c.write_tag(('Counts', 26, 'INT'))) - print(c.write_tag([('Counts', 26, 'INT')])) - print(c.write_tag([('Counts', -26, 'INT'), ('ControlWord', -30, 'DINT'), ('parts', 31, 'DINT')])) - sleep(1) - except Exception as e: - err = c.get_status() - c.close() - print err - pass - - # To read an array - r_array = c.read_array("TotalCount", 1750) - for tag in r_array: - print (tag) - - c.close() diff --git a/daq_sample/pycomm-master/examples/test_slc_only.py b/daq_sample/pycomm-master/examples/test_slc_only.py deleted file mode 100755 index f086efa..0000000 --- a/daq_sample/pycomm-master/examples/test_slc_only.py +++ /dev/null @@ -1,72 +0,0 @@ -__author__ = 'agostino' - -from pycomm.ab_comm.slc import Driver as SlcDriver - - -if __name__ == '__main__': - c = SlcDriver(True, 'delete_slc.log') - if c.open('172.16.2.160'): - - while 1: - try: - print c.read_tag('S:1/5') - print c.read_tag('S:60', 2) - - print c.write_tag('N7:0', [-30, 32767, -32767]) - print c.write_tag('N7:0', 21) - print c.read_tag('N7:0', 10) - - print c.write_tag('F8:0', [3.1, 4.95, -32.89]) - print c.write_tag('F8:0', 21) - print c.read_tag('F8:0', 3) - - print c.write_tag('B3:100', [23, -1, 4, 9]) - print c.write_tag('B3:100', 21) - print c.read_tag('B3:100', 4) - - print c.write_tag('T4:3.PRE', 431) - print c.read_tag('T4:3.PRE') - print c.write_tag('C5:0.PRE', 501) - print c.read_tag('C5:0.PRE') - print c.write_tag('T4:3.ACC', 432) - print c.read_tag('T4:3.ACC') - print c.write_tag('C5:0.ACC', 502) - print c.read_tag('C5:0.ACC') - - c.write_tag('T4:2.EN', 0) - c.write_tag('T4:2.TT', 0) - c.write_tag('T4:2.DN', 0) - print c.read_tag('T4:2.EN', 1) - print c.read_tag('T4:2.TT', 1) - print c.read_tag('T4:2.DN',) - - c.write_tag('C5:0.CU', 1) - c.write_tag('C5:0.CD', 0) - c.write_tag('C5:0.DN', 1) - c.write_tag('C5:0.OV', 0) - c.write_tag('C5:0.UN', 1) - c.write_tag('C5:0.UA', 0) - print c.read_tag('C5:0.CU') - print c.read_tag('C5:0.CD') - print c.read_tag('C5:0.DN') - print c.read_tag('C5:0.OV') - print c.read_tag('C5:0.UN') - print c.read_tag('C5:0.UA') - - c.write_tag('B3:100', 1) - print c.read_tag('B3:100') - - c.write_tag('B3/3955', 1) - print c.read_tag('B3/3955') - - c.write_tag('N7:0/2', 1) - print c.read_tag('N7:0/2') - - print c.write_tag('O:0.0/4', 1) - print c.read_tag('O:0.0/4') - except Exception as e: - err = c.get_status() - #c.close() - print err - pass - c.close() diff --git a/daq_sample/pycomm-master/pycomm/__init__.py b/daq_sample/pycomm-master/pycomm/__init__.py deleted file mode 100755 index 8c1f233..0000000 --- a/daq_sample/pycomm-master/pycomm/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'agostino' diff --git a/daq_sample/pycomm-master/pycomm/ab_comm/__init__.py b/daq_sample/pycomm-master/pycomm/ab_comm/__init__.py deleted file mode 100755 index 28c38a3..0000000 --- a/daq_sample/pycomm-master/pycomm/ab_comm/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -__author__ = 'agostino' -import logging diff --git a/daq_sample/pycomm-master/pycomm/ab_comm/clx.py b/daq_sample/pycomm-master/pycomm/ab_comm/clx.py deleted file mode 100755 index 47ea813..0000000 --- a/daq_sample/pycomm-master/pycomm/ab_comm/clx.py +++ /dev/null @@ -1,873 +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.cip.cip_base import * -import logging -try: # Python 2.7+ - from logging import NullHandler -except ImportError: - class NullHandler(logging.Handler): - def emit(self, record): - pass - -logger = logging.getLogger(__name__) -logger.addHandler(NullHandler()) - - -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): - super(Driver, self).__init__() - - 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)) - 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] - if self._output_raw: - value = fragment_returned[idx:idx+DATA_FUNCTION_SIZE[typ]] - else: - 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) - if self._output_raw: - self._tag_list += value - else: - 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.") - logger.warning(self._status) - raise DataError("Target did not connected. read_tag will not be executed.") - - 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]) - 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, raw=False): - """ 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 - :param raw: the value should output as raw-value (hex) - :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.") - logger.warning(self._status) - raise DataError("Target did not connected. read_tag will not be executed.") - - self._byte_offset = 0 - self._last_position = 0 - self._output_raw = raw - - if self._output_raw: - self._tag_list = '' - else: - 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.") - logger.warning(self._status) - raise DataError("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)) - 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, raw=False): - """ 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 raw: the frame with bytes - :param raw: indicates that the values are given as raw values (hex) - """ - if not isinstance(values, list): - self._status = (9, "A list of tags must be passed to write_array.") - 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.") - logger.warning(self._status) - raise DataError("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): - if raw: - array_of_values += value - else: - 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.") - logger.warning(self._status) - raise DataError("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.") - logger.warning(self._status) - raise DataError("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.") - logger.warning(self._status) - raise DataError("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 - - if tag['symbol_type'] & 0b1000000000000000 : - template_instance_id = tag['symbol_type'] & 0b0000111111111111 - 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' - datatype = tag['symbol_type'] & 0b0000000011111111 - data_type = I_DATA_TYPE[datatype] - if datatype == 0xc1: - bit_position = (tag['symbol_type'] & 0b0000011100000000) >> 8 - self._tag_list.append({'instance_id': tag['instance_id'], - 'tag_name': tag['tag_name'], - 'dim': dimension, - 'tag_type': tag_type, - 'data_type': data_type, - 'bit_position' : bit_position}) - else: - 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/daq_sample/pycomm-master/pycomm/ab_comm/slc.py b/daq_sample/pycomm-master/pycomm/ab_comm/slc.py deleted file mode 100755 index bbb1091..0000000 --- a/daq_sample/pycomm-master/pycomm/ab_comm/slc.py +++ /dev/null @@ -1,574 +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.cip.cip_base import * -import re -import math -#import binascii - -import logging -try: # Python 2.7+ - from logging import NullHandler -except ImportError: - class NullHandler(logging.Handler): - def emit(self, record): - pass - -logger = logging.getLogger(__name__) -logger.addHandler(NullHandler()) - - -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[LFBN])(?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): - super(Driver, self).__init__() - - 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 __queue_data_available(self, queue_number): - """ read the queue - - 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 - """ - - # Creating the Message Request Packet - self._last_sequence = pack_uint(Base._get_sequence()) - - # PCCC_Cmd_Rd_w3_Q2 = [0x0f, 0x00, 0x30, 0x00, 0xa2, 0x6d, 0x00, 0xa5, 0x02, 0x00] - 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], - '\xa2', # protected typed logical read with three address fields FNC - '\x6d', # Byte size to read = 109 - '\x00', # File Number - '\xa5', # File Type - pack_uint(queue_number) - ] - - 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_uint(self._reply[2:4])) - if sts == 146: - return True - else: - return False - else: - raise DataError("read_queue [send_unit_data] returned not valid data") - - def __save_record(self, filename): - with open(filename, "a") as csv_file: - logger.debug("SLC __save_record read:{0}".format(self._reply[61:])) - csv_file.write(self._reply[61:]+'\n') - csv_file.close() - - def __get_queue_size(self, queue_number): - """ get queue size - """ - # 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], - # '\x30', - # '\x00', - '\xa1', # FNC to get the queue size - '\x06', # Byte size to read = 06 - '\x00', # File Number - '\xea', # File Type ???? - '\xff', # File Type ???? - pack_uint(queue_number) - ] - - 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_uint(self._reply[65:67])) - logger.debug("SLC __get_queue_size({0}) returned {1}".format(queue_number, sts)) - return sts - else: - raise DataError("read_queue [send_unit_data] returned not valid data") - - def read_queue(self, queue_number, file_name): - """ read the queue - - """ - if not self._target_is_connected: - if not self.forward_open(): - self._status = (5, "Target did not connected. is_queue_available will not be executed.") - logger.warning(self._status) - raise DataError("Target did not connected. is_queue_available will not be executed.") - - if self.__queue_data_available(queue_number): - logger.debug("SLC read_queue: Queue {0} has data".format(queue_number)) - self.__save_record(file_name + str(queue_number) + ".csv") - size = self.__get_queue_size(queue_number) - if size > 0: - for i in range(0, size): - if self.__queue_data_available(queue_number): - self.__save_record(file_name + str(queue_number) + ".csv") - - logger.debug("SLC read_queue: {0} record extract from queue {1}".format(size, queue_number)) - else: - logger.debug("SLC read_queue: Queue {0} has no data".format(queue_number)) - - 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)) - 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.") - logger.warning(self._status) - raise DataError("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) - ] - - 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)) - 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)) - 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)) - 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)) - 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)) - 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.") - logger.warning(self._status) - raise DataError("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)) - 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) - ] - - 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)) - 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)) - 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") diff --git a/daq_sample/pycomm-master/pycomm/cip/__init__.py b/daq_sample/pycomm-master/pycomm/cip/__init__.py deleted file mode 100755 index 8c1f233..0000000 --- a/daq_sample/pycomm-master/pycomm/cip/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'agostino' diff --git a/daq_sample/pycomm-master/pycomm/cip/cip_base.py b/daq_sample/pycomm-master/pycomm/cip/cip_base.py deleted file mode 100755 index 91d0757..0000000 --- a/daq_sample/pycomm-master/pycomm/cip/cip_base.py +++ /dev/null @@ -1,864 +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 -import random - -from os import getpid -from pycomm.cip.cip_const import * -from pycomm.common import PycommError - - -import logging -try: # Python 2.7+ - from logging import NullHandler -except ImportError: - class NullHandler(logging.Handler): - def emit(self, record): - pass -logger = logging.getLogger(__name__) -logger.addHandler(NullHandler()) - - -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(' -# -# 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, - # 'L': 4, - '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/daq_sample/pycomm-master/pycomm/common.py b/daq_sample/pycomm-master/pycomm/common.py deleted file mode 100755 index 1f0eb63..0000000 --- a/daq_sample/pycomm-master/pycomm/common.py +++ /dev/null @@ -1,8 +0,0 @@ -__author__ = 'Agostino Ruscito' -__version__ = "1.0.8" -__date__ = "08 03 2015" - -class PycommError(Exception): - pass - - diff --git a/daq_sample/pycomm-master/setup.py b/daq_sample/pycomm-master/setup.py deleted file mode 100755 index 0f9f9ba..0000000 --- a/daq_sample/pycomm-master/setup.py +++ /dev/null @@ -1,37 +0,0 @@ -from distutils.core import setup -from pycomm import common -import os - - -def read(file_name): - return open(os.path.join(os.path.dirname(__file__), file_name)).read() - -setup( - name="pycomm", - author="Agostino Ruscito", - author_email="uscito@gmail.com", - version=common.__version__, - description="A PLC communication library for Python", - long_description=read('README.rst'), - license="MIT", - url="https://github.com/ruscito/pycomm", - packages=[ - "pycomm", - "pycomm.ab_comm", - "pycomm.cip" - ], - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Natural Language :: English', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', - 'Topic :: Software Development :: Libraries :: Python Modules', - ], -) \ No newline at end of file diff --git a/daq_sample/pycomm_helper b/daq_sample/pycomm_helper deleted file mode 160000 index a3b6c08..0000000 --- a/daq_sample/pycomm_helper +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a3b6c088c52a839c93e92493fd108b26ab235c70