При перезапуске wb-mqtt-serial инвертируются выходы

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

действительно, дело было в правилах. Спасибо за подсказку. Некоторые выходы не успевали инициализироваться, поэтому, когда правило их меняло, просто вылетает ошибка. А те, кто успевали инициализироваться, переключались.

Не поделитесь ли способом как реализовать обработку нажатий так чтобы подобного не происходило?

Как говориться “я не настоящий сварщик”, но кажется вот это описание:

В функцию, заданную в значении ключа then, передаются в качестве аргументов текущее значение параметра newValue, имя устройства devName и имя параметра cellName, изменение которого привело к срабатыванию правила.

В случае, если правило сработало из-за изменения функции, фигурирующей в whenChanged, в качестве единственного аргумента в then передаётся текущее значение этой функции.

Если срабатывание правила не связано непосредственно с изменением параметра (например, вызов при инициализации, по таймеру или через runRule()), then вызывается без аргументов, т.е. значением всех трёх аргументов будет undefined.

Говорит что можно отследить по значению newvalue. Т.е. если правило вызывается не изменение значения а по другим причина то значение newvalue должно быть undefined.

я делал на Home Assistant подобное, но там есть значение oldValue:
если oldValue == newValue + 1, то сработать.

Здесь oldValue нет. По логам вижу что newValue прилетает не undefined (текущее значение счетчика). Если oldValue существовал то его значение было бы undefined (поскольку это инициализация выхода и предыдущего значения нет).

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

хмммм, спасибо, посмотрю в эту сторону

На досуге накидал пример.

defineVirtualDevice('my-virtual-device', {
    title: 'MyVirtualDeviceTitle' ,
    cells: {
      base_value: {
        title: "base_value",
	    type: "temperature",
        value: 0,
	    },
      delta: {
        title: "delta",
	    type: "temperature",
        value: 0.5,
	    },
    }
})

defineRule("Examle_rule", {
    whenChanged: "wb-w1/28-00000eb85547",
    then: function() {
      new_value = dev["wb-w1/28-00000eb85547"]
      delta_value = Math.abs(dev["my-virtual-device/base_value"] - new_value)
      
      if (delta_value>dev["my-virtual-device/delta"]){
      	dev["buzzer/enabled"] = true;
        dev["my-virtual-device/base_value"] = new_value;
        
	    setTimeout(function () {
    	  	dev["buzzer/enabled"] = false;
    		}, 50);  
      }
    }

Здесь создано виртуальное устройство, в которой сохраняется предыдущее значение с которым идёт сравнение, в этом конкретном примере бипер срабатывает только если значение температуры изменилось больше чем на 0.5 градуса и после это значение запоминается и дальше сравнение идёт с ним. В случае с кнопкой достаточно запоминать значение счетчика и если оно изменилось на 1 то инвертировать вход, в остальных случаях нужно заполнить значение и ничего не делать.

2 лайка

Сработало, спасибо!!

Оставлю код для других

var counter = 0;

function toggleOnChange(source, target) {
  var deviceName = 'value-tracker-' + counter++;

  defineVirtualDevice(deviceName, {
    title: deviceName,
    cells: {
      prev: {
        title: 'prev',
        type: 'value',
        value: 0,
      },
    },
  });

  defineRule({
    whenChanged: source,
    then: function(newValue) {
      if (newValue > dev[deviceName + '/prev']) {
        dev[target] = !dev[target];
      }

      dev[deviceName + '/prev'] = newValue;
    },
  });
}

//Example
toggleOnChange('wb-mcm8_76/Input 4 Single Press Counter', 'wb-mrgbw-d-fw3_40/Channel 1 (B)'); 
toggleOnChange('wb-mcm8_76/Input 3 Single Press Counter', 'wb-mrgbw-d-fw3_46/Channel 2 (R)');
1 лайк

думаю что можно было простой JS объект использовать вместо virtualDevice. Но, работает - не трогай!

1 лайк

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

Эта тема была автоматически закрыта через 7 дней после последнего ответа. В ней больше нельзя отвечать.