Aira source package to input data from sensors. ROS-enabled telemetry agent
The Aira package allows you to read data from a SDS011 sensor and publish to different output channels. That said Aira is able to form Demand and Result messages and a few other channels. Also it includes Datalog feature which is still experimental. It could be used to publish data to Substrate based blockchain by Robonomics.
Assuming you work under AIRA do the following:
su - liability
git clone https://github.com/airalab/sensors-connectivity
cd sensors-connectivity
nix build -f release.nix
Allow liability user to open port
/dev/ttyUSB0
Most probably a user liability is not in the dialout group
Either do
sudo adduser liability dialout
or add the line to/etc/nixos/configuration.nix
on NixOS:users.users.liability.extraGroups = [ "dialout" ];
Basically you can think of the package as a black box with one input (sensor data) and many outputs. For now only SDS011 sensor is supported but if you are familiar with Python it'd be easy to add other sensors as well.
Have a look at configuration file:
# Please DO NOT edit this file
# Make a copy instead, make changes and pass the absolute path to the copy in arguments
general:
publish_interval: 300 # time between two published messages
comstation:
port: "/dev/ttyUSB0" # COM port of the device
work_period: 300 # time between two measurements in seconds
geo: "" # Geo coordinates as latitude,longitude
public_key: "" # If not provided, COMStation creates itself
tcpstation:
address: "" # IP and PORT to listen to, for example 0.0.0.0:31313
acl: # list of known addresses. If not specified accepts from everyone
# -
# -
luftdaten:
enable: true # whether or not publish to https://luftdaten.info/
robonomics:
enable: true # enable use of Robonomics Network
ipfs_provider: "" # ipfs endpoint
ipfs_topic: "airalab.lighthouse.5.robonomics.eth"
datalog:
enable: false # enable use of Datalog Robonomics subcommand
path: "" # path to Robonomics execution file
suri: "" # private key of publisher account
remote: "wss://substrate.ipci.io"
dump_interval: 3600 # time between two transactions in seconds
dev:
sentry: ""
At the moment it's possible to publish data to Luftdaten, Robonomics Network and Datalog. The last one is experimental!
DO NOT edit
config/default.yaml
file. Instead make a copy
Play around with the configuration!
Explanation of options:
general/publish_interval
- integer number from 1 and above. Tells how often send measurements. Keep in mind that if measurements from sensors come less often than this number connectivity sends last datacomstation/port
- valid path to com port, for example/dev/ttyUSB0
. It is where a sensor is connected tocomstation/work_period
- integer from 0 to 1800. For SDS011 sensor 0 means continuous work. Recommended period is 300 secondscomstation/geo
-lat,lon
a string with two floats separated by a comma. It represents latitude and longitude of a sensorcomstation/public_key
- Ed25519 verifying key in hex format. If not provided connectivity generates a new onetcpstation/address
- what address and port listen to. If you are willing to make it open for external connections put0.0.0.0
as an address.31313
is a port chosen by developers. You can pick any port you want but don't forget to change the port in an ESP firmware.tcpstation/acl
- a list of known public keys in hex formatluftdaten/enable
- true/false. Whether or not publish data to Luftdaten. Don't forget to register sensor's mac address on the siterobonomics/enable
- true/false. Whether or not publish data to IPFS topic according to Robonomics communication protocolrobonomics/ipfs_proveder
- an endpoint for IPFS daemon. By default it's/ip4/127.0.0.1/tcp/5001/http
that means local daemon. The endpoint must by in multiaddr format. For example for Infura.io it would be/dns/ipfs.infura.io/tcp/5001/https
robonomics/ipfs_topic
- IPFS topic's name. If you want to use DApp provided by Robonomics team leave it untoucheddatalog/enable
- true/false. Enable/Disable saving log to Robonomics on Substrate chaindatalog/path
- full path torobonomics
executable file. You can find the latest release on this pagedatalog/suri
- a private key from substrate chain accountdatalog/remote
- an endpoint to substrate instancedatalog/dump_interval
- specify a period of time for collecting log in secondsdev/sentry
- for development purpose. If you have a Sentry.io account you can put sentry's credentials in here
The easiest and the most straight forward way to connect your sensor to the network is using serial port
Connect you SDS011 sensor to a USB port, let's assume it got /dev/ttyUSB0
address. Copy configuration file:
cp config/default.yaml config/my.yaml
and make it look like:
general:
publish_interval: 15 # time between two published messages
comstation:
port: "/dev/ttyUSB0" # COM port of the device
work_period: 300 # time between two measurements in seconds
geo: "59.944954,30.294534" # Geo coordinates as latitude,longitude
public_key: "" # If not provided, COMStation creates itself
tcpstation:
address: "" # IP and PORT to listen to, for example 0.0.0.0:31313
acl: # list of known addresses. If not specified accepts from everyone
# -
# -
luftdaten:
enable: true # whether or not publish to https://luftdaten.info/
robonomics:
enable: true # enable use of Robonomics Network
ipfs_provider: "" # ipfs endpoint
ipfs_topic: "airalab.lighthouse.5.robonomics.eth"
datalog:
enable: false # enable use of Datalog Robonomics subcommand
path: "" # path to Robonomics execution file
suri: "" # private key of publisher account
remote: "wss://substrate.ipci.io"
dump_interval: 3600 # time between two transactions in seconds
dev:
sentry: ""
Launch the agent:
source result/setup.bash
roslaunch sensors_connectivity agent.launch config:=/var/lib/liability/sensors-connectivity/config/my.yaml
First you need to generate a signing/verifying keys pair. To do so:
source result/setup.bash
./utils/generate_secrets.py -o ./boards/esp/ESP_TCP/
Now you have a ./boards/esp/ESP_TCP/secrest.h
file. The script also outputs verifying key, let's say it is 49de10e0762517d209b7e61d8fe47e3fc06d08609707aeb290b425847cd2ce56
Now open ./boards/esp/ESP_TCP/ESP_TCP.ino
file in Arduino IDE. Install dependencies:
- ESP Boards
- SdsDustSensor library. Could be installed by searching SdsDustSensor in
Sketch -> Include library -> Manage libraries
(Hotkey:Ctrl + Shift + I
) - Extract Crypto folder to
~/Arduino/libraries
You need to set STASSID
, STAPSK
, HOST
, GEO_LAT
, GEO_LON
. Optional: rxPin
, txPin
, work_period
, port
#ifndef STASSID
#define STASSID ""
#define STAPSK ""
#endif
#define rxPin 2 // D2 on ESP TX of the sensor is connected to RX of the board
#define txPin 3 // D3 on ESP and vice versa sensor's rx is connected to boards's tx
const char* host = "HOST";
const uint16_t port = 31313;
const float GEO_LAT = 0.0;
const float GEO_LON = 0.0;
const byte work_period = 5; // minutes
Upload the firmware
cp config/default.yaml config/my.yaml
general:
publish_interval: 15 # time between two published messages
comstation:
port: "" # COM port of the device
work_period: 300 # time between two measurements in seconds
geo: "" # Geo coordinates as latitude,longitude
public_key: "" # If not provided, COMStation creates itself
tcpstation:
address: "0.0.0.0:31313" # IP and PORT to listen to, for example 0.0.0.0:31313
acl: # list of known addresses. If not specified accepts from everyone
- 49de10e0762517d209b7e61d8fe47e3fc06d08609707aeb290b425847cd2ce56 # PUT YOUR VERIFYING KEY HERE
luftdaten:
enable: true # whether or not publish to https://luftdaten.info/
robonomics:
enable: true # enable use of Robonomics Network
ipfs_provider: "" # ipfs endpoint
ipfs_topic: "airalab.lighthouse.5.robonomics.eth"
datalog:
enable: false # enable use of Datalog Robonomics subcommand
path: "" # path to Robonomics execution file
suri: "" # private key of publisher account
remote: "wss://substrate.ipci.io"
dump_interval: 3600 # time between two transactions in seconds
dev:
sentry: ""
Do not forget to open the port in system firewall
On NixOS you can do:
networking.firewall.allowedTCPPorts = [ 31313 ];
Launch connectivity:
roslaunch sensors_connectivity agent.launch config:=/var/lib/liability/sensors-connectivity/config/my.yaml
When initialization passed power your board or reset it. It's needed because the very first data from the board is header. If connectivity doesn't receive the header it drops the connection.
If you need to connect more sensors to a single instance of connectivity repeat ESP Board Preparation for every sensor. Then add all the keys to the configuration file, restart connectivity and power up/reset every board.
In order to upload a firmware to ESP board read ESP Board Preparation section.
Connect SDS011 to a serial port.
From root
user do:
echo "https://github.com/airalab/airapkgs/archive/nixos-unstable.tar.gz nixos" > /root/.nix-channels
nix-channel --update
Then edit /etc/nixos/configuration.nix
and add:
environment.systemPackages = with pkgs; [
substrate-node-robonomics-bin
];
Run rebuild and find out where robonomics
is:
nixos-rebuild switch
whereis robonomics
Let's assume you got the following path: /nix/store/2gz2ik17w5xad8w819bsb05a23pbjbya-system-path/bin/robonomics
general:
publish_interval: 15 # time between two published messages
comstation:
port: "/dev/ttyUSB0" # COM port of the device
work_period: 300 # time between two measurements in seconds
geo: "59.944954,30.294534" # Geo coordinates as latitude,longitude
public_key: "" # If not provided, COMStation creates itself
tcpstation:
address: "0.0.0.0:31313" # IP and PORT to listen to, for example 0.0.0.0:31313
acl: # list of known addresses. If not specified accepts from everyone
- 49de10e0762517d209b7e61d8fe47e3fc06d08609707aeb290b425847cd2ce56 # PUT YOUR VERIFYING KEY HERE
luftdaten:
enable: true # whether or not publish to https://luftdaten.info/
robonomics:
enable: true # enable use of Robonomics Network
ipfs_provider: "" # ipfs endpoint
ipfs_topic: "airalab.lighthouse.5.robonomics.eth"
datalog:
enable: false # enable use of Datalog Robonomics subcommand
path: "/nix/store/2gz2ik17w5xad8w819bsb05a23pbjbya-system-path/bin/robonomics" # path to Robonomics execution file
suri: "0x....." # private key of publisher account
remote: "wss://substrate.ipci.io"
dump_interval: 3600 # time between two transactions in seconds
dev:
sentry: ""
Start connectivity first and then all your boards:
su - liability
cd sensors-connectivity
source result/setup.bash
roslaunch sensors_connectivity agent.launch config:=/var/lib/liability/sensors-connectivity/config/my.yaml
It's way more convenient to launch the code as a systemd service. Add the following in /etc/nixos/configuration.nix
:
systemd.services.connectivity = {
requires = [ "roscore.service" ];
after = ["roscore.service" ];
wantedBy = [ "multi-user.target" ];
environment.ROS_MASTER_URI = "http://localhost:11311";
script = ''
source /var/lib/liability/sensors-connectivity/result/setup.bash \
&& roslaunch sensors_connectivity agent.launch config:=/var/lib/liability/sensors-connectivity/config/my.yaml
'';
serviceConfig = {
Restart = "on-failure";
StartLimitInterval = 0;
RestartSec = 60;
User = "liability";
};
};
Technically it's not necessary to specify the default.yaml
configuration file, but if you did changes please put the absolute path to config
parameter.
After that run nixos-rebuild switch
. The service should be up and running
Usually log files are stored in /var/lib/liability/.ros/log/latest/connectivity-worker-1.log
To view logs do:
tail -f /var/lib/liability/.ros/log/latest/connectivity-worker-1.log
Also you can use journalctl
but remember output is buffered so it could take some time before output appears
journalctl -u connectivity -f
Example of output:
root@hq-nuc-sds011> tail /var/lib/liability/.ros/log/latest/connectivity-worker-1.log -f
[rosout][INFO] 2020-06-02 13:55:48,427: Starting process...
[rosout][INFO] 2020-06-02 13:55:48,430: airalab-com-v0.1.0: [{MAC: 94c6911b42d6, Uptime: 0:00:30.997699, M: {Public: 4aebc455889ee993a615c479eb069079f643a8210aca0c866f0a7d126b8160f2, PM2.5: 8.3, PM10: 16.7, geo: (0.0,0.0), timestamp: 1591091717}}]
[rosout][INFO] 2020-06-02 13:55:48,520: new connection from ('192.168.20.23', 57336)
[rosout][INFO] 2020-06-02 13:55:48,865: LuftdatenFeeder: sent successfuly
[rosout][INFO] 2020-06-02 13:55:48,868: RobonomicsFeeder: {"4aebc455889ee993a615c479eb069079f643a8210aca0c866f0a7d126b8160f2": {"model": 2, "timestamp": 1591091717, "measurement": {"pm25": 8.3, "pm10": 16.7, "geo": "0.0,0.0"}}}
[rosout][INFO] 2020-06-02 13:55:48,877: airalab-tcp-v0.1.0: []
[rosout][INFO] 2020-06-02 13:55:50,524: Peer name: ('192.168.20.23', 57336)
[rosout][INFO] 2020-06-02 13:55:50,527: Unknown peer yet
[rosout][INFO] 2020-06-02 13:55:50,531: Welcome to the party: (5dff08595b74db99a997dab6cab851092d27373168f5b04c1035fd2c0a520ee3,2)
[rosout][INFO] 2020-06-02 13:56:03,880: Starting process...
[rosout][INFO] 2020-06-02 13:56:03,884: airalab-com-v0.1.0: [{MAC: 94c6911b42d6, Uptime: 0:00:46.451368, M: {Public: 4aebc455889ee993a615c479eb069079f643a8210aca0c866f0a7d126b8160f2, PM2.5: 8.3, PM10: 16.7, geo: (0.0,0.0), timestamp: 1591091717}}]
[rosout][INFO] 2020-06-02 13:56:04,241: LuftdatenFeeder: sent successfuly
[rosout][INFO] 2020-06-02 13:56:04,246: RobonomicsFeeder: {"4aebc455889ee993a615c479eb069079f643a8210aca0c866f0a7d126b8160f2": {"model": 2, "timestamp": 1591091717, "measurement": {"pm25": 8.3, "pm10": 16.7, "geo": "0.0,0.0"}}}
[rosout][INFO] 2020-06-02 13:56:04,266: airalab-tcp-v0.1.0: []
[rosout][INFO] 2020-06-02 13:56:14,330: Peer name: ('192.168.20.23', 57336)
[rosout][INFO] 2020-06-02 13:56:14,334: I know you buddy!
[rosout][INFO] 2020-06-02 13:56:14,340: {Public: 5dff08595b74db99a997dab6cab851092d27373168f5b04c1035fd2c0a520ee3, PM2.5: 3.8, PM10: 7.1, geo: (53.507675,49.252785), timestamp: 1591091774}