78 lines
3.3 KiB
Markdown
78 lines
3.3 KiB
Markdown
# Demeter ESP - CoAP Sensor Node with Observe
|
||
|
||
CoAP (RFC 7252) sensor node firmware for ESP32/ESP8266 running MicroPython, with CoAP Observe (RFC 7641) support for real-time push notifications.
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
demeter-esp/
|
||
├── microcoapy/ # Extended microCoAPy library
|
||
│ ├── __init__.py
|
||
│ ├── coap_macros.py # Constants + COAP_OBSERVE option number
|
||
│ ├── coap_option.py # CoapOption (str-compatible)
|
||
│ ├── coap_packet.py # CoapPacket + setObserve(), getObserveValue(), setMaxAge()
|
||
│ ├── coap_reader.py # Packet parser (unchanged)
|
||
│ ├── coap_writer.py # Packet serializer (unchanged)
|
||
│ ├── microcoapy.py # Main Coap class + Observe server/client methods
|
||
│ └── observe_manager.py # Observer registry with per-resource tracking
|
||
├── config.py # WiFi, device ID, pin assignments, thresholds
|
||
├── sensors.py # Hardware abstraction for analog/digital sensors
|
||
├── main.py # Entry point: CoAP server + sensor loop
|
||
└── tests/
|
||
└── test_observe.py # Observe extension tests (runs on CPython)
|
||
```
|
||
|
||
## CoAP Resources
|
||
|
||
| URI Path | Method | Observable | Description |
|
||
|----------|--------|------------|-------------|
|
||
| `/sensors/soil_moisture` | GET | Yes (periodic) | Soil moisture 0–100% |
|
||
| `/sensors/temperature` | GET | Yes (periodic) | Temperature in °C |
|
||
| `/sensors/water_level` | GET | Yes (periodic) | Water level 0–100% |
|
||
| `/events/trigger` | GET | Yes (event-driven) | Digital input state change |
|
||
| `/device/info` | GET | No | Device metadata, uptime |
|
||
| `/config/interval` | GET, PUT | No | Read/set polling interval |
|
||
|
||
## Observe Behavior
|
||
|
||
- **Periodic sensors** (soil, temp, water): NON-confirmable notifications at configurable intervals. Only sent when value changes beyond a configurable threshold.
|
||
- **Trigger events**: CON-confirmable notifications sent immediately on GPIO state change via hardware interrupt.
|
||
- **Max observers**: 4 per resource, 8 total (configurable in `observe_manager.py`).
|
||
- **Deregistration**: Via Observe option value 1, or automatically on RST response.
|
||
|
||
## Setup
|
||
|
||
1. Flash MicroPython to your ESP32/ESP8266
|
||
2. Edit `config.py` with your WiFi credentials, device ID, and pin assignments
|
||
3. Upload all files to the board (via `mpremote`, `ampy`, or Thonny)
|
||
4. The node starts automatically and listens on UDP port 5683
|
||
|
||
## Testing with aiocoap (from Demeter server)
|
||
|
||
```bash
|
||
# Simple GET
|
||
aiocoap-client coap://ESP_IP/sensors/temperature
|
||
|
||
# Observe subscription
|
||
aiocoap-client coap://ESP_IP/sensors/soil_moisture --observe
|
||
|
||
# Set polling interval to 10 seconds
|
||
echo '{"interval": 10}' | aiocoap-client coap://ESP_IP/config/interval -m PUT
|
||
```
|
||
|
||
## Running Tests
|
||
|
||
```bash
|
||
python tests/test_observe.py
|
||
```
|
||
|
||
## Changes from upstream microCoAPy
|
||
|
||
- Added `COAP_OBSERVE = 6` to option numbers
|
||
- Added `setObserve()`, `getObserveValue()`, `setMaxAge()`, `getUriPath()` to `CoapPacket`
|
||
- Added `ObserveManager` class for server-side observer tracking
|
||
- Added `notifyObservers()`, `observeGet()`, `observeCancel()` to `Coap`
|
||
- Modified `handleIncomingRequest()` to detect and handle Observe registrations
|
||
- Added RST handling to deregister observers
|
||
- Made `CoapOption` accept `str` input (CPython compatibility)
|