Парсинг погоды для Home Assistant с помощью Node-RED

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Глядя на красивый и удобный вывод информации о погоде у Яндекса и у MSN

выделил нужную мне информацию
выделил нужную мне информацию
выделил нужную мне информацию
выделил нужную мне информацию

Захотелось тоже самое сделать у себя, чтобы на планшете у входной двери отображалась такая информация (кроме непосредственно управлением умным домом).

Не уверен есть ли необходимая информация в API (думаю, что свободного вообще нет), решил автоматизировать получение этой полезной информации через плагин к HA - Node-RED. Предполагается, что он у вас уже установлен.

Весь код на NR будет в самом конце статьи.

В итоге "графически" алгоритмы получения информации с сайта Yandex выглядит так:

С сайта MSN так:

Первым делом нам нужно в коде Яндекс.Погоды найти селектор, в который выводится нужная нам информация:

Селектором оказывается div c классом title-icon__text

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

Следом кидаем узел отвечающий за обработку данных полученных с предыдущего узла, в поле Selector указываем найденный ранее селектор. В Output указываем что нам нужен только чистый текст.

В итоге по всем найденным селекторам будет сформирован поток данных, который нужно объединить в одну строку для вывода в будущий виртуальный датчик HA, делаем это с помощью узла Join

И последний важный узел это виртуальный датчик Home Assistant, куда будет отправлена сформированная строка ранее.

Тут важный параметр Entity config, нужно выбрать Add new ha-entity, после деплоя кода в области видимости сенсоров HA появится новый с транслитерированным названием.

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

В итоге в панели управления умным домом эта информация будет выглядеть примерно так:

Для получения информации с сайта MSN все очень похоже за исключением того что "удобного селектора" я не нашел; само название параметра и его значение выбираются двумя разными селекторами:

Это div.lifeIndexBarTitle-E1_1 и div.lifeIndexBarSummary-E1_1 мне пришлось их объединять в один поток с помощью стороннего узла Merge, он ставится в пару кликов в NR: Menu, Manage palette, Install.

Так как два разных потока формируют результат асинхронно, нужен этот узел, который после получения первого сигнала ждет (по умолчанию) две секунды для получения всех остальных, а потом объединенный поток отправляет дальше.

А дальше для нашего нового виртуального сенсора, нужно из этого большого объекта (внутри два потока) получить строку для вывода, для этого нам нужен узел Function, который может выполнять любой код на JS:

var array1 = msg.payload[0].payload;
var array2 = msg.payload[1].payload;

var newArray = "";
    for (var i = 0; i < array1.length && i < array2.length; i++) {
        newArray += array1[i] + ": " + array2[i]+"\r\n";
    }
msg.payload = newArray;
return msg;

Пример вывода нового сенсора от MSN:

И результат полностью:

Коды ниже можно импортировать непосредственно в Node-RED скопировав в буфер и вставив.

Код для Яндекс
[{"id":"ad1d92815f2810e3","type":"tab","label":"Осадки от Yandex","disabled":false,"info":"","env":[]},{"id":"91b656e34bb36636","type":"inject","z":"ad1d92815f2810e3","name":"каждый 15 минут","props":[{"p":"payload"}],"repeat":"900","crontab":"","once":true,"onceDelay":"5","topic":"","payload":"","payloadType":"date","x":130,"y":60,"wires":[["c2a6fc2cee844617","d147070d4e892acb"]]},{"id":"c2a6fc2cee844617","type":"delay","z":"ad1d92815f2810e3","name":"Случайная задержка","pauseType":"random","timeout":"30","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"10","randomLast":"50","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":380,"y":60,"wires":[["33244b375f9536ba"]]},{"id":"d147070d4e892acb","type":"http request","z":"ad1d92815f2810e3","name":"Запрос осадков сейчас","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://yandex.ru/pogoda/maps/nowcast?lat={{states.zone.home.attributes.latitude}}&lon={{states.zone.home.attributes.longitude}}","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[{"keyType":"other","keyValue":"user-agent","valueType":"other","valueValue":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"}],"x":170,"y":160,"wires":[["b83ef7431f50c2b9","088f18771b04025a"]]},{"id":"b83ef7431f50c2b9","type":"html","z":"ad1d92815f2810e3","name":"Выбираем строку с прогнозом","property":"payload","outproperty":"payload","tag":"div.weather-maps-fact__nowcast-alert","ret":"text","as":"single","x":430,"y":160,"wires":[["d5f87c9849faccbe"]]},{"id":"33244b375f9536ba","type":"http request","z":"ad1d92815f2810e3","name":"Запрос осадков на неделю","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://yandex.ru/pogoda/?lat={{states.zone.home.attributes.latitude}}&lon={{states.zone.home.attributes.longitude}}","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":160,"y":260,"wires":[["725a40f983bcb9ed","088f18771b04025a"]]},{"id":"725a40f983bcb9ed","type":"html","z":"ad1d92815f2810e3","name":"Выбираем строку с прогнозом","property":"payload","outproperty":"payload","tag":"div.title-icon__text","ret":"text","as":"single","x":430,"y":260,"wires":[["faec5435d1fd53df"]]},{"id":"088f18771b04025a","type":"html","z":"ad1d92815f2810e3","name":"Попали на SmartCaptcha?","property":"payload","outproperty":"payload","tag":"span.Text_typography_headline-s","ret":"text","as":"single","x":420,"y":360,"wires":[["079500ac2cd1bdb3"]]},{"id":"079500ac2cd1bdb3","type":"debug","z":"ad1d92815f2810e3","name":"SmartCaptcha","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":660,"y":360,"wires":[]},{"id":"0760bb2f15fda35b","type":"ha-sensor","z":"ad1d92815f2810e3","name":"Осадки сейчас","entityConfig":"e90834b91730474e","version":0,"state":"payload","stateType":"msg","attributes":[{"property":"update","value":"updated","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":940,"y":160,"wires":[[]]},{"id":"1b430bc67266fc46","type":"ha-sensor","z":"ad1d92815f2810e3","name":"Осадки на неделю","entityConfig":"079e8fb6221f5071","version":0,"state":"payload","stateType":"msg","attributes":[{"property":"update","value":"updated","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":950,"y":260,"wires":[[]]},{"id":"c8f660c6f44cbf00","type":"join","z":"ad1d92815f2810e3","name":"Объединение в строку","mode":"custom","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"1","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":710,"y":260,"wires":[["1b430bc67266fc46"]]},{"id":"d5f87c9849faccbe","type":"join","z":"ad1d92815f2810e3","name":"Объединение в строку","mode":"custom","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"1","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":710,"y":160,"wires":[["0760bb2f15fda35b"]]},{"id":"faec5435d1fd53df","type":"sort","z":"ad1d92815f2810e3","name":"","order":"ascending","as_num":false,"target":"payload","targetType":"msg","msgKey":"payload","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":570,"y":300,"wires":[["c8f660c6f44cbf00"]]},{"id":"e90834b91730474e","type":"ha-entity-config","server":"31f480d3.0e3b28","deviceConfig":"","name":"sensor config for Осадки сейчас","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Осадки сейчас"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:weather-pouring"},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"079e8fb6221f5071","type":"ha-entity-config","server":"31f480d3.0e3b28","deviceConfig":"","name":"sensor config for Осадки на неделю","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Осадки на неделю"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:weather-pouring"},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"31f480d3.0e3b28","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

Код для MSN
[{"id":"19cbf5e1e88f2024","type":"tab","label":"Зонт от MSN","disabled":false,"info":"","env":[]},{"id":"ab5ae602979d5186","type":"inject","z":"19cbf5e1e88f2024","name":"каждый 15 минут","props":[{"p":"payload"}],"repeat":"900","crontab":"","once":true,"onceDelay":"5","topic":"","payload":"","payloadType":"date","x":130,"y":80,"wires":[["7fb408618d93a612"]]},{"id":"7fb408618d93a612","type":"delay","z":"19cbf5e1e88f2024","name":"Случайная задержка","pauseType":"random","timeout":"30","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":360,"y":80,"wires":[["de2ef8c68437fb20"]]},{"id":"de2ef8c68437fb20","type":"http request","z":"19cbf5e1e88f2024","name":"Запрос осадков сейчас","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://www.msn.com/ru-ru/weather/life/in-Москва,Россия","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[{"keyType":"other","keyValue":"user-agent","valueType":"other","valueValue":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"}],"x":150,"y":180,"wires":[["cd3d04497b69e8b9","dafc373cb1e4ef54"]]},{"id":"cd3d04497b69e8b9","type":"html","z":"19cbf5e1e88f2024","name":"Выбираем характеристики","property":"payload","outproperty":"payload","tag":"div.lifeIndexBarTitle-E1_1","ret":"text","as":"single","x":460,"y":140,"wires":[["e2748d35141c91e0","30fda68a6944851f"]]},{"id":"dafc373cb1e4ef54","type":"html","z":"19cbf5e1e88f2024","name":"Выбираем значения характеристик","property":"payload","outproperty":"payload","tag":"div.lifeIndexBarSummary-E1_1","ret":"text","as":"single","x":490,"y":200,"wires":[["e2748d35141c91e0","30fda68a6944851f"]]},{"id":"30fda68a6944851f","type":"debug","z":"19cbf5e1e88f2024","name":"debug 1","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":950,"y":300,"wires":[]},{"id":"e2748d35141c91e0","type":"merge","z":"19cbf5e1e88f2024","name":"","timeout":"2","x":730,"y":160,"wires":[["d03b49b3583b8fea"]]},{"id":"d03b49b3583b8fea","type":"function","z":"19cbf5e1e88f2024","name":"Объединение значений","func":"var array1 = msg.payload[0].payload;\nvar array2 = msg.payload[1].payload;\n\nvar newArray = \"\";\n    for (var i = 0; i < array1.length && i < array2.length; i++) {\n        newArray += array1[i] + \": \" + array2[i]+\"\\r\\n\";\n    }\nmsg.payload = newArray;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":930,"y":160,"wires":[["30fda68a6944851f","eca2fbc2f5eb3a41"]]},{"id":"eca2fbc2f5eb3a41","type":"ha-sensor","z":"19cbf5e1e88f2024","name":"Одежда по погоде","entityConfig":"628079d19b822784","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1050,"y":60,"wires":[[]]},{"id":"628079d19b822784","type":"ha-entity-config","server":"31f480d3.0e3b28","deviceConfig":"","name":"lifeBar","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Одежда по погоде"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"entity_picture","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false},{"id":"31f480d3.0e3b28","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

Источник: https://habr.com/ru/post/724154/


Интересные статьи

Интересные статьи

Контекст: я занимаюсь администрированием небольшого Discord-сервера по разработке. И недавно один из пользователей сообщил, что кто-то пытался заставить его загрузить Exe-файл. Первое, что стоило...
Как безопасно и без лишнего труда открыть доступ к этим учетным данным и использовать их при разработке на Node.js? Ответу на этот вопрос посвящена эта статья.Содержание:Подключение к экземпляру Kafka...
Привет! Я Владимир Пасюга, QA Engineer в NIX. Общий опыт в IT у меня составляет 7 лет, из них 2,5 года я был мануальным тестировщиком в биомедицинском проекте, который включал и UI, и API-часть. Сейча...
Внезапно прогремевший около 13.8 миллиардов лет назад Большой Взрыв положил начало истории. Через несколько миллиардов лет после этого из облаков слегка остывшего газа сф...
При администрировании сервера очень важно понимать, как работают выполняемые процессы в подробностях — от высокой нагрузки до замедленного времени отклика. В случае, когд...