WB-MR6C blink mode, как лучше реализовать?

всем день добрый!
решил при помощи WB-MR6C организовать сигнальный щит
на котором будут зеленые и красные лампы
задумал три режима
1 - горит зеленым, “нормальная работа”
2 - горит красным, “холостой ход” (оборудование не запустилось после прогрева)
3 - мигает красным (blink mode), “запуск-прогрев”

вкл/выкл будет реализовано через действия заббикса, он у меня за всем следит, соответственно он будет запускать скрипт удаленно или выполнять команду по ssh

прошу совета, как лучше организовать “моргающий режим” - blink mode?

Добрый день. Вообще - я бы сделал штатным скриптовым движком wb-rules.
Использовать Как писать правила — Wiren Board
который срабатывая включает выход “на лампу” и запускает startTimer(); на перод свечения.

Ну и управление сигнализацией - свел бы к виртуальному устройству, управление которым легко делается через записть в MQTT топики.

я понял так:
делаю виртуальное устройство (type: “switch”) как в примере со " startTicker();"
потом через mqtt включаю и выключаю его, так?

виртуальное устройство сразу появится в mqtt после создания?

Да, только вместо пищалки - указываем устройство-реле. Ну и перод моргания подбиряем какой нравится. И включаем само моргание так:
https://wirenboard.com/wiki/MQTT#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D0.B5.D0.BD.D0.B8.D0.B5_.D1.83.D1.81.D1.82.D1.80.D0.BE.D0.B9.D1.81.D1.82.D0.B2.D0.B0.D0.BC.D0.B8_.D0.B8.D0.B7_.D0.BA.D0.BE.D0.BC.D0.B0.D0.BD.D0.B4.D0.BD.D0.BE.D0.B9_.D1.81.D1.82.D1.80.D0.BE.D0.BA.D0.B8

Да, сразу после сохранения скрипта.

Хотя, для меня странный выбор именно Modbus реле как выключателя лампочек. Для такого достаточно и Модуль релейных выходов 1А для контакторов WBIO-DO-R1G-16 — Wiren Board например.
Ну или ssr низковольтный модуль Модуль дискретных выходов типа «сухой контакт» WBIO-DO-SSR-8 — Wiren Board

где ж вы раньше были, почему я раньше не спросил?
у WBIO-DO-R1G-16 противопоказания на счет светодиодных ламп, а у меня лампы светодиодные, хотя думаю что в описании имеются в виду лампы освещения - их не рекомендуется подключать, а к сигнальным это не относится - они маломощные

а WBIO-DO-SSR-8 на оптронах, думаю самое то

вспомнил, почему выбрал WB-MR6C - потому что про него написано, что он:

"Предназначен для прямого управления маломощной нагрузкой (до 7А) без больших пусковых токов: сигнальные лампы, промежуточные контакторы.

так что ничего странного в выборе нет:)

Да, плюс там RC-цепь для гашения выбросов катушек контакторов. Но для сигнальных - работает.

прошу подсказать по синтаксису, где ошибка?
blink_r50k3 - определил в device name устройства в serial.conf
устройство в интерфейсе появилось, в mqtt отображается
switch переключается, только ничего не происходит

defineVirtualDevice("blink_r50k1", {
  title: "blink_r50k1",
  cells: {
    enabled: {
      type: "switch",
      value: false
    }
  }
});

defineRule("1",{
  asSoonAs: function () {
    return dev["WB-MR6C_50"]["K1"] ;
  },
  then: function () {
    startTicker("one_second", 1000);
    }
});
defineRule("2",{
  when: function () { return timers.one_second.firing; },
  then: function () {
    dev["WB-MR6C_50"]["K1"] = !dev["WB-MR6C_50"]["K1"];
    if (dev["WB-MR6C_50"]["K1"] == false){
      timers.one_second.stop();
    }
  }
});

в логах :

2021-05-19 17:23:16defineRule: 1

2021-05-19 17:23:17defineRule: 2

2021-05-19 17:23:17skipping rule due to incomplete cell 1: IncompleteCellCaught: incomplete cell encountered: K1

почему-то не хочет признавать K1, K2 и т.д., хотя в шаблоне /usr/share/wb-mqtt-serial/templates/config-wb-mr6c.json:
channels": [
{
“name”: “K1”,
“reg_type”: “coil”,
“address”: 0,
“type”: “switch”
},

есть подвижки, в таком виде работает:

  defineVirtualDevice("blink_r50k1", {
  title: "blink_r50k1",
  cells: {
enabled: {
  type: "switch",
  value: false
}
  }
});

defineRule("1",{
  asSoonAs: function () {
return dev["blink_r50k1"]["enabled"] ;
  },
  then: function () {
startTicker("one_second", 1000);
}
});
defineRule("2",{
  when: function () { return timers.one_second.firing; },
  then: function () {
dev["wb-mr6c_50"]["K3"] = !dev["wb-mr6c_50"]["K3"];
if (dev["blink_r50k1"]["enabled"] == false){
  timers.one_second.stop();
}
  }
});

команда включения:

mosquitto_pub -h localhost -t "/devices/blink_r50k1/controls/enabled/on" -d -m "1"
1 лайк

на данный момент создал 12 виртуальных устройств (использую два реле, на каждое по 6 шт)
я так понял что зона действия startTicker(); глобальна
т.е. пока в каждом скрипте не прописал свой таймер получалась непонятная ерунда
сейчас у каждого свой уникальный таймер, но кнопки моргают вразнобой, не совсем красиво
как лучше сделать, описать startTicker() как-то отдельно или оставить как есть?

А может быть - сделать один таймер, а в его функции - включать-выключать “разрешенные” для моргания лампы?

обрисуйте контуры пожалуйста, как это сделать?

Здравствуйте! В первом варианте правил у вас было несколько ошибок:

  1. В правиле “1” для функции Return используется регистр реле для запуска таймера, а надо использовать канал виртуального устройства.

  2. Использование заглавных букв в названиях топиков - нужно было проверить названия топиков на странице Settings → MQTT Channels

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

    Я бы предложил следующий вариант:

//виртуальные выключатели

defineVirtualDevice("blink_switches", {

    title: "blink_switches",

    cells: {

        k1: {

        type: "switch",

        value: false

        },

        k2: {

        type: "switch",

        value: false

        },

        k3: {

        type: "switch",

        value: false

        },

        k4: {

        type: "switch",

        value: false

        },

        k5: {

        type: "switch",

        value: false

        },

        k6: {

        type: "switch",

        value: false

        },     

            

  }

});

//запуск общего таймера

defineRule("start_timer",{

    //если хотя бы один переключатель включен

    whenChanged: function() { return (  dev["blink_switches/k1"] ||

                                        dev["blink_switches/k2"] ||

                                        dev["blink_switches/k3"] ||

                                        dev["blink_switches/k4"] ||

                                        dev["blink_switches/k5"] || 

                                        dev["blink_switches/k6"] 

                                    )

                            },

    then:   function (newValue, devName, cellName) {

                //запускаем общий таймер

                if ( newValue == true) { startTicker("clock_1s", 1000); }

                else { 

                    //иначе останавливаем таймер; отключаем все реле, чтобы они не остались во включенном состоянии

                    timers.clock_1s.stop();

                    dev["wb-mr6c_50/K1"] = false;

                    dev["wb-mr6c_50/K2"] = false;

                    dev["wb-mr6c_50/K3"] = false;

                    dev["wb-mr6c_50/K4"] = false;

                    dev["wb-mr6c_50/K5"] = false;

                    dev["wb-mr6c_50/K6"] = false;

                };

    }    

});

//управление реле

//добавляем переменную для определения времени включения реле

var oddCount = 0;

defineRule("switch_relay",{

    when: function () { return timers.clock_1s.firing; },

    then: function () {

  

        //меняем значение oddCount с 0 на 1 или наоборот

        oddCount = oddCount ^ 1;

        //если oddCount == 1 и переключатель соответствующего реле включен, то включить реле, иначе выключить

        if ( (oddCount == 1) && (dev["blink_switches/k1"] == true ) ) { dev["wb-mr6c_50/K1"] = true; } else { dev["wb-mr6c_50/K1"] = false; };

        if ( (oddCount == 1) && (dev["blink_switches/k2"] == true ) ) { dev["wb-mr6c_50/K2"] = true; } else { dev["wb-mr6c_50/K2"] = false; };

        if ( (oddCount == 1) && (dev["blink_switches/k3"] == true ) ) { dev["wb-mr6c_50/K3"] = true; } else { dev["wb-mr6c_50/K3"] = false; };

        if ( (oddCount == 1) && (dev["blink_switches/k4"] == true ) ) { dev["wb-mr6c_50/K4"] = true; } else { dev["wb-mr6c_50/K4"] = false; };

        if ( (oddCount == 1) && (dev["blink_switches/k5"] == true ) ) { dev["wb-mr6c_50/K5"] = true; } else { dev["wb-mr6c_50/K5"] = false; };

        if ( (oddCount == 1) && (dev["blink_switches/k6"] == true ) ) { dev["wb-mr6c_50/K6"] = true; } else { dev["wb-mr6c_50/K6"] = false; };

    }

});

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

попробовал
моргает, но
гасит все реле при включении и при выключении
мне надо чтобы конфигурация остальных реле, на момент включения блинка на каком-нибудь одном, не затрагивалась конфигурация остальных
попробовал несколько вариантов, не получается пока

по разным

Так вот же оно? Кусок кода - в нем достаточно закомментировать ненужные.

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

Что не получается в переделке “как надо”?

В этом случае, когда ни у одного реле не включен режим мигания как раз выполняется вот этот код:

Это делается, чтобы после остановки таймера все реле остались в выключенном состоянии.

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

если включить 1 блинк, то он не выключиться (если попал неудачно)

Это был только пример использования общего таймера для мигания ламп. Если у вас лампы еще и горят, то измените условия под себя, не отключайте нужные при остановке таймера. К тому же таймер можно вообще не останавливать.