Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
| ||||||
|
Proper Storage Extends Shelf-Life of Food. The shelf-life of food will depend upon the food itself, packaging, temperature, and humidity[1].
A pantry is a traditional solution for storing provisions. It is well known that a pantry should be dry, dark and cool. In fact, the quality and nutrient content of foods depend on how they are stored (e.g.: in order to have them stored of up to three months, potatoes should be stored at a temperature between 45° and 55° F (7-12º C) [2] and canned foods stored above 70º F (21º C) will have a shorter shelf life [3]). The truth is that, at the end, storage cabinets tend to be warmer above the range [3], the doors are opened more than recommended, letting in the light and the humidity is not always controlled.
In this project, I will use the NXP Rapid IoT Prototyping Kit to create a pantry monitoring system tracking the ambient light, hummidity, temperature and the air quality of a pantry.
This pantry monitor device will help the users to track the metrics related to their food storage and have in their mobile device all the information in the forms of a dashboard, helping them to take decisions about what food store, how much time and where.
Architecture and componentsThe picture above summarizes the set up. The Rapid IoT device is connected and powered through the RaspberryPi (via USB) and provides the measurements via Bluetooth. The RaspberryPi is connected to the home router to provide WiFi access to the dashboard.
Step 1: Rapid Iot applicationIn order to set up the system first we need to develop the firmware for the Rapid IoT device. The most convenient way to do it is to use the Rapid IoT Studio and drop some elements from the toolbox to generate something similar to the image below:
(Note: You can find the *.atmo file of this design, ready to be imported, in the code section)
I will summarize one of each types of components below, the behaviour of the other components is quite similar:
- Interval: It is set to "60000 milliseconds" in order to get the measures every minute
- Backlight: It is set to "off" since we didn't need to use it for this project
- Sensors: I added sensors for: AirQuality_TVOC, AirQuality_CO2, Pressure, Temperature, Humidity and AmbientLight ; and configured them to set their value (Ability: Set Value) in order to be published later via bluettooth
- BLE: Service and Characteristic UUID were created and they were set to Read and Notify.
- BatteryInfo: Reading the NXP SDK documentation (SLN-RPK-NODE-SDK-API-RM), I found that was easy to get the charging status of the battery and the battery level, so I added the next code to publish via bluetooth the battery percent level.
ATMO_Status_t BatteryInfo_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
uint8_t batteryPercentLevel = 0;
uint8_t batteryChargingState = 0;
BatterySensor_GetState(&batteryPercentLevel, &batteryChargingState);
ATMO_CreateValueUnsignedInt(out, batteryPercentLevel);
return ATMO_Status_Success;
}
Once everything is set up you can click in compile, download and then burn the firmware in your IoT Device (you can follow the step 3 "Build, Run" of the NXP getting started guide for more details on how to load your own firmware).
(Note: The full source code and the firmware are attached in the code section)
Step 2: System backendThe mission of the backend is to record the measures from the Rapid IoT device and store them in a database.
So I decided to create a cron job in Raspberry, use GATT to query the Rapid IoT and store the meassures in a time series database (InfluxDB).
To install InfluxDB you can follow their installation guide.
The Python3 code below (also in the code section) relies in PyGATT to do the connection and the reading of the values and in InfluxDB module to save the data in the database.
(Note: The CHAR_UUIDS are thesame ones we defined in the Rapid IoT Studio)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" Stores Rapid-IOT PantryBLE values in an InfluxDB database"""
import logging
import time
import pygatt
from influxdb import InfluxDBClient
RPK_ADDRESS = "00:00:00:00:00:00" # Change this with your Device's BT Address
CHAR_UUIDS = {
"battery" : "08d41e61-ac11-40a2-a95a-e0e0fb5336ff",
"tvoc" : "08d41e61-ac11-40a2-a95a-e0e0fb5336f9",
"co2" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fa",
"pressure" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fc",
"temperature" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fb",
"humidity" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fd",
"ambient-light" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fe"
}
def save_prk_values():
""" Saves PantryBLE sensor values, got using BLE-GATT, to an InfluxDB database """
logging.basicConfig(filename='PantryBLE.log', level=logging.WARNING)
adapter = pygatt.GATTToolBackend()
db_client = InfluxDBClient('localhost', database="rpkpantry")
try:
# Connect to the RPK device
adapter.start()
conn = adapter.connect(RPK_ADDRESS)
time_info = int(time.time()*1000000000.0)
# Get sensor values
sensor_values = {}
for sensor in CHAR_UUIDS:
value = conn.char_read(CHAR_UUIDS[sensor])
sensor_values[sensor] = float(value.decode("utf-8").rstrip('\x00'))
# Save to DB
measurements = []
for sensor in sensor_values:
measurement = {"measurement" : sensor, "time" : time_info, "fields" : {"value" : sensor_values[sensor]}}
measurements.append(measurement)
print (measurements)
db_client.write_points(measurements)
except Exception as e:
print ("Error: ", e)
msg = "PantryBLE: [%d] %s"%(time_info, e)
logging.warning(msg)
finally:
adapter.stop()
if __name__ == '__main__':
save_prk_values()
This file was added to the /etc/crontab to be launched every minute:
# m h dom mon dow user command
* * * * * root /root/pantryiot.py
Step 3: System frontendI wanted to use Grafana for the frontend. Grafana is an open platform for monitoring and supports InfluxDB as data source.
You can find installation guides for different distributions in the next link.
Once Grafana is installed you have to set up an InfluxDB data source and generate a dashboard adding panels like this one below.
(Note: I've included a sample dashboard in JSON format in the attachments section of this article, so you can import and adapt it to your requirements)
ConclusionThe Rapid IoT Pantry monitoring device has been running for some days. I can monitor it from my tablet and check from time to time the current and historical info of the pantry.
The image below shows a few picures of my current pantry monitoring dashboard.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" Stores Rapid-IOT PantryBLE values in an InfluxDB database"""
import logging
import time
import pygatt
from influxdb import InfluxDBClient
RPK_ADDRESS = "00:00:00:00:00:00" # Change this with your Device's BT Address
CHAR_UUIDS = {
"battery" : "08d41e61-ac11-40a2-a95a-e0e0fb5336ff",
"tvoc" : "08d41e61-ac11-40a2-a95a-e0e0fb5336f9",
"co2" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fa",
"pressure" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fc",
"temperature" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fb",
"humidity" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fd",
"ambient-light" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fe"
}
def save_prk_values():
""" Saves PantryBLE sensor values, got using BLE-GATT, to an InfluxDB database """
logging.basicConfig(filename='PantryBLE.log', level=logging.WARNING)
adapter = pygatt.GATTToolBackend()
db_client = InfluxDBClient('localhost', database="rpkpantry")
try:
# Connect to the RPK device
adapter.start()
conn = adapter.connect(RPK_ADDRESS)
time_info = int(time.time()*1000000000.0)
# Get sensor values
sensor_values = {}
for sensor in CHAR_UUIDS:
value = conn.char_read(CHAR_UUIDS[sensor])
sensor_values[sensor] = float(value.decode("utf-8").rstrip('\x00'))
# Save to DB
measurements = []
for sensor in sensor_values:
measurement = {"measurement" : sensor, "time" : time_info, "fields" : {"value" : sensor_values[sensor]}}
measurements.append(measurement)
print (measurements)
db_client.write_points(measurements)
except Exception as e:
print ("Error: ", e)
msg = "PantryBLE: [%d] %s"%(time_info, e)
logging.warning(msg)
finally:
adapter.stop()
if __name__ == '__main__':
save_prk_values()
backcall==0.1.0
certifi==2018.11.29
chardet==3.0.4
decorator==4.3.0
enum-compat==0.0.2
idna==2.8
influxdb==5.2.1
ipython==7.2.0
ipython-genutils==0.2.0
jedi==0.13.2
parso==0.3.1
pexpect==4.6.0
pickleshare==0.7.5
pkg-resources==0.0.0
prompt-toolkit==2.0.7
ptyprocess==0.6.0
pygatt==3.2.0
Pygments==2.3.1
pyserial==3.4
python-dateutil==2.7.5
pytz==2018.7
requests==2.21.0
six==1.12.0
traitlets==4.3.2
urllib3==1.24.1
wcwidth==0.1.7
PantryIoT_firmware.bin
Plain textDisclaimer: This binary is provided "as is" and "with all faults", the author is not responsible of any damage caused to the device.
No preview (download only).
{
"__inputs": [
{
"name": "DS_INFLUXDB",
"label": "InfluxDB",
"description": "",
"type": "datasource",
"pluginId": "influxdb",
"pluginName": "InfluxDB"
}
],
"__requires": [
{
"type": "panel",
"id": "alertlist",
"name": "Alert List",
"version": "5.0.0"
},
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "5.4.2"
},
{
"type": "panel",
"id": "graph",
"name": "Graph",
"version": "5.0.0"
},
{
"type": "panel",
"id": "heatmap",
"name": "Heatmap",
"version": "5.0.0"
},
{
"type": "datasource",
"id": "influxdb",
"name": "InfluxDB",
"version": "5.0.0"
},
{
"type": "panel",
"id": "singlestat",
"name": "Singlestat",
"version": "5.0.0"
},
{
"type": "panel",
"id": "text",
"name": "Text",
"version": "5.0.0"
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": null,
"links": [],
"panels": [
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": true,
"colors": [
"#299c46",
"rgba(237, 129, 40, 0.89)",
"#d44a3a"
],
"format": "celsius",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 3,
"w": 3,
"x": 0,
"y": 0
},
"id": 12,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false
},
"tableColumn": "",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "temperature",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": "25, 35",
"title": "Temperature",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "current"
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": false,
"colors": [
"rgb(255, 255, 255)",
"rgb(255, 255, 255)",
"rgb(255, 255, 255)"
],
"format": "humidity",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": true,
"thresholdLabels": false,
"thresholdMarkers": false
},
"gridPos": {
"h": 3,
"w": 3,
"x": 3,
"y": 0
},
"id": 10,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false
},
"tableColumn": "",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "humidity",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": "220, 660",
"title": "Humidity",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "current"
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": false,
"colors": [
"#299c46",
"rgba(237, 129, 40, 0.89)",
"#d44a3a"
],
"format": "pressurehpa",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 3,
"w": 3,
"x": 6,
"y": 0
},
"id": 11,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false
},
"tableColumn": "",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "pressure",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
},
{
"params": [
" / 100"
],
"type": "math"
}
]
],
"tags": []
}
],
"thresholds": "220, 660",
"title": "Pressure",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "current"
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": true,
"colors": [
"#299c46",
"rgba(237, 129, 40, 0.89)",
"#d44a3a"
],
"format": "ppm",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 3,
"w": 3,
"x": 9,
"y": 0
},
"id": 7,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false
},
"tableColumn": "",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "co2",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "last"
}
]
],
"tags": []
}
],
"thresholds": "1000, 5000",
"title": "CO2",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "current"
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": true,
"colors": [
"#299c46",
"rgba(237, 129, 40, 0.89)",
"#d44a3a"
],
"format": "conppb",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 3,
"w": 3,
"x": 12,
"y": 0
},
"id": 8,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false
},
"tableColumn": "",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tvoc",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": "220, 660",
"title": "TVOC",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "current"
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": true,
"colors": [
"rgb(0, 0, 0)",
"#2f575e",
"#dedaf7"
],
"decimals": null,
"format": "short",
"gauge": {
"maxValue": 20,
"minValue": 0,
"show": true,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 3,
"w": 3,
"x": 15,
"y": 0
},
"id": 9,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false
},
"tableColumn": "",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "ambient-light",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": "5,15",
"title": "Ambient Light",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [],
"valueName": "current"
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorPostfix": false,
"colorPrefix": false,
"colorValue": true,
"colors": [
"#d44a3a",
"rgba(237, 129, 40, 0.89)",
"#299c46"
],
"format": "percent",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 3,
"w": 3,
"x": 18,
"y": 0
},
"id": 5,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false
},
"tableColumn": "",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "battery",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": "30,60",
"title": "Battery",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "current"
},
{
"content": "# Rapid IOT\n# Pantry",
"gridPos": {
"h": 3,
"w": 3,
"x": 21,
"y": 0
},
"id": 14,
"links": [],
"mode": "markdown",
"title": "",
"transparent": false,
"type": "text"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fill": 1,
"gridPos": {
"h": 5,
"w": 12,
"x": 0,
"y": 3
},
"id": 3,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "temperature",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Temperature",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "celsius",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fill": 1,
"gridPos": {
"h": 5,
"w": 12,
"x": 12,
"y": 3
},
"id": 17,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
...
This file has been truncated, please download it to see its full contents.
{
"name": "PantryBLE",
"createVersion": "2017-08-12",
"description": "New Project",
"lastModified": "2018-12-27T18:56:25.349Z",
"created": "2018-12-27T18:56:25.349Z",
"meta": {
"projectTypeName": "NXP Rapid IoT",
"projectTypeId": "NxpRpk"
},
"planes": {
"NXP Rapid IoT": {
"type": "mcuxpresso",
"compilerVersion": "latest",
"variants": [
"NxpRpk"
],
"meta": {},
"elements": [
{
"name": "Interval",
"type": "EmbeddedInterval",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\n\tATMO_INTERVAL_Handle_t intervalHandle;\n ATMO_INTERVAL_AddAbilityInterval(\n\t\tATMO_PROPERTY(Interval, instance), \n\t\tATMO_ABILITY(Interval, interval), \n\t\tATMO_PROPERTY(Interval, time), \n\t\t&intervalHandle\n\t);\n\t\n\treturn ATMO_Status_Success;\n\t",
"interval": "\treturn ATMO_Status_Success;"
},
"variables": {},
"embeddedPropertyConversions": {},
"codeUserChanged": {
"setup": false,
"interval": false
},
"instance": 0,
"time": "60000"
},
"meta": {
"editorX": 104,
"editorY": 67,
"lastTrigger": "interval"
},
"triggers": {
"triggered": [],
"interval": [
{
"mapping": {},
"targetOrder": [],
"targetElement": "AirQuality_TVOC",
"targetAbility": "readTVOC"
},
{
"mapping": {},
"targetOrder": [],
"targetElement": "AirQuality_CO2",
"targetAbility": "readCO2"
},
{
"mapping": {},
"targetOrder": [],
"targetElement": "Pressure",
"targetAbility": "readPressure"
},
{
"mapping": {},
"targetOrder": [],
"targetElement": "Temperature",
"targetAbility": "readTemperature"
},
{
"mapping": {},
"targetOrder": [],
"targetElement": "Humidity",
"targetAbility": "readHumidity"
},
{
"mapping": {},
"targetOrder": [],
"targetElement": "AmbientLight",
"targetAbility": "readAmbientLight"
},
{
"mapping": {},
"targetOrder": [],
"targetElement": "BatteryInfo",
"targetAbility": "trigger"
}
]
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"interval": true
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "interval",
"triggers": [
"interval"
]
}
]
},
{
"name": "BLE_TVOC",
"type": "EmbeddedBLECharacteristicCustom",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables",
"ble"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\n\tATMO_BLE_GATTSAddService(\n\t\tATMO_PROPERTY(BLE_TVOC, instance),\n\t\t&ATMO_VARIABLE(BLE_TVOC, bleServiceHandle), \n\t\tATMO_PROPERTY(BLE_TVOC, bleServiceUuid));\n\t\n\tuint8_t property = 0;\n\tuint8_t permission = 0;\n\t\n\tproperty |= ATMO_PROPERTY(BLE_TVOC, read) ? ATMO_BLE_Property_Read : 0;\n\tproperty |= ATMO_PROPERTY(BLE_TVOC, write) ? ATMO_BLE_Property_Write : 0;\n\tproperty |= ATMO_PROPERTY(BLE_TVOC, notify) ? ATMO_BLE_Property_Notify : 0;\n\n\tpermission |= ATMO_PROPERTY(BLE_TVOC, read) ? ATMO_BLE_Permission_Read : 0;\n\tpermission |= ATMO_PROPERTY(BLE_TVOC, write) ? ATMO_BLE_Permission_Write : 0;\n\n\tATMO_DATATYPE types[3] = {ATMO_PROPERTY(BLE_TVOC, writeDataType), ATMO_PROPERTY(BLE_TVOC, readDataType), ATMO_PROPERTY(BLE_TVOC, notifyDataType)};\n\t\n\tATMO_BLE_GATTSAddCharacteristic(\n\t\tATMO_PROPERTY(BLE_TVOC, instance),\n\t\t&ATMO_VARIABLE(BLE_TVOC, bleCharacteristicHandle), \n\t\tATMO_VARIABLE(BLE_TVOC, bleServiceHandle), \n\t\tATMO_PROPERTY(BLE_TVOC, bleCharacteristicUuid), \n\t\tproperty, permission, ATMO_GetMaxValueSize(3, 64, types));\n\t\n\tATMO_BLE_GATTSRegisterCharacteristicAbilityHandle(\n\t\tATMO_PROPERTY(BLE_TVOC, instance),\n\t\tATMO_VARIABLE(BLE_TVOC, bleCharacteristicHandle), \n\t\tATMO_BLE_Characteristic_Written, \n\t\tATMO_ABILITY(BLE_TVOC, written));\n\t\n\treturn ATMO_Status_Success;\n\t",
"setValue": "\n\t\n\t// Convert to the desired write data type\n\tATMO_Value_t convertedValue;\n\tATMO_InitValue(&convertedValue);\n\tATMO_CreateValueConverted(&convertedValue, ATMO_PROPERTY(BLE_TVOC, readDataType), in);\n\n\tATMO_BLE_GATTSSetCharacteristic(\n\t\tATMO_PROPERTY(BLE_TVOC, instance),\n\t\tATMO_VARIABLE(BLE_TVOC, bleCharacteristicHandle),\n\t\tconvertedValue.size, \n\t\t(uint8_t *)convertedValue.data,\n\t\tNULL);\n\t\n\tATMO_FreeValue(&convertedValue);\n\t\t\n\treturn ATMO_Status_Success;\n\t",
"written": "\n\tATMO_CreateValueConverted(out, ATMO_PROPERTY(BLE_TVOC, writeDataType), in);\n\treturn ATMO_Status_Success;\n\t",
"subscibed": "\treturn ATMO_Status_Success;",
"unsubscribed": "\treturn ATMO_Status_Success;"
},
"variables": {
"bleServiceHandle": {
"type": "ATMO_BLE_Handle_t"
},
"bleCharacteristicHandle": {
"type": "ATMO_BLE_Handle_t"
}
},
"embeddedPropertyConversions": {
"bleServiceUuid": "string",
"bleCharacteristicUuid": "string"
},
"codeUserChanged": {
"setup": false,
"setValue": false,
"written": false,
"subscibed": false,
"unsubscribed": false
},
"instance": 0,
"bleServiceUuid": "08d41e61-ac11-40a2-a95a-e0e0fb5336f8",
"bleCharacteristicUuid": "08d41e61-ac11-40a2-a95a-e0e0fb5336f9",
"read": true,
"write": false,
"notify": true,
"readDataType": "ATMO_DATATYPE_STRING",
"writeDataType": "ATMO_DATATYPE_STRING",
"notifyDataType": "ATMO_DATATYPE_STRING"
},
"meta": {
"editorX": 603,
"editorY": 30,
"lastTrigger": "written"
},
"triggers": {
"triggered": [],
"written": [],
"subscibed": [],
"unsubscribed": []
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"setValue": "valueSet",
"written": true,
"subscibed": true,
"unsubscribed": true
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "setValue",
"triggers": []
},
{
"name": "written",
"triggers": [
"written"
]
},
{
"name": "subscibed",
"triggers": [
"subscibed"
]
},
{
"name": "unsubscribed",
"triggers": [
"unsubscribed"
]
}
]
},
{
"name": "AirQuality_TVOC",
"type": "EmbeddedCCS811",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\tATMO_CCS811_Config_t config;\n\tconfig.operatingMode = ATMO_PROPERTY(AirQuality_TVOC, operatingMode);\n\tconfig.address = ATMO_PROPERTY(AirQuality_TVOC, i2cAddress);\n\tconfig.i2cDriverInstance = ATMO_PROPERTY(AirQuality_TVOC, i2cInstance);\n\n\treturn ( ATMO_CCS811_Init(&config) == ATMO_CCS811_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;\n",
"setEnabled": "ATMO_CCS811_SetEnabled(true);\nreturn ATMO_Status_Success;",
"setDisabled": "ATMO_CCS811_SetEnabled(false);\nreturn ATMO_Status_Success;",
"setEnabledDisabled": "bool enabled = false;\nATMO_GetBool(in, &enabled);\nATMO_CCS811_SetEnabled(enabled);\nreturn ATMO_Status_Success;",
"readTVOC": " uint16_t tvoc;\n\n if(ATMO_CCS811_GetTVOC(&tvoc) == ATMO_CCS811_Status_Success)\n {\n ATMO_CreateValueUnsignedInt(out, (unsigned int)tvoc);\n }\n else\n {\n ATMO_CreateValueVoid(out);\n }\n \n return ATMO_Status_Success;",
"readCO2": " uint16_t co2;\n \n if(ATMO_CCS811_GetCO2(&co2) == ATMO_CCS811_Status_Success)\n {\n ATMO_CreateValueInt(out, (int)co2);\n }\n else\n {\n ATMO_CreateValueVoid(out);\n }\n \n return ATMO_Status_Success;"
},
"variables": {},
"embeddedPropertyConversions": {},
"codeUserChanged": {
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readTVOC": true,
"readCO2": false
},
"i2cInstance": 1,
"i2cAddress": "0x5A",
"operatingMode": "1"
},
"meta": {
"editorX": 300,
"editorY": 31,
"lastTrigger": "TVOCRead"
},
"triggers": {
"triggered": [],
"TVOCRead": [
{
"mapping": {},
"targetOrder": [],
"targetElement": "BLE_TVOC",
"targetAbility": "setValue"
}
],
"CO2Read": []
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readTVOC": false,
"readCO2": false
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "setEnabled",
"triggers": []
},
{
"name": "setDisabled",
"triggers": []
},
{
"name": "setEnabledDisabled",
"triggers": []
},
{
"name": "readTVOC",
"triggers": [
"TVOCRead"
]
},
{
"name": "readCO2",
"triggers": [
"CO2Read"
]
}
]
},
{
"name": "AirQuality_CO2",
"type": "EmbeddedCCS811",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\tATMO_CCS811_Config_t config;\n\tconfig.operatingMode = ATMO_PROPERTY(AirQuality_CO2, operatingMode);\n\tconfig.address = ATMO_PROPERTY(AirQuality_CO2, i2cAddress);\n\tconfig.i2cDriverInstance = ATMO_PROPERTY(AirQuality_CO2, i2cInstance);\n\n\treturn ( ATMO_CCS811_Init(&config) == ATMO_CCS811_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;\n",
"setEnabled": "ATMO_CCS811_SetEnabled(true);\nreturn ATMO_Status_Success;",
"setDisabled": "ATMO_CCS811_SetEnabled(false);\nreturn ATMO_Status_Success;",
"setEnabledDisabled": "bool enabled = false;\nATMO_GetBool(in, &enabled);\nATMO_CCS811_SetEnabled(enabled);\nreturn ATMO_Status_Success;",
"readTVOC": " uint16_t tvoc;\n\n if(ATMO_CCS811_GetTVOC(&tvoc) == ATMO_CCS811_Status_Success)\n {\n ATMO_CreateValueUnsignedInt(out, (unsigned int)tvoc);\n }\n else\n {\n ATMO_CreateValueVoid(out);\n }\n \n return ATMO_Status_Success;",
"readCO2": " uint16_t co2;\n \n if(ATMO_CCS811_GetCO2(&co2) == ATMO_CCS811_Status_Success)\n {\n ATMO_CreateValueInt(out, (int)co2);\n }\n else\n {\n ATMO_CreateValueVoid(out);\n }\n \n return ATMO_Status_Success;"
},
"variables": {},
"embeddedPropertyConversions": {},
"codeUserChanged": {
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readTVOC": false,
"readCO2": false
},
"i2cInstance": 1,
"i2cAddress": "0x5A",
"operatingMode": "1"
},
"meta": {
"editorX": 299,
"editorY": 117,
"lastTrigger": "CO2Read"
},
"triggers": {
"triggered": [],
"TVOCRead": [
{
"mapping": {},
"targetOrder": [],
"targetElement": "BLE_CO2",
"targetAbility": "setValue"
}
],
"CO2Read": [
{
"mapping": {},
"targetOrder": [],
"targetElement": "BLE_CO2",
"targetAbility": "setValue"
}
]
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readTVOC": false,
"readCO2": false
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "setEnabled",
"triggers": []
},
{
"name": "setDisabled",
"triggers": []
},
{
"name": "setEnabledDisabled",
"triggers": []
},
{
"name": "readTVOC",
"triggers": [
"TVOCRead"
]
},
{
"name": "readCO2",
"triggers": [
"CO2Read"
]
}
]
},
{
"name": "BLE_CO2",
"type": "EmbeddedBLECharacteristicCustom",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables",
"ble"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\n\tATMO_BLE_GATTSAddService(\n\t\tATMO_PROPERTY(BLE_CO2, instance),\n\t\t&ATMO_VARIABLE(BLE_CO2, bleServiceHandle), \n\t\tATMO_PROPERTY(BLE_CO2, bleServiceUuid));\n\t\n\tuint8_t property = 0;\n\tuint8_t permission = 0;\n\t\n\tproperty |= ATMO_PROPERTY(BLE_CO2, read) ? ATMO_BLE_Property_Read : 0;\n\tproperty |= ATMO_PROPERTY(BLE_CO2, write) ? ATMO_BLE_Property_Write : 0;\n\tproperty |= ATMO_PROPERTY(BLE_CO2, notify) ? ATMO_BLE_Property_Notify : 0;\n\n\tpermission |= ATMO_PROPERTY(BLE_CO2, read) ? ATMO_BLE_Permission_Read : 0;\n\tpermission |= ATMO_PROPERTY(BLE_CO2, write) ? ATMO_BLE_Permission_Write : 0;\n\n\tATMO_DATATYPE types[3] = {ATMO_PROPERTY(BLE_CO2, writeDataType), ATMO_PROPERTY(BLE_CO2, readDataType), ATMO_PROPERTY(BLE_CO2, notifyDataType)};\n\t\n\tATMO_BLE_GATTSAddCharacteristic(\n\t\tATMO_PROPERTY(BLE_CO2, instance),\n\t\t&ATMO_VARIABLE(BLE_CO2, bleCharacteristicHandle), \n\t\tATMO_VARIABLE(BLE_CO2, bleServiceHandle), \n\t\tATMO_PROPERTY(BLE_CO2, bleCharacteristicUuid), \n\t\tproperty, permission, ATMO_GetMaxValueSize(3, 64, types));\n\t\n\tATMO_BLE_GATTSRegisterCharacteristicAbilityHandle(\n\t\tATMO_PROPERTY(BLE_CO2, instance),\n\t\tATMO_VARIABLE(BLE_CO2, bleCharacteristicHandle), \n\t\tATMO_BLE_Characteristic_Written, \n\t\tATMO_ABILITY(BLE_CO2, written));\n\t\n\treturn ATMO_Status_Success;\n\t",
"setValue": "\n\t\n\t// Convert to the desired write data type\n\tATMO_Value_t convertedValue;\n\tATMO_InitValue(&convertedValue);\n\tATMO_CreateValueConverted(&convertedValue, ATMO_PROPERTY(BLE_CO2, readDataType), in);\n\n\tATMO_BLE_GATTSSetCharacteristic(\n\t\tATMO_PROPERTY(BLE_CO2, instance),\n\t\tATMO_VARIABLE(BLE_CO2, bleCharacteristicHandle),\n\t\tconvertedValue.size, \n\t\t(uint8_t *)convertedValue.data,\n\t\tNULL);\n\t\n\tATMO_FreeValue(&convertedValue);\n\t\t\n\treturn ATMO_Status_Success;\n\t",
"written": "\n\tATMO_CreateValueConverted(out, ATMO_PROPERTY(BLE_CO2, writeDataType), in);\n\treturn ATMO_Status_Success;\n\t",
"subscibed": "\treturn ATMO_Status_Success;",
"unsubscribed": "\treturn ATMO_Status_Success;"
},
"variables": {
"bleServiceHandle": {
"type": "ATMO_BLE_Handle_t"
},
"bleCharacteristicHandle": {
"type": "ATMO_BLE_Handle_t"
}
},
"embeddedPropertyConversions": {
"bleServiceUuid": "string",
"bleCharacteristicUuid": "string"
},
"codeUserChanged": {
"setup": false,
"setValue": false,
"written": false,
"subscibed": false,
"unsubscribed": false
},
"instance": 0,
"bleServiceUuid": "08d41e61-ac11-40a2-a95a-e0e0fb5336f8",
"bleCharacteristicUuid": "08d41e61-ac11-40a2-a95a-e0e0fb5336fa",
"read": true,
"write": false,
"notify": true,
"readDataType": "ATMO_DATATYPE_STRING",
"writeDataType": "ATMO_DATATYPE_STRING",
"notifyDataType": "ATMO_DATATYPE_STRING"
},
"meta": {
"editorX": 602,
"editorY": 116,
"lastTrigger": "written"
},
"triggers": {
"triggered": [],
"written": [],
"subscibed": [],
"unsubscribed": []
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"setValue": "valueSet",
"written": true,
"subscibed": true,
"unsubscribed": true
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "setValue",
"triggers": []
},
{
"name": "written",
"triggers": [
"written"
]
},
{
"name": "subscibed",
"triggers": [
"subscibed"
]
},
{
"name": "unsubscribed",
"triggers": [
"unsubscribed"
]
}
]
},
{
"name": "Pressure",
"type": "EmbeddedMPL3115",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\tATMO_MPL3115_Config_t config;\n\tconfig.address = ATMO_PROPERTY(Pressure, i2cAddress);\n\tconfig.i2cDriverInstance = ATMO_PROPERTY(Pressure, i2cInstance);\n\tconfig.MPLsettings.mode = MPL_MODE_PRESSURE;\n\tconfig.MPLsettings.oversample = MPL_OS_0;\t\t\t// oversampling = 1\n\tconfig.MPLsettings.autoAcquisitionTime = MPL_ST_0;\t// Auto acquisition time = 1s\n\tconfig.MPLsettings.pressureOffset = ATMO_PROPERTY(Pressure, pressureOffset);\t// Offset pressure correction = 4*-128 = -512Pa (8 bits signed integer)\n\tconfig.MPLsettings.altitudeOffset = ATMO_PROPERTY(Pressure, altitudeOffset);\t// Offset altitude correction = 128m (signed 8 bits integer)\n\tconfig.MPLsettings.tempOffset = ATMO_PROPERTY(Pressure, tempOffset);\t\t\t// Offset temperature correction -8C (0.0625C/LSB)\n\tconfig.MPLsettings.fifoMode = FIFO_DISABLED;\t\t// FIFO mode disabled\n\tconfig.MPLsettings.fifoWatermark = 5;\t\t\t\t// 6 bits to set the number of FIFO samples required to trigger a watermark interrupt.\n\tconfig.MPLsettings.fifoINTpin = FIFO_INT1;\t\t\t// set pin INT1 as output for FIFO interrupt\n\n\treturn ( ATMO_MPL3115_Init(&config) == ATMO_MPL3115_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;\n",
"setEnabled": "ATMO_MPL3115_SetEnabled(true);\nreturn ATMO_Status_Success;",
"setDisabled": "ATMO_MPL3115_SetEnabled(false);\nreturn ATMO_Status_Success;",
"setEnabledDisabled": "bool enabled = false;\nATMO_GetBool(in, &enabled);\nATMO_MPL3115_SetEnabled(enabled);\nreturn ATMO_Status_Success;",
"readAltitude": " uint32_t altitudeMeters;\n if(ATMO_MPL3115_GetAltitude(&altitudeMeters) != ATMO_MPL3115_Status_Success)\n {\n ATMO_CreateValueVoid(out);\n return ATMO_Status_Fail;\n }\n ATMO_CreateValueInt(out, (int)altitudeMeters);\n return ATMO_Status_Success;",
"readPressure": " uint32_t pressurePa;\n if(ATMO_MPL3115_GetPressure(&pressurePa) != ATMO_MPL3115_Status_Success)\n {\n ATMO_CreateValueVoid(out);\n return ATMO_Status_Fail;\n }\n ATMO_CreateValueInt(out, (int)pressurePa);\n return ATMO_Status_Success;",
"readPressureKpa": " uint32_t pressurePa;\n if(ATMO_MPL3115_GetPressure(&pressurePa) != ATMO_MPL3115_Status_Success)\n {\n ATMO_CreateValueVoid(out);\n return ATMO_Status_Fail;\n }\n ATMO_CreateValueInt(out, (int)(pressurePa/1000));\n return ATMO_Status_Success;"
},
"variables": {},
"embeddedPropertyConversions": {},
"codeUserChanged": {
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readAltitude": false,
"readPressure": false,
"readPressureKpa": false
},
"i2cInstance": 1,
"i2cAddress": "0x60",
"pressureOffset": "0",
"altitudeOffset": "0",
"tempOffset": "0"
},
"meta": {
"editorX": 298,
"editorY": 199,
"lastTrigger": "pressureRead"
},
"triggers": {
"triggered": [],
"altitudeRead": [],
"pressureRead": [
{
"mapping": {},
"targetOrder": [],
"targetElement": "BLE_Pressure",
"targetAbility": "setValue"
}
],
"pressureReadKpa": []
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readAltitude": false,
"readPressure": false,
"readPressureKpa": false
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "setEnabled",
"triggers": []
},
{
"name": "setDisabled",
"triggers": []
},
{
"name": "setEnabledDisabled",
"triggers": []
},
{
"name": "readAltitude",
"triggers": [
"altitudeRead"
]
},
{
"name": "readPressure",
"triggers": [
"pressureRead"
]
},
{
"name": "readPressureKpa",
"triggers": [
"pressureReadKpa"
]
}
]
},
{
"name": "BLE_Pressure",
"type": "EmbeddedBLECharacteristicCustom",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables",
"ble"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\n\tATMO_BLE_GATTSAddService(\n\t\tATMO_PROPERTY(BLE_Pressure, instance),\n\t\t&ATMO_VARIABLE(BLE_Pressure, bleServiceHandle), \n\t\tATMO_PROPERTY(BLE_Pressure, bleServiceUuid));\n\t\n\tuint8_t property = 0;\n\tuint8_t permission = 0;\n\t\n\tproperty |= ATMO_PROPERTY(BLE_Pressure, read) ? ATMO_BLE_Property_Read : 0;\n\tproperty |= ATMO_PROPERTY(BLE_Pressure, write) ? ATMO_BLE_Property_Write : 0;\n\tproperty |= ATMO_PROPERTY(BLE_Pressure, notify) ? ATMO_BLE_Property_Notify : 0;\n\n\tpermission |= ATMO_PROPERTY(BLE_Pressure, read) ? ATMO_BLE_Permission_Read : 0;\n\tpermission |= ATMO_PROPERTY(BLE_Pressure, write) ? ATMO_BLE_Permission_Write : 0;\n\n\tATMO_DATATYPE types[3] = {ATMO_PROPERTY(BLE_Pressure, writeDataType), ATMO_PROPERTY(BLE_Pressure, readDataType), ATMO_PROPERTY(BLE_Pressure, notifyDataType)};\n\t\n\tATMO_BLE_GATTSAddCharacteristic(\n\t\tATMO_PROPERTY(BLE_Pressure, instance),\n\t\t&ATMO_VARIABLE(BLE_Pressure, bleCharacteristicHandle), \n\t\tATMO_VARIABLE(BLE_Pressure, bleServiceHandle), \n\t\tATMO_PROPERTY(BLE_Pressure, bleCharacteristicUuid), \n\t\tproperty, permission, ATMO_GetMaxValueSize(3, 64, types));\n\t\n\tATMO_BLE_GATTSRegisterCharacteristicAbilityHandle(\n\t\tATMO_PROPERTY(BLE_Pressure, instance),\n\t\tATMO_VARIABLE(BLE_Pressure, bleCharacteristicHandle), \n\t\tATMO_BLE_Characteristic_Written, \n\t\tATMO_ABILITY(BLE_Pressure, written));\n\t\n\treturn ATMO_Status_Success;\n\t",
"setValue": "\n\t\n\t// Convert to the desired write data type\n\tATMO_Value_t convertedValue;\n\tATMO_InitValue(&convertedValue);\n\tATMO_CreateValueConverted(&convertedValue, ATMO_PROPERTY(BLE_Pressure, readDataType), in);\n\n\tATMO_BLE_GATTSSetCharacteristic(\n\t\tATMO_PROPERTY(BLE_Pressure, instance),\n\t\tATMO_VARIABLE(BLE_Pressure, bleCharacteristicHandle),\n\t\tconvertedValue.size, \n\t\t(uint8_t *)convertedValue.data,\n\t\tNULL);\n\t\n\tATMO_FreeValue(&convertedValue);\n\t\t\n\treturn ATMO_Status_Success;\n\t",
"written": "\n\tATMO_CreateValueConverted(out, ATMO_PROPERTY(BLE_Pressure, writeDataType), in);\n\treturn ATMO_Status_Success;\n\t",
"subscibed": "\treturn ATMO_Status_Success;",
"unsubscribed": "\treturn ATMO_Status_Success;"
},
"variables": {
"bleServiceHandle": {
"type": "ATMO_BLE_Handle_t"
},
"bleCharacteristicHandle": {
"type": "ATMO_BLE_Handle_t"
}
},
"embeddedPropertyConversions": {
"bleServiceUuid": "string",
"bleCharacteristicUuid": "string"
},
"codeUserChanged": {
"setup": false,
"setValue": false,
"written": false,
"subscibed": false,
"unsubscribed": false
},
"instance": 0,
"bleServiceUuid": "08d41e61-ac11-40a2-a95a-e0e0fb5336f8",
"bleCharacteristicUuid": "08d41e61-ac11-40a2-a95a-e0e0fb5336fc",
"read": true,
"write": false,
"notify": true,
"readDataType": "ATMO_DATATYPE_STRING",
"writeDataType": "ATMO_DATATYPE_STRING",
"notifyDataType": "ATMO_DATATYPE_STRING"
},
"meta": {
"editorX": 600,
"editorY": 199,
"lastTrigger": "written"
},
"triggers": {
"triggered": [],
"written": [],
"subscibed": [],
"unsubscribed": []
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"setValue": "valueSet",
"written": true,
"subscibed": true,
"unsubscribed": true
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "setValue",
"triggers": []
},
{
"name": "written",
"triggers": [
"written"
]
},
{
"name": "subscibed",
"triggers": [
"subscibed"
]
},
{
"name": "unsubscribed",
"triggers": [
"unsubscribed"
]
}
]
},
{
"name": "Temperature",
"type": "EmbeddedENS210",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\tATMO_ENS210_Config_t config;\n\tconfig.address = ATMO_PROPERTY(Temperature, i2cAddress);\n\tconfig.i2cDriverInstance = ATMO_PROPERTY(Temperature, i2cInstance);\n\tconfig.tempCalibrationOffset = ATMO_PROPERTY(Temperature, tempCalibrationOffset);\n\n\treturn ( ATMO_ENS210_Init(&config) == ATMO_ENS210_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;\n",
"setEnabled": "ATMO_ENS210_SetEnabled(true);\nreturn ATMO_Status_Success;",
"setDisabled": "ATMO_ENS210_SetEnabled(false);\nreturn ATMO_Status_Success;",
"setEnabledDisabled": "bool enabled = false;\nATMO_GetBool(in, &enabled);\nATMO_ENS210_SetEnabled(enabled);\nreturn ATMO_Status_Success;",
"readTemperature": " float tempC;\n \n if(ATMO_ENS210_GetTemperatureFloat(&tempC) == ATMO_ENS210_Status_Success)\n {\n ATMO_CreateValueFloat(out, tempC);\n }\n else\n {\n ATMO_CreateValueVoid(out);\n }\n \n return ATMO_Status_Success;",
"readHumidity": " float humidityPct;\n\n if(ATMO_ENS210_GetHumidityFloat(&humidityPct) == ATMO_ENS210_Status_Success)\n {\n ATMO_CreateValueFloat(out, humidityPct);\n }\n else\n {\n ATMO_CreateValueVoid(out);\n }\n \n return ATMO_Status_Success;"
},
"variables": {},
"embeddedPropertyConversions": {},
"codeUserChanged": {
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readTemperature": false,
"readHumidity": false
},
"i2cInstance": 1,
"i2cAddress": "0x43",
"tempCalibrationOffset": -7
},
"meta": {
"editorX": 299,
"editorY": 289,
"lastTrigger": "temperatureRead"
},
"triggers": {
"triggered": [],
"temperatureRead": [
{
"mapping": {},
"targetOrder": [],
"targetElement": "BLE_Temperature",
"targetAbility": "setValue"
}
],
"humidityRead": []
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readTemperature": false,
"readHumidity": false
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "setEnabled",
"triggers": []
},
{
"name": "setDisabled",
"triggers": []
},
{
"name": "setEnabledDisabled",
"triggers": []
},
{
"name": "readTemperature",
"triggers": [
"temperatureRead"
]
},
{
"name": "readHumidity",
"triggers": [
"humidityRead"
]
}
]
},
{
"name": "BLE_Temperature",
"type": "EmbeddedBLECharacteristicCustom",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables",
"ble"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\n\tATMO_BLE_GATTSAddService(\n\t\tATMO_PROPERTY(BLE_Temperature, instance),\n\t\t&ATMO_VARIABLE(BLE_Temperature, bleServiceHandle), \n\t\tATMO_PROPERTY(BLE_Temperature, bleServiceUuid));\n\t\n\tuint8_t property = 0;\n\tuint8_t permission = 0;\n\t\n\tproperty |= ATMO_PROPERTY(BLE_Temperature, read) ? ATMO_BLE_Property_Read : 0;\n\tproperty |= ATMO_PROPERTY(BLE_Temperature, write) ? ATMO_BLE_Property_Write : 0;\n\tproperty |= ATMO_PROPERTY(BLE_Temperature, notify) ? ATMO_BLE_Property_Notify : 0;\n\n\tpermission |= ATMO_PROPERTY(BLE_Temperature, read) ? ATMO_BLE_Permission_Read : 0;\n\tpermission |= ATMO_PROPERTY(BLE_Temperature, write) ? ATMO_BLE_Permission_Write : 0;\n\n\tATMO_DATATYPE types[3] = {ATMO_PROPERTY(BLE_Temperature, writeDataType), ATMO_PROPERTY(BLE_Temperature, readDataType), ATMO_PROPERTY(BLE_Temperature, notifyDataType)};\n\t\n\tATMO_BLE_GATTSAddCharacteristic(\n\t\tATMO_PROPERTY(BLE_Temperature, instance),\n\t\t&ATMO_VARIABLE(BLE_Temperature, bleCharacteristicHandle), \n\t\tATMO_VARIABLE(BLE_Temperature, bleServiceHandle), \n\t\tATMO_PROPERTY(BLE_Temperature, bleCharacteristicUuid), \n\t\tproperty, permission, ATMO_GetMaxValueSize(3, 64, types));\n\t\n\tATMO_BLE_GATTSRegisterCharacteristicAbilityHandle(\n\t\tATMO_PROPERTY(BLE_Temperature, instance),\n\t\tATMO_VARIABLE(BLE_Temperature, bleCharacteristicHandle), \n\t\tATMO_BLE_Characteristic_Written, \n\t\tATMO_ABILITY(BLE_Temperature, written));\n\t\n\treturn ATMO_Status_Success;\n\t",
"setValue": "\n\t\n\t// Convert to the desired write data type\n\tATMO_Value_t convertedValue;\n\tATMO_InitValue(&convertedValue);\n\tATMO_CreateValueConverted(&convertedValue, ATMO_PROPERTY(BLE_Temperature, readDataType), in);\n\n\tATMO_BLE_GATTSSetCharacteristic(\n\t\tATMO_PROPERTY(BLE_Temperature, instance),\n\t\tATMO_VARIABLE(BLE_Temperature, bleCharacteristicHandle),\n\t\tconvertedValue.size, \n\t\t(uint8_t *)convertedValue.data,\n\t\tNULL);\n\t\n\tATMO_FreeValue(&convertedValue);\n\t\t\n\treturn ATMO_Status_Success;\n\t",
"written": "\n\tATMO_CreateValueConverted(out, ATMO_PROPERTY(BLE_Temperature, writeDataType), in);\n\treturn ATMO_Status_Success;\n\t",
"subscibed": "\treturn ATMO_Status_Success;",
"unsubscribed": "\treturn ATMO_Status_Success;"
},
"variables": {
"bleServiceHandle": {
"type": "ATMO_BLE_Handle_t"
},
"bleCharacteristicHandle": {
"type": "ATMO_BLE_Handle_t"
}
},
"embeddedPropertyConversions": {
"bleServiceUuid": "string",
"bleCharacteristicUuid": "string"
},
"codeUserChanged": {
"setup": false,
"setValue": false,
"written": false,
"subscibed": false,
"unsubscribed": false
},
"instance": 0,
"bleServiceUuid": "08d41e61-ac11-40a2-a95a-e0e0fb5336f8",
"bleCharacteristicUuid": "08d41e61-ac11-40a2-a95a-e0e0fb5336fb",
"read": true,
"write": false,
"notify": true,
"readDataType": "ATMO_DATATYPE_STRING",
"writeDataType": "ATMO_DATATYPE_STRING",
"notifyDataType": "ATMO_DATATYPE_STRING"
},
"meta": {
"editorX": 600,
"editorY": 289,
"lastTrigger": "written"
},
"triggers": {
"triggered": [],
"written": [],
"subscibed": [],
"unsubscribed": []
},
"interruptAbilities": {
"trigger": false,
"setup": false,
"setValue": "valueSet",
"written": true,
"subscibed": true,
"unsubscribed": true
},
"abilities": [
{
"name": "trigger",
"triggers": [
"triggered"
]
},
{
"name": "setup",
"triggers": []
},
{
"name": "setValue",
"triggers": []
},
{
"name": "written",
"triggers": [
"written"
]
},
{
"name": "subscibed",
"triggers": [
"subscibed"
]
},
{
"name": "unsubscribed",
"triggers": [
"unsubscribed"
]
}
]
},
{
"name": "Humidity",
"type": "EmbeddedENS210",
"variants": [
"embedded",
"triggers",
"abilities",
"properties",
"variables"
],
"properties": {
"errorData": {},
"code": {
"trigger": "\treturn ATMO_Status_Success;",
"setup": "\tATMO_ENS210_Config_t config;\n\tconfig.address = ATMO_PROPERTY(Humidity, i2cAddress);\n\tconfig.i2cDriverInstance = ATMO_PROPERTY(Humidity, i2cInstance);\n\tconfig.tempCalibrationOffset = ATMO_PROPERTY(Humidity, tempCalibrationOffset);\n\n\treturn ( ATMO_ENS210_Init(&config) == ATMO_ENS210_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;\n",
"setEnabled": "ATMO_ENS210_SetEnabled(true);\nreturn ATMO_Status_Success;",
"setDisabled": "ATMO_ENS210_SetEnabled(false);\nreturn ATMO_Status_Success;",
"setEnabledDisabled": "bool enabled = false;\nATMO_GetBool(in, &enabled);\nATMO_ENS210_SetEnabled(enabled);\nreturn ATMO_Status_Success;",
"readTemperature": " float tempC;\n \n if(ATMO_ENS210_GetTemperatureFloat(&tempC) == ATMO_ENS210_Status_Success)\n {\n ATMO_CreateValueFloat(out, tempC);\n }\n else\n {\n ATMO_CreateValueVoid(out);\n }\n \n return ATMO_Status_Success;",
"readHumidity": " float humidityPct;\n\n if(ATMO_ENS210_GetHumidityFloat(&humidityPct) == ATMO_ENS210_Status_Success)\n {\n ATMO_CreateValueFloat(out, humidityPct);\n }\n else\n {\n ATMO_CreateValueVoid(out);\n }\n \n return ATMO_Status_Success;"
},
"variables": {},
"embeddedPropertyConversions": {},
"codeUserChanged": {
"setup": false,
"setEnabled": false,
"setDisabled": false,
"setEnabledDisabled": false,
"readTemperature": false,
"readHumidity": false
},
"i2cInstance": 1,
"i2cAddress": "0x43",
"tempCalibrationOffset": -7
},
"meta": {
"editorX": 303,
"editorY": 384,
"lastTrigger": "humidityRead"
},
"triggers": {
"triggered": [],
"temperatureRead": [
{
"mapping": {},
"targetOrder": [],
"targetElement": "BLE_Humidity",
"targetAbility": "setValue"
}
],
"humidityRead": [
{
...
This file has been truncated, please download it to see its full contents.
Comments