Disclaimer: Настоятельно не рекомендую использовать код из статьи в продакшне
В это статье я…
- Использую старую вебку с raspberry pi
- Пишу тупой телеграм бот
- Скачиваю картинки от бота
- Склеиваю картинки в гифку при помощи ffmpeg
Идея
Итак. Растения странные. Они двигаются. Много двигаются. Но вы этого не видим. Я решил за ними пошпионить. Пришло время сдуть пыль со старой малинки и чертовски древней веб-камеры и написать немного кода для периодического сбора картинок.
Как мне показалось, на эту историю хорошо ложится создане телеграм бота - его можно быстро накодить, не нужно грепать логи на raspberry pi, чтобы разобраться, что там происходит.
Ну и, конечно же, результат надо как-то продемонстрировать, например, в формате гифки. С чем мне поможет ffmpeg.
Так. Здесь кто-то, наверняка, просто захочет посмотреть результат, без технических подробностей.
Как это устроено
CamBot
(за нейминг простите) написан на python с использованием библиотек python-telegram-bot
и APScheduler
. Каждые 30 минут бот делает фотку при помощи вебки и отрпавляет её списку телеграм айдишников. Также фотку можно запросить через /
-команду, но кому какое дело.
Note: из соображений “безопасности” (я же весь такое “безопасный”) у CamBot
есть whitelist (мне нужно извиниться за нейминг, да?) айдишников телеграма. Не пытайтесь стучаться в моего пода. Просто не пытайтесь. Пожалуйста?
Для тех никого, кто захочет повторить это добро, есть несколько (и порой реально грязных) хаков.
APScheduler на малинке
(И с питоном версией <= 3.5.3)
Используем версию APScheduler ==3.6.3
и, для большего удобства, своруем код CronScheduler
из последующих релизов:
from apscheduler.triggers.cron import CronTrigger as VendorCronTrigger
class CronTrigger(VendorCronTrigger):
@classmethod
def from_crontab(cls, expr, timezone=None):
values = expr.split()
if len(values) != 5:
raise ValueError('Wrong number of fields; got {}, expected 5'.format(len(values)))
return cls(minute=values[0], hour=values[1], day=values[2], month=values[3],
day_of_week=values[4], timezone=timezone)
# usage:
scheduler.add_job(
...
CronTrigger.from_crontab("*/30 * * * *"),
...
)
python-telegram-bot на малинке, отрпавка сообщений rpi
(И с питоном версией <= 3.5.3)
На моей малинке с питоном 3.5.3 отлично работает библиотека с версией ==13.1
.
Я потратил некоторое количество времени на то, чтобы реализовать чтение картинки с вебки и отсыл картинки в виде байтов, но, кажется, старая версия телеграм-библиотеки не поддерживает такой вариант (или у меня кривые руки).
Так что (я предупреждал!) я забил и решил не тратить лишнее время, сделав следующее:
Image.frombytes("RGB", res, img).save(file_name)
with open(file_name, 'rb') as f:
# for whatever reason, bot doesn't want to work with bytes or BytesIO
update.send_photo(chat_id=user_id, photo=f)
Переживаем рестарт малинки без докера
Docker был бы оверкилом для малинки, так что я решил задеплоить всё через systemd
. Я не эксперт, но оно работает. Так выглядит cam-py.sevice:
[Unit]
Description=Cam Bot
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/someusername/cam_bot.py
User=someusername
[Install]
WantedBy=multi-user.target
Устанавливаем:
cp cam-py.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable cam-py
systemctl start cam-py
ffmpeg - из картинок в гифку (на mac)
Одному туда идти опасно! Возьми этот… восхитительный однострочник:
ffmpeg -f image2 -framerate 25 -y -pattern_type glob -i "*.jpeg" calathea.gif