# OHMq Specifications

To facilitate the integration of third-party devices compatible with the *MQTT* protocol, specifications have been defined to easily communicate with an *Ohm Automation* home automation system.

## MQTT Protocol

Communication occurs over the local network using the *MQTT* protocol and requires adherence to a specific format for *topics* and *payloads*.

### Topics

Topics are generally defined as follows:

```
ohmq/<device_id>/<message_type>/<category>/<item_id>
```

Where:

* `ohmq`: required prefix.
* `device_id`: ID of the device to integrate, which must be unique. It is preferable to use the *MAC address* without the `:`.
* `message_type`: defines the type of message, such as a state message (`state`) or command (`command`).
* `category`: if the message is directed at a specific element, it indicates its category (e.g., `board`, `output`, etc.).
* `item_id`: ID of the board element to which the message refers.

For example, the topic `ohmq/a861a504ab/command/output/R1` refers to a message to execute a command on the output with ID `R1` belonging to the device `a861a504ab` (a more specific example will follow).

{% hint style="info" %}
`item_id` refers to the element ID, which is typically aligned with the coding assigned to it (e.g., written on the terminal); there are no strict constraints on the format of the ID, but it must be unique to the device. If the output represents the first relay on the board, its coding (and thus its ID) might be `R1`.
{% endhint %}

There is also a "universal" topic that all boards supporting *OHMq* specifications must subscribe to:

```
ohmq/universe
```

Messages sent to this topic must be handled by all devices, and in particular, all boards must support the [Discovery](#discovery).

### Payload

The *payload* is generally in JSON format, and its content varies depending on the type of message.

The two main types of messages are:

* `state`: state message.
* `command`: command message.

#### **Command Messages**

Command messages must always contain the `action` field, which defines the operation to be performed. For example, to turn on an output, the message would be:

```json
{
    "action": "on"
}
```

{% hint style="warning" %}
Important Command messages must always be sent with the `retain` setting set to `false`, as they should not be stored but only have value at the moment they are sent.
{% endhint %}

#### **State Messages**

State messages must be sent to notify the system of a change in the state of a given element. For example, after turning on a light, the message might be:

```json
{
    "on": true,
    "value": 255
}
```

When a button is pressed, the message would be:

```json
{
    "value": 1
}
```

{% hint style="warning" %}
Important State messages require the `retain` setting to be `true`, allowing the state to be recovered later.
{% endhint %}

## Discovery

All boards must support this functionality as it is the official way to allow the system to discover the boards.

To ensure this function, boards must *subscribe* to the `ohmq/universe` topic and respond with their configuration to the following message:

```json
{
    "action": "announce"
}
```

The configuration must be sent in JSON format and should look something like:

```json
{
    "id": "a861a504ab",
    "name": "Example",
    "model": "ESP32",
    "ip": "192.168.0.x",
    "mac": "00:00:00:00:00",
    "supported_commands": ["find", "set_network", "set_name", "restart"],
    "outputs": [{"code": "R1", "n": 14}],
    "inputs": [{"code": "I1", "n": 16}],
    "sensors": [{"code": "S1", "n": 2}]
}
```

Fields of particular interest include:

* `supported_commands`: indicates the types of commands supported by the board (e.g., `find` indicates the ability to be visually located, perhaps with a flashing or color-changing LED).
* `outputs` / `inputs`: the list of outputs/inputs managed by the board.

The configuration message should be sent to the following topic:

```
ohmq/<device_id>/hi
```

### mDNS

To enable quicker and easier implementation, support is provided for the `_mqtt._tcp.local.` service of *mDNS*, allowing connection to the broker using `ohmb-master.local` as the hostname and `1883` as the port.

## Categories

The main categories are:

* `board`: represents the board.
* `output`: for managing outputs.
* `input`: for managing digital inputs.
* `sensor`: for managing analog inputs.

### `board`

The topic for sending commands to the board is:

```
ohmb/<device_id>/command/board
```

Commands must always include the `action` parameter, which defines the operation to be performed. Here are the main operations and their corresponding *payload*.

#### **`find`**

This operation allows physically locating the board, useful if there are many devices and it is necessary to identify the correct one for wiring.

The message sent to the board will simply be:

```json
{
    "action": "find"
}
```

After receiving this message, any action that allows the visual identification of the device can be performed, such as making a dedicated LED flash.

#### **`restart`**

This operation requires restarting the board, and the message sent will be:

```json
{
    "action": "restart"
}
```

#### **`set_name`**

To ensure easy identification of the board in the configuration app, it is recommended to assign a name that allows for easy differentiation between boards. Therefore, the board must support the `set_name` command and implement a strategy for saving the assigned name.

The message received by the board will look like:

```json
{
    "action": "set_name",
    "name": "Board 1"
}
```

### `output`

Each output is defined as follows:

```json
{
    "code": "R1",
    "n": 10
}
```

Where `code` indicates the user-visible coding, such as on the terminal, and `n` represents the pin number used on the microcontroller.

When sending the board configuration, it is essential to include at least the `code` parameter, as it is used for MQTT communication.

#### **Commands**

The topic for commands sent to an output is:

```
ohmb/<device_id>/command/output/<item_id>
```

For simplicity and convenience, the board can subscribe to the topic `ohmb/<device_id>/command/output/+`, using the `_wildcard_` `+`.

As with the board, commands should be sent in JSON format with the `action` parameter, and include:

* `on`: to activate.
* `off`: to deactivate.
* `toggle`: to change the state.
* `set`: to set a value between `0` and `255` for analog outputs.
* `preset`: to set the value of an analog output without activating it, so it takes the desired value only after a subsequent activation.

For example:

```json
{
    "action": "set",
    "value": 120
}
```

#### **State**

The state of the output should be sent to the topic:

```
ohmb/<device_id>/state/output/<item_id>
```

{% hint style="warning" %}
It is crucial to send the state every time the element's value changes.
{% endhint %}

The state should be sent as follows:

```json
{
    "is_on": false,
    "value": 210
}
```

For digital (binary) outputs, the `value` parameter will be `0` (when off) or `255` (when on).

The `is_on` parameter indicates whether the output is on or off. The `value` parameter must be sent for analog outputs, even when the element is off, as it helps restore the previous state upon reactivation.

### `input`

Each input is defined as follows:

```json
{
    "code": "I1",
    "n": 16
}
```

Where `code` indicates the user-visible coding, such as on the terminal, and `n` represents the pin number used on the microcontroller.

When sending the board configuration, it is essential to include at least the `code` parameter, as it is used for MQTT communication.

#### **State**

The state of the input should be sent to the topic:

```
ohmb/<device_id>/state/input/<item_id>
```

{% hint style="warning" %}
It is crucial to send the state every time the element's value changes.
{% endhint %}

The state should be sent as follows:

```json
{
    "value": 1
}
```

Items in the `input` category are understood as digital (binary) inputs, so they only assume values `0` and `1`. For analog inputs, refer to the `sensor` category.

### `sensor`

Each sensor (analog input) is defined as follows:

```json
{
    "code": "S1",
    "n": 2
}
```

Where `code` indicates the user-visible coding, such as on the terminal, and `n` represents the pin number used on the microcontroller.

When sending the board configuration, it is essential to include at least the `code` parameter, as it is used for MQTT communication.

#### **State**

The state of the sensor should be sent to the topic:

```
ohmb/<device_id>/state/sensor/<item_id>
```

{% hint style="warning" %}
For sensors, it is advisable to limit the frequency of data transmission to avoid overloading the MQTT Broker. Except for certain types of sensors (e.g., alarm sensors), there is generally no advantage in sending real-time state changes. It is therefore advisable to implement filters (e.g., exponential smoothing).
{% endhint %}

The state should be sent as follows:

```json
{
    "value": 22.5
}
```
