An app to investigate your power consumption habits for BUZZN customers.
We recommend to setup a virtual environment for the projects' requirements.
cd PROJECT_ROOT
virtualenv -p `whereis python | cut -d ' ' -f3` .venv
source .venv/bin/activate
Install the requirements
pip install -r "requirements.txt"
pip install git+https://github.com/buzzn/discovergy.git
The following environment variables need to be set:
EMAIL
PASSWORD
BUZZN_SQLALCHEMY_DATABASE_URI # Indicates where the database is stored
BUZZN_SECRET_KEY # Security ussues like session data
BUZZN_PASSWORD_SALT # The salt for the users' passwords
BUZZN_SMTP_SERVER # SMTP server to use for sending mails
BUZZN_EMAIL # The email used to send mails from the backend
BUZZN_EMAIL_PASSWORD # Mailpassword of the mailaccount
BUZZN_BASE_URL # Baseurl of the backend i.e. address.
# Everyhing which needs to be in front of the
# api calls. Example mybuzzn-backend.buzzn.net
REDIS_HOST # Indicates where the redis database is stored
REDIS_PORT # The port to access the redis database, usually 6379
REDIS_DB # The redis database
Starting the app:
python app.py
Currently the webserver is running in development mode to restart after source
code changes. To change this behaviour, set the parameter debug
to False
in the
socketio.run()
call in app.py
.
Starting the worker to populate and periodically update the redis db with metering data from discovergy:
python util/task.py
Make sure to run it from the root directory, otherwise it cannot access the SQLite database properly.
project root
├── migrations # Database migration stuff
├── models # Data-Models
├── routes # Defines the http api
├── templates # HTML templates for specific app routes and testing purposes
├── tests # Unittests
├── util # Misc. db interaction, error handling, translations, mailing, websocket interaction, eventlet tasks
└── app.py # The app-main.
To access the database, the app reads the database's address from the
environment variable BUZZN_SQLALCHEMY_DATABASE_URI
.
The database structure is created using migrations. A migration is a
script which transforms the database between two consecutive versions
(i.e. git revisions) of the app. The model classes (usually stored in
/models
) model the entities used by the app and provide methods to
load and store them in from/in the database. To generate the
according tables given a new model use the flask migrate method:
flask db migrate
generates a new migration file in
/migrations/versions
to transform the databse structure to meet the models'
needs. To apply the migrations run flask db upgrade
.
The metering data periodially obtained from discovergy is stored in a Redis database,
so you need to have a Redis server running. On Linux, you can likely get it as a
package through your operating system's package manager (e.g. sudo pacman -S redis
).
You will not need to interact with Redis at all outside of just ensuring that
the service is running (e.g. sudo systemctl start redis.service; redis-cli ping
).
Set environment variables
source ./setup_testing_environment.sh
Run tests
python -m unittest
Install Coverage.py
pip install coverage
Calculate code coverage
coverage run -m unittest
All unittests are run and the code coverage is calculated.
Show code coverage report
coverage report -m
pylint app.py apitests models routes tests util
This chapter describes how to get a production instance running.
Clone the sources:
git clone https://github.com/buzzn/mybuzzn-backend.git
We recommend to setup a virtual environment for the projects' requirements.
cd PROJECT_ROOT
virtualenv -p `whereis python | cut -d ' ' -f3` .venv
source .venv/bin/activate
Install the python requirements
pip install -r "requirements.txt"
pip install git+https://github.com/buzzn/discovergy.git
Now create a systemd service mybuzzn-backend.service
, which starts the socketio server we use to run
the app in:
[Unit]
Description=Run mybuzzn-backend as an flask socketio instance.
[Service]
WorkingDirectory=/var/www/mybuzzn-backend.buzzn.net/mybuzznbackend
ExecStart=/var/www/mybuzzn-backend.buzzn.net/mybuzznbackend/env/bin/python mybuzzn-backend.py
After=network.target
User=mybuzznbackend
Group=mybuzznbackend
[Install]
WantedBy=multi-user.target
Either store it on /etc/systemd/system/ or create a link there pointing to it.
Start it with systemctl start mybuzzn-backend.service
.
Create an endpoint in your webserver, for example for nginx, create a new
server in /etc/nginx/sites-available/mybuzzn-backend.net
server {
listen 80;
server_name mybuzzn-backend.buzzn.net
error_log /var/www/mybuzzn-backend.buzzn.net/logs/error.log warn;
access_log /var/www/mybuzzn-backend.buzzn.net/logs/access.log combined;
# This is where our socketio server should respond
location / {
include proxy_params;
proxy_pass http://127.0.0.1:5000;
}
# This is where the websocket should respond
location /socket.io {
include proxy_params;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:5000/socket.io;
}
}
And create a link from /etc/nginx/sites-enable/mybuzzn-backend.net
pointing to
it. Then restart nginx systemctl restart nginx
Make sure a file setup_environment.py
exists in the project root which sets
environment variables like this:
import os
os.environ['BUZZN_SECRET_KEY'] = '...'
os.environ['DISCOVERGY_EMAIL'] = '...'
os.environ['DISCOVERGY_PASSWORD'] = '...'
os.environ['JWT_SECRET_KEY'] = '...'
os.environ['BUZZN_SQLALCHEMY_DATABASE_URI'] = '...'
os.environ['BUZZN_PASSWORD_SALT'] = '...'
os.environ['BUZZN_SMTP_SERVER'] = '...'
os.environ['BUZZN_SMTP_SERVER_PORT'] = '...'
os.environ['BUZZN_EMAIL'] = '...'
os.environ['BUZZN_EMAIL_PASSWORD'] = '...'
os.environ['BUZZN_BASE_URL'] = '...'
os.environ['BUZZN_MAILER'] = '...'
os.environ['REDIS_HOST'] = '...'
os.environ['REDIS_PORT'] = '...'
os.environ['REDIS_DB'] = '...'
Make you have a running instance of redis systemctl start redis.service
and
the start_redis_task.py
is running. If you are running systemd, this can be
done using a service:
[Unit]
Description=Fill redis db with current reading values
After=network.target redis.service
[Service]
Type=simple
Reastart=always
WorkingDirectory=/var/www/mybuzzn-backend.buzzn.net/mybuzznbackend
ExecStart=/var/www/mybuzzn-backend.buzzn.net/mybuzznbackend/env/bin/python start_redis_task.py
StandardOutput=journal
User=mybuzznbackend
Group=mybuzznbackend
[Install]
WantedBy=multi-user.target⏎
To upgrade to a new version, go to the project root and run git pull
.
If something has changed in the database models, run source ./venv/bin/activate
to
activate the python environment. Then run ./flask db upgrade
to
upgrade the database.
Finally restart the the web server and the redis task which fills the redis database with meter
readings:
systemctl restart apache2.service redis-task.service mybuzzn-backend.service
To ensure that the logger has the correct configuration, you must create a logger configuration file named logger_configuration.conf
and save it under util
. The configuration file should look like this:
[loggers]
keys=root
[handlers]
keys=consoleHandler,fileHandler
[formatters]
keys=consoleFormatter,fileFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler,fileHandler
[handler_consoleHandler]
class=StreamHandler
level=INFO
formatter=consoleFormatter
args=(sys.stdout,)
[handler_fileHandler]
class=FileHandler
level=ERROR
formatter=fileFormatter
args=('/var/www/mybuzzn-backend.buzzn.net/logs/logfile.log',)
[formatter_consoleFormatter]
format=%(name)s - %(levelname)s - %(message)s
[formatter_fileFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
You can change the path of the logfile in args=('/var/www/mybuzzn-backend.buzzn.net/logs/logfile.log',)
under [handler_fileHandler]
to what suits your production. When running it locally you can relace it with args=('logfile.log',)
.
We use swagger for our api documentation. The documentation is available at baseurl/api/doc
.
Term | Description |
---|---|
per capita consumption / pcc | Defined as consumption divided by inhabitants in kWh |