docs(gateway): add README with architecture and MQTT interface

Assisted-by: Claude:claude-sonnet-4-6 — ASCII architecture diagram
This commit is contained in:
DjeAvd
2026-04-08 09:33:11 +01:00
committed by Klagarge
parent 2a7546fe8b
commit a5b64aeb3d

View File

@@ -1,118 +1,91 @@
# Gateway — BLE to MQTT
This component runs on a Raspberry Pi 4 and acts as the communication bridge
between the Nordic Thingy:52 sensor nodes and the rest of the system.
It reads environmental data from the nodes over BLE and publishes it to a
local MQTT broker (Mosquitto) in a structured JSON format.
## Role in the architecture
```
Thingy:52 nodes --> (BLE) --> Raspberry Pi --> (MQTT) --> Database / ML / Notifications
```
## Dependencies
Install the required Python libraries:
```bash
pip3 install bleak paho-mqtt --break-system-packages
```
Install and start the Mosquitto MQTT broker:
```bash
sudo apt install -y mosquitto mosquitto-clients
sudo systemctl enable mosquitto
sudo systemctl start mosquitto
```
## Usage
```bash
python3 gateway.py
```
At startup, the script asks for the room ID (e.g. C1, A2, B5).
It then automatically discovers all Thingy:52 nodes in range by filtering
BLE advertising packets on the Nordic Configuration service UUID (ef680100).
Each detected node is assigned a name based on the room ID and a counter
(e.g. C1_thingy1, C1_thingy2).
To run the gateway in the background and keep it running after closing SSH:
```bash
nohup python3 gateway.py > log.txt 2>&1 &
```
## MQTT topic structure
```
classroom/{room_id}/{node_id}
```
Example: `classroom/C1/C1_thingy1`
## Message format
Each message is published as a JSON object with the following structure:
```json
{
"timestamp": "2026-03-26T13:24:05.176072+00:00",
"room_id": "C1",
"node_id": "C1_thingy1",
"sensors": {
"co2_ppm": 400,
"temperature_c": 25.37,
"humidity_pct": 44
}
}
```
| Field | Type | Description |
|---|---|---|
| timestamp | string (ISO 8601 UTC) | Time of measurement, added by the gateway |
| room_id | string | Identifier of the monitored room |
| node_id | string | Identifier of the Thingy:52 node |
| co2_ppm | integer | eCO2 concentration in parts per million |
| temperature_c | float | Indoor air temperature in degrees Celsius |
| humidity_pct | integer | Relative humidity in percent |
## Output files
For each session, two local files are created in the gateway directory:
- `data_{room_id}.csv` — comma-separated file for local analysis
- `data_{room_id}.json` — JSON file following the database team format
## Publishing interval
The default publishing interval is 5 minutes (300 seconds).
This can be adjusted by modifying the `INTERVAL` variable in `gateway.py`.
## Utility scripts
- `scan.py` — scans for nearby BLE devices and prints their name and MAC address
- `check_uuid.py` — connects to Thingy:52 nodes and prints their advertised service UUIDs
## Notes on the CO2 sensor
The Thingy:52 uses a CCS811 sensor which measures eCO2 (equivalent CO2),
estimated from volatile organic compound (VOC) levels rather than directly
measuring CO2 concentration. Values should be interpreted as indicative trends
rather than precise measurements, particularly during the first 24 to 48 hours
of operation while the sensor calibrates.
## Overnight test results
An overnight test was conducted with 2 Thingy:52 nodes placed in two separate
rooms (windows closed, 7h session, 5 minute interval).
- Room 1: 4 occupants (2 adults, 2 children)
- Room 2: unoccupied
![Overnight measurements](mesures_nuit.png)
CO2 rose progressively from 400 ppm to a peak of 1071 ppm in the occupied room,
consistent with human respiration in a confined space. The unoccupied room
remained stable between 400 and 465 ppm, confirming that variations in Room 1
are directly linked to human presence.
Note: the CCS811 sensor measures eCO2 estimated from VOC levels, not direct CO2.
Occasional spikes (e.g. 877 ppm at 02:45, 1071 ppm at 03:05) may be caused by
factors such as perspiration or movement near the sensor and should be interpreted
with caution.
# Gateway
BLE-to-MQTT gateway running on a Raspberry Pi 4. Discovers Nordic Thingy:52
sensor nodes, reads environmental data over BLE and publishes it to a local
MQTT broker on each notification received.
## Architecture
Thingy:52 nodes Raspberry Pi MQTT broker
[Thingy #1] --+
|
[Thingy #2] --+--> (BLE) --> [gateway.py] --> (MQTT) --> [Mosquitto]
|
[Thingy #n] --+
The gateway discovers nodes automatically by filtering BLE advertising packets
on the Nordic Configuration service UUID (`ef680100`). Once connected, it
subscribes to GATT notifications for temperature, humidity and CO2. Each
received value triggers an immediate MQTT publication.
## MQTT interface
**Topic:** `{gateway_id}/{thingy_mac}/update`
Example: `gateway_lausanne_01/C4:64:02:60:D9:16/update`
**Payload:**
```json
{
"timestamp": "2026-04-08T07:53:28Z",
"temp": 25.37,
"humidity": 44,
"co2_ppm": 400
}
```
Fields `temp`, `humidity` and `co2_ppm` are included only once the
corresponding value has been received from the node. The CO2 sensor
requires a warm-up period of approximately 60 seconds before returning
valid readings.
## Configuration
All environment-specific parameters are defined in `config.json`:
```json
{
"gateway_id": "gateway_lausanne_01",
"mqtt": {
"broker": "localhost",
"port": 1883
},
"ble": {
"service_uuid": "ef680100-9b35-4933-9b10-52ffa9740042",
"characteristics": {
"temperature": "ef680201-9b35-4933-9b10-52ffa9740042",
"co2": "ef680204-9b35-4933-9b10-52ffa9740042",
"humidity": "ef680203-9b35-4933-9b10-52ffa9740042"
}
}
}
```
Each deployed gateway has its own `config.json`. The source code remains
identical across all deployments.
## Installation
```bash
sudo apt install -y mosquitto mosquitto-clients
sudo systemctl enable mosquitto
sudo systemctl start mosquitto
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
## Usage
```bash
source venv/bin/activate
python gateway.py
```
## Notes on the CO2 sensor
The Thingy:52 embeds a CCS811 sensor which measures eCO2 — an estimated
CO2 value derived from volatile organic compound (VOC) levels rather than
a direct CO2 measurement. Values should be interpreted as indicative trends.
The sensor requires a burn-in period of 48 hours on first use, and a warm-up
of approximately 20 minutes on each startup before readings stabilize.