Сломаное виртуальное устройство

Добрый день.

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

Именно устройство с конкретным именем и конкретным топиком heat_out_store/targetTemperature.

Пример кода:

var deviceName = 'heat_out_store';
var cellName = 'targetTemperature';
var topic = "{}/{}".format(deviceName, cellName);
var device = defineVirtualDevice(deviceName, {
    title: "Термостат: Уличная кладовка",
    cells: {
        targetTemperature: {
            type: "value",
            value: 24,
            title: "Уставка",
            order: 1,
            max: 30,
            min: 15,
            readonly: false
        }
    }
});

 log(">>> Test1 - dev[{}]: {}",topic, dev[topic]);
var cell = device.getControl(cellName);
log(">>> Test2 - cell = {}", cell);
var val = cell.getValue();
log(">>> Test3 - val = {}", val);

Логи выдают такую ошибку:

Apr 08 01:43:16 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: reloading file: /etc/wb-rules/experiments.js
Apr 08 01:43:16 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: [rule info] >>> Test1 - dev[heat_out_store/targetTemperature]: null
Apr 08 01:43:16 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: [rule info] >>> Test2 - cell = [object Object]
Apr 08 01:43:16 wirenboard-AC6A3GB6 wb-rules[4864]: ERROR: getValue (heat_out_store/targetTemperature) failed: This control is incomplete
Apr 08 01:43:16 wirenboard-AC6A3GB6 wb-rules[4864]: WARNING: warning: failed to load /etc/wb-rules/experiments.js: Error: error error (rc -100)
                                                            anon  native strict preventsyield
                                                            F /etc/wb-rules/experiments.js:22 preventsyield
Apr 08 01:43:16 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: [rule info] _update_git_status started!

меняю одну букву в названии устройства или топике и все создается нормально:
heat_out_store1/targetTemperature

var deviceName = 'heat_out_store1';
var cellName = 'targetTemperature';
var topic = "{}/{}".format(deviceName, cellName);
var device = defineVirtualDevice(deviceName, {
    title: "Термостат: Уличная кладовка",
    cells: {
        targetTemperature: {
            type: "value",
            value: 24,
            title: "Уставка",
            order: 1,
            max: 30,
            min: 15,
            readonly: false
        }
    }
});

 log(">>> Test1 - dev[{}]: {}",topic, dev[topic]);
var cell = device.getControl(cellName);
log(">>> Test2 - cell = {}", cell);
var val = cell.getValue();
log(">>> Test3 - val = {}", val);


Apr 08 01:45:11 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: reloading file: /etc/wb-rules/experiments.js
Apr 08 01:45:11 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: [rule info] >>> Test1 - dev[heat_out_store1/targetTemperature]: 24
Apr 08 01:45:11 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: [rule info] >>> Test2 - cell = [object Object]
Apr 08 01:45:11 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: [rule info] >>> Test3 - val = 24
Apr 08 01:45:16 wirenboard-AC6A3GB6 wb-rules[4864]: INFO: [rule info] _update_git_status started!

Пробовал перегружать правила, перегружать serial-mqtt, даже контроллер перегрузил, это не помогло. Где-то закешировалось сломанное состояние устройства, во флеш памяти (раз перезагрузка контроллера не помогла).

Где еще может хранится состояния виртуальных устройств?
Нашел файл wbrules-vdev.db, но формат у него мне не известный (sqlite не открыл).
diag_output_AC6A3GB6_2025-04-08-02.02.00.zip (440,2 КБ)

Добрый день.
А попробую воспроизвести.
Для этого на контроллере WB8, стабильный релиз 2501 создаю скрипт.

//04_08_test_1.js
var deviceName = 'heat_out_store';
var cellName = 'targetTemperature';
var topic = "{}/{}".format(deviceName, cellName);
var device = defineVirtualDevice(deviceName, {
    title: "Термостат: Уличная кладовка",
    cells: {
        targetTemperature: {
            type: "value",
            value: 24,
            title: "Уставка",
            order: 1,
            max: 30,
            min: 15,
            readonly: false
        }
    }
});

 log(">>> Test1 - dev[{}]: {}",topic, dev[topic]);
var cell = device.getControl(cellName);
log(">>> Test2 - cell = {}", cell);
var val = cell.getValue();
log(">>> Test3 - val = {}", val);

Получаю вывод в mqtt:

/rpc/v1/wbrules/Editor/Save/wb-mqtt-homeui-6RGkjOTJV2 {"id":6,"params":{"path":"04_08_test_1.js","content":"//04_08_test_1.js\nvar deviceName = 'heat_out_store';\nvar cellName = 'targetTemperature';\nvar topic = \"{}/{}\".format(deviceName, cellName);\nvar device = defineVirtualDevice(deviceName, {\n    title: \"Термостат: Уличная кладовка\",\n    cells: {\n        targetTemperature: {\n            type: \"value\",\n            value: 24,\n            title: \"Уставка\",\n            order: 1,\n            max: 30,\n            min: 15,\n            readonly: false\n        }\n    }\n});\n\n log(\">>> Test1 - dev[{}]: {}\",topic, dev[topic]);\nvar cell = device.getControl(cellName);\nlog(\">>> Test2 - cell = {}\", cell);\nvar val = cell.getValue();\nlog(\">>> Test3 - val = {}\", val);"}}
/devices/heat_out_store/meta/name Термостат: Уличная кладовка
/devices/heat_out_store/meta/driver wb-rules
/devices/heat_out_store/meta {"driver":"wb-rules","title":{"en":"Термостат: Уличная кладовка"}}
/devices/heat_out_store/controls/targetTemperature/meta/min 15
/devices/heat_out_store/controls/targetTemperature/meta/order 1
/devices/heat_out_store/controls/targetTemperature/meta/readonly 0
/devices/heat_out_store/controls/targetTemperature/meta/type value
/devices/heat_out_store/controls/targetTemperature/meta/max 30
/devices/heat_out_store/controls/targetTemperature/meta {"max":30,"min":15,"order":1,"readonly":false,"title":{"en":"Уставка"},"type":"value"}
/devices/heat_out_store/controls/targetTemperature 24
/wbrules/log/info >>> Test1 - dev[heat_out_store/targetTemperature]: 24
/wbrules/log/info >>> Test2 - cell = [object Object]
/wbrules/log/info >>> Test3 - val = 24

В логах:

Apr 08 12:37:23 wirenboard-AC4U5OVN wb-rules[1873]: INFO: [rule info] >>> Test1 - dev[heat_out_store/targetTemperature]: 24
Apr 08 12:37:23 wirenboard-AC4U5OVN wb-rules[1873]: INFO: [rule info] >>> Test2 - cell = [object Object]
Apr 08 12:37:23 wirenboard-AC4U5OVN wb-rules[1873]: INFO: [rule info] >>> Test3 - val = 24
Apr 08 12:37:23 wirenboard-AC4U5OVN wb-mqtt-db[1827]: INFO: [sqlite] Creating channel heat_out_store/targetTemperature
Apr 08 12:37:24 wirenboard-AC4U5OVN wb-rules[1873]: INFO: reloading file: /etc/wb-rules/04_08_test_1.js

Ну и

А загружен ли контроллер именно в момент выполнения скрипта? Такое впечатление что не все топики успели создаться на момент чтения.

Андрей, добрый день!

Вы вряд ли это воспроизведете.
Я сам не понял как такое состояние получилось.
Скорее всего когда писал и тестировал термостаты где-то словил исключение, что устройство с конкретно этим топиком как-то закешировалось в неконситсентном состоянии.

У меня тоже все работает штатно, если изменить имя виртуального устройства или топика.
Тут вопрос чисто технический, на уровне архитектуры, где и как могут кешироваться виртуальные устройства?
Да так, что даже перезагрузка контроллера не помогает. Т.е. где-то в постоянной памяти.
Предположу, что нужно копать в сторону файла wbrules-vdev.db. Не подскажете, что там хранится и что за формат у этого файла?

Не загружен. Пробовал и обратиться к этому топику через какое то время. Устройство создается корректно, но получить данные из этого топика не получается. Реакция такая же, та же ошибка.

код
var cellName = 'targetTemperature';
var topic = "{}/{}".format(deviceName, cellName);
var device = defineVirtualDevice(deviceName, {
    title: "Термостат: Уличная кладовка",
    cells: {
        targetTemperature: {
            type: "value",
            value: 24,
            title: "Уставка",
            order: 1,
            max: 30,
            min: 15,
            readonly: false
        }
    }
});
setTimeout(function (){
    log(">>> Test1 - dev[{}]: {}",topic, dev[topic]);
    var cell = device.getControl(cellName);
    log(">>> Test2 - cell = {}", cell);
    var val = cell.getValue();
    log(">>> Test3 - val = {}", val);
}, 30000); 


Хранятся - значения счетчиков нажатий (ну, вообще - всех топиков). Сделано для того чтобы обрабатывать отключения питания.
Можно остановить сервис и удалить этот файл. - для проверки. Пересоздастся.

Что-то в ченжлоге не пойму когда оно добавлено было, спрошу у разработчиков.

А, кстати, persistence в брокере не включали? В /etc/mosquitto/mosquitto.conf ?

Глянул, там стандартно, выключено

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

#pid_file /run/mosquitto/mosquitto.pid

# persistence is disabled by default. enable in /etc/mosquitto/conf.d/000persistence.conf
persistence_location /var/lib/mosquitto/

log_dest syslog

include_dir /usr/share/wb-configs/mosquitto
include_dir /etc/mosquitto/conf.d

Интересно, может там какое-то невалидное значение записалось для этого топика? Из-за чего при создании виртуального устройства он не может его корректно считать.
Там какой-то стандартный формат у этого файла?
Как-то боязно спразу удалять его)
Могу дать удаленный доступ, если WB будет интересен этот кейс поковырять

Попробовал остановить сервис, переименовать файл и запустить заново и ошибка действительно ушла! Значит действительно закешировалось что-то.
Проблема, что все параметры ранее созданных виртуальных устройств тоже сбросились.
Можно ли как-то ручками залезть в этот файл и подправить/подчистить данные? Или там какой-то не стандартный формат данных?

А выложите сюда его.

Да еще не узнавал…
Так-то похоже на “IBM” формат.

old_wbrules-vdev.db (64 КБ)
Приложил файл

Описал багу, попробую ее, конечно, воспроизвести…

Скормил файл онлайн просмотрщику IBM файлов, да, похоже, что запись именно этого топика отличается

Там нет значения

Но воспроизвести пока, к сожалению, не выходит. Ладно, может быть разработчики смогут понять.

Интересно.
Т.е. если этот файлик подложить и создать устройство с таким топиком и взять значение его, у вас отрабатывает корректно?

Если использовать поврежденный - воспроизводится. Но как добиться такого ж состояния файла - пока не придумал.