Из скрипта прочитать регист modbus

Добрый день

Есть считыватель ключей.

С, по сути, двумя полезным топиками - Касание и Номер Ключа

Скрипт ждёт касания. Читает из dev[] номер ключа и что-то делает.

Всё бы хорошо, но иногда вылезает race-condition - опрос модбаса уже прочитал и опубликовал в MQTT регистр Касание, но ещё не добрался до регистра Номер Ключа.

Как результат - ошибочное решение какой ключ использовался при касании.

Хочется штатную функцию “Прочитать регистр” (хорошо бы вне очереди).

Понятно, что можно вызвать runShellCommand(modbus_client_rpc) и разобрать его вывод, но это большие накладные расходны системы и время.

Понято, что можно что-то типа sleep(1) и “мне повезёт” что опрос шины доберётся до регистра.

Но штатная функция был бы самым правильным решением.

Добрый день.

Для того чтобы читать (произвольные) регистры в нужном порядке логично использовать RPC вызовы, так: GitHub - wirenboard/wb-mqtt-serial: Wiren Board MQTT serial protocol driver · GitHub

Пример, не для modbus но там работа аналогична: Подключение Daly BMS по RS485 - #4 от пользователя Zed

Нет, довольно костыльно, да и совместно с драйвером на порту работать не будет.

т.е. я пишу в через publish json с запросом, а ответ жду асинхронно из trackMqtt ?

спасибо, это вполне вариант.

хотя, кончено, для случаев когда асинхронная работа не нужна одна функция делающая всё была бы удобнее.

Да.
Или ответа или сообщение о ошибке либо таймауте. В общем в пределах заданного таймаута.
Ну и - в очередь будет ставиться (и выполняться) как раз в порядке запроса.

А - как? Эта функция может результат вернуть через 500мс, например.

так от предметной области зависит :slight_smile:

мозг потребителя гибок и быстренько с таким столкнувшись выдаст два типичных сценария которые он уже и ранее видел в других местах

или “считыватель тормозит” и надо “ключ подольше подержать”

или “что-то ключ не считался” и “приложу ещё раз”

что мне для-дома-для-семьи подходит - race condtion пока только один раз вылез за месяц

(отсюда и был тикет про метрику “время цикла опроса шины” - я временно перевесил считыватель на более нагруженную шину и словил - стало интересно сколько один опрос занимает нагруженой шины и не нагруженой)

Я про то что в “общем случае” функция в js не может “ждать” ответа. То есть оно в любом случае асинхронно будет срабатывать.
Да, функцию можно сделать создающей “одноразовый” обработчик, который получив ответ взведет какой-то флаг в коде и запишет переменную. Но все то же самое проще и надежнее сделать штатным tarckMqtt.

Или я не правильно понимаю документацию
Запрос с использованием идентификатора устройства или что-то не так

Хочу прочесть по имени, а не вшивать в скрипт шину, адрес, скорость и прочее.

Топик есть

>mosquitto_sub -t '/devices/avt-301-003_128/controls/key_number_low'
1006707795

Запрос

>mosquitto_pub -t '/rpc/v1/wb-mqtt-serial/port/Load/test' -m '{"params":{"protocol":"modbus","count":2,"device_id":"/devices/avt-301-003_128/controls/key_number_low"},"id":123456}'

Ответ

>mosquitto_sub -t '/rpc/v1/wb-mqtt-serial/port/Load/test/reply'

{"error":{"code":-32000,"data":"Validation failed.\nError 1\n  context: <root>\n  
desc: Missing required property 'baud_rate'.\nError 2\n  context: <root>\n  
desc: Missing required property 'data_bits'.\nError 3\n  context: <root>\n  
desc: Missing required property 'parity'.\nError 4\n  context: <root>\n  
desc: Missing required property 'path'.\nError 5\n  context: <root>\n  
desc: Missing required property 'stop_bits'.\nError 6\n  context: <root>\n  
desc: Failed to validate against child schema #0.\nError 7\n  context: <root>\n  
desc: Missing required property 'ip'.\nError 8\n  context: <root>\n  
desc: Missing required property 'port'.\nError 9\n  context: <root>\n  
desc: Failed to validate against child schema #1.\nError 10\n  context: <root>\n  
desc: Failed to validate against any child schemas allowed by oneOf constraint.\nError 11\n  сontext: <root>\n  
desc: Failed to validate against child schema #0.\n","message":"Server error"},"id":123456}

Вы вместо ID (адреса) передаете строку.

Запрос можно выполнить, указав идентификатор устройства в MQTT (часть имени топика /devices/<ИДЕНТИФИКАТОР>/controls/...), он должен передаваться в параметре device_id. В этом случае настройки порта, протокол и адрес устройства берутся из конфигурационного файла wb-mqtt-serial, указывать их в запросе не надо.

“device_id”:“avt-301-003_128”
“address”: 12345

?

тоже не работает. сдаюсь и прошу правильный вариант запроса.

Для примера:
Устройство


Соответственно идентификатор “wb-mr6cv3_93”
Запрос:

mosquitto_pub -t '/rpc/v1/wb-mqtt-serial/device/Load/kva'   -m '{"id":1,"params":{"device_id":"wb-mr6cv3_93"}}'

Ответ:

mosquitto_sub -t '/rpc/v1/wb-mqtt-serial/device/Load/kva/reply' -v
/rpc/v1/wb-mqtt-serial/device/Load/kva/reply {"error":null,"id":1,"result":{"channels":{"Bus Power Supply":1,"Curtain 1 Close":0,"Curtain 1 Open":0,"FW Version":1.22,"Input 0":0,"Input 0 counter":0,"Input 0 freq":0,"Input 1":0,"Input 1 Double Press Counter":0,"Input 1 Long Press Counter":0,"Input 1 Shortlong Press Counter":0,"Input 1 Single Press Counter":0,"Input 1 counter":0,"Input 1 freq":0,"Input 2":0,"Input 2 counter":0,"Input 2 freq":0,"Input 3":0,"Input 3 counter":0,"Input 3 freq":0,"Input 4":0,"Input 4 counter":0,"Input 4 freq":0,"Input 5":0,"Input 5 counter":0,"Input 5 freq":0,"Input 6":0,"Input 6 counter":0,"Input 6 freq":0,"K1":0,"K2":0,"K3":0,"K4":0,"K5":0,"K6":0,"MCU Temperature":27.6,"MCU Voltage":3.402,"Minimum Voltage Since Startup":10.568,"Serial":104363,"Supply Voltage":12.484,"Uptime":5334069},"readonly":["Bus Power Supply","Input 1 counter","Input 2 counter","Input 3 counter","Input 4 counter","Input 5 counter","Input 6 counter","Input 0 counter","Input 1 freq","Input 2 freq","Input 3 freq","Input 4 freq","Input 5 freq","Input 6 freq","Input 0 freq","Uptime","Supply Voltage","Minimum Voltage Since Startup","MCU Voltage","MCU Temperature","FW Version","Serial","Input 1 Single Press Counter","Input 1 Long Press Counter","Input 1 Double Press Counter","Input 1 Shortlong Press Counter","K1","K2","Input 1","Input 2","Input 3","Input 4","Input 5","Input 6","Input 0"]}}


Ну и просто регистр:

mosquitto_pub -t '/rpc/v1/wb-mqtt-serial/port/Load/kva3'   -m '{"id":1,"params":{"device_id":"wb-mr6cv3_93","function":3,"address":128,"count":1}}'

Ответ:

/rpc/v1/wb-mqtt-serial/port/Load/kva3 {"id":1,"params":{"device_id":"wb-mr6cv3_93","function":3,"address":128,"count":1}}
/rpc/v1/wb-mqtt-serial/port/Load/kva3/reply {"error":null,"id":1,"result":{"response":"\u0000]"}}

Наркоманы писали тот абзац вики.
Совершенно не очевидно, что вернутся ВСЕ каналы - там чётко контекст от предыдущего описания где рассказано как прочесть конкретные регистры.
И совершенно не очевидно, что device_id вообще единственный параметр.

Тем не менее, или я продолжаю тупить или не работает.
Может такого способа ещё нет в stable ? (WB 8.5, все пакеты обновлены)

>mosquitto_pub -t '/rpc/v1/wb-mqtt-serial/port/Load/test'
-m '{"params":{"device_id":"avt-301-003"},"id":123}'

{“error”:{“code”:-32000,“data”:“Validation failed.\nError 1\n context: \n desc: Missing required property ‘baud_rate’.\nError 2\n context: \n desc: Missing required property ‘data_bits’.\nError 3\n context: \n desc: Missing required property ‘parity’.\nError 4\n context: \n desc: Missing required property ‘path’.\nError 5\n context: \n desc: Missing required property ‘stop_bits’.\nError 6\n context: \n desc: Failed to validate against child schema #0.\nError 7\n context: \n desc: Missing required property ‘ip’.\nError 8\n context: \n desc: Missing required property ‘port’.\nError 9\n context: \n desc: Failed to validate against child schema #1.\nError 10\n context: \n desc: Failed to validate against any child schemas allowed by oneOf constraint.\nError 11\n context: \n desc: Failed to validate against child schema #0.\n”,“message”:“Server error”},“id”:123}

“/port” лишнее.
У меня, при запросе параметров:

“/device”
А при запросе регистра (что и нужно в общем-то)

да, “/port”.

mosquitto_pub -t ‘/rpc/v1/wb-mqtt-serial/port/Load/kva3’
-m ‘{“id”:1,“params”:{“device_id”:“avt-301-003_128”,“function”:3,“address”:0,“count”:1}}’

ответы

{“id”:1,“params”:{“device_id”:“avt-301-003_128”,“function”:3,“address”:0,“count”:1}}

и

{“error”:{“code”:-32000,“data”:“Validation failed.\nError 1\n context: \n desc: Missing required property ‘baud_rate’.\nError 2\n context: \n desc: Missing required property ‘data_bits’.\nError 3\n context: \n desc: Missing required property ‘parity’.\nError 4\n context: \n desc: Missing required property ‘path’.\nError 5\n context: \n desc: Missing required property ‘stop_bits’.\nError 6\n context: \n desc: Failed to validate against child schema #0.\nError 7\n context: \n desc: Missing required property ‘ip’.\nError 8\n context: \n desc: Missing required property ‘port’.\nError 9\n context: \n desc: Failed to validate against child schema #1.\nError 10\n context: \n desc: Failed to validate against any child schemas allowed by oneOf constraint.\nError 11\n context: \n desc: Failed to validate against child schema #0.\n”,“message”:“Server error”},“id”:1}

Да, кстати, это есть только в testing.

:)))) ну блин…

окей. подождём продакшена.

но вики перепишите плиз - там абзац совешенно не вменяемый

и совсем удобно если доработаете что бы можно было просто что-то типа

"port_id":"/devices/avt-301-003_128/controls/key_number_low"

-- может отсутствовать, тогда чтение, а какое именно зависит
-- от того чему контрол соответствует - coil/descrete/holding/input
"function": "read" | "write"

 -- может отсутствовать, тогда "1"
"count": 99

что бы не только не знать порт, адрес, скорость и прочие, но и номер регистра не знать и тип - использовать имя.

и в самом ходовом случае “читать 1 регистр” не указывать ни функцию ни каунт