Простой ответ: установить и регулярно соблюдать режим сна. Ответ простой, но, к сожалению, способ сложный. Казалось бы, просто поставь будильник. Но тут и кроется проблема, ради решения которой я и пошел на все эти костыли.
Я не могу встать по обычному будильнику. Я либо проснусь и сброшу его, либо не проснусь вовсе. Причем не важно, орущий телефон это или вибрирующие часы. Мне нужен будильник достаточно громкий и у которого нет таймера остановки или он сильно больше, чем пара минут стандартных будильников в телефонах. А так же, чтобы его нельзя было бы так просто сбросить или отложить.
Приложение
Первым, хоть как то рабочим решением, было приложение Alarmy (конечно же реклама). Оно позволяло телефону орать без остановки и что самое главное, выбрать способ отключения будильника. Из интересных вариантов: решение математических выражений и сканирование штрих кода. Выбрав последнее, по утрам мне было нужно взять iPad, почему не телефон скажу позже, дойти до ванной и отсканировать штрих с пачки спиртовых салфеток.
Так я жил несколько лет. Вариант рабочий, но не без минусов. Из самого банального, если выбросить упаковку со штрихом, но не переназначить на что-то другое, утром, штатно будильник не остановишь. Резервного сброса у приложения я не нашел. Если приложение зависнет, система выгрузит его из памяти или после перезагрузки устройства не запустив его повторно – будильник не сработает. В какой-то момент приложение на андроиде начало работать через раз. Возможно именно из-за выгрузки его из памяти. Если уйти, оставив планшет дома, но не отключив при этом будильник – он будет орать до тех пор, пока iPad не сядет. Возможно именно это ментально травмирует вашу кошку или другого зверя не умеющего пользоваться сенсорным экраном. А если взять с собой, но штрих останется дома… Думаю вы понимаете. В подобных случаях, для отключения звонка я выключал iPad целиком.
Еще один минус – постоянная работа в фоне. От этого аккумулятор садится так быстро, что ощущение будто будильник майнит крипту на твоем железе. Ну и конечно же, если устройство за ночь сядет и выключится, будильник не сработает. Для основного телефона, с уставшей батареей, данное приложение противопоказано. По этому я поставил его на iPad и заряжал его каждую ночь.
Умный дом
Решив избавиться от этого приложения, решено было реализовать похожую схему средствами умного дома.
У сервера УД нет акустики. К нему можно ее подключить, но он находится не в моей комнате, а громкость, напомню, важна. Другой вариант, у меня есть raspberry, и колонки основного PC с двумя аудио входами. С источником звука разобрались, далее остановка будильника. Берем zigbee кнопку и закидываем ее в ванную комнату. По ее нажатию останавливаем сигнал. Помимо этого, мой умный дом знает, находится ли кто-то дома, так что лишний раз будильник включать не будем. У меня даже есть информация спит ли сейчас кто-то. Так что можно сделать отключение будильника по покиданию кровати, и следить за тем, чтобы я туда не вернулся. Но этим пока что заморачиваться не будем.
MQTT спикер
В качестве связи с умным домом используем MQTT, скрипт напишем на языке Python, а запустим на одноплатнике Raspberry Pi.
Подготовка Raspberry Pi
Я обязываю вас использовать именно Raspberry Pi 4. Более того, данный одноплатный компьютер является оверкилом для данной задачи, и применен мной только из-за того, что у меня не было других подходящих устройств с аудио jack’ом.
Первым делом скачиваем прошивку. Для данной задачи будет достаточно лайт версии. Далее загружаем прошивку на карту памяти, для этого предлагаю воспользоваться BalenaEtcher.
Поскольку SSH по умолчанию не включен, необходимо один раз подключиться к малине с монитором и клавиатурой.
В новых сборках Raspberry Pi OS, при первом запуске запрашивают имя и пароль для нового пользователя. А ранее создавался стандартный пользователь с логином pi
и паролем raspberry
. В этом случае советую сменить пароль:
|
|
Залогинившись активируем SSH через raspi-config
. Пункт меню: Interfacing Options
→ SSH
.
|
|
Там же прописываем параметры WiFi, если не собираемся использовать подключение к сети по кабелю. System Options
→ Wireless LAN
. И укажем часовой пояс, это понадобиться для корректной работы cron. Localisation Options
→ Timezone
→ Europe
→ …
С настройкой raspi-config
закончили, закрываем его. Но перед отключением монитора, можно подсмотреть ip малины, чтобы потом не копаться в настойках роутера.
|
|
Если есть ip отключаем лишнюю периферию, далее работать будем через ssh. Учтите что raspi-config при настройке WiFi не выдает ошибку, если указан неверный пароль. Проверьте что вы подключены, прежде чем прятать малину в дальний угол.
Подключаемся по ssh (стандартный порт 22) через терминал, Putty или Termius. Интерфейс последнего мне нравится больше всего.
Для обновления системы
|
|
Подготовка среды
Для взаимодействия с протоколом MQTT будем использовать Python библиотеку Eclipse Paho.
Если нет pip
:
|
|
Установка библиотеки:
|
|
Для воспроизведения аудио воспользуемся консольным плеером mpg123:
|
|
Настроем громкость в системе:
|
|
Скрипт
Теперь напишем небольшую программу на Python, для воспроизведения звуков.
Для запуска mpg123 нам понадобится subprocess.Popen()
.
|
|
Из полезного, можно дождаться завершения программы mpg123, выполнив метод wait, у вернувшегося объекта Popen.
|
|
Однако в моем случае, наоборот нужно не ждать пока музыка доиграет, а слушать MQTT, ожидая команды сброса будильника. И если это произошло, завершить процесс немедленно.
|
|
В случае если будильник не сброшен, а воспроизведение уже закончилась, запускаем его повторно.
|
|
Теперь разберемся как подключиться к MQTT. Создаем объект класса Client
и установим логин, пароль, ip и порт от нашего MQTT сервера.
|
|
После чего указываем функции, которые выполнятся при успешном подключении и получении сообщений.
|
|
Сами функции выглядят следующем образом:
|
|
По факту функция on_message у меня используется только на момент отладки, за обработку сообщений отвечает receiving_info.
|
|
userdata
– переменная передающаяся во все функции обработки сообщений. Она задается методом user_data_set(userdata)
. Через нее я сохраняю информацию от умного дома в словарь.
|
|
После всей настройки нужно запустить MQTT клиент. Делаем это либо через loop_forever()
. Тогда python скрипт будет вечно крутится в фоне и слушать топики MQTT. И если вам нужны аудио уведомления от вашего умного дома, то это хороший вариант.
|
|
Либо через “разовый” метод loop()
. В случае будильника, проще не следить за временем и датой в самом скрипте, а воспользоваться средствами ОС (cron). От туда будем запускать скрипт, который будет работать до момента сброса будильника.
Для этого в конструкции while следим за наличием людей в квартире, подключились ли мы вообще к серверу и затем, не нажата ли кнопка сброса.
|
|
Весь код программы выложен на GitHub. Настройки паролей, юзеров, путей аудио файлов и т. п. вынесены в отдельный конфиг settings.np.json
, скопируйте публичный шаблон settings.json
и введите свои данные.
|
|
Cron
Сперва проверяем дату и время на текущей машине:
|
|
Если все ок, открываем для редактирования cron:
|
|
В данном случае я делаю это от пользователя pi, а не root (без sudo). У каждого пользователя свой crontab.
Добавляем правила:
|
|
Смысл тут такой:
- С понедельника по пятницу, в 04:30, запускать
mqtt_speaker.py
, находящийся в директории/home/pi/mqtt_speaker
, используяpython3
. Весь вывод программы записатьmqtt_speaker.log
, в той же директории. - С субботу и воскресенье, в 05:30, запускать
mqtt_speaker.py
, находящийся …
Для понимания как кодируется время в cron, советую воспользоваться калькулятором Crontab Guru или посмотреть примеры у них же.
На данный момент с отдноплатником все, переходим к настройке системы умного дома.
Node-RED
У меня вся логика УД прописана в Node-RED. Если у вас другая система, то можете работать в ней, главное чтобы в ней была поддержка mqtt и zigbee кнопки.
Задача слушать MQTT топик speaker/nodered
и при получении сообщения get_info
, отправить информацию в топик speaker/nodered/info
. А если кнопка нажата отправить сообщение в speaker/nodered/button
. Пропишем эту логику в ноде function
:
|
|
На вход этой ноды подключим две других – mqtt in
где подпишемся на speaker/nodered/#
и ноду deCONZ in
. Через deCONZ я подключаю все zigbee устройства к Node-RED.
На выход подключаем mqtt out
, в ней самой не будем указывать топик, так как они указываются скриптом в function
.