#python #protocols #ethernet #industrial
#python #протоколы #ethernet #Рабочая обувь
Вопрос:
Я работаю над созданием скрипта Python для связи с устройством EtherNet / IP (система распыления Graco PD2K). Единственная документация, предоставленная поставщиком, — это как настроить ПЛК Allen Bradley в качестве клиента для связи с устройством.
Используя следующий код, я могу прочитать массив атрибутов в экземпляре сборки 100:
from cpppo.server.enip.get_attribute import proxy_simple
via = proxy_simple('192.168.10.5')
with via:
data, = via.read( [('@4/100/3','DINT')] )
… что приводит к получению ожидаемого массива:
[0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
(39 целых чисел размером 32 бита)
При попытке записи в атрибуты в экземпляре сборки 150 я получаю True
ответ от контроллера, но контроллер не обновляет параметры. Ожидается, что 25 x 32-разрядный целочисленный массив:
with via:
result, = via.read([('@4/150/3=(DINT)4, 1, 0, 0, 1, 0, 0, 0, 1, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0','@4/150/3')],1)
Вывод сверху:
@4/150/3=(DINT)4, 1, 0, 0, 1, 0, 0, 0, 1, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 == True
Если я добавляю одно целое число в массив (или вычитаю, или попытаюсь установить значение, отличное от @4/150/3, я получаю ответ None
, поэтому ясно, что я близок к формату, и команда проходит.
Я несколько раз обращался к поставщику, и они настаивают, что это проблема с Python (или, более конкретно, они не поддерживают Python и рекомендуют интеграцию с ПЛК).
Мне интересно, является ли проблемой параметр «Конфигурация» в экземпляре сборки 1 (см. Изображение выше). Я попробовал несколько версий следующего кода, чтобы попытаться записать этот параметр. Не до конца понимая протокол EtherNet / IP, я даже не уверен, что делает этот конкретный экземпляр — однако то, что это параметр в конфигурации Аллена-Брэдли, указывает, что это важно в данном случае.
Попытка создания кода:
result, = via.read([('@4/1/3=(USINT)0','@4/1/3')],1)
Я пытался использовать утилиту Molex EnIP, а также что-то подобное в SourceForge, чтобы исключить Python из уравнения, но результаты аналогичны. Я также пробовал модуль PyComm3, но я даже не могу заставить его возвращать идентификационную информацию. Я также пытался использовать -vvv
утилиты командной строки CPPPO:
python -m cpppo.server.enip.get_attribute -a 192.168.10.5 '@4/150/3=(DINT)4, 1, 0, 0, 1, 0, 0, 0, 1, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0' -vv -S
Результаты (наряду с гораздо большим количеством выходных данных, которые, по моему мнению, не имеют значения):
11-09 12:11:18.119 MainThread enip.cli DETAIL issue Sending 1 (Context b'0')
11-09 12:11:18.120 MainThread enip.cli DETAIL pipeline Issuing 0/ 1; curr: 0 - last: -1 == 1 depth vs. max 0
11-09 12:11:18.124 MainThread enip.cli DETAIL __next__ Client CIP Rcvd: {
"send_data.interface": 0,
"send_data.timeout": 8,
"send_data.CPF.count": 2,
"send_data.CPF.item[0].type_id": 0,
"send_data.CPF.item[0].length": 0,
"send_data.CPF.item[1].type_id": 178,
"send_data.CPF.item[1].length": 4,
"send_data.CPF.item[1].unconnected_send.request.input": "array('B', [144, 0, 0, 0])",
"send_data.CPF.item[1].unconnected_send.request.service": 144,
"send_data.CPF.item[1].unconnected_send.request.status": 0,
"send_data.CPF.item[1].unconnected_send.request.status_ext.size": 0,
"send_data.CPF.item[1].unconnected_send.request.set_attribute_single": true
}
11-09 12:11:18.124 MainThread enip.cli DETAIL collect Receive 1 (Context b'0')
11-09 12:11:18.124 MainThread enip.cli DETAIL pipeline Completed 1/ 1; curr: 0 - last: 0 == 0 depth vs. max 0
Mon Nov 9 12:11:18 2020: 0: Single S_A_S @0x0004/150/3 == True
11-09 12:11:18.124 MainThread enip.cli DETAIL pipeline Pipelined 1/ 1; curr: 0 - last: 0 == 0 depth vs. max 0
11-09 12:11:18.125 MainThread enip.get NORMAL main 1 requests in 0.006s at pipeline depth 0; 153.919 TPS
Опять же, результатом запроса является True
, но контроллер не обновляет ни один из параметров.
Я не уверен, что попробовать дальше…