Активность
Добавил комментарий к статье Прошивка датчика Xiaomi Mijia Bluetooth Hygrothermograph 2 LYWSD03MMC и подключение к Home Assistant
«<p>Добрый вечер.</p>
<p>Зверушку перешил, настроил все ОК. Дальше начались танцев с бубном. Сделал все по инструкции, но интеграцию использовал стандартную. НА все нашел, но вот данных ожидаемо не показал. Версия 2021.1.5 . Решил поставить как было указанно выше - кастомную интеграцию, но она не завелать, по не известным для меня причинам. Возможно питон 3.7 не понравился, но это не точно.</p>
<p>Вообщем как обычно. Продолжил копать, а именно запустил NODE-RED поставил node-red-contrib-ble-scan и стал смотреть, что творится вокруг. Нашлась зверушка и куча фитнес браслетов MI BAND 3, последние вообще жутко спамили, странно как они так долго живут (а может как раз не долго , но у меня AMAZFIT BIP). Вообщем я отвлекся от темы, продолжу. Смотрю что на выходе и вижу JSON примерно такого вида:<code></code><code></code></p>
<p><code>"payload": {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "id": "a4c138c9d0d7",</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "address": "a4:c1:38:c9:d0:d7",</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "addressType": "public",</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "connectable": true,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "advertisement": {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "localName": "ATC_C9D0D7",</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "serviceData": [</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "uuid": "fe95",</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "data": [</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 80,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 48,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 91,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 5,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 54,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 215,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 208,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 201,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 56,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 193,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 164,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 10,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 16,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 1,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 100,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 0,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 0,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 0</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> ]</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> }</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> ],</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "serviceUuids": [],</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "solicitationServiceUuids": [],</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "serviceSolicitationUuids": []</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> },</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "rssi": -60,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "mtu": null,</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "state": "disconnected"</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> },</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> "_msgid": "4f054cc2216c1b62"</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code></code> </p>
<p> В котором наблюдаю массив: "serviceData". Начинаю радоваться, особенно вспоминая выдержку</p>
<p> из документации к прошивке, где сказано следующее:</p>
<p> <code></code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> The custom firmware sends every minute an update of advertising data on the UUID 0x181A </code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> with the Tempereature, Humidity and Battery data.</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> The format of the advertising data is as follow:</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 5-10 MAC in correct order</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 11-12 Temperature in int16</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 13 Humidity in percent</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 14 Battery in percent</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 15-16 Battery in mV uint16_t</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 17 frame packet counter</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Example: 0x0e, 0x16, 0x1a, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, </code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> 0xbb, 0xcc, 0xdd, 0xdd, 0x00</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> </code> </p>
<p> Ну думаю, сейчас все прочитаю и дело в шляпе... но как всегда в программировании все оказалось ни фига не просто. Данные в массиве совсем не похожи на то, что нужно. Посмотрел на них со всех сторон и опечалился. Стал гуглить, что это такое "fe95" и в гитхабе нашел фрагмент функции, которая дешифрует данные:</p>
<p> <code></code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> var r = {};</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> d = msg.payload.advertisement.serviceData[0].data</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> if (d[11] == 0x04) {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> var temp = d[15] << 8 | d[14];</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> if (temp & 0x8000) temp -= 0x10000;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.temp = temp / 10;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> } else if (d[11] == 0x06) {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.humidity = (d[15] << 8 | d[14]) / 10;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> } else if (d[11] == 0x0a) {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.battery = d[14];</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> } else if (d[11] == 0x0d) {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> var temp = d[15] << 8 | d[14];</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> if (temp & 0x8000) temp -= 0x10000;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.temp = temp / 10;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.humidity = (d[17] << 8 | d[16]) / 10;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> }</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> </code></p>
<p> То, что я увидел - мне понравилось. Вставил в node-red запустил и ... увидел в принципе, что надо.</p>
<p> <code></code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> if (msg.payload.address == 'a4:c1:38:c9:d0:d7') {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> /*</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 5-10 MAC in correct order</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 11-12 Temperature in int16</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 13 Humidity in percent</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 14 Battery in percent</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 15-16 Battery in mV uint16_t</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> Byte 17 frame packet counter</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> */</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> var r = {};</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> d = msg.payload.advertisement.serviceData[0].data</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> if (d[11] == 0x04) {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> var temp = d[15] << 8 | d[14];</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> if (temp & 0x8000) temp -= 0x10000;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.temp = temp / 10;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> } else if (d[11] == 0x06) {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.humidity = (d[15] << 8 | d[14]) / 10;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> } else if (d[11] == 0x0a) {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.battery = d[14];</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> } else if (d[11] == 0x0d) {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> var temp = d[15] << 8 | d[14];</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> if (temp & 0x8000) temp -= 0x10000;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.temp = temp / 10;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> r.humidity = (d[17] << 8 | d[16]) / 10;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> }</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> /*</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> node.warn(d[14]);</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> node.warn('temp');</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> node.warn(r.temp);</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> node.warn('humidity');</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> node.warn(r.humidity);</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> node.warn('battery');</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> node.warn(r.battery);</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> return msg;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> */</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> if(typeof r.temp != 'undefined') {</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> msg1 = {};</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> msg1.temp = r.temp;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> msg1.humidity = r.humidity;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> msg1.battery = d[13];</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> msg1.p = msg.payload;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> return msg1;</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> }</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> }</code></p>
<p><code></code></p><code>
</code><p><code></code></p>
<p><code> </code></p>
<p>результат</p>
<p>"temp": 24.3,
"humidity": 39,
"battery": 4, p...</p>
<p>в переменную P записана оригинальная строка для дальнейшего анализа.<br /> У меня стоит период опроса 10 минут, что работает, но не верно показывает заряд батареи. С этим буду разбираться позже. Еще заметил,, что после 10 минутного сна зверушка радостно спамит сообщениями почти минуту, если не больше. В чем причина - пока не понял.</p>»
Регистрация
Присоединился к порталу