Блог

Node-red, кто дома?

Давайте набросам небольшое флоу для определения кто и когда пришел или ушел из дома. Принцип работы прост — опрашиваем по MAC-адресу личные телефоны хозяев и если устройство в сети, делаем вывод, что персона дома. Для меня вариант рабочий, т.к. дома всегда к Wi-Fi подключены. Нотификации по приходу и уходу будем слать в телеграм.

Весь флоу выглядит так: (цифры — это шаги ниже)

Приступим:1. Для начала установим node-red-contrib-arp. Эта нода предоставляет содержимое таблицы ARP. С помощью ее и будем узнавать о наличии устройства в сети. Так же нам понадобится node-red-contrib-telegrambot.2. Перетащим ноду на флоу и начнем ее настройку. Введем имя (в моем случае это iPhone 7 (Me)) и MAC-адрес устройства. 
3. Присоеденим ко входу ARP ноды inject. Настроим его так, чтобы инжектил данные каждую минуту.
4. К выходу ARP присоединяем switch с двумя выходами: 1. is empty и 2. otherwise5. Если из свитча вышли пустые данные, значит "нет дома". Ведем выход к функции код которой очень прост:msg.payload = "away";return msg;6. Иначе — дома.msg.payload = "home";return msg;7. Далее сделаем дополнительный фильтр, который будет пропускать сообщения дальше если получит подряд два с одинаковым значением. На случай если переподключение к вайфай будет и т.д.

var x = context.get('count'); var y = context.get('message'); //set defaults & return payload if (x === null || x === undefined || y === null || y === undefined) { x = 0; context.set('count', x); context.set('message', msg.payload); return msg; } //count only if payloads are the same or reset var current = msg.payload; var last = context.get('message'); if (x < 2) { if (current === last) { x++; context.set('count', x); } else { x = 0; context.set('message', msg.payload); } } if (x == 2) { current = msg.payload; last = context.get('message'); if (current === last) { x = 0; context.set('count', x); return msg; } }

8. Добавим ноду rbe. Она пропускает сообщение дальше только если его значение изменилось. Таким образом мы фильтруем ежеминутные пинги и в нотификации отдаем исключительно изиенение статуса.

9. На этом шаге мы формируем сообщение для телеграм бота. Не забудьте вписать свой chatID.

var message = msg.payload; msg.payload = {}; msg.payload.chatId = "4311871"; msg.payload.type = "message"; if (message === "home") { msg.payload.content = "Богдан пришел домой."; } else { msg.payload.content = "Богдан ушел из дома."; } return msg;

10. И завершающий этап — нотификация в телеграм. Берем ноду sender из набора Telegram. Создаем бота в телеграм если такого не имеем. Для этого пишем @BotFather и дальше по инструкции. В настройке ноды телеграма вводим имя вашего бота и токен, который выдал вам папа ботов. 

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

Можем выводить данные на график в дашборд и таблицу с последней активностю юзеров. Если интересно, напишу.

Код всего флоу ниже.

[{"id": "d015bb63.821888","type": "tab","label": "Who's home?","disabled": false,"info": ""},{"id": "b1a6c235.bf71e","type": "arp","z": "d015bb63.821888","name": "iPhone 7 (Me)","macs": "FF:FF:FF:FF:FF:FF","x": 320,"y": 260,"wires": [["4e77f910.568ce8"]]},{"id": "c79013fc.5bf5a","type": "inject","z": "d015bb63.821888","name": "1 min","topic": "","payload": "","payloadType": "date","repeat": "60","crontab": "","once": false,"onceDelay": 0.1,"x": 150,"y": 320,"wires": [["b1a6c235.bf71e"]]},{"id": "4e77f910.568ce8","type": "switch","z": "d015bb63.821888","name": "","property": "payload","propertyType": "msg","rules": [{"t": "empty"},{"t": "else"}],"checkall": "true","repair": false,"outputs": 2,"x": 490,"y": 220,"wires": [["5477df49.d5358"],["660d10a6.b46d"]]},{"id": "5477df49.d5358","type": "function","z": "d015bb63.821888","name": "not home?","func": "msg.payload = \"away\";\nreturn msg;","outputs": 1,"noerr": 0,"x": 650,"y": 180,"wires": [["34e3872a.5596a8"]]},{"id": "660d10a6.b46d","type": "function","z": "d015bb63.821888","name": "is home?","func": "msg.payload = \"home\";\nreturn msg;","outputs": 1,"noerr": 0,"x": 640,"y": 260,"wires": [["34e3872a.5596a8"]]},{"id": "9e5b70aa.20b56","type": "rbe","z": "d015bb63.821888","name": "","func": "rbe","gap": "","start": "","inout": "out","property": "payload","x": 1090,"y": 220,"wires": [["b46ca9c.5a68958"]]},{"id": "34e3872a.5596a8","type": "function","z": "d015bb63.821888","name": "Subsequen reading (every 2)","func": "var x = context.get('count');\nvar y = context.get('message');\n\n//set defaults & return payload\nif (x === null || x === undefined || y === null || y === undefined) {\nx = 0;\ncontext.set('count', x);\ncontext.set('message', msg.payload);\nreturn msg;\n}\n\n//count only if payloads are the same or reset\nvar current = msg.payload;\nvar last = context.get('message');\nif (x < 2) {\nif (current === last) {\nx++;\ncontext.set('count', x);\n} else {\nx = 0;\ncontext.set('message', msg.payload);\n}\n}\n\nif (x == 2) {\n current = msg.payload;\n last = context.get('message');\n if (current === last) {\nx = 0;\ncontext.set('count', x);\nreturn msg;\n}\n}","outputs": 1,"noerr": 0,"x": 880,"y": 220,"wires": [["9e5b70aa.20b56"]]},{"id": "b46ca9c.5a68958","type": "function","z": "d015bb63.821888","name": "Богдан","func": "var message = msg.payload;\nmsg.payload = {};\nmsg.payload.chatId = \"\";\nmsg.payload.type = \"message\";\n\nif (message === \"home\") {\nmsg.payload.content = \"Богдан пришел домой.\";\n} else {\nmsg.payload.content = \"Богдан ушел из дома.\";\n}\nreturn msg;\n","outputs": 1,"noerr": 0,"x": 1240,"y": 220,"wires": [["ec600a75.8012f8"]]},{"id": "ec600a75.8012f8","type": "telegram sender","z": "d015bb63.821888","name": "","bot": "7705c3d4.8f862c","x": 1430,"y": 220,"wires": [[]]},{"id": "7705c3d4.8f862c","type": "telegram bot","z": "","botname": "","usernames": "","chatids": "","baseapiurl": "","updatemode": "polling","pollinterval": "300","usesocks": false,"sockshost": "","socksport": "6667","socksusername": "anonymous","sockspassword": "","bothost": "","localbotport": "8443","publicbotport": "8443","privatekey": "","certificate": "","useselfsignedcertificate": false,"verboselogging": false}]


Очень своеобразное решение. Айфон имеет свойство засыпать и отключаться от домашнего вай-фая.  Готовьтесь получать сообщения в телеграм, о своём приходе/уходе среди ночи. Не думаю, что вашим домашним понравиться просыпаться. Я бы добавил дополнительный фильтр по геолокации. Чтобы один раз вернувшись домой, вы не «уходили» из дому, при отключении айфона от вай-фая, пока не покинете локацию дома

2 суток, пока полет нормальный. Я там фильтрую переключения состояний. Посмотрим, будут сбои, буду думать решение. Можно через iCloud еще. Но тогда андроиды в пролете. 

Не работает когда появляется снова мак адрес. Да и мне кажется можно упростить все, просто создать две глобальных переменных при запуске и

var peremennaya1=global.get('peremennaya1');
var peremennaya2=global.get('peremennaya2');
var msg2 = {};

if (msg.payload != 'home' && peremennaya1 == '0'){
global.set('peremennaya1','1');
global.set('peremennaya2','0');
msg2.payload = 'ishome';

}

else if (msg.payload == 'goaway' && peremennaya2 == '0'){
global.set('peremennaya1','0');
global.set('peremennaya2','1');
msg2.payload = 'away';
}

return msg2;

Да, с iPhone работает криво

Когда были только андроид телефоны - прекрасно работал

Теперь кол-во телефонов андроид телефонов в семье сократилось до одного ( меня😀)-работает четко только для моего телефона 

Зато прекрасно видно, что ребёнок телефон ночью берет )) - сразу появляется дома )

Кто -нибудь придумал, каким способом можно решить проблему с эппловским творением?


Да у меня вторая запись в блоге есть по этому поводу. 

Да, спасибо, видел...но у меня нет УД на устройствах Эппл - только home assistant - поэтому пока в поисках решения)

А зря, ХомКит очень удобно. Тогда есть приложение life360 и нода от нашего сообщества.

Сейчас пытаюсь на айпаде сделать, надеюсь сбои не часто будут



Попробовал сегодня это сделать, получаю такую ошибку (скрин) от node-red-contrib-arp, хотя ввожу точно правильный mac адрес, делаю это на Windows, т.к. я новичек, пришел сюда)) подскажите что можно сделать пж (Вашу вторую статью через homekit видел, классно, но у меня нет устройства для автоматизации (ни iPad, appletv, homepod) :) если есть вариант его тоже как-то эмулировать, будет классно)

https://sprut.ai/static/media/cache/00/57/44/5/4017038/59944/1000x_image.png?1591448869" alt="1000x_image.png?1591448869" />

Вернуться назад
Вернуться назад