Skip to content

Docker: Use External Sensors

If you wish to use external sensors that can't be plugged into a Spark, you can synchronize its measured value using a Temp Sensor (External) block.

You manually push new values to this block, and the Spark will treat it as any other sensor. To improve safety, the block has a timeout setting. If the timeout is 5m, then if no new value has been written for 5 minutes, the Spark will consider the sensor disconnected, and stop using its value.

You can find the type documentation in the block data types page.

This tutorial shows you how to change block data using the Brewblox eventbus, and run the script in a Docker container. It assumes you're either familiar with Docker, or have followed the dockerized script tutorial.

This script can be combined with reading a serial port.

Creating the block

First, in the UI create a new Temp Sensor (External) block. Call it Tutorial Sensor.

You can adjust its settings here. In the tutorial we will only be writing a new temperature value. The enabled and timeout settings will not be changed.

Source code

On your Pi, create a new directory sensorscript. In it, create two files:

script.py

py
"""
Code example for synchronizing data from an external sensor to a Spark sensor

Dependencies:
- paho-mqtt
"""

import json
from random import random
from time import sleep

from paho.mqtt import client as mqtt

# 172.17.0.1 is the default IP address for the host running the Docker container
# Change this value if Brewblox is installed on a different computer
HOST = '172.17.0.1'

# 1883 is the default port for MQTT, but this can be changed in brewblox env settings.
PORT = 1883

# This is a constant value. You never need to change it.
API_TOPIC = 'brewcast/spark/blocks'

# We'll be using the 'patch' command
# 'create', 'write', and 'delete' are also available
# https://www.brewblox.com/dev/reference/blocks_api.html
TOPIC = API_TOPIC + '/patch'

# Create a websocket MQTT client
client = mqtt.Client()

try:
    client.connect_async(host=HOST, port=PORT)
    client.loop_start()

    value = 20

    while True:
        # Randomize value, so we can easily see the change in the UI
        value += ((random() - 0.5) * 10)

        # IMPORTANT !!
        # Don't forget to first create the 'Tutorial Sensor' block
        # Patch writes to non-existent blocks will be ignored

        message = {
            # The block ID
            'id': 'Tutorial Sensor',

            # The unique service name
            'serviceId': 'spark-one',

            # https://www.brewblox.com/dev/reference/block_types.html#tempsensorexternal
            'type': 'TempSensorExternal',

            # We only write the field we want to change
            # Because we're using patch, the other settings will remain unchanged
            'data': { 'setting[degC]': value },
        }

        client.publish(TOPIC, json.dumps(message))
        print(f'sent {message}')
        sleep(5)

finally:
    client.loop_stop()

Dockerfile

FROM python:3.11-slim

COPY script.py /app/script.py

RUN pip3 install paho-mqtt

CMD ["python3", "-u", "/app/script.py"]

Building

Your sensorscript directory should look like this:

txt
.
├── script.py
└── Dockerfile

To build the image, run:

sh
docker build --tag sensorscript sensorscript/

Running

To run the built image:

sh
docker run --rm --tty sensorscript

Testing

It's often useful to listen in on what messages the eventbus actually received.

You can do so using https://mqtt-explorer.com/. Connect to mqtt://PI_ADDRESS:1883, and you can see all published events.