P1Monitor Docker Image improvements

Based on some user feedback (I’m proud of my first Github issue in a way haha) I received here I decided to figure out how this image building thing in Docker works a bit more in detail. It’s not that hard and quite fun.

Basically the source for building the Docker image you’ll find in my repo. In there is the Dockerfile which “builds” the image, which I build cross platform with Docker Buildx. My build command line is

docker buildx build -t rvleij/p1monitor:testing --platform linux/amd64,linux/arm64,linux/arm/v7 --push .

which builds for AMD64, ARM64 and ARMv7 and then pushes the images to Docker Hub (where you pull them with docker pull).

The requested addition was to include Socat (serial over IP), start it with config passed via environment vars and make it available for use in P1Monitor. That way you can run P1Monitor on a server that’s not connected to the Smart Meter, there you only need a light weight serial to IP (like ser2net of something similar).

I added the apt installation lines to the Dockerfile, that worked. Then I wrote a super simple Python script:

import os


while enable:
  os.system("socat pty,link=/dev/ttyUSB4,raw,user=p1mon,group=dialout,mode=777 tcp:%s:%s,forever,interval=10" %(host,port))

And I start this from the main CMD start script. With no env vars it’ll exit right away. With SOCAT_ENABLE set to something it’s going into a loop, providing /dev/ttyUSB4 from the start for P1monitor to use and restarting if socat looses the connection. The “forever” parameter for socat makes it not exit if it doesn’t work from the start.

It took a bit of late night Googling and testing, but I think I got it running. Currently you can test this by pulling rvleij/p1monitor:testing:

docker pull rvleij/p1monitor:testing

You then start the P1Monitor docker instance with Socat support like this:

docker run -d -p 80:80 -p 10721:10721 -p 40721:40721 \
--name="p1mon" -h p1mon --cap-add=SYS_NICE \
--tmpfs /tmp --tmpfs /run --tmpfs /p1mon/mnt/ramdisk \
-v /<insert local path>/p1mon/data:/p1mon/data:rw \
-v /<insert local path>/p1mon/usbdisk:/p1mon/mnt/usb:rw \
-v /etc/localtime:/etc/localtime:ro \
-e "SOCAT_HOST=<your ser2net IP>" \
-e "SOCAT_PORT=<port you run serial stuff on>" \
--device=/dev/ttyUSB4 \
--restart=unless-stopped \

Let’s see if the number of issues doubles to 2 because of issues with this setup or if I can make this the default behaviour. :)