Как управлять умной розеткой Xiaomi с часов Garmin

Исходные данные:

а) В распоряжении имеются надежные, хоть и не новые смарт-часы Garmin Fenix 6 Pro Solar, функционирующие на базе проприетарной ОС.
б) Комплект умных розеток Xiaomi Smart Plug 2 Wi-Fi.

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

Приступаю к изучению вопроса и поиску нестандартных путей реализации.

Для начала разберемся с логикой работы устройств Xiaomi. Основным инструментом взаимодействия выступает приложение Xiaomi Home, представляющее собой массивный программный «комбайн» для управления экосистемой. Очевидно, что портировать столь ресурсоемкий софт на ограниченную программную среду Garmin невозможно.

Следовательно, стратегия будет иной:

  1. Поскольку розетки скрыты за NAT домашнего роутера, необходимо определить локальный IP-адрес устройства. Это делается либо через настройки приложения Xiaomi Home, либо с помощью сетевого сканера (ориентируясь на производителя Beijing Xiaomi Mobile Software Co., Ltd.). В моем случае розетка имеет адрес 192.168.8.199 и работает по UDP-протоколу на порту 54321.

  2. Имея доступ к роутеру по SSH, настраиваем трансляцию адресов для тестов:

iptables -t nat -I POSTROUTING -p udp -d 192.168.8.199 —dport 54321 -j MASQUERADE

Этот метод временный, так как правила сбросятся после перезагрузки оборудования. Также потребуется настроить проброс порта 54321 из внешней сети на внутренний IP розетки.

Дальнейшие манипуляции проводим на удаленном сервере (подойдет как Windows, так и Linux), где уже развернут Node.js, обеспечивающий круглосуточную работу сервиса.

Пошаговый план:

  1. Создаем рабочую директорию, например, «c:\Xiaomi».

  2. В терминале выполняем установку необходимых зависимостей:

npm install express npm install miio npm install miio-api

Для обеспечения безопасности и устранения уязвимостей выполняем команду:

npm audit fix —force

3. Формируем управляющий скрипт index.js (с комментариями для наглядности):

const express = require(‘express’); const miio = require(‘miio-api’); const app = express();

const deviceIp = ‘111.111.111.111’; const deviceToken = ‘1855c4f24c7fb6592e348903f78e4c164’;

async function setPlugState(state) { const device = await miio.device({ address: deviceIp, token: deviceToken }); const res = await device.call(‘set_properties’, [ { did: ‘any’, siid: 2, piid: 1, value: state } ]); return res; }

app.get(‘/on’, async (req, res) => { try { await setPlugState(true); res.send(‘Розетка включена’); } catch (err) { res.status(500).send(‘Ошибка: ’ + err.message); } });

app.get(‘/off’, async (req, res) => { try { await setPlugState(false); res.send(‘Розетка выключена’); } catch (err) { res.status(500).send(‘Ошибка: ’ + err.message); } });

app.listen(3000, () => console.log(‘Сервер запущен: http://localhost:3000/on’));

Здесь необходимо указать внешний IP вашего роутера и уникальный 32-значный токен устройства. Получить токен можно, воспользовавшись инструментом «Xiaomi-cloud-tokens-extractor» с GitHub.

4. Для организации веб-интерфейса, доступного извне, сгенерируем SSH-ключи:

ssh-keygen -t ed25519

Затем используем сервис (например, srv.us) для создания публичного тоннеля к локальному серверу:

ssh srv.us -R 1:127.0.0.1:3000

В результате вы получите уникальный домен, например: https://esnivup33tkale57bmnamz6l7m.srv.us/. Теперь управление питанием осуществляется через простые GET-запросы:

https://esnivup33tkale57bmnamz6l7m.srv.us/off

https://esnivup33tkale57bmnamz6l7m.srv.us/on

Финальный этап — интеграция с часами Garmin. Для этого достаточно воспользоваться сторонним виджетом, поддерживающим создание кнопок с привязкой к URL, например, «MyHomeControl». Добавляем созданные ссылки в виджет, и управление домом оказывается прямо на запястье.

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

 

Источник

Читайте также