> **Version:** `1`  
> **Authored by:** `Raine <raine@ixvd.net>`  
> **Status**: `planning`

# Prelude

Version 1 has zero security on itself.
This can be changed with something like TLS but that's up to the implementer.

# Structure

Packets are sent in big endian.

| offset                           | size                      | name          | description                                                                        | example      |
| -------------------------------- | ------------------------- | ------------- | ---------------------------------------------------------------------------------- | ------------ |
| `0x00`                           | 1 byte                    | `version`     | This describes the version of the packet                                           | `0x01`       |
| `0x01`                           | 4 bytes                   | `dest`        | This describes who the packet is for a.k.a. destination device id                  | `0xAABBCCDD` |
| `0x05`                           | 4 bytes                   | `src`         | This describes who sent the packet a.k.a. source device id                         | `0xAABBCCDD` |
| `0x09`                           | 4 bytes                   | `packet_id`   | This is the unique identifier of the packet                                        | `0xFAB1B39D` |
| `0x0D`                           | 4 bytes                   | `reply_to`    | This describes what this packet is replying to, if initial message, value is `0x0` | `0x00000000` |
| `0x11`                           | 1 byte                    | `command`     | This describes what kind of command is sent                                        | `0x00`       |
| `0x12`                           | 2 bytes                   | `data_length` | This describes the length of the data in bytes                                     | `0x0001`     |
| `0x14`                           | `<0x11-0x12:data_length>` | `data`        | This is the data of the command                                                    | `0x0000`     |
| `0x14 + <0x11-0x12:data_length>` | 4 bytes                   | `checksum`    | This is the CRC32 checksum of the packet without the checksum.                     | `0x00000000` |

# Packets in practice

## Statuses

When an error occurs the response should be a `0x0E` (error command).  
This can contain error data.

To mark a success, you should just send back the expected response.

## Reserved fields

The "reserved" column (if present) will state what should be filled in by each side.

- "no": this should be filled in by both sides. (default)
- "request": this should only be filled in the request.
- "response": this should only be filled in the response.

# Error checking

If the CRC32 doesn't match up the receiver will send a `0x0E` (error) packet to the probable source.  
The error code `0x01`/`net_broken_packet` should be used. The metadata may contain some textual info on what went
wrong.  
The master will not track the broken packet's `packet_id`, so the slave can send it again.

# Data types

Domo has a data framework reliant on data types.
These define what kind of data the property holds.

| `data_type` | size      | type       | description                                                            |
| ----------- | --------- | ---------- | ---------------------------------------------------------------------- |
| `0x0*`      |           |            | **Meta**                                                               |
| `0x00`      | 0 bytes   | Nothing    | Nothing                                                                |
| `0x01`      | 2+ bytes  | Array      | An array of DataTypes. first two bytes is the length in u16 BE         |
| `0x1*`      |           |            | **Basic**                                                              |
| `0x10`      | 1 byte    | Boolean    | `0x00` = false, `0x01` = true, `0x02` = toggle item (reserved for set) |
| `0x11`      | 8 bytes   | Number     | A number.                                                              |
| `0x12`      | 256 bytes | Text       | A simple bit of text.                                                  |
| `0x13`      | 4 bytes   | Identifier | An identifier.                                                         |
| `0x2*`      |           |            | **Color**                                                              |
| `0x20`      | 3 bytes   | RGB        | An RGB value.                                                          |

<!-- 
    REQ prop/get "firmware"
    RES prop/get <DataType::Identifier(0xABFF21FA)> // this is the setup packet id
    RES raw/setup size=10B
    RES raw/data [0x0000 (0x2710)] ....
 -->

## Dynamic data (`dynamic_data`)

Dynamic data is a data snippet with a `prop_data_type` byte and the data next to it.

> **Note**: this section uses relative offset

| offset | size                          | name             | description             | example |
| ------ | ----------------------------- | ---------------- | ----------------------- | ------- |
| `0x00` | 1 byte                        | `prop_data_type` | Describes the data type | `0x00`  |
| `0x01` | depending on `prop_data_type` | `data`           | The data                |         |

# Commands

These are the default commands. All Domo nodes should support these.

> **Note:** all offsets are *absolute*.

## `0x0*` - Node management

These are commands specifically for management of the nodes.

### `0x00` - Ping

Check to see if a node is up.

#### Command data

there is no command data.

### `0x01` - Register node

This command will register a node.

You can try to register as a node with a specific device_id but this might result in an error `0x03`.  
Leave `0` to get a random id.

#### Command data

| offset | size    | name        | description                                                | reserved | example      |
| ------ | ------- | ----------- | ---------------------------------------------------------- | -------- | ------------ |
| `0x14` | 4 bytes | `device_id` | the device identifier. leave `0x00000000` to get random id | no       | `0x00000000` |

### `0x02` - Remove node

Remove node from network

#### Command data

there is no extra data required.

### `0x03` - Register property

#### Command data

| offset | size     | name            | description                                                        | reserved | example |
| ------ | -------- | --------------- | ------------------------------------------------------------------ | -------- | ------- |
| `0x14` | 32 bytes | `property_name` | The name of the property as a UTF-8 string.                        | no       | "Power" |
| `0x34` | 1 byte   | `data_type`     | The type of data; see "Data types".                                | no       | `0x01`  |
| `0x35` | 1 byte   | `read_only`     | Whether the property is readonly. <br/>(`0x00` = no, `0x01` = yes) | no       | `0x00`  |

### `0x04` - Remove property

#### Command data

| offset | size     | name            | description                                 | reserved | example |
| ------ | -------- | --------------- | ------------------------------------------- | -------- | ------- |
| `0x14` | 32 bytes | `property_name` | The name of the property as a UTF-8 string. | no       | "Power" |

### `0x0E` - Error

Send a packet to state an error occurred.

#### Command data

| offset | size                          | name              | description                     | example  |
| ------ | ----------------------------- | ----------------- | ------------------------------- | -------- |
| `0x14` | 1 byte                        | `error_code`      | error code; check 'Error codes' | `0x00`   |
| `0x15` | 2 bytes                       | `metadata_length` | metadata length                 | `0x0000` |
| `0x17` | `<0x14-0x15:metadata_length>` | `metadata`        | metadata                        |          |

#### Error codes

| `status_code` | name                   | description                                                                                  | recoverable                       |
| ------------- | ---------------------- | -------------------------------------------------------------------------------------------- | --------------------------------- |
| `0x1*`        | `net_*`                | **Network errors**                                                                           |                                   |
| `0x00`        | `net_duplicate_packet` | `reply_to` packet is invalid because another packet was sent recently with same `packet_id`. | resend with different `packet_id` |
| `0x01`        | `net_broken_packet`    | recent packet was broken.                                                                    | resend packet                     |
| `0x02`        | `net_invalid_packet`   | the packet sent is not valid                                                                 | send packet with proper values    |
| `0x03`        | `net_addr_in_use`      | the addr requested is in use already                                                         | register with another id or `0`   |
| `0x04`        | `net_dest_unreachable` | the destination could not be reached                                                         | no                                |
| `0x1*`        | `errc_*`               | **Client errors**                                                                            |                                   |
| `0x10`        | `errc_not_registered`  | client is not registered                                                                     | register client                   |
| `0x2*`        | `errs_*`               | **Server errors**                                                                            |                                   |
| `0x20`        | `errs_not_delivered`   | server could not deliver packet.                                                             | depends on situation              |

## `0x1*` - Properties control

### `0x10` - Get property

Get a properties value

#### Command data

| offset | size     | name            | description                                 | reserved | example  |
| ------ | -------- | --------------- | ------------------------------------------- | -------- | -------- |
| `0x14` | 32 bytes | `property_name` | The name of the property as a UTF-8 string. | no       | "Power"  |
| `0x34` | dynamic  | `dynamic_data`  | Dynamic data snippet                        | response | `0x0100` |

### `0x11` - Set property

#### Command data

| offset | size     | name            | description                                 | reserved | example  |
| ------ | -------- | --------------- | ------------------------------------------- | -------- | -------- |
| `0x14` | 32 bytes | `property_name` | The name of the property as a UTF-8 string. | no       | "Power"  |
| `0x34` | dynamic  | `dynamic_data`  | Dynamic data snippet                        | no       | `0x0100` |

### `0x12` - Reset property

#### Command data

| offset | size     | name            | description                                 | reserved | example |
| ------ | -------- | --------------- | ------------------------------------------- | -------- | ------- |
| `0x14` | 32 bytes | `property_name` | The name of the property as a UTF-8 string. | no       | "Power" |

### `0x1A` - Subscribe to property

| offset | size     | name            | description                                 | reserved | example      |
| ------ | -------- | --------------- | ------------------------------------------- | -------- | ------------ |
| `0x14` | 4 bytes  | `device_id`     | Who's property?                             | no       | `0x00000000` |
| `0x18` | 32 bytes | `property_name` | The name of the property as a UTF-8 string. | no       | "Power"      |

### `0x1A` - Unsubscribe to property

| offset | size     | name            | description                                 | reserved | example      |
| ------ | -------- | --------------- | ------------------------------------------- | -------- | ------------ |
| `0x14` | 4 bytes  | `device_id`     | Who's property?                             | no       | `0x00000000` |
| `0x18` | 32 bytes | `property_name` | The name of the property as a UTF-8 string. | no       | "Power"      |

## `0xF*` - Raw data transmission

This is useful for things like OTA updates.  

### `0xF0` - Setup transfer

Since this procedure is quite expensive (network wise), the sides must shake hands.

#### Command data

| offset | size      | name   | description          | reserved | example |
| ------ | --------- | ------ | -------------------- | -------- | ------- |
| `0x14` | 8 bytes   | `size` | u64 size of the data | request  | `0x00`  |
| `0x1c` | 128 bytes | `mime` | media type of data   | request  | `0x00`  |

### `0xF1` - Data

This is raw data.
This may be sent without the initial transfer setup for custom implementations.

#### Command data

The `sequence_number` is added for redundancy, all data sent will always reply to it's previous data segment.

| offset | size     | name              | description                     | example      |
| ------ | -------- | ----------------- | ------------------------------- | ------------ |
| `0x14` | 4 bytes  | `sequence_number` | the sequence number of the data | `0x00000000` |
| `0x18` | 4 bytes  | `size`            | size of this slice of data      | `0x00000000` |
| `0x1c` | `<size>` | `data`            | the data                        |              |