# IoT examples for HEART Hub

**A sensor that reports its health to HEART Hub in about 30 lines, on MicroPython or the Arduino core, and a bridge for devices on MQTT.**

SPDX-License-Identifier: Apache-2.0 · The manual: [HEART for IoT](../docs/HEART-for-IoT.md) · The rules: [HEART Hub profile](../spec/HEART-Monitor-1.0.md), Sections 2, 3, 5.4 to 5.6 and 7.

| File | What it is |
|---|---|
| `micropython_sensor.py` | MicroPython on an ESP32 (or any board with Wi-Fi and `urequests`) |
| `arduino_sensor/arduino_sensor.ino` | ESP32 with the Arduino core 2.x or 3.x: `WiFiClientSecure` and `HTTPClient` |
| `heart_mqtt_bridge.py` | Relays hello and reports from an MQTT broker to the Hub over HTTPS. Python 3, standard library only. |
| `test_iot_examples.py` | The tests |

## What each sensor does

1. **Once:** makes a device ID, a claim code and a key from the random source, and keeps them (`heart.json` on MicroPython, flash on the ESP32). It says hello with only their hashes, and prints its link and claim code on the console:

   ```
   HEART: register this device at https://heartcortex.ai/register?id=3f9c0a71b2d4e865 with claim code K7Q2M-9XMBA-3RTVW-HP6DZ
   ```

2. **Every 5 minutes:** reads its sensor, checks the reading itself, and sends a light report:

   ```json
   {"status": "healthy", "figures": {"sensor.volts": 1.652}, "sleepSec": 300}
   ```

   A reading outside the sensible range makes it `degraded`, with the alert `sensors.out-of-range`. When the reading is good again, the alert leaves the list and the Hub resolves it.
3. **Sleeps** in deep sleep until the next report. `sleepSec` tells the Hub, so the page shows "Asleep until …" and no "gone quiet" email is sent. Set `DEEP_SLEEP = False` to stay awake and follow the Hub's `nextSec` instead.

Neither example offers settings, so neither takes anything from the Hub. To offer one, check every request as Section 7.2 of the profile says, with the Hub's key pinned at hello.

## Before you start

- Put your Wi-Fi name and password at the top of the file. Change `HUB` if you run your own site.
- **Arduino:** paste the root certificate of your Hub into `HUB_ROOT_CA`. Find it with `openssl s_client -connect heartcortex.ai:443 -showcerts </dev/null` (the last certificate shown), and check its fingerprint with your browser. Never use `setInsecure()`: the device key travels in every report. The sketch sets the clock from NTP first, because checking a certificate needs the time.
- **MicroPython:** `urequests` on most ports does not check the server's certificate. That is fine for trying it out on your own network. For a product, use a port and version that check certificates, or the Arduino example.
- The ID, claim code and key stay on the device. Erasing its flash makes a new device, which must be registered again.

## The MQTT bridge

```sh
python3 heart_mqtt_bridge.py --broker mqtts://bridge:secret@broker.example:8883 --hub https://heartcortex.ai
```

A device publishes its hello on `heart/v1/hub/{deviceId}/hello` and its report as `{"key": ..., "report": ...}` on `heart/v1/hub/{deviceId}/report`, QoS 1, not retained. The bridge posts each one to the Hub and publishes the answer on `heart/v1/hub/{deviceId}/reply`. Let only the device publish on its topics and read its replies, and only the bridge read the reports. The bridge speaks MQTT 3.1.1 itself (CONNECT, SUBSCRIBE, PUBLISH at QoS 0 and 1), so it needs no other package.

## Tests

```sh
node heart-monitor/tools/build-worker.mjs                      # once: build the Hub
python3 iot-examples/test_iot_examples.py                      # 10 tests
HEART_MQTT_TEST_BROKER=127.0.0.1:1883 python3 iot-examples/test_iot_examples.py   # also through a real broker
```

| Test | How |
|---|---|
| MQTT packets and the relay | A socket pair plays the broker, byte for byte: CONNECT, SUBSCRIBE, PUBLISH, the reply and its PUBACK. Bad topics, bad payloads and an unreachable Hub. |
| The MicroPython example | Runs unchanged on CPython, with small stand-ins for `machine`, `network` and `urequests`, against a local copy of HEART Hub. It says hello, is registered through the web pages, reports, sleeps, raises and resolves an alert, and goes "Not heard from" only after its sleep and grace. |
| Through a broker | With `HEART_MQTT_TEST_BROKER`: a device says hello and reports through a real broker and the bridge, to a local copy of HEART Hub |
| The Arduino sketch | Not compiled here: it needs the ESP32 toolchain. Build it with the Arduino IDE or `arduino-cli compile --fqbn esp32:esp32:esp32`. |
