DSMR Reader in Docker.
text
* Docker >= 20.x
* Python 3.x
* Postgres >= 13.x, max 16.x
* MySQL ??.?? (untested by me)
properties
# Required (defaults are shown as value):
- DJANGO_TIME_ZONE=Europe/Amsterdam
- VIRTUAL_HOST=localhost
# It's possible to map a UID/GID with a user/group from your local system.
# This will not change the username, only match IDs to prevent issues with access rights!
- DUID=803
- DGID=803
properties
# Default inside the container nginx is running on port 80.
# In some cases (host network f.e.), some people requested to be able to change the default listen port.
# However, in most cases this setting isn't being used.
NGINX_LISTEN_PORT=80
properties
# Default nginx generated access logs.
# In some cases you want to disable this, because e.g., you use a reverse proxy which also generates access logs
DISABLE_NGINX_ACCESS_LOGS=true
properties
# Enables port 443 for nginx
# /etc/ssl/private/fullchain.pem and /etc/ssl/private/privkey.pem are required to be mounted!
ENABLE_NGINX_SSL=false
properties
# ENABLE HSTS on SSL: https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
ENABLE_NGINX_ENABLE_HSTS=false
properties
# Redirect HTTP traffic to HTTPS
ENABLE_NGINX_SSL_REDIRECT=false
properties
ENABLE_HTTP_AUTH=false
HTTP_AUTH_USERNAME=
HTTP_AUTH_PASSWORD=
properties
ENABLE_NGINX_SSL
NGINX_LISTEN_PORT
properties
# Webinterface user:
DSMRREADER_ADMIN_USER=admin
# Webinterface user password:
DSMRREADER_ADMIN_PASSWORD=admin
# Loglevel. Valid values are ERROR, WARNING, DEBUG:
DSMRREADER_LOGLEVEL=WARNING
# Secret key for encryption:
DJANGO_SECRET_KEY=dsmrreader
# Ignore database size notifications:
DSMRREADER_SUPPRESS_STORAGE_SIZE_WARNINGS=True
# Plugins (custom) setup:
DSMRREADER_PLUGINS=dsmr_plugins.modules.plugin_name1,dsmr_plugins.modules.plugin_name2
# Enable IFrame support (e.g., for use in HASS).
ENABLE_IFRAME=false
properties
# Optional. Vacuum clean Postgres on startup:
VACUUM_DB_ON_STARTUP=false
# Required. Defaults are set to:
DJANGO_DATABASE_ENGINE=django.db.backends.postgresql
DJANGO_DATABASE_NAME=dsmrreader
DJANGO_DATABASE_USER=dsmrreader
DJANGO_DATABASE_PASSWORD=dsmrreader
DJANGO_DATABASE_HOST=dsmrdb
DJANGO_DATABASE_PORT=5432
DJANGO_DATABASE_CONN_MAX_AGE=60
/dev/ttyUSB*
and head over to the DSMR Reader datalogger configuration in the admin panel and configure the setting so it matches your environment. More info: Issue #303DSMRREADER_OPERATION_MODE
- Run DSMR Reader in one of the following modes (default is standalone with the serial flavor):standalone
- Run all processes, including backend, GUI, and datalogger. There are two flavors:standalone - serial
- Use a serial connection for the datalogger.standalone - ipv4
- Use a network socket for the datalogger.api_server
- Run all processes, except the datalogger process. A remote datalogger is required to collect DSMR Reader telegrams.api_client
- Only start the datalogger client, which sends the P1 telegrams to the api_server
. It is required to set up DATALOGGER_API_*
environment variables.properties
DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD=serial
DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT=/dev/ttyUSB0
# DSMR meter version 4/5
DSMRREADER_REMOTE_DATALOGGER_SERIAL_BAUDRATE=115200
DSMRREADER_REMOTE_DATALOGGER_SERIAL_BYTESIZE=8
DSMRREADER_REMOTE_DATALOGGER_SERIAL_PARITY=N
properties
# DSMR meter version 2/3 settings
DSMRREADER_REMOTE_DATALOGGER_SERIAL_BAUDRATE=9600
DSMRREADER_REMOTE_DATALOGGER_SERIAL_BYTESIZE=7
DSMRREADER_REMOTE_DATALOGGER_SERIAL_PARITY=E
properties
DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD=ipv4
DSMRREADER_REMOTE_DATALOGGER_NETWORK_HOST=127.0.0.1 # default
DSMRREADER_REMOTE_DATALOGGER_NETWORK_PORT=2000 # default
properties
# Required. Instructs dsmr reader to start in api_client mode
DSMRREADER_OPERATION_MODE=api_client
# Required. Destination(s) of the DSMR Reader (Docker) host(s)
DSMRREADER_REMOTE_DATALOGGER_API_HOSTS=x
# Required. Add the API keys of the DSMR Reader (Docker) destination host(s)
DSMRREADER_REMOTE_DATALOGGER_API_KEYS=x
api_client
will push data to the api_server
. The only difference between standalone
and api_server
is that the datalogger process isn’t running.properties
# Required. Instructs dsmr reader to start in api_server mode, which means no datalogger process.
# All telegrams are coming in through the API
DSMRREADER_OPERATION_MODE=api_server
properties
DSMRREADER_REMOTE_DATALOGGER_TIMEOUT=x
DSMRREADER_REMOTE_DATALOGGER_SLEEP=x
DSMRREADER_REMOTE_DATALOGGER_DEBUG_LOGGING=false
docker-compose.yaml
file can be found here.docker-compose
file with parameters that suit your environment, then run:bash
docker-compose up -d
text
http://<hostname>:7777
text
http://<hostname>:7777/admin/dsmr_datalogger/dataloggersettings/
bash
docker run -d \
--name dsmr \
--restart always \
-p 7777:80 \
-p 7779:443 \
-e DJANGO_TIME_ZONE=Europe/Amsterdam \
-e DJANGO_DATABASE_HOST=x.x.x.x \
-e DJANGO_DATABASE_USER=dsmrreader \
-e DJANGO_DATABASE_PASSWORD=dsmrreader \
-e VIRTUAL_HOST=localhost \
--no-healthcheck \
--device /dev/ttyUSB0:/dev/ttyUSB0 \
xirixiz/dsmr-reader-docker
--no-healthcheck
argument should only be used when the containers function without presenting the DSMR Reader web interface, for example in datalogger sender mode. By default, this argument should not be used!FILE__
.yaml
services:
some_service:
image: some_image
environment:
FILE__SECRET: /run/secrets/a_secret_file
secrets:
- a_secret_file
secrets:
a_secret_file:
file: somedir/my_secret.txt
my_secret.txt
as /run/secrets/a_secret_file
. The secrets section under the service authorizes the service to use the a_secret_file
secret. The environment variable FILE__SECRET
tells the service what file to read to set/get the value of the environment variable SECRET
.yaml
secrets:
a_secret_file:
file: ./secrets/a_secret_file.txt # Define the path to your secret file
yaml
secrets:
a_secret_file:
external: true
docker-compose.yaml
file is in the folder /home/pi/dsmr
/home/pi/dsmr/plugins
/home/pi/dsmr/plugins
, create a file homewizard_p1.py
with the following contents (replace 1.2.3.4
with the Homewizard P1 meter IP address):python
import requests
from django.dispatch import receiver
from dsmr_backend.signals import backend_called
import dsmr_datalogger.services.datalogger
HOMEWIZARD_ENDPOINT = 'http://1.2.3.4:80/api/v1/telegram'
HOMEWIZARD_TIMEOUT = 5
@receiver(backend_called)
def handle_backend_called(**kwargs):
response = requests.get(HOMEWIZARD_ENDPOINT, timeout=HOMEWIZARD_TIMEOUT)
if response.status_code != 200:
print(' [!] HomeWizard plugin: v1 telegram endpoint failed (HTTP {}): {}'.format(response.status_code, response.text))
return
dsmr_datalogger.services.datalogger.telegram_to_reading(data=response.text)
/home/pi/dsmr
docker-compose.yaml
filevolumes:
section:yaml
- ./plugins/homewizard_p1.py:/app/dsmr_plugins/modules/homewizard_p1.py
environment:
section:yaml
- DSMRREADER_OPERATION_MODE=api_server
- DSMRREADER_PLUGINS=dsmr_plugins.modules.homewizard_p1
docker-compose.yaml
filebash
docker-compose down
bash
docker-compose up -d
bash
docker exec -ti dsmr bash -c '/app/cleandb.sh'
bash
docker exec -ti dsmr bash -c '/app/cleandb.sh -v'
yaml
volumes:
- ./modules/forward_telegram_to_api.py:/app/dsmr_plugins/modules/forward_telegram_to_api.py
environment:
- DSMRREADER_PLUGINS=dsmr_plugins.modules.forward_telegram_to_api
dsmrdb
in docker-compose
is configured to use a Docker volume. So when the application and Docker container have been removed, the Postgres data still persists.bash
docker-compose stop dsmr
docker exec -t dsmrdb pg_dumpall -c -U dsmrreader > dsmrreader.sql
docker-compose start dsmr
bash
docker exec -t dsmrdb pg_dumpall -c -U dsmrreader | /bin/gzip > dsmrreader.sql.gz
bash
docker-compose stop dsmr
docker exec -t dsmrdb dropdb dsmrreader -U dsmrreader
docker exec -t dsmrdb createdb -O dsmrreader dsmrreader -U dsmrreader
cat dsmrreader.sql | docker exec -i dsmrdb psql -U dsmrreader
docker-compose start dsmr
bash
docker run -it --rm -v dsmrdb:/volume -v /tmp:/backup alpine \
tar -cjf /backup/dsmrdb.tar.bz2 -C /volume ./
bash
docker run -it --rm -v dsmrdb:/volume -v /tmp:/backup alpine \
sh -c "rm -rf /volume/* /volume/..?* /volume/.[!.]* ; tar -C /volume/ -xjf /backup/dsmrdb.tar.bz2"
dsmr
container, not via the dsmrdb
container!bash
docker exec -ti dsmr bash -c 'PGPASSWORD=${DJANGO_DATABASE_PASSWORD} /usr/bin/pg_dump \
-h "${DJANGO_DATABASE_HOST}" \
-p "${DJANGO_DATABASE_PORT}" \
-d "${DJANGO_DATABASE_NAME}" \
-U "${DJANGO_DATABASE_USER}"'
text
- Stop the DSMR Reader container ONLY
- Backup the dsmrdb database (see "Backup and restore mechanism" in the README.md)
- Validate the dsmrdb backup!
- Consider "vacuuming" the database following "DSMR Reader - Database cleanup/vacuum" in the README.md.
- Stop and remove the dsmrdb container
- Rename the db folder that is mounted in the Docker container, containing the database data, to something else (.old, etc.)
- Create a new db folder with the original mount name
- Update `docker-compose` or your Docker run command with the new Postgres version
- Ensure the client package is compatible with the Postgres version you're using. Check the DSMR image for supported versions.
- Start `dsmrdb` (it's an empty but valid Postgres DB now).
- Restore the database backup created in step 2 (see "Backup and restore mechanism" in the README.md)
- Restart the `dsmrdb` container
- Start the `dsmr` container
-v
or --volume
flags), permissions issues can occur between the host OS and the container. To avoid this, specify a user ID DUID
and group ID DGID
from the local system in the Docker container. Ensure the owner of the directory has all permissions on the volume you’d like to mount into the Docker container.bash
id xirixiz
uid=1000(xirixiz) gid=1000(xirixiz) groups=1000(xirixiz) 1001(docker)
- Docker 19.03.9 or newer
- libseccomp 2.4.2 or newer
libseccomp
package hasn’t been updated for Debian stable yet. Therefore, this image won’t run on any Debian (or Raspbian) stable host.bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC 648ACFD622F3D138
echo 'deb http://httpredir.debian.org/debian buster-backports main contrib non-free' | sudo tee -a /etc/apt/sources.list.d/debian-backports.list
sudo apt update
sudo apt install libseccomp2 -t buster-backports
/etc/localtime:/etc/localtime
often results in incorrect timestamps in DSMR Reader (+/- 1 hour). Removing the mount usually solves the problem.lsusb -cui
sudo chmod 666 /dev/tty<your_usb_device>