Запуск правила по приходящему значению

Здравствуйте! Мне необходимо при значении, приходящему в виртуальное устройство по MQTT, и в зависимости от него, выполнять какие-то действия.

Пример: пришло "off", записываем в нужный топик "false". Пришло "heat", записываем в один топик "true", во второй "1".

Есть два вопроса:

  1. Не могу понять, как мне запускать правило по событию “в нужный топик пришло свежее значение”. Причём важно, что правило должно срабатывать только если пришло свежее значение, и опираться именно на него. Нас интересует второе правило, где сейчас я написал whenChanged: ["hwmon/CPU Temperature"], как placeholder.
  2. Почему-то сейчас, при записи в топик
    devices/IntesisboxINMBSDAI001R000_14_virt_mode/controls/mode_command_topic значения, допустим, “off”, и после изменения температуры CPU (триггер сработки правила), не выключается нужный параметр целевого устройства. Перепробовал уже и MQTT топик, и через device. Как сделать правильно?
Правило
//Ver. 0.1
var intesis_name = "IntesisboxINMBSDAI001R000_14"; //Устройство, на которое ориентируемся

defineVirtualDevice(intesis_name + "_virt_mode", {
    title: intesis_name + "_virt_mode" ,
    cells: {
      mode_state_topic: {
        title: "mode_state_topic",
	    type: "text",
	    value: "unknown"
	    },
      mode_command_topic: {
        title: "mode_command_topic",
	    type: "text",
	    value: "unknown"
	    },
    }
})

defineRule({
  whenChanged: [intesis_name + "/Power", intesis_name + "/Mode", "system/Current uptime"],
  then: function () {
      if (dev[intesis_name + "/Power"] == false){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "off"
      } else if (dev[intesis_name + "/Mode"] == 0){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "auto"
      } else if (dev[intesis_name + "/Mode"] == 1){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "heat"
      } else if (dev[intesis_name + "/Mode"] == 2){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "dry"
      } else if (dev[intesis_name + "/Mode"] == 3){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "fan_only"
      } else if (dev[intesis_name + "/Mode"] == 4){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "cool"
      }
    }
  }
)

defineRule({
  whenChanged: ["hwmon/CPU Temperature"],
  then: function () {
      if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == off){
        dev[intesis_name + "/Power"] = false
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == auto){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 0
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == heat){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 1
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == dry){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 2
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == fan_only){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 3
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == cool){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 4
      }
    }
  }
)

Заранее спасибо!

Если вы создаете виртуальное устройство средствами wb-rules, то и изменять его топики вы должны тоже средствами wb-rules. Если изменять топики сторонними средствами, wb-rules их не видит. Думаю, ваша проблема в этом.

Чтобы решить вашу задачу, вам надо топик создать также сторонними средствами. А дальнейшие действия можно выполнять средствами wb-rules. Тот же whenChanged обеспечит вам нужную функциональность, если топик будет создан согласно нашим конвенциям.

Неверно. Для установки нового следует писать новое значение в
“devices/IntesisboxINMBSDAI001R000_14_virt_mode/controls/mode_command_topic/on”
В таком случае драйвер, обрабатывающий этот контрол - уже изменит и само значение и правило - сработает.

Почему-то сейчас при отправке в /devices/IntesisboxINMBSDAI001R000_14_virt_mode/controls/mode_command_topic/on любого значения, в MQTT Channels в топике остаётся значение unknown. Если же отправить в /devices/IntesisboxINMBSDAI001R000_14_virt_mode/controls/mode_command_topic значение, оно появится в топике в MQTT Channels.

Сейчас вообще каким-то образом в топик записался сам топик:


Я удалил правило, добавил заново (скопировал из шапки темы), в топике всё равно лежит топик…

Это как вообще возможно?

Добавил кавычки для проверки состояния топика во втором правиле.

Спойлер
//Ver. 0.1
var intesis_name = "IntesisboxINMBSDAI001R000_14"; //Устройство, на которое ориентируемся

defineVirtualDevice(intesis_name + "_virt_mode", {
    title: intesis_name + "_virt_mode" ,
    cells: {
      mode_state_topic: {
        title: "mode_state_topic",
	    type: "text",
	    value: "unknown"
	    },
      mode_command_topic: {
        title: "mode_command_topic",
	    type: "text",
	    value: "unknown"
	    },
    }
})

defineRule({
  whenChanged: [intesis_name + "/Power", intesis_name + "/Mode", "system/Current uptime"],
  then: function () {
      if (dev[intesis_name + "/Power"] == false){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "off"
      } else if (dev[intesis_name + "/Mode"] == 0){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "auto"
      } else if (dev[intesis_name + "/Mode"] == 1){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "heat"
      } else if (dev[intesis_name + "/Mode"] == 2){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "dry"
      } else if (dev[intesis_name + "/Mode"] == 3){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "fan_only"
      } else if (dev[intesis_name + "/Mode"] == 4){
        dev[intesis_name + "_virt_mode"]["mode_state_topic"] = "cool"
      }
    }
  }
)

defineRule({
  whenChanged: ["hwmon/CPU Temperature"],
  then: function () {
      if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == "off"){
        dev[intesis_name + "/Power"] = false
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == "auto"){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 0
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == "heat"){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 1
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == "dry"){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 2
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == "fan_only"){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 3
      } else if (dev[intesis_name + "_virt_mode"]["mode_command_topic"] == "cool"){
        dev[intesis_name + "/Power"] = true
        dev[intesis_name + "/Mode"] = 4
      }
    }
  }
)

При попытке записи в /devices/IntesisboxINMBSDAI001R000_14_virt_mode/controls/mode_command_topic/on в логе появляется ошибка:

06-03-2024 16:47:19.760 ERROR: [backend] failed to process /on request to IntesisboxINMBSDAI001R000_14_virt_mode/mode_command_topic: This control is not writable

Если в виртуальном устройстве для топиков включен readonly:true- то да. если выключить:

mosquitto_pub -t "/devices/IntesisboxINMBSDAI001R000_14_virt_mode/controls/mode_command_topic/on" -m "kva-kva-kva"
mosquitto_pub -t "/devices/IntesisboxINMBSDAI001R000_14_virt_mode/controls/mode_state_topic/on" -m "kva-kva-kva22222""

то работает.

Судя по всему, добавление readonly : false решило сразу все проблемы. Сейчас ещё чуть потестирую и закрою тему. Спасибо!

Выходит, контролы у устройств по умолчанию всегда readonly?

Да, если не указано явно что значение записываемое.