# MQTT Entry Point

Proxy MQTT publish and subscribe traffic to an MQTT/MQTTS broker.

This entry point accepts MQTT actions from an Air for Cellular device and forwards the action to an MQTT broker via MQTT or MQTTS. Both _publish_ (from device to broker) and _subscribe_ (receive messages from the broker) are supported.

## Versions

When using the Beam MQTT entry point, you may select between version `201509` and `201912`.

> [!NOTE]
>
> As of January 2022, MQTT entry point version `201509` has been officially deprecated. While version `201509` can still be selected for use, technical support cannot be provided for it, and it will be removed as an option entirely in the future. For these reasons, Soracom suggests that all new configurations be created using version `201912`.

> [!NOTE]
>
> Beam does not support MQTT protocol v5.

### Protocol Behavior

Version `201509` is based on MQTT protocol v3.1.1, but with the following limitations:

- Will property is not supported and will be ignored.
- Beam does not save the session state, however it will transfer clean session parameters to the MQTT broker as-is.
- QoS levels `1` and `2` are not supported. A client may send a message to Beam with QoS `1` or `2`, however Beam will not guarantee the delivery of the message to the destination MQTT broker.
- If you specify a QoS level that is not supported by the destination MQTT broker, the connection may be disconnected by the broker.
- When connecting to Azure IoT Hub or Google IoT Core, Beam will connect to the destination MQTT broker using MQTT protocol v3.1.1 regardless of the version specified by the client.

When using version `201912`:

- The available MQTT features depend the MQTT protocol versions supported by the destination MQTT broker. It is recommended to check the MQTT protocol versions supported by the destination MQTT broker, and then explicitly specify the MQTT protocol version on the client.
- Similarly, Beam will connect to the destination MQTT broker using the protocol version specified by the client.

> [!NOTE]
>
> In particular, when connecting to Azure IoT Hub or Google IoT Core, Beam will no longer override the MQTT protocol version used to connect to the destination MQTT broker. As Azure IoT Hub and Google IoT Core do not support MQTT protocol v3.1, a connection error will occur if the client connects to Beam while specifying MQTT protocol v3.1.
>
> When changing from Beam MQTT entry point version `201509` to version `201912`, ensure that your client is updated to specify MQTT protocol v3.1.1.

- When connecting to the Beam MQTT entry point, keepalive can be set to `0`, or an integer greater than or equal to `5` and less than or equal to `1200`. If you set any other value, the `NOT_AUTHORIZED` code will be returned in the connect request.

### Authentication

When using version `201509`, if the client cert option is enabled, Beam will connect to the destination MQTT broker using MQTTS regardless of the configured destination protocol.

On the other hand, when using version `201912`, Beam will connect to the destination MQTT broker using the configured destination protocol, regardless of whether the client cert option is enabled.

### Billing

Beam is billed according to the number of requests made. When using the MQTT entry point with version `201509`, each of the following events is counted as an individual request:

- A client sending a `SUBSCRIBE`, `PUBLISH`, `PINGREQ`, or `UNSUBSCRIBE` command to Beam.
- Beam sending the `SUBSCRIBE`, `PUBLISH`, `PINGREQ`, or `UNSUBSCRIBE` command to a destination MQTT broker.
- A destination broker sending a message to Beam as a result of a `PUBLISH` command.
- Beam sending the message to the client.

Version `201912` also treats the above events as individual requests, however `PINGREQ` commands are not counted.

For both versions, Beam fees do not apply for Air for Cellular devices when the corresponding group is attached to a customer VPG.

## Configuration

### Entry Point

Your device should be configured to publish or subscribe to topics on: `beam.soracom.io:1883`. The maximum message size of a request is not limited by Beam's MQTT entry points.

### Parameters

- **Configuration name** (_string_, required) - A string to identify this configuration.

- **Destination** - The forwarding destination.

  - **Type** (required) - Select the destination MQTT broker. Depending on the selected broker, additional parameters will be set automatically.
  - **Protocol** (`MQTT` or `MQTTS`, required) - The protocol to use for transferring MQTT actions.
  - **Host name** (_string_, required) - The FQDN of the destination broker.
  - **Port number** (_number_, required) - The port number of the destination broker.
  - **Username** (_string_, optional) - The username to send to the destination broker for authentication. Use the `#{imsi}` or `#{imei}` placeholders to automatically insert the subscriber IMSI or device IMEI in the field.
  - **Password** (_string_, optional) - The password to send to the destination broker for authentication. Use the `#{imsi}` or `#{imei}` placeholders to automatically insert the subscriber IMSI or device IMEI in the field.
  - **Passthrough** (optional) - Instead of sending authentication credentials defined in the **Username** and **Password** parameters, this option will allow the device to send its own username and password to the destination broker.
  - **Client cert** (optional) - Enables or disables using X.509 certificates for authentication.
  - **Credential Set** (optional) - Select the X.509 certificate to use for authentication. Use the `#{imsi}` or `#{imei}` placeholders to automatically insert the subscriber IMSI or device IMEI in the field.

- **Options** - Additional MQTT options.

  - **Copy to Soracom Harvest Data** (optional) - Simultaneously send the topic and payload content to Soracom Harvest Data.
  - **Append IMSI to topic** (optional) - Enables or disables appending the IMSI of the subscriber to the MQTT topic.
  - **Use the connected device information in topics** (optional) - When enabled, automatically replace `{{ "{{imsi}}" }}`, `{{ "{{simId}}" }}`, and `{{ "{{imei}}" }}` placeholders in the MQTT topic with the subscriber IMSI or SIM ID and device IMEI.
  - **Platform Version** (required) - Select the Beam MQTT entry point version to use. See [Versions](https://docs.soracom.io/en/services/beam/mqtt/#versions).

### Multiple Credentials

When the **Client cert** option is enabled, you can select an X.509 certificate in the **Credential Set** parameter that Beam will use for authenticating the connection to your MQTT broker. By default, selecting a single **Credential Set** will tell Beam to use the same X.509 certificate credentials no matter which device is connecting to the Beam MQTT entry point.

You can alternatively use a `#{imsi}` or `#{imei}` placeholder variable in the **Credential Set** parameter. When a device connects to the Beam MQTT entry point, Beam will subtitute the placeholder variable with the subscriber IMSI or device IMEI, and then use the credential set that matches the resulting ID.

For example, by registering the following X.509 certificates:

- **Credential Set 1**

  - **ID** - `device-295050012345678`
  - **Credentials** - X.509 certificate (certificate, private key, root CA)

- **Credential Set 2**

  - **ID** - `device-295050012345679`
  - **Credentials** - X.509 certificate (certificate, private key, root CA)

Then when the **Credential Set** parameter is set to `device-#{imsi}`, Beam will dynamically select the correct credential set when either device connects to the Beam MQTT entry point.

### Default Credentials

In some situations, Beam will not be able to find a matching **Credential Set**. This may occur because you are using a new SIM or device, and have not yet registered a new set of X.509 certificates that will be used for that subscriber IMSI or device IMEI.

If Beam cannot find a **Credential Set** that matches the ID, it will then replace the `#{imsi}` or `#{imei}` placeholder variable with the string `default` and attempt to find a credential set that matches the resulting ID. In the example above, if a device using a SIM with IMSI `295050012345680` connects to the Beam MQTT entry point, Beam will not be able to find any credential sets that match the `device-295050012345680` ID, and will instead look for a credential set that matches the `device-default` ID.

By registering a **Default Credential** with the ID `device-default`, you can ensure that devices are still able to securely connect to your MQTT broker. Depending on your MQTT broker, you may choose to enforce specific security policies associated with this default credential, such as limiting devices to requesting provisioning on a specific MQTT topic, and blocking their ability to transmit data until provisioning is complete.

> [!NOTE]
>
> When using the `#{imsi}` placeholder, Beam will always be able to infer the subscriber IMSI. The `default` string is used only when a credential set that matches the ID is not found.
>
> On the other hand, when using the `#{imei}` placeholder, the `default` string will be used in both of the following situations:
>
> - The device IMEI is reported from the network, but a matching credential set is not found.
> - The device IMEI is not reported from the network.

## Behavior

### Publish Example

When publishing a message, our device output looks something like this:

```bash
mosquitto_pub -h beam.soracom.io -p 1883 -t mytopic -m message -d

Client mosqpub/my-device sending CONNECT
Client mosqpub/my-device received CONNACK
Client mosqpub/my-device sending PUBLISH (d0, q0, r0, m1, 'mytopic', ... (7 bytes))
Client mosqpub/my-device sending DISCONNECT
```

If we inspect the MQTT broker, we should see our message:

```bash
1482290763: New connection from 52.198.245.54 on port 8080.
1482290763: New client connected from 52.198.245.54 as mosqpub/my-device (c1, k60).
1482290763: Sending CONNACK to mosqpub/my-device (0, 0)
1482290767: Received PUBLISH from mosqpub/my-device (d0, q0, r0, m0, 'mytopic/295000012345678', ... (7 bytes))
1482290767: Received DISCONNECT from mosqpub/my-device
1482290767: Client mosqpub/my-device disconnected.
```

In this example, **Append IMSI to topic** is enabled. When our MQTT broker receives the publish message action, the topic has been updated to include the IMSI of our subscriber.

### Subscribe Example

Subscribing to a topic works similarly. Here, we will use two subscribers, with one subscribing to an MQTT topic on our broker, and the other publishing a message on that topic.

On our subscribing device:

```bash
mosquitto_sub -h beam.soracom.io -p 1883 -t mytopic -d
Client mosqsub/my-subscriber sending CONNECT
Client mosqsub/my-subscriber received CONNACK
Client mosqsub/my-subscriber sending SUBSCRIBE (Mid: 1, Topic: test, QoS: 0)
Client mosqsub/my-subscriber received SUBACK
Subscribed (mid: 1): 0
```

On our broker, we can confirm that our first device has subscribed:

```bash
1482291094: New connection from 52.198.245.54 on port 8080.
1482291094: New client connected from 52.198.245.54 as mosqsub/my-subscriber (c1, k60).
1482291094: Sending CONNACK to mosqsub/my-subscriber (0, 0)
1482291094: Received SUBSCRIBE from mosqsub/my-subscriber
1482291094:     mytopic (QoS 0)
1482291094: mosqsub/my-subscriber 0 mytopic
1482291094: Sending SUBACK to mosqsub/my-subscriber
```

When we publish a message from our second device, our MQTT broker should report:

```bash
1482291169: New connection from 127.0.0.1 on port 8080.
1482291169: New client connected from 127.0.0.1 as mosqpub/my-publisher (c1, k60).
1482291169: Sending CONNACK to mosqpub/my-publisher (0, 0)
1482291169: Received PUBLISH from mosqpub/my-publisher (d0, q0, r0, m0, 'mytopic', ... (7 bytes))
1482291169: Sending PUBLISH to mosqsub/my-subscriber (d0, q0, r0, m0, 'mytopic', ... (7 bytes))
1482291169: Received DISCONNECT from mosqpub/my-publisher
1482291169: Client mosqpub/my-publisher disconnected.
```

And on our first device, we will receive the published message:

```bash
Client mosqsub/my-subscriber received PUBLISH (d0, q0, r0, m0, 'test', ... (7 bytes))
message
```

## Advanced Configuration

The MQTT entry point can also be configured through the Soracom API or CLI by using the **SoracomBeam** namespace.

Configuration should be performed using `mqtt://beam.soracom.io:1883` as the configuration **key** value.

### Parameters

- **key** (_string_, required) - `mqtt://beam.soracom.io:1883`

- **value** (_object_, required) - The configuration parameters.

  - **name** (_string_, optional) - Name to identify this configuration.
  - **destination** (_string_, required) - Scheme, hostname, and port of the forwarding destination.
  - **enabled** (_boolean_, required) - Enables or disables the configuration.
  - **fork** (_object_, optional) - Enables or disables sending a copy of the topic and payload of `PUBLISH` events to other Soracom services.
    - **SoracomHarvest** (_boolean_, optional) - Enables or disables sending a copy to Harvest Data.
  - **username** (_string_, optional) - The username used to connect to the MQTT broker. Use the `#{imsi}` or `#{imei}` placeholders to automatically insert the subscriber IMSI or device IMEI in the field.
  - **password** (_string_, optional) - The password used to connect to the MQTT broker. Use the `#{imsi}` or `#{imei}` placeholders to automatically insert the subscriber IMSI or device IMEI in the field.
  - **useClientCredentials** (_boolean_, optional) - Enables or disables using the **username** and **password** provided by the MQTT client, rather than the **username** and **password** specified in the parameters above.
  - **useClientCert** (_boolean_, required) - Enables or disables using X.509 certificate for authentication when connecting to the MQTT broker.
  - **clientCerts** (_object_, optional) - Defines the X.509 certificates when **useClientCert** is enabled. Currently only one certificate can be registered, and is defined using a **default** object:
    - **default** (_object_, required) - The object containing credentials.
      - **$credentialsId** (_string_, required) - The ID of the [Credential Set](https://docs.soracom.io/en/services/authentication/credential-sets) to use for authentication. Use the `#{imsi}` or `#{imei}` placeholders to automatically insert the subscriber IMSI or device IMEI in the field.
  - **addSubscriberHeader** - (_boolean_, optional) - Enables or disables adding subscriber information as an MQTT topic in the forwarded request.
  - **replaceTopic** (_boolean_, required) - Enables or disables replacing `{{ "{{imsi}}" }}`, `{{ "{{simId}}" }}`, and `{{ "{{imei}}" }}` placeholders in the MQTT topic with the subscriber IMSI or SIM ID and device IMEI.
  - **version** (_string_, required) - Sets the Beam MQTT entry point version to use. Valid options are `"201509"` or `"201912"`. Refer to the Versions section above for more information.
  - **usePubnub** (_boolean_, optional) - Set to `true` if the destination is PubNub.
  - **useAzureIoT** (_boolean_, optional) - Set to `true` if the destination is Azure IoT.
  - **useGoogleIoT** (_boolean_, optional) - Set to `true` if the destination is GoogleIoT.

### Sample

```json
[
  {
    "key": "mqtt://beam.soracom.io:1883",
    "value": {
      "name": "AWS IoT",
      "destination": "mqtts://abcd0012345678-ats.iot.us-east-2.amazonaws.com:8883",
      "enabled": true,
      "useClientCert": true,
      "clientCerts": {
        "default": {
          "$credentialsId": "my-device-credentials"
        }
      },
      "addSubscriberHeader": false,
      "replaceTopic": false,
      "version": "201912"
    }
  }
]
```
