Поменять значение switch в правилах без whenChanged

Дорогие разработчики wb-rules, помогите с таким вопросом.

Есть физустройство - wifi розетка. Есть скрипт на wb, который ее опрашивает и публикует состояние вкл/выкл в топик (упрощенно) /wifisocket/power.Также есть топик /wifisocket/power/set, на который подписан скрипт и он транслирует команды 1/0 включая и выключая розетку. Также розетка может быть включена руками.

Мне нужно создать виртуальное устройство dev[‘virtSocket/state’] с контролом типа switch который отображает состояние розетки и при нажатии на контрол переключает состояние. Но при этом хочется отображать текущее состояние в этом же контроле.

Я делаю правило whenChanged:‘virtSocket/state’ на включение и выключение розетки в дашборде, все хорошо.

Если подписаться на топик через trackMqtt(‘/wifisocket/power’) и менять состояние switch (при изменении состояния розетки например с выкл на вкл) через установку dev[‘virtSocket/state’], срабатывает правило whenChanged и на устройство еще раз летит повторная команда.

Есть ли механизм установления отображения контрола switch в нужное положение без срабатывания whenChange, или есть другой способ зеркального отображения состояния устройства в switch?

как вариант, я решил сделать так:

завести переменную wifisocketPower. через trackMqtt(‘/wifisocket/power’) устанавливать ее в текущий статус розетки.

а дальше в правиле для виртуального устройства whenChanged:‘virtSocket/state’ сверять новое состояние контрола с wifisocketPower. Если они различны - то подавать команду на включение, если одинаковы - то не отправлять. Но, это кажется немного неуклюже, может быть есть другой способ?

Вот так работает, но я не уверен, что это правильно. Последние 2 trackMqtt для эмуляции реального устройства.

defineVirtualDevice("virtWifiSocket", {
	title: "Virtual wifi socket",
  	cells: {
      power: {
        type: 'switch',
        value: false
      },
    }
});

var realSocketVal = null
trackMqtt('/devices/realwifisocket/controls/power', function (message) {
  log(message.value)
  realSocketVal = !!(+message.value)
  dev['virtWifiSocket/power'] = realSocketVal
});

defineRule({
 	whenChanged: "virtWifiSocket/power",
 	then: function (newValue, devName, cellName) {
 		if (newValue !== realSocketVal) {
          publish('/devices/realwifisocket/controls/power/set', newValue ? 1 : 0)
        }        
 	}
 });

trackMqtt('/devices/realwifisocket/controls/power/set', function (message) {
  log(message.value)
  var newState = +message.value
  publish('/devices/realwifisocket/controls/power', newState ? 1 : 0, 0,1)
});

trackMqtt('/devices/realwifisocket/controls/power/toggle', function (message) {
  log(message.value)
  publish('/devices/realwifisocket/controls/power', realSocketVal ? 0 : 1, 0,1)
});

Добрый день.

Да, например как описано тут.
Но это хак, не учитывающий (возможную) реакцию других драйверов. То есть он сработает для правил wb-rules, но если система связана еще с чем-то то можно получить неожиданное поведение.

Вот так обычно и делают.
Но не совсем: типично проверяют состояние устанавливаемого контрола, если он уже в нужном - то не делают ничего, лишняя переменная ни к чему.
Вот тут обсуждалось.

Так как устройство пишет в топики внешним питон скриптом, то я не знаю его состояние в правилах, если не сделаю trackMqtt на его топик состояния. Как сделать это без отдельной переменной - я не знаю.

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

Если устройство конвенционнае - то достаточно получить (именно текущее) как dev[устройство/контрол]