Добавить свои пути в /etc/default/wb-rules нет такого файла

Переписал функции подписки и создания виртуального устройства пока так

Спойлер
// Скрипт подписывается на топики ошибок связи и выводит в UI информацию о ошибках
var Device      = "Check_serial_error";
var NameEN      = "Check serial error";
var NameRU      = "Обработка ошибок связи"
var nDevice     = Device;
var sErrorTXT   = "/Error_TXT";
var sWarningTXT = "/Warning_TXT";
var sResetError = "/pbReset";

//----------------СОЗДАНИЕ ВИРТУАЛЬНОГО УСТРОЙСТВА----------------------//
// Функция создание виртуального устройства 
function Create_VDevice(vdDevice,vdNameEN,vdNameRU) {
    try {
        return defineVirtualDevice(vdDevice, {
            // имя виджета в GUI
            title: { en: vdNameEN, ru: vdNameRU},
            cells: {
                // Текущая ошибка WEB UI
                Error_TXT: {
                    title: { en: "Current Error", ru: "Текущая ошибка" },
                    type: "text",
                    value: "Отсутствует",
                    readonly: true,
                    forceDefault: true,
                    order: 1,
                },
                  // Текущая предупреждение WEB UI
                Warning_TXT: {
                    title: { en: "Current warning", ru: "Предупреждение" },
                    type: "text",
                    value: "Отсутствует",
                    readonly: true,
                    forceDefault: true,
                    order: 2,
                },
                // Кнопка сброса ошибки.
                pbReset: {
                    title: { en: "Reset error", ru: "Сброс ошибки" },
                    type: "pushbutton",
                    value: "false",
                    forceDefault: true,
                    order: 3,
                },
            },
        });
    } catch (error) {
        log.error("try Error Create " + NameVD + "  =" + error);
        return undefined;
    };
};

// Функция подписки на изменение топика кнопки "СБРОС ОШИБКИ" в WEB UI
function RuleResetError(RuleName) {
    try {
        return defineRule(RuleName, {
            whenChanged: Device + sResetError,                    // подписка на событие нажатия на кнопку "Сброс ошибки" в WEB UI
            then: function (newValue, devName, cellName) {        // devName = Control cellName = pbResetFID
                log("Произведен ручной сброс ошибки");            // логирование в консоли
                //ResetCurrentError();                            // Вызываем функцию сброса ошибок
                dev[Device + sWarningTXT] = "Отсутствует";        // Очищаем поле предупреждений
                dev[nDevice + sErrorTXT] = "Отсутствует";         // Выводим подсказку  в WEB UI
            },
        });
    } catch (error) {
        log.error("try Error RuleResetError: '" + error + "'");
        return undefined;
    };
};

//----------------ФУНКЦИИ СОЗДАНИЯ ПОДПИСОК НА ТОПИКИ MQTT----------------------//
// Функция создания правила подписки на пропадании связи с устройствами 
function CheckSerialDevices (){
    try {
        // Подписка на все устройства в которых есть топики /meta/error"
        return trackMqtt("/devices/+/controls/+/meta/error", function(message){     // Подписка на все устройства в которых есть топики /meta/error"
        // log.info("name: {}, value: {}".format(message.topic, message.value))
            
            // Функция извлечения текста в виде "устройство/топик"
            function GetDeviceName(string) {
                var parts = string.split('/');                                      // Разделяем строку по символу '/'
                return parts[2] + '/' + parts[4];                                   // Извлекаем нужные части и объединяем их
            };

            // Преобразовываем полученное значение для дальнейшего использования
            var ShortDeviceString = GetDeviceName(message.topic); 

            // В зависимости от полученного значения ошибки (message.value) выполняем различные действия  
            switch (message.value) {

                // Если текущая ошибка равна "r" нет ответа от устройства то
                case "r":
                    dev[nDevice + sErrorTXT] = "Ошибка чтения из устройства";  // Выводим подсказку  в WEB UI
                    dev[nDevice + sWarningTXT] = ShortDeviceString;            // Выводим подсказку  в WEB UI
                    log.error(
                        "Ошибка чтения из устройства:  {}",
                        ShortDeviceString
                    );
                    break;
                    
                // Если текущая ошибка равна "w" запись в устройство не удалась 
                case "w":
                    dev[nDevice + sErrorTXT] = "Ошибка записи в устройство";   // Выводим подсказку  в WEB UI
                    dev[nDevice + sWarningTXT] = ShortDeviceString;            // Выводим подсказку  в WEB UI
                    log.error(
                        "Ошибка записи в устройств  {}",
                        ShortDeviceString
                    );
                    break;

                // Если текущая ошибка равна "rp" попытка возобновить чтение после таймаута не удалась 
                case "rp":
                    dev[nDevice + sErrorTXT] = "Ошибка возобновления чтения";  // Выводим подсказку  в WEB UI
                    dev[nDevice + sWarningTXT] = ShortDeviceString;            // Выводим подсказку  в WEB UI
                    log.error(                                                 // Выводим в лог
                        "Попытка возобновить чтение с устройства:  {} не удалась",
                        ShortDeviceString
                    );
                    break;

                // Если текущая ошибка равна "wp". Прим. (сюда не разу не попал наверно такого не бывает)      
                case "wp":
                    log.warning(
                        "Попытка возобновить запись в устройство?:  {}, ",        // Выводим в лог
                        ShortDeviceString
                    );
                break;

                // Если текущая ошибка равна (p)периодическая попытка чтения? 
                case "p":
                    dev[nDevice + sErrorTXT] = "Ошибка возобновления";         // Выводим подсказку  в WEB UI
                    dev[nDevice + sWarningTXT] = ShortDeviceString;            // Выводим подсказку  в WEB UI
                    log.error(                                                 // Выводим в лог
                        "Попытка возобновить чтение с устройства:  {} не удалась",
                        ShortDeviceString
                    );
                    break;

                // Насколько понял сюда попадем в случае возобновления связи с устройством (чтение или запись которые раньше не читались или не записывались)
                default:
                    dev[nDevice + sErrorTXT] = "Связь восстановлена";          // Выводим подсказку  в WEB UI
                    dev[nDevice + sWarningTXT] = ShortDeviceString;            // Выводим подсказку  в WEB UI
                    log.warning(
                        "Возобновление связи c устройством:  {}, код: ({})",      // Выводим в лог
                        ShortDeviceString, message.value
                    );
                    break;
            };
      });
    // При исключении выводим в MQTT и лог значение которое привело  к этому        
    } catch (error) {
        dev[nDevice + sErrorTXT] = " Try checkSerialDevices: " + error;
        log.error("Try checkSerialDevices: " + error);
        return null;  
    };
};
//----------------НЕПОСРЕДСТВЕННОЕ СОЗДАНИЕ ----------------------//
var vdCreateCheckSerialError = Create_VDevice (Device,NameEN,NameRU);
var ChangedCheck = CheckSerialDevices ();
var ChangedButton = RuleResetError ("RuleResetError");

вложение
TEST.zip (2,4 КБ)

в интерфейсе это выглядиn так
Serial err1

в логе
Err Serial2 log

при восстановлении
Serial warningPNG
Прим. Сохраняем последнюю ошибку в предупреждении.(после перенесу в журнал ошибок)

в логе так
Serial log warning

да конечно можно сделать еще алармом, но все равно не так будет. У реального устройства видна в том числе попытка реанимировать связь (появляется еще значок)
Err real2

Искал долго информацию что может быть в meta/error? нашел в https://github.com/wirenboard/conventions/blob/main/README.md#errors, где на мой взгляд не очень понятно написано topics can contain a combination of values в переводе и их вариации ???, какие??? .Можете перечислить? это же не трудно. Как именно я понял все возможные комбинации см. под спойлер или вложение. Даже пример в Wiki на который здесь ссылались отслеживает только чтение, а если есть и критичная запись в устройство? например (отключить реле). Почему сразу не привести пример на все возможные комбинации?
И не понятно почему это не описать и в https://github.com/wirenboard/wb-mqtt-serial раз оно более всего к нему относится например в главе Обработка ошибок связи и/или где то здесь https://github.com/wirenboard/wb-rules?tab=readme-ov-file#%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF-%D0%BA-%D1%82%D0%BE%D0%BF%D0%B8%D0%BA%D0%B0%D0%BC-meta
Но это так, лирическое отступления пока жду ответ на предыдущие вопросы. В любом случае спасибо Вам за поддержку!
P.S. Причина редактирования ошибки отображения и изменение кода примера