Disclaimer: I stricltly encourage you not to use code from this article in production
In this article I’m…
- Using an old webcam with a raspberry pi
- Writing stupid telegram bot
- Downloading images from bot
- Stitching images into a gif with ffmpeg
Idea
So. Plants are weird. They move, like, A LOT, but you never see plants moving. So I’ve decided to spy on them. It was time to shake off the dust from my raspberry pi and the damn old webcam and write some code to ocassionaly take pictures.
I thought telegram bot would be a cool thing to do - it’s fast to code and there is no need to frequently access raspberry pi (which is some kind of pain in … ssh) to figure out what’s up.
Of course I had to visualize the result as a gif or something - ffmpeg was my hero of choice for such quest (ugh, such a show-off).
You probably would like to skip technical details and skip to result.
How to do this
CamBot
(oh god sorry for this naming) is written in python with use of python-telegram-bot
and APScheduler
. Every 30 minutes it takes a picture with a webcam and sends to a list of telegram ids. It’s possible to request an image time you want with a /
-command but who cares.
Note: for “security” (I’m a “secure” guy you know) reasons CamBot
has a whitelist (should I be sorry for this naming?) of telegram ids. Do not try to find my bot. Just don’t. Please?
For those zero enthusiasts who would do the same there are some (dirty and in some cases I really mean it) hacks.
APScheduler on rpi
(And/or python <= 3.5.3)
Use version ==3.6.3
and for more convinience update CronScheduler
with code from future releases:
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 on rpi and sending images
(And/or python <= 3.5.3)
My rpi on python 3.5.3 is ok ==13.1
.
I wasted some time on trying to send images - read image from webcam to memory and send bytes but it seems like an old version of python-telegram-bot
is somehow broken (or my arms are) and is not able to do that.
So (I had warned you in disclaimer!) I stopped wasting my time on this side-project and did that:
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)
Survive reboot of rpi without docker
Docker would be too heavy for my rpi so I considered using systemd
. I’m no expert there but it works just fine for me. Here’s my 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
To install:
cp cam-py.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable cam-py
systemctl start cam-py
ffmpeg images to gif (on mac)
It’s dangerous to go alone. Take this… awesome one-liner:
ffmpeg -f image2 -framerate 25 -y -pattern_type glob -i "*.jpeg" calathea.gif