Интеграция Wi-Fi розетки в WB

Интегрировал Wi-Fi розетку в WB, делюсь наработкой. Авто-обновляется статус каждые 30 секунд, но и кнопку ручную приделал.

Имею розетку Gauss Умная розетка Smart Home(артикул 5510122) и для её интеграции следующий wb-rule:

var WIZ_IP = "IP адрес розетки";
var WIZ_PORT = 38899;

defineVirtualDevice("rozetka_room1_wifi", {
  title: "Розетка комната 1 WiFi",
  cells: {
    online: {
      title: "Статус",
      type: "switch",
      value: false,
      readonly: true,
      order: 1
    },
    rssi: {
      title: "Сигнал",
      type: "value",
      value: 0,
      units: "dBm",
      order: 2
    },
    power: {
      title: "Питание",
      type: "switch",
      value: false,
      order: 3
    },
    refresh: {
      title: "Обновить",
      type: "pushbutton",
      order: 4
    }
  }
});

function wizSendRaw(json) {
  var payload = json.replace(/'/g, "'\\''");
  runShellCommand("printf '" + payload + "' | nc -u -w2 " + WIZ_IP + " " + WIZ_PORT);
}

function wizSetState(isOn) {
  wizSendRaw(JSON.stringify({
    method: "setState",
    params: {
      state: !!isOn
    }
  }));
}

function wizRefreshState() {
  runShellCommand("/usr/local/bin/wifi_rozetka_room1.sh");
}

// управление розеткой
defineRule("rozetka_room1_wifi_write", {
  whenChanged: "rozetka_room1_wifi/power",
  then: function (val) {
    wizSetState(val);
    log.info("[WIZ_ROOM1] set " + (val ? "ON" : "OFF"));

    setTimeout(function () {
      wizRefreshState();
    }, 1000);
  }
});

// ручное обновление
defineRule("rozetka_room1_wifi_refresh", {
  whenChanged: "rozetka_room1_wifi/refresh",
  then: function (v) {
    if (!v) return;

    wizRefreshState();
    log.info("[WIZ_ROOM1] refresh requested");
  }
});

// автоопрос каждые 30 секунд
defineRule("rozetka_room1_wifi_poll", {
  when: cron("*/30 * * * * *"),
  then: function () {
    wizRefreshState();
  }
});

для опроса состояния(в сети или не в сети, сигнал wi-fi) скрипт sh, который положил сюда:
/usr/local/bin/wifi_rozetka_room1.sh:

#!/bin/bash

IP="IP адрес Wi-Fi розетки"
PORT="38899"
DEVICE="rozetka_room1_wifi"

RESP=$(printf '{"method":"getPilot"}' | nc -u -w2 "$IP" "$PORT")

if [ -z "$RESP" ]; then
  mosquitto_pub -t "/devices/$DEVICE/controls/online" -m "0"
  mosquitto_pub -t "/devices/$DEVICE/controls/rssi" -m "0"
  mosquitto_pub -t "/devices/$DEVICE/controls/power" -m "0"
  exit 0
fi

mosquitto_pub -t "/devices/$DEVICE/controls/online" -m "1"

STATE=$(echo "$RESP" | sed -n 's/.*"state":\(true\|false\).*/\1/p')
RSSI=$(echo "$RESP" | sed -n 's/.*"rssi":\(-\?[0-9]\+\).*/\1/p')

if [ -n "$STATE" ]; then
  if [ "$STATE" = "true" ]; then
    mosquitto_pub -t "/devices/$DEVICE/controls/power" -m "1"
  else
    mosquitto_pub -t "/devices/$DEVICE/controls/power" -m "0"
  fi
fi

if [ -n "$RSSI" ]; then
  mosquitto_pub -t "/devices/$DEVICE/controls/rssi" -m "$RSSI"
fi

Здравствуйте! Я автоматический помощник техподдержки Wiren Board. Сейчас выходной — я попробую помочь сразу, а в ближайший рабочий день инженеры посмотрят тему и ответят.
Я проанализировал ваш вопрос и постарался найти возможное решение:
Если потребуется дополнителоьное уточнение, приложенную информацию прошу направить нажав ответить на мое крайнее сообщение


Вы интегрируете Wi‑Fi‑розетку Gauss (протокол, совместимый с WiZ) в контроллер Wiren Board через wb-rules и nc/mosquitto_pub. Ниже — несколько замечаний, чтобы это работало стабильнее и удобнее.

1. Мелкие ошибки и опечатки в коде

  1. Имя виртуального устройства

В js‑правиле:

defineVirtualDevice("rozetka_room1_wifi", { ... });

а в shell‑скрипте:

DEVICE=“rozetka_wifi_room1_wifi”

Из‑за этого MQTT‑топики не совпадают. Должно быть одинаково, например:

DEVICE="rozetka_room1_wifi"

И тогда топики будут вида /devices/rozetka_room1_wifi/controls/....

  1. Кавычки

В bash‑скрипте у вас «типографские» кавычки `“ ” ‘ ’. Bash их не понимает. Нужно заменить на обычные:

#!/bin/bash

IP="IP_адрес_розетки"
PORT="38899"
DEVICE="rozetka_room1_wifi"

RESP=$(printf '{"method":"getPilot"}' | nc -u -w2 "$IP" "$PORT")

То же самое — для всех if [ -z "$RESP" ], "$STATE" и т.д.

  1. Топик для управления power

Виртуальное устройство описано так:

power: {
  title: "Питание",
  type: "switch",
  value: false,
  order: 3
}

Для switch корректный топик состояния в MQTT:
/devices/rozetka_room1_wifi/controls/power
(без /on на конце). В скрипте сейчас:

mosquitto_pub -t "/devices/$DEVICE/controls/power/on" -m "1"

Нужно:

if [ "$STATE" = "true" ]; then
  mosquitto_pub -t "/devices/$DEVICE/controls/power" -m "1"
else
  mosquitto_pub -t "/devices/$DEVICE/controls/power" -m "0"
fi

2. Статус «online» и тип ячейки

Вы публикуете:

mosquitto_pub -t "/devices/$DEVICE/controls/online" -m "0"  # или "1"

В js‑правиле online объявлен как type: "switch". Это допустимо, но для статуса обычно используют:

online: {
  title: "Статус",
  type: "value",
  readonly: true
}

Или оставить switch, но тогда для красоты можно добавить meta‑данные:

mosquitto_pub -t "/devices/$DEVICE/controls/online/meta/type" -m "switch"
mosquitto_pub -t "/devices/$DEVICE/controls/online/meta/readonly" -m "1"

(если не хотите править js‑правило).

3. Извлечение state и rssi

Ваш sed‑парсинг в принципе рабочий, но чувствителен к формату ответа. Более надёжно использовать jq (если он установлен):

STATE=$(echo "$RESP" | jq -r '.result.state // empty')
RSSI=$(echo "$RESP" | jq -r '.result.rssi // empty')

Тогда не будет проблем при изменении порядка полей. На контроллерах WB jq обычно доступен из репозиториев Debian.

4. Права и исполнение скрипта

Убедитесь, что скрипт исполняемый и владелец/права корректны:

chmod +x /usr/local/bin/wifi_rozetka_room1.sh

И что в wb-rules он вызывается именно по этому пути (как у вас сейчас).

5. Надёжность опроса

В cron("*/30 * * * * *") вы опрашиваете устройство каждые 30 секунд. Это ок, но если сети часто нет, лучше рассмотреть увеличенный интервал (например, раз в 60–120 секунд), чтобы не засорять лог и не грузить розетку.


Если захотите, могу помочь оформить это в виде отдельного device-template (через wb-mqtt-serial или как виртуальное устройство, чтобы было проще тиражировать на несколько розеток/комнат).

Примечание: Я — искусственный интеллект, а не сотрудник-человек. В моих ответах возможны неточности.

Добрый день!
Благодарю за вклад в наше дружное сообщество!

мда конечно вызов внешней команды для отправки единственного UDP пакета это очень расточительно особенно на такой дохлой железке как Cortex A53 (это еще если WB8 а то и того хуже). Но изнутри duktape конечно нет другого варианта. Очень хотелось бы чтобы разрабы перешли на node.js, чтобы была норм сеть, ES6 итд