Pheromon is a open innovation project to deploy, administrate and harvest data from a swarm of sensors. It has been developed in the scope of project 6element dedicated to waste optimisation, and is now in production on the projet vamos.
Use our open API, you can have a look at the dedicated wiki.
Pheromon communicates with sensors over TCP using MQTT protocol. The MQTT broker dispatches the messages depending on the publish/subscribe status of various clients on various subjects. For example, a meteorological sensor will publish on the topics rain
and temperature
while a sensor measuring peoples fluxes will publish on wifidevices
and bluetoothdevices
. Meanwhile, the admin interface can publish to all sensors on the all
topic, or to one particular sensor on mySensorId
topic.
All the messages are persisted in a database that can be queried by a API able to answer queries like "give me all mesaurements of sensor X since Y".
Two clients are available for now.
The Dashboard is useful to visualize the measurements on a map.
You can also administrate your sensors with the Admin.
More on those clients later.
- clone the repository :
git clone git@github.com:anthill/pheromon.git
cd pheromon
-
Copy / Create the files
PRIVATE/*.json
-
Install dependencies
npm install
Use this for development.
npm run dev
Use npm run stop-dev
to stop.
Use this for production.
npm run prod // launch the service
- Initialisation If you run a service without an initialized db, you need to
node database/management/init-db.js
- Backups and restore : At anytime you can backup the db using
node database/management/backup.js > backups/test.sql
or restore an previous db with
node database/management/restore.js backups/test.sql
you can also use a gziped file (comming from the automated backup for example).
MQTT is the communication protocol between the server and the sensors.
The communication protocol is composed of 3 elements:
- broker: authenticates clients and relays messages
- sensor: client
- maestro: client, on the kerrigan server
From sensor to maestro:
init/mySensorSimId
, when sensor needs to initialize. There is no content.status/mySensorSimId/type
, when a sensor status updates. The content is a string describing the actual status.measurement/mySensorSimId/type
, when a measurement is sent from sensor. The content is an array of measurements.cmdResult/mySensorSimId
, when a sensor processed a command sent from maestro. The content is a string describing the output of the command.
From maestro to sensor:
mySensorSimId
, when maestro sends command to sensor. The content is a string of the command.all
, when maestro sends command to all registered sensors. The content is a string of the command.
We don't want sensors to have a manually hard-coded id (for deployment's simplicity) so we use mac addresses of devices:
Sequence
- [sensor] when powering up, sensor tries to connect to MQTT broker with authentification token.
- [broker] authenticates sensor.
- [sensor] when authenticated, sensor subscribes to
mySensorSimId
andall
topics, then sends an empty message oninit/mySensorSimId
topic. - [maestro] receives message, checks
mySensorSimId
in DB, creates Sensor if needed, and sends back [init
,parameters
] onsimId
topic. - [sensor] receives message, initializes its
parameters
and routines.
Each time the sensor's status changes, a message is sent to the maestro to update the DB and react accordingly depending on the situation. Status can be of 3 types:
client
: state of communication between sensor and kerrigan serversignal
: power of signal between sensor and kerrigan serverwifi
: wifi monitoring state of sensorblue
: bluetooth monitoring state of sensor
Sequence
- [somewhere] something happens that changes the sensor
type
status tonewStatus
. - [sensor] sends
newStatus
onstatus/mySensorSimId/type
topic. - [maestro] receives message, check
mySensorSimId
in DB, creates Sensor if needed, and updates sensor in DB.
By default, sensor has measurement capabilities (for wifi and bluetooth). Every n
minutes, sensor send measurements to kerrigan server to be recorded in DB.
Sequence
- [time passing]
n
minutes has passed since last measurement onmeasurementType
. - [sensor] wraps collected information into
measurementContent
and sendsmeasurementContent
onmeasurement/mySensorSimId/measurementType
topic. - [maestro] receives message, check
mySensorSimId
in DB, creates Sensor if needed, and then creates Measurement in DB.
You can send commands to the sensors.
Sequence
- [some admin client] sends a
command
to[mySensorSimId]
through socketIO. - [maestro] receives
command
from client, and forwards it to the corresponding sensors through MQTT. - [sensor] receives message, execute
command
, and sends back the result of the command on the topiccmdResult/mySensorSimId
- [maestro] receives message, check
mySensorSimId
in DB, creates Sensor if needed, and then updates Sensor in DB.
You can run Pheromon tests in a dedicated docker.
You can use
npm run test
- Create a user
sudo useradd -m sensorSSH;
sudo passwd sensorSSH;
- Create ssh keys for the user
su sensorSSH -c 'ssh-keygen -t rsa -b 4096';
-
Add the sensor public key to the authorized_keys and vice-versa
-
Add group docker to the user
sudo usermod -G docker sensorSSH;
- Add theses lines to
/etc/ssh/sshd_config
AllowTcpForwarding yes
GatewayPorts yes
- Disable the user (chrooting it would be great)
sudo usermod -s /usr/sbin/nologin sensorSSH;
add "ip": ...
in pheromon secret.json
where kerrigan is the name of the host in .ssh/config
There are 2 PRIVATE files:
secret.json
: this file is very sensitive. Leaking it would potentially allow people to access your db, server, sensors, etc... It should not be required in non protected clients. Here, the only client that requires it isAdmin
, whose access is protected byhtml_token
.
{
"server_ip": ..., // your server ip, used by the sensor updater
"html_token": ..., // token you should use to protect the access to your Admin client or database API
"mqtt_user": ..., // username for mqtt
"mqtt_token": ..., // MQTT for the broker to authenticate sensor
"cmd_token": ... // token to allow cmd sending to sensor
}
server_ip
is used in api/maestro.js
.
html_token
is used in api/api.js
and api/routes.js
.
cmd_token
is used in api/maestro.js
and api/clients/Admin/src/main.js
.
mapbox.json
: this file is not very sensitive. It only contains mapbox infos
{
"token": ..., // token for your mapbox account
"map_id": ..., // id of your map background,
"center": [16.1496297,-61.39705]
}
Both mapbox.json
fields are used in api/clients/Dashboard/src/main.js
.
-
Clone the repository.
-
Create a new branch to work in.
-
Make a pull request explaining why and what you changed.