This is first in a series of community posts where we invite users to share how they are using resin. It could be anything from a useful snippet to a fully fledged product they are building as long as it benefits and inspires the community.
Kicking things off we have Dražen Lučanin from CloudFleet, a startup building an open source personal data center for plug-and-play encrypted email. They are currently running a crowdfunding campaign, so be sure to check them out if you're interested in having your own cloud that protects your privacy! In his post he details how to schedule chromecast control from a resin.io device. Enjoy!
We are all a bit lazy in this post-holiday period, so what better project to work on during these relaxed evenings at home, but on a home automation system. Having Docker containers on a physical device that has access to all other IoT devices in our network with exposed APIs like
TVs,
speakers or maybe even
droids and being able to iteratively upgrade these containers gives us ample opportunity to play.
I love the elegance of resin.io's Docker container deployment & upgrade method, so I use it a lot for
hobby projects & freelance work. In this tutorial, I'll show you how to create a Python
Flask app with periodic
Celery tasks for controlling your TV via the Chromecast API. All of the source code can be found in
this repo. So, go get a hot cup of tea, clone the repo and let's get started...
I listed instructions for how to get the development environment running locally directly on your machine or using
Docker-machine in the
README. Deployment is as easy as setting up a new application by following the Resin.io
getting started documentation, setting the remote for your app (something like
username@git.resin.io:username/homeautomator.git)
and doing a:
git push resin master
This should be enough to get an app running on your ARM device ready that plays a video at 9:00, stops it at 9:20 and exposes a basic web app for triggering play/pause events using web requests. These web requests can even be sent remotely from outside your LAN by exposing the
public url for your Resin device to the internet if you want to surprise the folks at home.
The core of the app lives in
src/main.py where we bootstrap the
Flask and
Celery settings. The interesting part is where we define the times when the tasks are automatically called:
from celery.schedules import crontab
app.config['CELERYBEAT_SCHEDULE'] = {
'play-every-morning': {
'task': 'tasks.play_task',
'schedule': crontab(hour=9, minute=0)
},
'pause-later': {
'task': 'tasks.pause_task',
'schedule': crontab(hour=9, minute=10)
}
}
Different rules for days of the week (work days), periods (from 9 am - 5 pm) or intervals (e.g. every 5 minutes) can be used to trigger job calls using the Celery
periodic task syntax. The tasks are defined as:
@celery.task(name='tasks.play_task')
def play_task():
print('play something')
return play()
@celery.task(name='tasks.pause_task')
def pause_task():
print('enough fun')
return pause()
In this case, they just reach out to the
tv.play and
tv.pause functions I defined to play or pause a video using the
pychromecast Chromecast API wrapper.
The same tasks are also exposed as Flask routes. The delay() method makes sure the task is executed in the Celery worker project asynchronously without blocking the return values.
@app.route('/play')
def get_play():
play_task.delay()
return 'Playing! <a href="/">back</a>'
In the end, both the web and the worker process are started from a Procfile using Honcho (a Python alternative to Ruby's foreman). Redis is used as the Celery message queue.
redis: redis-server
web: ./venv/bin/gunicorn main:app -b 0.0.0.0:5000 --chdir=src --log-level info --access-logfile=- --error-logfile=-
worker: ./venv/bin/celery worker -A main.celery --loglevel=info --workdir=src -B
And that's it. With basically two Python files and a couple of configuration files (for Docker, Honcho), we get an app that we can deploy to as many devices as we want, has an API that we can expose via the Internet and has a task queue supporting periodic tasks. The API functions I showed here are very basic.
I hope you'll let your imagination run wild on this one and pull together some neat APIs your devices at home expose to do cool stuff.
If you’re interested in sharing your resin experience with the rest of the community, say hi to craig - craig[at]resin.io