242 lines
7.1 KiB
Markdown
242 lines
7.1 KiB
Markdown
# Device Discovery Specification
|
|
|
|
This specification defines the format and protocol that microcontroller-based IoT devices must follow to register themselves with the Lambda IoT Core system.
|
|
|
|
## Overview
|
|
|
|
At boot, each device must submit a single JSON message containing:
|
|
- Device information (name, description, location)
|
|
- List of sensors
|
|
- List of actors (actuators)
|
|
|
|
All UUIDs are **deterministically generated** based on the device's MAC address to ensure consistency across reboots.
|
|
|
|
## UUID Generation
|
|
|
|
### Device UUID
|
|
Generate a UUID v5 using:
|
|
- **Namespace**: `6ba7b810-9dad-11d1-80b4-00c04fd430c8` (DNS namespace)
|
|
- **Name**: Device MAC address in lowercase, no separators (e.g., `aabbccddeeff`)
|
|
|
|
### Sensor UUID
|
|
Generate a UUID v5 using:
|
|
- **Namespace**: Device UUID
|
|
- **Name**: `sensor-{N}` where N is the 0-based sensor index
|
|
|
|
### Actor UUID
|
|
Generate a UUID v5 using:
|
|
- **Namespace**: Device UUID
|
|
- **Name**: `actor-{N}` where N is the 0-based actor index
|
|
|
|
## Discovery Message Format
|
|
|
|
### MQTT Topic
|
|
Devices must publish to: `{MQTT_TOPIC}/discovery`
|
|
|
|
Where `{MQTT_TOPIC}` is the configured MQTT topic (e.g., `lambdaiot`, resulting in `lambdaiot/discovery`)
|
|
|
|
### Message Structure
|
|
|
|
```json
|
|
{
|
|
"mac_address": "aa:bb:cc:dd:ee:ff",
|
|
"device": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"name": "Living Room Sensor",
|
|
"description": "Multi-sensor device for home monitoring",
|
|
"location": "Living Room",
|
|
"status_id": 1
|
|
},
|
|
"sensors": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440001",
|
|
"name": "Temperature",
|
|
"type": "DHT22",
|
|
"data_type_id": 2
|
|
},
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440002",
|
|
"name": "Humidity",
|
|
"type": "DHT22",
|
|
"data_type_id": 2
|
|
},
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440003",
|
|
"name": "Motion",
|
|
"type": "PIR",
|
|
"data_type_id": 1
|
|
}
|
|
],
|
|
"actors": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440004",
|
|
"name": "LED",
|
|
"type": "RGB_LED",
|
|
"data_type_id": 1
|
|
},
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440005",
|
|
"name": "Fan",
|
|
"type": "PWM_FAN",
|
|
"data_type_id": 2
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Field Definitions
|
|
|
|
### Device Object
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `id` | UUID string | Yes | Deterministic UUID v5 based on MAC |
|
|
| `name` | String | Yes | Human-readable device name |
|
|
| `description` | String | No | Device description |
|
|
| `location` | String | No | Physical location (e.g., "Living Room") |
|
|
| `status_id` | Integer | Yes | Status code: 1=ok, 2=pending, 3=lost, 4=disabled |
|
|
|
|
### Sensor/Actor Object
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `id` | UUID string | Yes | Deterministic UUID v5 (device UUID + "sensor-N" or "actor-N") |
|
|
| `name` | String | Yes | Human-readable sensor/actor name |
|
|
| `type` | String | Yes | Hardware type (e.g., "DHT22", "PIR", "RGB_LED") |
|
|
| `data_type_id` | Integer | Yes | Data type: 1=bool, 2=float |
|
|
|
|
### Root Object
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `mac_address` | String | Yes | Device MAC address (lowercase with colons) |
|
|
| `device` | Object | Yes | Device information |
|
|
| `sensors` | Array | Yes | Array of sensor objects (can be empty) |
|
|
| `actors` | Array | Yes | Array of actor objects (can be empty) |
|
|
|
|
## Behavior
|
|
|
|
### On First Boot
|
|
1. Device generates deterministic UUIDs based on its MAC address
|
|
2. Device publishes discovery message to `{MQTT_TOPIC}/discovery`
|
|
3. Backend receives message, creates device record with status_id=1 (ok)
|
|
4. Sensors and actors are created
|
|
|
|
### On Subsequent Boots
|
|
1. Device uses same deterministic UUIDs (based on MAC)
|
|
2. Device publishes discovery message again
|
|
3. Backend detects existing device by UUID
|
|
4. Device details (name, description, location) are updated
|
|
5. Sensors/actors are synchronized:
|
|
- New sensors/actors are added
|
|
- Existing sensors/actors with same ID but different properties are updated
|
|
- Sensors/actors no longer in the message are deleted
|
|
6. Device status is set to ok (1)
|
|
|
|
### Conflict Resolution
|
|
- If a device UUID already exists, it is updated rather than creating a duplicate
|
|
- Sensors and actors are matched by UUID, not by position
|
|
- Removing a sensor/actor from the discovery message will delete it from the database
|
|
|
|
### UUID Collision Handling
|
|
Devices with different MACs will generate different UUIDs. If two devices somehow share the same MAC (misconfiguration), they will overwrite each other's records. This is acceptable as MAC duplication is a network configuration error.
|
|
|
|
## Data Type Codes
|
|
|
|
| Code | Type | Description |
|
|
|------|------|-------------|
|
|
| 1 | bool | Boolean value (true/false or 0/1) |
|
|
| 2 | float | Floating-point numeric value |
|
|
|
|
## Status Codes
|
|
|
|
| Code | Status | Description |
|
|
|------|--------|-------------|
|
|
| 1 | ok | Device is functioning normally |
|
|
| 2 | pending | Device is initializing |
|
|
| 3 | lost | Device has not checked in recently |
|
|
| 4 | disabled | Device has been administratively disabled |
|
|
|
|
## Example Device Implementations
|
|
|
|
### Minimal Device (1 sensor, no actors)
|
|
```json
|
|
{
|
|
"mac_address": "aa:bb:cc:dd:ee:ff",
|
|
"device": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"name": "Temperature Sensor",
|
|
"description": "",
|
|
"location": "",
|
|
"status_id": 1
|
|
},
|
|
"sensors": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440001",
|
|
"name": "Temp",
|
|
"type": "DHT22",
|
|
"data_type_id": 2
|
|
}
|
|
],
|
|
"actors": []
|
|
}
|
|
```
|
|
|
|
### Complex Device (3 sensors, 2 actors)
|
|
```json
|
|
{
|
|
"mac_address": "11:22:33:44:55:66",
|
|
"device": {
|
|
"id": "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
|
|
"name": "Greenhouse Controller",
|
|
"description": "Automated greenhouse monitoring and control",
|
|
"location": "Greenhouse A",
|
|
"status_id": 1
|
|
},
|
|
"sensors": [
|
|
{
|
|
"id": "6ba7b812-9dad-11d1-80b4-00c04fd430c8",
|
|
"name": "Temperature",
|
|
"type": "DHT22",
|
|
"data_type_id": 2
|
|
},
|
|
{
|
|
"id": "6ba7b813-9dad-11d1-80b4-00c04fd430c8",
|
|
"name": "Humidity",
|
|
"type": "DHT22",
|
|
"data_type_id": 2
|
|
},
|
|
{
|
|
"id": "6ba7b814-9dad-11d1-80b4-00c04fd430c8",
|
|
"name": "Soil Moisture",
|
|
"type": "Capacitive",
|
|
"data_type_id": 2
|
|
}
|
|
],
|
|
"actors": [
|
|
{
|
|
"id": "6ba7b815-9dad-11d1-80b4-00c04fd430c8",
|
|
"name": "Irrigation Pump",
|
|
"type": "Relay",
|
|
"data_type_id": 1
|
|
},
|
|
{
|
|
"id": "6ba7b816-9dad-11d1-80b4-00c04fd430c8",
|
|
"name": "Ventilation Fan",
|
|
"type": "PWM",
|
|
"data_type_id": 2
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Notes for Device Developers
|
|
|
|
- Always use the same UUID generation algorithm to ensure consistency
|
|
- Preserve sensor/actor order to maintain deterministic IDs
|
|
- If hardware changes (sensors added/removed), rearrange the array to maintain backward compatibility, or accept that indices will shift
|
|
- Include sufficient description and location information for users to identify devices
|
|
- Set status_id to 1 (ok) on successful boot
|
|
- Consider publishing discovery message periodically (e.g., every 5 minutes) as a heartbeat
|
|
- Use MQTT QoS 1 (at-least-once) for discovery messages
|