Skip to content

Commit

Permalink
Merge branch 'python'
Browse files Browse the repository at this point in the history
  • Loading branch information
raven-worx committed Jun 22, 2023
2 parents 99c1998 + cf0ea35 commit 6680ae0
Show file tree
Hide file tree
Showing 30 changed files with 3,607 additions and 46 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# text files
*.sh text eol=lf
*.py text eol=lf

# binary files
*.jpg binary
Expand Down
67 changes: 63 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
version_num: ${{ steps.version.outputs.version_num }}
archive_filename_tar: mbuspico_${{ steps.version.outputs.version }}.tar.gz
archive_filename_zip: mbuspico_${{ steps.version.outputs.version }}.zip
archive_filename_python: mbuspico_python_${{ steps.version.outputs.version }}.zip
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -34,11 +35,11 @@ jobs:
run: |
ver=${VERSION_REF##*/}
if [[ "$ver" =~ ^v([0-9]+).([0-9]+) ]]; then
echo "::set-output name=version::$ver"
echo "::set-output name=version_num::${ver:1}"
echo "version=$ver" >> $GITHUB_OUTPUT
echo "version_num=${ver:1}" >> $GITHUB_OUTPUT
else
echo "::set-output name=version::v0.0"
echo "::set-output name=version_num::0.0"
echo "version=v0.0" >> $GITHUB_OUTPUT
echo "version_num=0.0" >> $GITHUB_OUTPUT
fi
env:
VERSION_REF: ${{ github.ref }}
Expand Down Expand Up @@ -72,6 +73,48 @@ jobs:
with:
name: artifact-archive-zip
path: dist/mbuspico.zip

- name: Create archive python
run: |
cd python
zip -r ../dist/$ARCHIVE_NAME .
env:
ARCHIVE_NAME: python.zip
id: create-python-zip
- name: Upload ypthon archive artifact
uses: actions/upload-artifact@v3
with:
name: artifact-archive-python
path: dist/python.zip

docker:
runs-on: ubuntu-latest
needs:
- build-artifacts
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}

- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm/v7,linux/arm64
file: docker/python-run.Dockerfile
push: true
tags: ravenworx/mbuspico:latest, ravenworx/mbuspico:${{needs.build-artifacts.outputs.version_num}}

create-release:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -112,6 +155,12 @@ jobs:
name: artifact-archive-zip
path: dist

- name: Download python artifact
uses: actions/download-artifact@v3
with:
name: artifact-archive-python
path: dist

- name: Upload archive tar artifact
uses: actions/upload-release-asset@v1
env:
Expand All @@ -131,3 +180,13 @@ jobs:
asset_path: dist/mbuspico.zip
asset_name: ${{ needs.build-artifacts.outputs.archive_filename_zip }}
asset_content_type: application/zip

- name: Upload python artifact
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create-release.outputs.upload_url }}
asset_path: dist/python.zip
asset_name: ${{ needs.build-artifacts.outputs.archive_filename_python }}
asset_content_type: application/zip
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@ dkms.conf

# Ignore code-workspaces
*.code-workspace

*.pyc
Binary file added 3d/wiring_pi.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
96 changes: 80 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/raven-worx/mbuspico?logo=github&sort=semver)](https://github.com/raven-worx/mbuspico/releases)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](/LICENSE)

> **NEW IN VERSION 2.0: ADDED MICROPYTHON AND PYTHON SUPPORT. RASPBERRY PI IS NOW SUPPORTED. ADDED READY-TO-USE DOCKER IMAGE**
This project was created mostly out of interest and the wish to read out and display my power meter data in my Loxone smart home setup. (Thus the option with the 24V power supply - see below)

Currently the only smart meter device supported is the **Kaifa MA309M** (Austrian power provider Netz NÖ), but could be extended to any other model. Credits for the data intepretation code goes out to **[firegore/esphome-dlms-meter](https://github.com/firegore/esphome-dlms-meter)**!
Expand Down Expand Up @@ -59,13 +61,20 @@ The read meter data values are published via HTTP and/or UDP in JSON format:

## Software

The software for the Pico W microcontroller is written in C using
There are two versions of MBusPico available:

There is a native Raspberry Pico application written in C using the following components:
* [pico-sdk](https://github.com/raspberrypi/pico-sdk)
* [FreeRTOS](https://github.com/FreeRTOS/FreeRTOS-Kernel)
* [mbedtls](https://github.com/Mbed-TLS/mbedtls)
* [mongoose](https://github.com/cesanta/mongoose)

## Build
And (since v2.0) there is also a Python/Micropython version available, using the following moduls:
* [microdot](https://github.com/miguelgrinberg/microdot)
* PySerial
* PyCryptodome

## Build (native application)

1. Download and extract [latest release archive](https://github.com/raven-worx/mbuspico/releases) - or clone repository: `git clone --recurse-submodules https://github.com/raven-worx/MBusPico.git`
2. Edit build options (see below) in `options.ini` to configure MBusPico application to your needs
Expand All @@ -82,14 +91,17 @@ If you do not have a checkout of the pico-sdk yet, you can instead add the optio

For Windows i recommend using [Docker](https://docs.docker.com/get-docker/) for a quick and painless build.

Create a (local) docker image with the file provided in the `docker` folder of this repository:
You can also use the already available prebuilt docker image `ravenworx/pico-sdk-build:1.5.0` which contains already all required packages to build MBusPico.

```console
docker build -t mbuspico/build -f docker/Dockerfile
docker run -v ${PWD}:/opt/mbuspico --entrypoint=/opt/mbuspico/build.sh ravenworx/mbus-pico-build:1.5.0
```
After the build of the docker image has finished (might take a few minutes) simply start the built docker image which implicitly starts building the application:

Alternatively you can create a (local) docker image with the file provided in the `docker` folder of this repository.
```console
docker run -v ${PWD}:/opt/mbuspico mbuspico/build
docker build -t my/mbuspico-build -f docker/Dockerfile
```
After the build of the docker image has finished (might take a few minutes) simply start the built with the `my/mbuspico-build` instead.

### Build options

Expand All @@ -106,15 +118,47 @@ docker run -v ${PWD}:/opt/mbuspico mbuspico/build
| MBUSPICO_UDP_RECEIVER_PORT | | yes, if MBUSPICO_UDP_ENABLED | the UDP receiver port the meter data packet should be send to |
| MBUSPICO_UDP_INTERVAL_S | 30 | no | the maximum interval [sec] the meter data should be send out via UDP |
| MBUSPICO_HTTP_ENABLED | ON | no | specifies if the device should launch a simple HTTP server to provide the read meter data |
| MBUSPICO_HTTP_SERVER_PORT | 80 | no | specifies the listening port for the HTTP webserver |
| MBUSPICO_HTTP_SERVER_PORT | 80 | no | specifies the listening port for the HTTP webserver |
| MBUSPICO_HTTP_AUTH_USER | | no | Protect access to data with authentication
| MBUSPICO_HTTP_AUTH_PWD | | no | Protect access to data with authentication

# Transfer MBusPico onto the device
## Transfer MBusPico onto the device

### Native application

Hold the BOOTSEL button on the Pico W while connecting it to the PC via a USB cable. Since v1.2 its also possible to call `http://<ip-address>/update` to restart into the bootloader (if built with HTTP option).
Hold the BOOTSEL button on the Raspberry Pico W while connecting it to the PC via a USB cable. Since v1.2 its also possible to call `http://<ip-address>/update` to restart into the bootloader (if built with HTTP option).
The Pico will show up as a flash drive. Copy the `mbuspico.uf2` file from the build directory to the appeared flash drive. The Pico W will automatically reboot into the just flashed firmware after copying has finished. Done.

### MicroPython application

To copy MicroPython to the Raspberry Pico, hold the BOOTSEL button on the Raspberry Pico W while connecting it to the PC via a USB cable
and copy the `micropython.uf2` to the appeared flash drive.

> **Important:** MBusPico requires MicroPython with built-in support for AES-CTR ciphre, which is disabled by default in the official release builds.
> A prebuilt MicroPython version can be found in the python archive of each [MBusPico release](https://github.com/raven-worx/mbuspico/releases) (since v2.0 onwards), or in the `python` directory of this respository.
Now make sure you have adapted `config.py` to your needs before you copy all folders and files from `python/dist` to the Raspberry Pico:

For example you can use [Thonny IDE](https://thonny.org/) to transfer files to the Raspberry Pico.

Or via command line using python3/pip3 with the following commands.
On Windows make sure `python3.exe` can be found in the `PATH`. Probably the easiest is to install Python3 from the [Windows Marketplace](https://apps.microsoft.com/store/detail/python-311/9NRWMJP3717K).

Install ampy CLI tool:
```console
pip3 install adafruit-ampy
```

Use ampy to copy files and folders to device. `<PORT>` must the serial port of the connected Raspberry Pico running MicroPython. e.g. Linux: `/dev/ttyS0`, Windows `COM5`
To see a list of available serial ports you can run `python3 -m serial.tools.list_ports`
```console
cd python/dist
ampy --port <PORT> put mbus
ampy --port <PORT> put provider
ampy --port <PORT> put config.py
ampy --port <PORT> put main.py
```

# HTTP endpoints

When built with `MBUSPICO_HTTP_ENABLED` option enabled the following HTTP endpoints are provided.
Expand All @@ -127,7 +171,7 @@ When built with `MBUSPICO_HTTP_ENABLED` option enabled the following HTTP endpoi

# Hardware wiring / assembly

See the tables below how to wire the Raspberry Pico W with the used hardware components and power supply.
## Raspberry Pico W

| **Pico W** | **M-Bus Slave CLICK** | **RJ11** | **Notes** |
| --------------- | ----------------------- | -------- | --------- |
Expand All @@ -147,17 +191,37 @@ Power supply (24V):
| - | - | VIN | DC+/24V | 24V external power supply |
| - | - | GND | DC-/GND | Ground |

[<img src="/3d/image.jpg?raw=true" width="600"/>](/3d/image.jpg?raw=true)
[<img src="/3d/wiring_pico.jpg?raw=true" width="600"/>](/3d/wiring_pico.jpg?raw=true)

# Loxone integration
## Raspberry Pi

| **Raspberry Pi** | **M-Bus Slave CLICK** | **RJ11** | **Notes** |
| ---------------- | ----------------------- | -------- | --------- |
| GPIO14 (PIN 8) | RX | - | UART RX of MBUS module <--> UART TX of Raspberry Pi |
| GPIO15 (PIN 10) | TX | - | UART TX of MBUS module <--> UART RX of Raspberry Pi |
| - | MBUS1 | 3 | MBUS module to RJ11 cable line 3 or 4 (polarity doesn't matter) |
| - | MBUS2 | 4 | MBUS module to RJ11 cable line 3 or 4 (polarity doesn't matter) |

Power supply (24V):

| **Raspberry Pi** | **M-Bus Slave CLICK** | **24V -> 5V module** | **24V -> 3.3V module** | **24V power source** | **Notes** |
| ---------------- | ----------------------- | ----------------------- | ---------------------- | -------------------- | ---------- |
| 5V | - | VOUT+ | | | 5V power supply for Raspberry Pi |
| 5V | - | VOUT+ | | | 5V power supply for Raspberry Pi |
| GND | - | VOUT- | | | Ground |
| - | - | VIN+ | | DC+/24V | 24V external power supply |
| - | - | VIN- | | DC-/GND | Ground |
| - | 3V3 | | VOUT+ | | 3.3V power supply for MBus CLICK module |
| - | GND | | VOUT- | | Ground |
| - | - | | VIN+ | DC+/24V | 24V external power supply |
| - | - | | VIN- | DC-/GND | Ground |

The folder `loxone` contains a ready made HTTP VI template file for quick integration into Loxone Config.

[<img src="/loxone/config.png?raw=true" width="600"/>](/loxone/config.png?raw=true)
[<img src="/3d/wiring_pi.jpg?raw=true" width="300"/>](/3d/wiring_pi.jpg?raw=true)

Visualization in Loxone App:
# Loxone integration

[<img src="/loxone/app.png?raw=true" width="200"/>](/loxone/app.png?raw=true)
See [loxone/README.md](loxone/README.md)

# 3D printer files

Expand Down
12 changes: 0 additions & 12 deletions docker/Dockerfile

This file was deleted.

16 changes: 16 additions & 0 deletions docker/picosdk-build.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# image to build MBusPico against pico-sdk

FROM debian:bookworm-slim

ENV DEBIAN_FRONTEND=noninteractive \
PICO_SDK_PATH=/opt/pico-sdk

ENTRYPOINT ["/bin/bash"]

RUN apt update && apt install -y git cmake gcc-arm-none-eabi python3 g++ curl python3-venv \
&& apt autoremove -y \
&& apt clean -y \
&& rm -rf /var/lib/apt/lists/* \
&& git clone --branch "1.5.0" https://github.com/raspberrypi/pico-sdk /opt/pico-sdk \
&& cd /opt/pico-sdk \
&& git submodule update --init --recursive
20 changes: 20 additions & 0 deletions docker/python-run.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Python runtime image to execute MBusPico

FROM debian:12-slim

ENV DEBIAN_FRONTEND=noninteractive \
PIP_DEFAULT_TIMEOUT=100 \
PYTHONUNBUFFERED=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1

RUN set -ex \
&& apt update && apt install -y python3-pycryptodome python3-serial \
&& apt autoremove -y \
&& apt clean -y \
&& rm -rf /var/lib/apt/lists/*

COPY python/dist /opt/mbuspico/

WORKDIR /opt/mbuspico
ENTRYPOINT ["python3", "/opt/mbuspico/main.py"]
21 changes: 21 additions & 0 deletions loxone/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Loxone integration

To integrate MBusPico into Loxone and start optimizing your energy management you can import the [HTTP VirtualIn](VI_MBusPico.xml)
or [UDP VirtualIn](VIU_MBusPico.xml) template into Loxone Config.

[<img src="config.png?raw=true" width="600"/>](config.png?raw=true)

Visualization in Loxone App:

[<img src="app.png?raw=true" width="200"/>](app.png?raw=true)

## Loxberry

Since MBusPico v2.0 there is also a Python version available. Including a ready-made Python docker container running MBusPico.

This enables the usage of MBusPico application on your RaspberryPi already running [LoxBerry](https://github.com/mschlenstedt/Loxberry).

After installing the [Loxberry Docker Plugin](https://wiki.loxberry.de/plugins/docker/start) you can run the MBusPico docker container with the following settings:

[TODO]

17 changes: 17 additions & 0 deletions loxone/VIU_MBusPico.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<VirtualInUdp Title="MBusPico" Comment="UDP VirtualIn Template for MBusPico" Address="" Port="0">
<Info templateType="1" minVersion="14000000"/>
<VirtualInUdpCmd Title="Timestamp" Comment="" Address="" Check="&quot;lxTimestamp&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Voltage L1" Comment="" Address="" Check="&quot;voltageL1&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Voltage L2" Comment="" Address="" Check="&quot;voltageL2&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Voltage L3" Comment="" Address="" Check="&quot;voltageL3&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Current L1" Comment="" Address="" Check="&quot;currentL1&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Current L2" Comment="" Address="" Check="&quot;currentL2&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Current L3" Comment="" Address="" Check="&quot;currentL3&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Power Consumption" Comment="" Address="" Check="&quot;activePowerPlus&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Power Production" Comment="" Address="" Check="&quot;activePowerMinus&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Power Factor" Comment="" Address="" Check="&quot;powerFactor&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Meter Number" Comment="" Address="" Check="&quot;meterNumber&quot;: &quot;\v&quot;" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Meter Consumption" Comment="" Address="" Check="&quot;activeEnergyPlus&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
<VirtualInUdpCmd Title="Meter Production" Comment="" Address="" Check="&quot;activeEnergyMinus&quot;: \v" Signed="true" Analog="true" SourceValLow="0" DestValLow="0" SourceValHigh="100" DestValHigh="100" DefVal="0" MinVal="-10000" MaxVal="10000"/>
</VirtualInUdp>
Loading

0 comments on commit 6680ae0

Please sign in to comment.