СОДЕРЖАНИЕ

Перехват данных от монитора качества воздуха Xiaomi/Qingping ClearGrass CGS1

25.02.2022

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

Купил я когда-то это прекрасное устройство. Как и многие другие устройства, идущие под маркой Xiaomi, это устройство само по себе работало, но вот отдавать мне данные никак не хотело.

Без этой функции оно мне было не очень нужно, поэтому было несколько итераций его обмана.

1. Перехват его трафика на роутере. Вариант был в целом рабочий. ClearGrass слал все свои данные по MQTT-протоколу на адрес 39.106.170.175:1883. Какой-то простенький скрипт на perl перехватывал эти данные через libpcap и отдавал их дальше. Было немного неудобно, что при замене роутера было нужно обязательно помнить про это. Ну плюс нагрузка какая-никакая на систему. Но проработал этот вариант больше года.

2. Перехват DNS-запросов. Тоже живая идея. Все свои данные ClearGrass пытался отправить на адрес mqtt.cleargrass.com:1883. Подмена ip-адреса на ближайшем DNS-сервере на адрес местного MQTT-сервера решила проблему. Авторизации и прочего там не было. Ну а дальше дело техники. Так тоже проработало больше года.

3. Перехват на уровне nftables (iptables). После очередного изменения топологии сети стало немного неудобно подменять DNS, но простейшее правило на wifi-маршрутизаторе по замене DST-адреса с 39.106.170.175 на нужный мне – опять решила проблему. Так оно проработало ещё около полугода.

И вот где-то на этом этапе – ClearGrass начал зависать раз в месяц. Какое-то время я терпел, но потом стало совсем лень ходить его перезагружать. И я решил попробовать обновить на нём прошивку. И это был билет в один конец. Мало того, что из ClearGrass он стал Qingping, так они, конечно же, перелопатили всё что касалось его работы с центральным сервером.

От MQTT-протокола они отказались. Осталось общение по https (что внутри – само собой неизвестно) и какое-то сервисное соединение по TCP. Что за протокол был в сервисном соединении – понять не удалось. Да, оттуда можно было достать plain-данные путём перехвата трафика, но этого делать уже совсем не хотелось.

В надежде, что что-то поменялось за последние несколько лет в мире Xiaomi – я полез искать, нельзя ли всё-таки как-то попросить это устройство отдать мне те данные, которые мне нужны.

Никакой внятной документации найти не удалось. Но путём склеивания заплаток – что-то начало получаться.

Для начала – все проекты требовали как-то получить token устройства. Это я помнил ещё с давних времён, когда я пытался увлекаться устройствам Xiaomi. Вот здесь пишут как получить токен.

https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor

Всё вроде предельно просто и понятно. Но не заработало. После запуска - эта утилита начала жаловаться что, у меня двухфакторная авторизация и что мне нужно открыть какую-то ссылку, а потом перезапустить экстрактор. Попытки проделать эту операцию пять раз подряд - не привели ни к чему. Показалось, что это тупик. Потом мне подумалось, что возможно это было из-за того, что экстрактор я запускал на одном сервере, а авторизационную ссылку открывал на другом…

Попробовал ещё поискать. Оказалось – есть версия по Windows.

https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor/releases/latest/download/token_extractor.exe

Тут дело пошло гораздо более весело. И токен я получил, можно сказать, что вообще сразу. Часть задачи решилась.

Теперь нужно чем-то обратиться к устройству за данными. Поиски навели на проект miiocli.

https://github.com/rytilahti/python-miio

Поставить его было несложно. И вроде как он даже заработал по самой простой инструкции! Но потом… Потом стало как-то непонятно. Он то работал, то не работал. И работал всё хуже и хуже, пока не дошло до состояния того, что данные от устройства он получать перестал окончательно. И было совсем непонятно почему. Попытался его поотлаживать в debug-режиме, но не нашёл ничего примечательного. Анализ трафика тоже помог мало.

Стал дальше искать. Может ещё клиенты есть? Нашёл php-miio.

https://github.com/skysilver-lab/php-miio

А вот эта штука – заработала просто сразу и без проблем! Ну как – заработала… Стала выдавать хоть что-то. Но оказалось, что про сам ClearGrass она ничего не знает и общаться нужно своими командами. А эти команды нигде не описаны! И тут мне вспомнилось, что при отладке python-miio я видел что-то похожее не нужную команду. Полез туда – и точно!

Команду я скопировал, немного видоизменил под себя, даже добавил что-то. Но вот при выполнении этой команды – опять началась какая-тол неразбериха – то устройство отвечает на запрос, то не отвечает. Ни на что не похоже.

И тут мне бросилось в глаза, что в запросе к устройству есть параметр "id". Так вот, если отправить несколько последовательных запросов с одинаковым id, то ответы могут быть, а могут и не прийти. Но если id менять, то ответы приходят реально каждый раз! И тут стало понятно, что именно мешало python-miio. Но это знание мне всё равно никак не помогло, поскольку никаких параметров на смену id в запросе python-miio не имел.

Но php-miio вполне живенько справился с поставленной задачей:

host# php miio-cli.php --ip 172.000.000.135 --token 644372754d0000841476a566d43734f --sendcmd '{"id":1659280190,"method":"get_prop","params":["temperature", "co2", "pm25", "pm10", "tvoc", "humidity"]}'

Устройство 172.000.000.135 доступно и ответило:
{"result":{"co2":655,"humidity":44.4,"pm25":1.8,"temperature":22.6,"tvoc":2187},"id":1659280190}
host#