Skip to content

Commit 92cc1d7

Browse files
committed
examples: standalone: try to fix zigbee2mqtt
1 parent e55765d commit 92cc1d7

File tree

6 files changed

+84
-72
lines changed

6 files changed

+84
-72
lines changed

examples/standalone/zigbee2mqtt/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.10-alpine3.16
1+
FROM python:3.13-alpine
22

33
WORKDIR /app
44

examples/standalone/zigbee2mqtt/README.md

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,54 @@
11
# Zigbee Sensor (MQTT)
22

3-
This example describes the implementation of the [Standalone UCM](https://handbook.enapter.com/software/virtual_ucm/) concept using the opensource [Enapter python-sdk](https://github.com/Enapter/python-sdk) for monitoring Zigbee Sensor via MQTT protocol (Zigbee2Mqtt).
3+
This example describes the implementation of the Standalone Device concept
4+
using the opensource [Enapter
5+
python-sdk](https://github.com/Enapter/python-sdk) for monitoring Zigbee Sensor
6+
via MQTT protocol (Zigbee2Mqtt).
47

5-
In order to use this UCM you need to have [Zigbee2MQTT](https://www.zigbee2mqtt.io/guide/installation/) and some MQTT broker (for example [Mosquitto](https://mosquitto.org)) running.
8+
In order to use this Standalone Device you need to have
9+
[Zigbee2MQTT](https://www.zigbee2mqtt.io/guide/installation/) and some MQTT
10+
broker (for example [Mosquitto](https://mosquitto.org)) running.
611

7-
As an example in this guide we will use the following dummy settings for configuration:
12+
As an example in this guide we will use the following dummy settings for
13+
configuration:
814

9-
MQTT Broker Address: 192.168.192.190
10-
11-
MQTT Broker Port: 9883
12-
13-
MQTT User: mqtt_user
14-
15-
MQTT Password: mqtt_password
16-
17-
Device MQTT topic: zigbee2mqtt/MyDevice
15+
- MQTT Broker Address: 192.168.192.190
16+
- MQTT Broker Port: 9883
17+
- MQTT User: mqtt_user
18+
- MQTT Password: mqtt_password
19+
- Device MQTT topic: zigbee2mqtt/MyDevice
1820

1921
## Requirements
2022

21-
It is recommended to run this UCM using Docker and Docker Compose. This will ensure that environment is correct.
22-
23-
The MQTT broker must be reachable from the computer where the Docker Container will be running.
23+
It is recommended to run this Standalone Device using Docker and Docker
24+
Compose. This will ensure that environment is correct.
2425

25-
## Step 1. Create Standalone UCM in Enapter Cloud
26+
The MQTT broker must be reachable from the computer where the Docker Container
27+
will be running.
2628

27-
Log in to the Enapter Cloud, navigate to the Site where you want to create Standalone UCM and click on `Add new` button in the Standalone Device section.
29+
## Step 1. Create Standalone Device in Enapter Cloud
2830

29-
After creating Standalone UCM, you need to Generate and save Configuration string also known as ENAPTER_VUCM_BLOB as well as save UCM ID which will be needed for the next step
31+
Log in to the Enapter Cloud, navigate to the Site where you want to create
32+
Standalone Device and click on `Add new` button in the Standalone Device
33+
section.
3034

31-
More information you can find on [this page](https://developers.enapter.com/docs/tutorial/software-ucms/standalone).
35+
After creating Standalone Device, you need to Generate and save Configuration
36+
string also known as `ENAPTER_STANDALONE_COMMUNICATION_CONFIG` as well as save
37+
UCM ID which will be needed for the next step.
3238

3339
## Step 2. Upload Blueprint into the Cloud
3440

35-
The general case [Enapter Blueprint](https://marketplace.enapter.com/about) consists of two files - declaration in YAML format (manifest.yaml) and logic written in Lua. Howerver for this case the logic is written in Python as Lua implementation doesn't have SNMP integration.
41+
The general case [Enapter Blueprint](https://marketplace.enapter.com/about)
42+
consists of two files - declaration in YAML format (manifest.yaml) and logic
43+
written in Lua. Howerver for this case the logic is written in Python.
3644

37-
But for both cases we need to tell Enapter Cloud which telemetry we are going to send and store and how to name it.
45+
But for both cases we need to tell Enapter Cloud which telemetry we are going
46+
to send and store and how to name it.
3847

39-
The easiest way to do that - using [Enapter CLI](https://github.com/Enapter/enapter-cli) to upload manifest.yaml into Cloud. The other option is to use [Web IDE](https://developers.enapter.com/docs/tutorial/uploading-blueprint).
48+
The easiest way to do that - using [Enapter
49+
CLI](https://github.com/Enapter/enapter-cli) to upload manifest.yaml into
50+
Cloud. The other option is to use [Web
51+
IDE](https://developers.enapter.com/docs/tutorial/uploading-blueprint).
4052

4153
```bash
4254
user@pc zigbee2mqtt % enapter devices upload --blueprint-dir . --hardware-id REAL_UCM_ID
@@ -53,16 +65,17 @@ Done!
5365
5466
Open `docker-compose.yaml` in any editor.
5567
56-
Set environment variables according to your configuration settings. With dummy settings your file will look like this:
68+
Set environment variables according to your configuration settings. With dummy
69+
settings your file will look like this:
5770
5871
```yaml
5972
version: "3"
6073
services:
61-
zigbee2mqtt-ucm:
74+
zigbee2mqtt-standalone:
6275
build: .
63-
image: enapter-vucm-examples/zigbee2mqtt:latest
76+
image: enapter-standalone-examples/zigbee2mqtt:latest
6477
environment:
65-
- ENAPTER_VUCM_BLOB: "REALENAPTERVUCMBLOBMUSTBEHERE="
78+
- ENAPTER_STANDALONE_COMMUNICATION_CONFIG: "PUT_YOUR_CONFIG_HERE"
6679
- ZIGBEE_MQTT_HOST: "192.168.192.190"
6780
- ZIGBEE_MQTT_PORT: "9883"
6881
- ZIGBEE_MQTT_USER: "mqtt_user"
@@ -72,12 +85,13 @@ services:
7285
- ZIGBEE_SENSOR_MODEL: "Device Model"
7386
```
7487
75-
## Step 4. Build Docker Image with Standalone UCM
88+
## Step 4. Build Docker Image with Standalone Device
7689
77-
> You can you can skip this step and go directly to th Step 5.
78-
> Docker Compose will automatically build your image before starting container.
90+
> You can you can skip this step and go directly to Step 5. Docker Compose will
91+
> automatically build your image before starting container.
7992
80-
Build your Docker image by running `bash docker_build.sh` command in directory with UCM.
93+
Build your Docker image by running `bash docker_build.sh` command in directory
94+
with Standalone Device.
8195
8296
```bash
8397
user@pc zigbee2mqtt % bash docker_build.sh
@@ -122,20 +136,21 @@ user@pc zigbee2mqtt % bash docker_build.sh
122136
#12 exporting to image
123137
#12 exporting layers done
124138
#12 writing image sha256:92e1050debeabaff5837c6ca5bc26b0b966d09fc6f24e21b1d10cbb2f4d9aeec done
125-
#12 naming to docker.io/enapter-vucm-examples/zigbee2mqtt:latest done
139+
#12 naming to docker.io/enapter-standalone-examples/zigbee2mqtt:latest done
126140
#12 DONE 0.0s
127141
```
128142
129-
Your `enapter-vucm-examples/zigbee2mqtt` image is now built and you can see it by running `docker images` command:
143+
Your `enapter-standalone-examples/zigbee2mqtt` image is now built and you can
144+
see it by running `docker images` command:
130145
131146
```bash
132-
user@pc zigbee2mqtt % docker images enapter-vucm-examples/zigbee2mqtt
133-
REPOSITORY TAG IMAGE ID CREATED SIZE
134-
enapter-vucm-examples/zigbee2mqtt latest 92e1050debea 5 hours ago 285MB
147+
user@pc zigbee2mqtt % docker images enapter-standalone-examples/zigbee2mqtt
148+
REPOSITORY TAG IMAGE ID CREATED SIZE
149+
enapter-standalone-examples/zigbee2mqtt latest 92e1050debea 5 hours ago 285MB
135150
```
136151
137-
## Step 5. Run your Standalone UCM Docker Container
152+
## Step 5. Run your Standalone Device Docker Container
138153
139-
Finally run your Standalone UCM with `docker-compose up` command:
154+
Finally run your Standalone Device with `docker-compose up` command:
140155
141-
On this step you can check that your UCM is now Online in the Cloud.
156+
On this step you can check that your Device is now Online in the Cloud.

examples/standalone/zigbee2mqtt/docker-compose.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
version: "3"
22
services:
3-
zigbee2mqtt-ucm:
3+
zigbee2mqtt-standalone:
44
build: .
5-
image: enapter-vucm-examples/zigbee2mqtt:latest
5+
image: enapter-standalone-examples/zigbee2mqtt:latest
66
environment:
7-
- ENAPTER_VUCM_BLOB: "REALENAPTERVUCMBLOBMUSTBEHERE="
7+
- ENAPTER_STANDALONE_COMMUNICATION_CONFIG: "PUT_YOUR_CONFIG_HERE"
88
- ZIGBEE_MQTT_HOST: "192.168.192.190"
99
- ZIGBEE_MQTT_PORT: "9883"
1010
- ZIGBEE_MQTT_USER: "mqtt_user"

examples/standalone/zigbee2mqtt/docker_build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ set -euo pipefail
44
IFS=$'\n\t'
55

66
SCRIPT_DIR="$(realpath "$(dirname "$0")")"
7-
IMAGE_TAG="${IMAGE_TAG:-"enapter-vucm-examples/$(basename "$SCRIPT_DIR"):latest"}"
7+
IMAGE_TAG="${IMAGE_TAG:-"enapter-standalone-examples/$(basename "$SCRIPT_DIR"):latest"}"
88

99
docker build --progress=plain --tag "$IMAGE_TAG" "$SCRIPT_DIR"

examples/standalone/zigbee2mqtt/docker_run.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ set -euo pipefail
44
IFS=$'\n\t'
55

66
SCRIPT_DIR="$(realpath "$(dirname "$0")")"
7-
IMAGE_TAG="${IMAGE_TAG:-"enapter-vucm-examples/$(basename "$SCRIPT_DIR"):latest"}"
7+
IMAGE_TAG="${IMAGE_TAG:-"enapter-standalone-examples/$(basename "$SCRIPT_DIR"):latest"}"
88

99
bash $SCRIPT_DIR/docker_build.sh
1010

1111
docker run --rm -it \
1212
--network host \
1313
-e ENAPTER_LOG_LEVEL="${ENAPTER_LOG_LEVEL:-info}" \
14-
-e ENAPTER_VUCM_BLOB="$ENAPTER_VUCM_BLOB" \
14+
-e ENAPTER_STANDALONE_COMMUNICATION_CONFIG="$ENAPTER_STANDALONE_COMMUNICATION_CONFIG" \
1515
-e ZIGBEE_MQTT_HOST="$ZIGBEE_MQTT_HOST" \
1616
-e ZIGBEE_MQTT_PORT="$ZIGBEE_MQTT_PORT" \
1717
-e ZIGBEE_MQTT_USER="$ZIGBEE_MQTT_USER" \
Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import asyncio
2-
import functools
32
import json
43
import os
54

@@ -9,52 +8,47 @@
98
async def main():
109
env_prefix = "ZIGBEE_"
1110
mqtt_client_config = enapter.mqtt.Config.from_env(prefix=env_prefix)
12-
device_factory = functools.partial(
13-
ZigbeeMqtt,
11+
zigbee_mqtt = ZigbeeMqtt(
1412
mqtt_client_config=mqtt_client_config,
1513
mqtt_topic=os.environ[env_prefix + "MQTT_TOPIC"],
1614
sensor_manufacturer=os.environ[env_prefix + "SENSOR_MANUFACTURER"],
1715
sensor_model=os.environ[env_prefix + "SENSOR_MODEL"],
1816
)
19-
await enapter.vucm.run(device_factory)
17+
await enapter.standalone.run(zigbee_mqtt)
2018

2119

22-
class ZigbeeMqtt(enapter.vucm.Device):
20+
class ZigbeeMqtt(enapter.standalone.Device):
21+
2322
def __init__(
24-
self,
25-
mqtt_client_config,
26-
mqtt_topic,
27-
sensor_manufacturer,
28-
sensor_model,
29-
**kwargs,
23+
self, mqtt_client_config, mqtt_topic, sensor_manufacturer, sensor_model
3024
):
31-
super().__init__(**kwargs)
32-
25+
super().__init__()
3326
self.telemetry = {}
34-
3527
self.mqtt_client_config = mqtt_client_config
3628
self.mqtt_topic = mqtt_topic
37-
3829
self.sensor_manufacturer = sensor_manufacturer
3930
self.sensor_model = sensor_model
4031

41-
@enapter.vucm.device_task
42-
async def consume(self):
43-
async with enapter.mqtt.Client(self.mqtt_client_config) as client:
44-
async with client.subscribe(self.mqtt_topic) as messages:
45-
async for msg in messages:
46-
try:
47-
self.telemetry = json.loads(msg.payload)
48-
except json.JSONDecodeError as e:
49-
await self.log.error(f"failed to decode json payload: {e}")
32+
async def run(self):
33+
async with asyncio.TaskGroup() as tg:
34+
tg.create_task(self.consumer(tg))
35+
tg.create_task(self.telemetry_sender())
36+
tg.create_task(self.properties_sender())
37+
38+
async def consumer(self, tg):
39+
client = enapter.mqtt.Client(tg, self.mqtt_client_config)
40+
async with client.subscribe(self.mqtt_topic) as messages:
41+
async for msg in messages:
42+
try:
43+
self.telemetry = json.loads(msg.payload)
44+
except json.JSONDecodeError as e:
45+
await self.log.error(f"failed to decode json payload: {e}")
5046

51-
@enapter.vucm.device_task
5247
async def telemetry_sender(self):
5348
while True:
5449
await self.send_telemetry(self.telemetry)
5550
await asyncio.sleep(1)
5651

57-
@enapter.vucm.device_task
5852
async def properties_sender(self):
5953
while True:
6054
await self.send_properties(
@@ -67,4 +61,7 @@ async def properties_sender(self):
6761

6862

6963
if __name__ == "__main__":
70-
asyncio.run(main())
64+
try:
65+
asyncio.run(main())
66+
except KeyboardInterrupt:
67+
pass

0 commit comments

Comments
 (0)