This article discusses the key aspects to adding sensors to the UrsaLeo Gateway. The platform framework has been designed to ease the process of sending data to the cloud by implementing a polling process that reads sensor data, packages it as an MQTT message payload and publishes to the UrsaLeo Cloud.
There are 3 steps to the implementation:
- Create a sensor driver that writes its data to a file buffer
- Create a configuration file to map the file buffer to a data channel in the UrsaLeo Cloud
- Create a systemd service unit for the sensor driver
Each of these steps are detailed below. A full working example implementation of these guidelines is available pre-installed on the UrsaLeo Evaluation Kit for iMX.6 and Raspberry Pi, available from:
or as a Debian Package for Raspberry Pi available here:
Creating a Sensor Driver
Sensor drivers can be written in any language supported by the platform. The sensor data output must be written to a file buffer in /tmp. The file name can be user defined. The example uses /tmp/temperature0.out to represent the first temperature sensor attached to the Gateway.
Sensor output can be raw un-scaled values like 2050 which is then scaled to 20.5 by configuring the Gauge on the cloud platform. It can also be written in its final format eg 20.5
Sensor sampling rates are independent of message publication frequency, so a sensor could be sampled every second and published every 5 seconds for example.
Note: All files in /tmp are deleted during the OS startup so backup these values elsewhere if this is important
A Python code example below shows a simulated temperature sensor sampling every second, writing a raw value to the file buffer in /tmp/temperature0.out:
pi@raspberrypi:~ $ cat sensor-simulator.py
"""Simple sensor simulator"""
buffer = '/tmp/temperature0.out'
reading = '2050' # Replace with call to sample real sensor
def write_buffer(buffer: str, data: str):
"""Writes data to buffer"""
if data is not None:
with open(buffer, 'w') as b:
print('ERROR: writing data')
Creating a Configuration File
The file buffer for each of the attached sensors must be mapped to a data channel that corresponds to the data displayed in Gauges and Charts in the UrsaLeo Cloud.
Create a standard .ini file containing the mapping information.
The example below shows the mapping for a gateway with two BME280 (six environment sensors) attached:
pi@raspberrypi:/etc/ursaleo $ cat bme280.ini
# This section can contain configuration for sensor driver - optional
[channels] # Each channel names a unique file buffer
Create a symlink to the mapping configuration in /etc/ursaleo named device.ini:
ln -sf /etc/ursaleo/bme280.ini /etc/ursaleo/device.ini
A special case exists for gateways that have a single instance of each sensor type. It is possible to name the channel using a reserved word so that the gauges auto-configure when the gateway first connects.
The details are documented in the API article - the supported auto-configured sensors are:
|Sensor Type||Reserved Channel Name|
|Total Volatile Organic Compounds||tvoc|
|X,Y,Z 3-Axis orientation||Orient|
The example below shows the configuration for a gateway with a single Thunderboard2 (9 integrated sensors) attached:
pi@raspberrypi:/etc/ursaleo $ cat ble-thunder.ini
Finally, create a systemd service unit.
The sensor driver should be started in its own systemd service. The example below shows a service unit for a bme280 driver:
Description=BME280 I2C Sensor Driver
ExecStart=/usr/bin/python3 -u bme280drv.py \
--sensor_id %i \
As root, restart the demo service and the data will be sampled from the sensors, packaged into the message payload and transported to the cloud. From there, the gauges and charts can be configured.
systemctl restart demo.service
Messages are published every 5 seconds by default. The gateway packs all the current sensor readings into a single payload before publishing to MQTT. Alter the rate by changing the sleep parameter (seconds) in /usr/lib/ursaleo/gcp/gcp.py
payload = cmd_invoker.createPayload()
client.publish(mqtt_topic, payload, qos=1)
time.sleep(5) # message frequency in seconds