Здравствуйте! Я автоматический помощник техподдержки Wiren Board. Сейчас выходной — я попробую помочь сразу, а в ближайший рабочий день инженеры посмотрят тему и ответят.
Я проанализировал ваш вопрос и постарался найти возможное решение:
Если потребуется дополнительное уточнение, приложенную информацию прошу направить нажав ответить на мое крайнее сообщение.
Оборудование и контекст
Речь идёт о контроллере Wiren Board (скорее всего WB6/WB7/WB8) и движке правил wb-rules. Ошибка возникает при выполнении:
var my_topic = 'BathTambHeater/temp1Sensor';
var my_device_id = my_topic.split('/')[0];
var my_channel_id = my_topic.split('/')[1];
var s9 = '';
s9 = getDevice(my_device_id).getControl(my_channel_id).getValue();
в файле rules.js (стр. 3014–3018), при этом аналогичный фрагмент в 33.js работает.
Сообщение:
TypeError: invalid base value duk_hobject_props.c:2000 F /etc/wb-rules/rules.js:3018 preventsyield
означает, что один из вызовов по цепочке getDevice(...).getControl(...).getValue() вызывается на undefined / null и движок Duktape не может получить свойство/метод.
Что, скорее всего, происходит
-
getDevice(my_device_id) возвращает undefined
Это бывает, если:
- на момент выполнения правила устройства с таким ID ещё нет в
wb-mqtt-db (например, драйвер ещё не поднялся, устройство по Modbus ещё не опрошено, или MQTT-топик ещё не появился);
- устройство существует, но его ID отличается от ожидаемого (регистр/опечатка, лишние пробелы, другой prefix и т.д.).
-
или getControl(my_channel_id) возвращает undefined
Аналогично — если контрол не существует / ещё не создан.
-
Почему в 33.js работает, а в rules.js нет
Наиболее частые причины:
- в одном правиле код выполняется позже, когда устройство гарантированно есть (например, внутри
defineRule с when: function () { return dev[...] } или по таймеру),
а во втором — при загрузке правил (глобально, при старте wb-rules), когда устройства ещё не доступны;
- в одном файле вы вызываете код в обработчике события (по изменению топика), а в другом — однократно при загрузке;
- возможны отличия в строке
my_topic (даже один символ или регистр).
Что проверить прямо сейчас
- Убедитесь, что устройство и контрол реально есть и названия совпадают:
mqtt-sub -t '/devices/+/controls/+'
Посмотрите, появляется ли топик /devices/BathTambHeater/controls/temp1Sensor.
В wb-rules это должно соответствовать:
getDevice("BathTambHeater").getControl("temp1Sensor")
- Вставьте временную отладку в проблемный участок
rules.js:
var my_topic = 'BathTambHeater/temp1Sensor';
var my_device_id = my_topic.split('/')[0];
var my_channel_id = my_topic.split('/')[1];
log.info("my_device_id =", my_device_id, "my_channel_id =", my_channel_id);
var devObj = getDevice(my_device_id);
log.info("devObj =", devObj);
if (!devObj) {
log.error("Device not found:", my_device_id);
} else {
var ctrlObj = devObj.getControl(my_channel_id);
log.info("ctrlObj =", ctrlObj);
if (!ctrlObj) {
log.error("Control not found:", my_channel_id);
} else {
var s9 = ctrlObj.getValue();
log.info("s9 =", s9);
}
}
Если на этапе devObj или ctrlObj увидите undefined — значит проблема именно в отсутствии устройства/контрола в момент выполнения.
Как корректно защититься от ошибки
- Проверяйте наличие устройства и контрола:
var devObj = getDevice(my_device_id);
if (!devObj) {
log.error("No such device:", my_device_id);
return;
}
var ctrlObj = devObj.getControl(my_channel_id);
if (!ctrlObj) {
log.error("No such control:", my_channel_id);
return;
}
var s9 = ctrlObj.getValue();
-
Не вызывать это глобально при загрузке файла, а выполнять:
- либо внутри
defineRule по событию/условию:defineRule("read_bath_temp", {
when: function () {
return dev["BathTambHeater"]["temp1Sensor"] != undefined;
},
then: function () {
var s9 = dev["BathTambHeater"]["temp1Sensor"];
// ...
}
});
- либо через таймер, который подождёт некоторое время после старта:
setTimeout(function () {
// тот же код с проверками devObj / ctrlObj
}, 5000);
-
Упростить запись через dev[...], если подходит:
var s9 = dev["BathTambHeater"]["temp1Sensor"];
Это тоже бросит ошибку, если устройства нет, но вы можете обернуть в try/catch или в условие:
if (dev["BathTambHeater"] && dev["BathTambHeater"]["temp1Sensor"] != undefined) {
var s9 = dev["BathTambHeater"]["temp1Sensor"];
}
Что лучше приложить дальше
Чтобы инженеры могли точно воспроизвести проблему, пожалуйста, ответьте в теме и приложите:
- Обе версии фрагмента кода:
- из работающего
33.js (строки 11–15),
- и из
rules.js (строки 3010–3020) целиком — с контекстом (внутри/вне defineRule, есть ли setTimeout, и т.п.).
- Вывод:
mqtt-sub -t '/devices/+/controls/+'
(хотя бы строки с BathTambHeater).
- Лог фрагмента
service wb-rules status или часть journalctl -u wb-rules с этой ошибкой.
*Примечание: Я — искусственный