Более эффективный побитовый разбор регистра modbus

Пишу шаблон для modbus-устройства, которое в одном из выдает битовую маску своего состояния.
Формат регистра - 0 0 0 0 0 0 0 0 0 0 0 0 W X Y Z
Буквами обозначены биты, сигнализирующие о том или ином состоянии

Благодаря @my-wb обнаружил, что WB умеет каналы, читающие битовые маски из регистра modbus. Покопавшись на github-е нашел “описание” ( искать в коде “109:1:2”)

В результате у меня получился следующий шаблон:

Часть шаблона


{
“name”: “Fire”,
“reg_type”: “holding”,
“address”: “0x0012:0:1”,
“type”: “switch”,
“readonly”: true
},
{
“name”: “Bypass on”,
“reg_type”: “holding”,
“address”: “0x0012:1:1”,
“type”: “switch”,
“readonly”: true
},
{
“name”: “Bypass off”,
“reg_type”: “holding”,
“address”: “0x0012:2:1”,
“type”: “switch”,
“readonly”: true
},
{
“name”: “Defrosting”,
“reg_type”: “holding”,
“address”: “0x0012:3:1”,
“type”: “switch”,
“readonly”: true
}

И все вроде работает и отображается, НО wb-serial читает этот регистр 4 раза (для каждого канала индивидуально) :frowning:

А нет ли способа сделать более оптимально с одним единственным считыванием регистра и его разбором?

Сейчас нет, но можно прочитать регистр одним куском и распарсить его силами правил, например.

То есть создать еще одно устройство и его состояние отрабатывать правилами?

Можно добавить контрол к существующему.

Пример здесь.

1 лайк

Написал следующий код в правилах:

var deviceName="rcs350p_11";
var controls=["Status FIRE", "Status Bypass On","Status Bypass Off", "Status Defrosting"];

if (!getDevice(deviceName)) log("device not present");

for (ctrl in controls) {
  if (!getDevice(deviceName).isControlExists(controls[ctrl])) {
    log("Adding ",ctrl, controls[ctrl], 1<<ctrl, Boolean(dev[deviceName+"/Fire-bypass-defrosting signal"]&1<<ctrl));
    getDevice(deviceName).addControl(controls[ctrl], {
          type: "switch",
          value: Boolean(dev[deviceName+"/Fire-bypass-defrosting signal"]&1<<ctrl),
          readonly: true
    });
  }
}

В логе пишет все абсолютно правильно, а контролы не добавляются. Что я делаю не так?

UPD: Поменял код так, чтобы вносить изменения в виртуальное устройство, а не устройство, заведенное с помощью template через настройки wb-mqtt-serial – код работает как надо. Значит ли это что добавлять контролы можно только в виртуальные устройства?

1 лайк

Добавлять контролы можно к любым устрйоствам.
“виртуальное” или нет - определить можно так:

if (!getDevice(deviceName).isVirtual())

Воспроизведу, возможно на выходных.

У меня лично не получилось добавить контролы к не виртуальному устройству. А у вас?

Ну конечно получилось.
Вот только сегодня до компьютера добрался
Если брать мой пример реализации и проверить устрйство на “виртуальность”, как намекал выше - достаточно сделать так:

//05_10_test_01.js
var dashName = "wb-gpio";
var ctrlName = "cDate";

//Если устройство "не виртуально" - получим
//ERROR: Error in creating control cDate on device wb-gpio: Device is external

//Тут проверим, виртуальное ли устройство. Если нет - сделаем его таковым.
if (getDevice(dashName).isVirtual()){
  log.info("Устройство",dashName, "вируальное")
}
else {
  log.info("Устройство",dashName, "НЕ вируальное")
  defineVirtualDevice(dashName, {
                                title: dashName,
                                cells: {},
                            });
}
  
      
//Тут проверим есть ли уже контрол и если нет - создадим.
  if (!getDevice(dashName).isControlExists(ctrlName)) {
    log.info("Контрола нет, создаем.")
    getDevice(dashName).addControl(ctrlName, {
      type: "text",
      value: "",
      readonly: true
    });
  }

//Тут сделаем таймер, котрый будет обновлять контрл
setInterval(function(){
 dev[dashName][ctrlName] = (new Date()).toString();
 log.info("timer fired", (new Date()).toString());
}, 1000);

Результат:
Screenshot_20230510_140251

Ну и “виртуальность” - определяется, собственно топиками /devices/wb-gpio/meta/driver и /devices/wb-gpio/meta

PS: вот благодаря таким вопросам работать интересно и увлекательно. :slight_smile: Благодарю!
PPS: А еще можно динамически контролы двигать, записывая разные занчения order :wink:

1 лайк

Видимо я что-то делаю не так :frowning:

Итак дано заведомо НЕ виртуальное устройство rcs350p_11

Делаю по Вашему образу и подобию код:

var deviceName="rcs350p_11";

if (getDevice(deviceName).isVirtual()){
  log.info("Устройство",deviceName, "вируальное")
}
else {
  log.info("Устройство",deviceName, "НЕ вируальное")
  defineVirtualDevice(deviceName, {
                               title: deviceName,
                                cells: {},
                            });
}

И огребаю вот такую ошибку при его сохранении:

 Script error: Error: Device with given ID already exists
/sbuild-nonexistent/go/pkg/mod/github.com/wirenboard/go-duktape@v0.0.0-20210723134114-881337fff8cb/api.go:124
anon native strict preventsyield
anon /etc/wb-rules/Ventilation-CTRL.js:78 preventsyield

То есть мне не дают, в отличии от Вас, создать виртуальное устройство с таким-же именем как и не виртуальное

Что я делаю не так?

UPD: Скопировал Ваш код 1-в-1. Такая же ошибка

Коллеги обратили внимание что я пользуюсь довольно грязным хаком, заменяя сервис-родитель.
В чем искренне раскаиваюсь.
Поэтому - предлагаю не добавлять топики в реальное (созданное и обслуживаемое не wb-rules) устройство. Такой хак может перестать работать вот в ближайшем релизе.
Все равно “пользовательский” интерфес - это виджеты, а в виджет можно собрать топики и из разных “устройств”.