A Raspberry Pi thermostat control app
On the raspi you'll need libblas
before installing scipy:
sudo apt-get install libblas-dev libatlas-base-dev rpi.gpio
This project uses python 3. It's recommended that you use virtualenvwrapper. On raspbian, do:
sudo pip3 install virtualenv virtualenvwrapper
Add the following to ~/.bash_profile:
export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/bin/virtualenvwrapper.sh
Then:
mkvirtualenv therm
workon therm
Then install python requirements:
pip install -r requirements.txt -r requirements-device.txt
This will probably take a while (1-2hr on a RasPi zero); some of the requirements do not have wheels available for raspi, and therefore will be built from source.
To run the tests (requires python 3.6, specifically for assert_called_once
):
pip install -r requirements-test.txt
pytest
Therm uses a database to store temperature observations and thermostat state.
Any DB that SQLALchemy can talk to works. To configure your DB, set the
following environment variables (or handcode them in therm.settings
if you're
feeling bold):
export THERM_DB_URL=thermdb.cln2j9a8fio32eu.us-east-1.rds.amazonaws.com
export THERM_DB_UNAME=thermuser
export THERM_DB_PASS=correct-horse-battery-staple
If you want to send status messages to SQS using flask poll --to-sqs
, you'll
need to configure boto3.
The full thermostat consists of three processes: a polling loop, a web server, and a browser displaying the web UI on the raspi screen.
To start the polling loop:
FLASK_APP=therm flask poll
The polling loop reads the temp sensor and write samples to the DB. It also
looks at the latest State
in the DB, and if the state represents a thermostat
"hold" temperature, it will enable/disable the heat relay.
The polling loop also handles button presses (TODO: explain State)
To start the web server:
FLASK_APP=therm flask run
To start Chromium in 320x240 kiosk mode on display 0
:
./kiosk.sh
Running any of this in an environment without the raspberry pi library (e.g. your laptop)
will fallback to fake-rpi
, which provides fake sensor inputs and GPIO outputs to
the program, as well as dumping debug information to the console.
Jupyter is included in test requirements, see https://blog.sneawo.com/blog/2017/06/27/how-to-use-jupyter-notebooks-with-flask-app/ for how to import your flask app into a jupyter notebook (and for some reason use docker if you want.)
I currently have two devices: a raspi Zero without a screen running the relay and temp sensor, and a raspi B+ with a 2.2" screen running the web UI and buttons
To run the web UI on startup on the b+, add to /etc/xdg/lxsession/LXDE-pi/autostart
:
@/bin/bash /home/pi/devel/therm/run_kiosk.sh
To run relay and sensor on the zero, add to /etc/rc.local
:
su pi /home/pi/devel/therm/run_temp.sh
In this setup, there are no buttons (pi B TFT hat has buttons, but they run in poll loop, so not enabled in this mode.)
To run everything on a single device, add to /etc/xdg/lxsession/LXDE-pi/autostart
:
@/bin/bash /home/pi/devel/therm/run_all.sh
Install nginx and uwsgi globally (make sure you're using python 3 install!):
sudo pip3 install uwsgi
sudo apt-get install nginx
Add your site config in /etc/nginx/sites-available/therm.conf
:
server {
listen 80;
server_name pi.local;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi/therm.sock;
}
}
Create a systemd service for uwsgi in /etc/systemd/system/uwsgi.service
[Unit]
Description=uWSGI instance to serve therm
[Service]
ExecStartPre=-/bin/bash -c 'mkdir -p /tmp/uwsgi; chown www-data /tmp/uwsgi'
ExecStart=/bin/bash -c 'cd /home/pi/devel/therm; source /home/pi/.virtualenvs/therm/bin/activate; uwsgi --ini uwsgi.ini --logto /var/log/therm.log'
[Install]
WantedBy=multi-user.target
Test it:
sudo systemctl start uwsgi
Launch nginx and make sure everything's working:
sudo service nginx start
If everything works, you can have nginx and uwsgi launch on boot:
$ sudo systemctl enable nginx
$ sudo systemctl enable uwsgi