Как периодически опрашивать виртуальное устройство

Добрый день.
Создал в редакторе правил defineVirtualDevice устройство, описал принимаемые данные, реализовал логику считывания и при сохранении правил один раз считываются нужные мне данные.
Вопрос: как правильно реализовать периодическое считывание данных и виртуального устройства?

Пример, того, что я делаю по порядку:

  1. Формирую запрос через MQTT
Спойлер
/*
Функция отправки RPC запроса через MQTT
{string} modbusPort - Путь к модбас-порту
{number} modbusSpeed - Скорость передачи данных
{string} modbusParity - Тип четности
{number} modbusStopbit - Количество стоп-битов
{string} clientID - Идентификатор клиента
{number} requiestID - ID запроса
{string} messageType - Тип сообщения (HEX)
{string} message - Данные для отправки
{number} responseSize - Размер ожидаемого ответа
 */
function requestRPC(modbusPort, modbusSpeed, modbusParity, modbusStopbit, clientID, requiestID, messageType, message, responseSize)
{
    // Формирование JSON строки с параметрами запроса:
    var strJson = JSON.stringify(
      {
        params: 
        {
            // Размер ожидаемого ответа от устройства
            response_size: responseSize,
            // Тип формата данных (HEX - шестнадцатеричный)
            format: messageType,
            // Путь к модбас-порту
            path: modbusPort,
            // Скорость передачи данных
            baud_rate: modbusSpeed,
            // Тип четности
            parity: modbusParity,
            // Количество данных битов (8 бит)
            "data_bits" : 8,
            // Количество стоп-битов
            "stop_bits" : modbusStopbit,
            // Данные для отправки в формате HEX
            "msg": message
        },
        // Уникальный ID запроса для отслеживания ответа
        "id" : requiestID
    });
    
    // Вывод отладочной информации о JSON строке
    log.debug("Запрос!!! strJson =", strJson);

    // Отправка JSON запроса через MQTT на указанный топик
    publish(pathRPC+clientID, strJson, 2, false)
};
  1. Подписываюсь на получение ответа:
Спойлер
/**
 * Подписка на получение ответа от устройства
 * Слушает топик с ответами для указанного клиента
 */
trackMqtt(pathRPC+clientID+"/reply", function(message)
{
   // Вывод информации о полученных данных (топик и значение)
   log.debug("Ответ!!! name: {}, value: {}".format(message.topic, message.value))
   try 
   {
      // Преобразование строки в объект JSON
      var responseStringData = JSON.parse(message.value);

      // Проверка наличия данных и их обработка
      if (responseStringData.result && responseStringData.result.response) 
      {
         // Получение сырых данных из ответа
         var raw_data = responseStringData.result.response;
            
         // Обработка данных в зависимости от ID запроса
         if (responseStringData.id == 90) 
         {
           log.debug("responseStringData.id == 90")
            // Обработка данных Состояние заряда
            parseVoltCurrSoc(raw_data);
         }
         else if (responseStringData.id == 91) 
         {
           log.debug("responseStringData.id == 91")
            // Обработка данных Максимальное и минимальное напряжение отдельных ячеек батареи
            parseMaxMinCellVolt(raw_data);
          }
      } 
     var timestamp = new Date().toISOString();
     dev["DalyBms_RS485/timestamp"] = timestamp;
   }
   catch (e) 
   {
      log.error("Error parsing MQTT message:", e.message);
   }
   
});
  1. Делаю вызов (отправку RPC запроса через MQTT):
Спойлер
/**
 * Вызов функции отправки RPC запроса
 * Отправляет сообщение на модбас-порт с указанными параметрами
 */
requestRPC(modbusPort, modbusSpeed, modbusParity, modbusStopbit, clientID, 90, "HEX", voltCurrSoc, 13)

Если я правильно понял задачу, то вам нужно просто опрашивать ваше устройство по ModBus через RPC раз в какое-то время?

Чтобы вызывать функции периодически нужно создать правило вида:

defineRule('getDataByCron',{  
  when: cron("*/10 * * * *"),
  then: function () {
    requestRPC(modbusPort, modbusSpeed, modbusParity, modbusStopbit, clientID, 90, "HEX", voltCurrSoc, 13)
  }
});

Этот пример будет вызываться каждые 10 секунд (*/<количество единиц в интервале> в параметрах cron). В принципе нотация там стандартная для Cron. Можно указать конкретное значение секунд, минут, часов и дней, в которые будет запускаться правило, гибкость там большая.

Ознакомиться с логикой описания периодичности можно тут: Cron-формат
Однако следует иметь ввиду, что в документации выше стандартная Cron-нотация, в ней первый параметр – минуты. В WB-Rules же первый параметр секунды. Все остальное работает так же.

P.S. Важное замечание: если вы в коде используете (или хотите использовать) включение и выключение правил, то следует учитывать, что с правилами на базе Cron этот трюк не работает.

2 лайка

Добрый день!
Для переодического опроса вам может помочь данная статья.

Спасибо большое! Очень помогли, при чтении документации пропустил этот момент.