Чтение/запись значений с использованием Ethernet/IP

Недавно я приобрел линейный привод ACS (Tolomatic Stepper), на который я пытаюсь отправить данные из приложения Python. Само устройство обменивается данными по протоколу Ethernet/IP.

Я установил библиотеку cpppo через pip. Когда я запускаю команду, пытаясь прочитать состояние устройства, я получаю None. Изучая связь с Wireshark, я вижу, что она работает правильно, однако я замечаю ответ от устройства, указывающий: Служба не поддерживается.

Пример кода, который я использую для проверки чтения «Входной сборки»:

from cpppo.server.enip import client

HOST = "192.168.1.100"
TAGS = ["@4/100/3"]

with client.connector(host=HOST) as conn:
    for index, descr, op, reply, status, value in conn.synchronous(
            operations=client.parse_operations(TAGS)):
        print(": %20s: %s" % (descr, value))

Я ожидаю прочитать «входную сборку», но, похоже, она не работает таким образом. Я предполагаю, что я что-то упускаю, так как это первая попытка связи Ethernet/IP.

Я не знаю, что делать дальше или что мне не хватает в Ethernet/IP, что может заставить это работать правильно.


person clutton    schedule 16.07.2015    source источник


Ответы (2)


clutton -- я автор модуля cpppo.

Извините за задержку ответа. Мы только недавно реализовали возможность связи с простыми (немаршрутизирующими) устройствами CIP. Контроллеры ControlLogix/CompactLogix реализуют расширенный набор возможностей EtherNet/IP CIP, чего нет в большинстве простых устройств CIP. Кроме того, они обычно также не реализуют запрос «Чтение тега» *Logix; вам приходится бороться с базовыми запросами «Получить атрибут один/все», которые просто возвращают необработанные 8-битные данные. Вам решать, как превратить это обратно в CIP REAL, INT, DINT и т. д.

Для связи с вашим линейным приводом вам необходимо отключить эти расширенные инкапсуляции и использовать запросы «Получить одиночный атрибут». Это делается путем указания пустого route_path=[] и send_path='' при анализе операций и использования атрибутов_операций cpppo.server.enip.getattr (вместо parse_operations cpppo.server.enip.client):

from cpppo.server.enip import client
from cpppo.server.enip.getattr import attribute_operations

HOST = "192.168.1.100"
TAGS = ["@4/100/3"]

with client.connector(host=HOST) as conn:
    for index, descr, op, reply, status, value in conn.synchronous(
        operations=attribute_operations(
            TAGS, route_path=[], send_path='' )):
        print(": %20s: %s" % (descr, value))

Это должно делать свое дело!

Мы находимся в процессе развертывания крупного обновления модуля cpppo, поэтому клонируйте https://github.com/pjkundert/cpppo.git репозиторий Git и ознакомьтесь с веткой feature-list-identity, чтобы получить ранний доступ к гораздо более совершенным API для доступа к необработанным данным с этих простых устройств для тестирования. Вы сможете использовать cpppo для преобразования необработанных данных в CIP REAL вместо того, чтобы делать это самостоятельно...

...

С Cpppo >= 3.9.0 теперь вы можете использовать гораздо более мощные интерфейсы cpppo.server.enip.get_attribute 'proxy' и 'proxy_simple' для маршрутизации устройств CIP (например, ControlLogix, Compactlogix) и немаршрутизирующих «простых» CIP. устройства (например, MicroLogix, PowerFlex и т. д.):

$ python
>>> from cpppo.server.enip.get_attribute import proxy_simple
>>> product_name, = proxy_simple( '10.0.1.2' ).read( [('@1/1/7','SSTRING')] )
>>> product_name
[u'1756-L61/C LOGIX5561']

Если вам нужны регулярные обновления, используйте cpppo.server.enip.poll:

import logging
import sys
import time
import threading

from cpppo.server.enip import poll
from cpppo.server.enip.get_attribute import proxy_simple as device
params                  = [('@1/1/1','INT'),('@1/1/7','SSTRING')]

# If you have an A-B PowerFlex, try:
# from cpppo.server.enip.ab import powerflex_750_series as device
# parms                 = [ "Motor Velocity", "Output Current" ]

hostname                = '10.0.1.2'
values                  = {} # { <parameter>: <value>, ... }
poller                  = threading.Thread(
    target=poll.poll, args=(device,), kwargs={
        'address':      (hostname, 44818),
        'cycle':        1.0,
        'timeout':      0.5,
        'process':      lambda par,val: values.update( { par: val } ),
        'params':       params,
    })
poller.daemon           = True
poller.start()

# Monitor the values dict (updated in another Thread)
while True:
    while values:
        logging.warning( "%16s == %r", *values.popitem() )
    time.sleep( .1 )

И, Вуаля! Теперь вы регулярно обновляете имена и значения параметров в словаре «значения». См. примеры в cpppo/server/enip/poll_example*.py для получения дополнительной информации, например, о том, как сообщать об ошибках, управлять экспоненциальным отставанием повторных попыток подключения и т. д.

Недавно была выпущена версия 3.9.5, которая поддерживает запись в теги и атрибуты CIP с использованием прокси-сервера cpppo.server.enip.get_attribute и API-интерфейсов proxy_simple. См. cpppo/server/enip/poll_example_many_with_write.py.

person pjkundert    schedule 29.01.2016
comment
Можно ли использовать proxy_simple для записи одного атрибута? - person JPelletier; 21.06.2016
comment
@JPelletier Я пришел сюда в поисках того же ответа. Кажется, что нет, proxy_simpleproxy) выдают нереализованное исключение. Однако я успешно записал атрибуты, используя connector и attribute_operations, как в первом примере. Насколько я могу судить, записи ограничены типом данных USINT. - person Rich; 31.10.2016
comment
Извините, исправление к моему комментарию выше. Записывает (устанавливает) работу, используя UINT в качестве типа данных. У меня были проблемы с чтением (получением) при использовании UINT. - person Rich; 01.11.2016

надеюсь, это очевидно, но доступ к HOST = "192.168.1.100" будет возможен только из системы, расположенной в подсети 192.168.1.*

person jobeard    schedule 16.07.2015
comment
Связь с устройством происходит корректно с использованием этого адреса. Специально для этой цели я настроил тестовую среду с «правильными» адресами. - person clutton; 16.07.2015