Auto-detects connected i2c sensors and publsihes data on HTTP or MQTT.
Docker compose file
To use this image, create a container in your docker-compose.yml
file as shown below:
services:
sensor:
image: bh.cr/balenalabs/sensor-<arch>
privileged: true
labels:
io.balena.features.kernel-modules: '1'
io.balena.features.sysfs: '1'
io.balena.features.supervisor-api: '1'
expose:
- '7575' # Only needed if using http server
This block utilizes the Linux Industrial I/O Subsystem ("iio") which is a kernel subsystem that allows for ease of implementing drivers for sensors and other similar devices such as ADCs, DACs, etc. You can see a list of available iio drivers here but in order to save space, most OSes do not include all these drivers. The easiest way to check if your board supports a driver is to use the modinfo command on a running device. For instance:
modinfo ti-ads1015
This command searches the running kernel for all the drivers it includes and prints out a description of any that are found to match. (Use the info in the Kconfig file in each folder of the driver list above to find the proper driver name to use with this command) BalenaOS for Raspberry Pi 3 includes a small subset of these drivers which are listed in the table below. As we continue to test sensors and improve the block, more sensors should be supported and the chart will be updated accordingly. Also note that as kernel and OS versions change, the supported drivers may change somewhat as well. It's best therefore to use modinfo as described above to test compatibility with any sensor being considered for use with this block.
Sensor Model | Sensor Name | Driver Name | Address(es) | Tested? |
---|---|---|---|---|
AD5301 | Analog Devices AD5446 and similar single channel DACs driver, TI DACs | ads5446 | 0xC, 0xD, 0xE, 0xF | Not tested |
APDS9960 | Avago APDS9960 gesture/RGB/ALS/proximity sensor | apds9960 | 0x39 | Yes, NOT working |
BME680 | Bosch Sensortec BME680 sensor | bme680 | 0x76, 0x77 | Yes, works |
BMP180 | Bosch Sensortec BMP180 sensor | bmp280 | 0x77 | Not tested |
BMP280 | Bosch Sensortec BMP280 sensor | bmp280 | 0x76, 0x77 | Yes, works |
BME280 | Bosch Sensortec BME280 sensor | bmp280 | 0x76, 0x77 | Yes, works |
HDC1000 | TI HDC100x relative humidity and temperature sensor | hdc100x | 0x40 - 0x43 | Not tested |
HTU21 | Measurement Specialties HTU21 humidity & temperature sensor | htu21 | 0x40 | Yes, works |
MS8607 | TE Connectivity PHT sensor | htu21 | 0x40, 0x76 | Yes, works partially (no pressure reading) |
MCP342x | Microchip Technology MCP3421/2/3/4/5/6/7/8 ADC | mcp3422 | 0x68 - 0x6F | Not tested |
ADS1015 | Texas Instruments ADS1015 ADC | ti-ads1015 | 0x48 - 0x4B | Yes, NOT working |
TSL4531 | TAOS TSL4531 ambient light sensors | tsl4531 | 0x29 | Not tested |
VEML6070 | VEML6070 UV A light sensor | veml6070 | 0x38, 0x39 | Yes, works |
By default, the block searches for sensors on SMBus number 1 (/dev/i2c-1) however you can set the bus number (an integer value) using the BUS_NUMBER
service variable.
The sensor data is available in json format either as an mqtt payload and/or via the built-in http server. If you include an mqtt broker container named "mqtt" in your application, the block will automatically publish to that. If you provide an address for the MQTT_ADDRESS
service variable, it will publish to that broker instead. The default interval for publishing data is eight seconds, which you can override with the MQTT_PUB_INTERVAL
service variable by providing a value in seconds. The default topic is set to sensors
(which is compatible with the connector block ) which can be overridden by setting the MQTT_PUB_TOPIC
service variable.
If no mqtt broker is set, the http server will be available on port 7575. To force the http server to be active even with mqtt, set the ALWAYS_USE_HTTPSERVER
service variable to True.
The http data defaults to only be available to other containers in the application via sensor:7575
- if you want this to be available externally, you'll need to map port 7575 to an external port in your docker-compose file.
The JSON for raw sensor data is available in one of two formats and is determined by the COLLAPSE_FIELDS
service variable. The default value of 0
(zero) causes each sensor to output a separate measurement:
[{"measurement": "htu21", "fields": {"humidityrelative": 29700, "temp": 23356}}, {"measurement": "bmp280", "fields": {"pressure": 99.911941406, "temp": 23710}}, {"measurement": "short_UUID", "fields": {"short_uuid": "0f33e61"}}]
Changing COLLAPSE_FIELDS
to 1
collapses all of the field values into one list like this:
{"short_uuid": "0f33e61", "humidityrelative": 29700, "temp": 23356, "pressure": 99.911941406}
Note that if two sensors output the same field name, it will only show up once in the list from one of the sensors. This feature is best used when the field names from sensors do not overlap.
The above examples display the raw data from the sensor as exposed by the driver, which is the default setting for the block. In many cases, the values and names need transformations to be useful. You can change the RAW_VALUES
service variable from the default value of 1
to 0
(zero) to output transformed data instead. All the transformations are defined per-sensor in the transformations.py
file which you can edit to your needs. We've included some basic ones for you. For example, here is the raw output of a bme680:
{"short_uuid": "0f33e61", "humidityrelative": 35.524, "pressure": 1005.48, "resistance": 52046.0, "temp": 24620.0}
Here is the transformed output with RAW_VALUES
set to 0
:
{"short_uuid": "0f33e61", "pressure": 1005.4, "resistance": 65454.0, "humidity": 35.541, "temperature": 24.54}
When using transformed data outputs, you can change the temperature field from Celsius to Farenheit by setting the TEMP_UNIT
variable to F
(the default is C
)
Note that the device's short UUID is always included in the data output, which can be useful for aggregating data from multiple devices. The short UUID is a string value so it will not show up in Grafana dashboards based on the dashboard block.
The sensor block works well with our connector block and dashboard block. See the latest version of balenaSense for an example of using all of these blocks together to read data from one or more sensor.