пятница, 8 февраля 2019 г.

Часы с memcache и свистелками


Привет, коллеги.
В общем, да, еще один маленький пост про python. Спойлер. Скоро будет много интересного про сети, обещаю. Сегодня про домашние часы... хочу просто поделиться.
Как, наверное, у многих у меня есть Raspberry Pi. Девайсом я всячески доволен и последние несколько лет "пишка" служила мне домашними часами с возможностью изменять температуру и влажность. До тех пор, пока на ней не сдохла флешка. Некоторое время у меня не доходили руки её восстановить, но очень хотелось. В итоге, я собрался с мыслями и решил все переделать с нуля добавив много всяких интересных функций.


Дано

  1. Raspberry Pi 1 Model B
  2. Два семисегментных дисплея
  3. Сенсор температуры
  4. Сенсор влажности
  5. Сенсор атмосферного давления

Цели

  1. Замер показателей и отображение информации с сенсоров
  2. Хранение данных для последующего анализа
  3. Возможность строить и просматривать графики через web
  4. Ах, да... часы

Мысли по реализации


Прошлая реализация была написана мной в далекие годы, когда программировал я ещё хуже, чем сейчас... Поэтому тогда это был один python скрипт, который содержал в себе весь функционал. Его правда было не так много. Стало быстро понятно, что такой подход в моем случае уже не подходит. 

Было решено разделить все "решение" на модули, каждый из которых делает только одну задачу.
  1. Опрос датчиков
  2. Отображение данных на дисплее
  3. Веб фронтенд
  4. Запись данных в базу для хранения

Я довольно быстро столкнулся с проблемой передачи данных между всеми процессами. Писать в локальный файл не хотелось (помним прошлую сдохшую флешку), импортировать модули и исполнять из одного скрипта еще худшая идея. Мало того, что это не масштабируется (масштабирование в часах...), так еще и "фризы" в работе появляются. Когда делаешь часы фризы очень заметны... )

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

Для графиков сразу же был выбран pygal за простоту и svg файл в "выхлопе".

В качестве фронтенда выступает Flask, очень классный и простой микрофреймфорк с достаточным количеством плюшек.

Хранить файлы нужно структурировано и красиво, а значит нужна SQL база. sqlite подошел как нельзя лучше.

В итоге получаем довольно тривиальный список:
  • flask
  • sqlite3
  • memcached

Для датчиков используем соответствующее драйвера:
  • Luma.LED_Matrix: драйвер дисплея MAX7219
  • Adafruit_DHT: AM2302 (для температуры и влажности)
  • Adafruit_BMP: BMP085 (для давления)

В итоге схема взаимодействия выглядит примерно так (кликабельно).


Хотя мне больше нравится такая версия. Как-то она больше отражает суть дела. Как видно Web модуль имеет возможность обращаться не только к базе, но и к памяти для отображения текущий показателей.


Реализация

Честно говоря, не уверен, что стоит расписывать конкретные функции. Во-первых, все можно посмотреть на GitHub. Во-вторых, кода все больше и описать его все сложнее и сложнее.

Поэтому просто опишу каждый модуль с пояснениями и особенностями.

Опрашивает датчики каждые 10 секунд и кладет данные в память. Здесь же ставим таймер на 300 секунд. Если процесс упадет и данные не обновятся, они будут удалены из памяти. Очень хотелось получать еще и температуру за окном, поэтому забираю прогноз отсюда http://wttr.in/?format=3.

Берет данные из памяти и отображает на дисплее. На гифке в начале поста виден пример. Правая часть всегда показывает часы, а левая меняется каждые 3 секунды.

В файле с модулями есть несколько функций
get_db_data - вынимает данные из базы за определенный период
graph_from_data - забирает данные и строит по ним график
db_to_graph - объединение прошлых двух функций, идем и в базу и строим график

В самом модуле описана простая "web-морда". Фреймфорк "слушает" два пути
/ - в случае GET генерируется старичка по jinja-шаблону на которой отображается форма с вводами дат для которых нужно построить график. Так же здесь отображаются текущие показатели выдернутые из памяти. В случае POST выполняется функция db_to_graph из прошлого пункта.
/today - на странице есть ссылка на график за сегодня. Скрипт вычисляет сегодняшнюю дату и строит график по данным из базы. Картинка кешится на 1 час.
Тут все совсем тривиально. Берем данные из памяти и пишем в базу. 

Все скрипты запускаются как systemd сервисы (файлики), кроме последнего, который стартует по крону.

Заключение

В общем-то все. Хотелось поделиться. Конечно, немного сложновато для часов, но, блин, OSPF, PIM и IPv6 тоже не особо нужно дома, но как же без них... Думаю прикупить датчик CO2 и наружный датчик температуры еще. Спасибо тем, кто дочитал до конца. Если есть чем прокомментировать, прошу. 

В качестве благодарности тем, кто все же смог доскролить до конца. Недавно со мной на связь вышли ребята из Cumulus Linux после того, как я скачал их виртуальный образ на потестить. Очень приятно пообщались. Горю энтузиазмом собрать лабу и хорошенько все погонять. Так что надеюсь что в скором будущем, порадую сетевую аудиторию интересными сетевыми постами.

Комментариев нет:

Отправить комментарий