# 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
