# 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)