Reporting

The gateway will report from devices by publishing to the following generic topic structure:

  • mt/gateway/{g}/device/{d}/...

where {g} is gateway MAC address and {d} is device MAC address. The format of MAC addresses is 12 lowercase hex digits.

The message payload is an UTF-8 encoded JSON object and always contains a property time. This is the time of the message in ISO-8601 format.

heartbeat

mt/gateway/{g}/device/{d}/heartbeat

Device heartbeat.

Payload

  • time: time in ISO-8601 format.

  • seq: sequence number 0-255

  • status: a device status value. Non-zero values are used to indicate device error/warning.

  • lastCount: number of heartbeat duplicates received for the previous seq. Introduced in version 1.3.0.

Example

mt/gateway/ef6d7dd1d9ed/device/cd10a7eff81f/heartbeat
{
  "time": "2025-11-04T10:07:20.585Z",
  "seq": 12,
  "status": 0,
  "lastCount:" 3
}

dfu

mt/gateway/{g}/device/{d}/dfu

Device is advertising in DFU mode. This can be looked upon as a DFU mode “heartbeat”.

Payload

  • time: time in ISO-8601 format.

  • parent: Network node that picked up the DFU mode advertisement

  • rssi: RSSI value.

Example

mt/gateway/e4ebc3f77f09/device/da51bdeef18c/rssi
{
  "time": "2025-12-03T11:31:39.788Z",
  "parent": "ef6d7dd1d9ed",
  "rssi": -58
}

rssi

mt/gateway/{g}/device/{d}/rssi

Signal strength between network node (parent) and a device. RSSI values from multiple parents can be used to estimate position of a device.

Payload

  • time: time in ISO-8601 format.

  • parent: Network node reporting the RSSI.

  • channel: BLE advertising channel. Range: 37-39. (optional)

  • rssi: RSSI value.

  • seq: Sequence Number 0-255 (optional)

  • unreachable: Boolean (optional, false by default when not present)

When unreachable is true the device cannot be reached through this parent.

Example

mt/gateway/e4ebc3f77f09/device/da51bdeef18c/rssi

{
  "time": "2025-10-19T12:32:47.485Z",
  "parent": "e4ebc3f77f09",
  "rssi": -58
}

property

mt/gateway/{g}/device/{d}/property/{identifer}

A device reported a property value.

This topic is used:

  • In raw mode

  • In decoded mode when the gateway is unable to decode

The identifier is a lowercase hex string identifier and value is a hex string.

Payload

  • time: time in ISO-8601 format.

  • value: the property value (hex string)

  • seq: sequence number 0-255 (optional)

Example

mt/gateway/e4ebc3f77f09/device/da51bdeef18c/property/8810
{
  "time": "2025-10-19T11:19:20.610Z",
  "value": "00"
}

property-decoded

mt/gateway/{g}/device/{d}/property-decoded/{identifer-name}

A device reported a property value.

This topic is used in decoded mode when the gateway is able to decode.

Note

If the gateway is unable to decode the identifier, it will publish as raw on the property topic.

Payload

  • time: time in ISO-8601 format

  • value: property value (JSON)

  • ext: value extensions (JSON object, optional)

  • seq: sequence number 0-255 (optional)

Example

mt/gateway/e4ebc3f77f09/device/da51bdeef18c/property-decoded/motion
{
  "time": "2025-10-19T11:19:20.610Z",
  "value": 0  
}

measurement

mt/gateway/{g}/device/{d}/measurement/{identifer}

A device reported a measurement.

This topic is used:

  • In raw mode

  • In decoded mode when the gateway is unable to decode

Payload

  • time: time in ISO-8601 format.

  • seq: measurement sequence number (0-255)

  • value: value of measurement (hex string)

Example

mt/gateway/ef6d7dd1d9ed/device/cd10a7eff81f/measurement/8800
{
  "time": "2025-11-04T10:09:42.662Z",
  "seq": 128,
  "value": "0A8B"
}

measurement-decoded

mt/gateway/{g}/device/{d}/measurement-decoded/{identifer-name}

A device reported a measurement.

This topic is used in decoded mode when the gateway is able to decode.

Note

If the gateway is unable to decode the identifier, it will publish as raw on the measurement topic.

Payload

  • time: time in ISO-8601 format.

  • seq: measurement sequence number (0-255)

  • value: value of measurement (JSON)

  • ext: value extensions (JSON object, optional)

Example

mt/gateway/ef6d7dd1d9ed/device/cd10a7eff81f/measurement-decoded/temperature
{
  "time": "2025-11-04T10:09:42.662Z",
  "seq": 128,
  "value": 26.99
}

measurement-error

mt/gateway/{g}/device/{d}/measurement-error/{identifer}

A device reported a measurement error.

This topic is used:

  • In raw mode

  • In decoded mode when the gateway is unable to decode

Payload

  • time: time in ISO-8601 format.

  • seq: measurement sequence number (0-255)

  • error: error code (integer). See Status Codes.

  • errorExt: error code extension (integer) (optional)

Example

mt/gateway/ef6d7dd1d9ed/device/cd10a7eff81f/measurement-error/8800
{
  "time": "2025-11-04T10:09:42.662Z",
  "seq": 128,
  "error": 35074
}

measurement-error-decoded

mt/gateway/{g}/device/{d}/measurement-error/{identifer-name}

A device reported a measurement error.

This topic is used in decoded mode when the gateway is able to decode.

Note

If the gateway is unable to decode the identifier, it will publish as raw on the measurement-error topic.

Payload

  • time: time in ISO-8601 format.

  • seq: measurement sequence number (0-255)

  • error: error code (integer). See Status Codes.

  • errorExt: error code extension (integer) (optional)

Example

mt/gateway/ef6d7dd1d9ed/device/cd10a7eff81f/measurement-error-decoded/temperature
{
  "time": "2025-11-04T10:09:42.662Z",
  "seq": 128,
  "error": 8902
}

event

mt/gateway/{g}/device/{d}/event/{identifer}

A device fired an event.

This topic is used:

  • In raw mode

  • In decoded mode when the gateway is unable to decode

Payload

  • time: time in ISO-8601 format.

  • seq: sequence number (0-255)

  • value: value associated with event (hex string) (optional)

Example

Button press:

mt/gateway/e4ebc3f77f09/device/da51bdeef18c/event/998000
{
  "time": "2025-10-19T12:35:38.479Z",
  "seq": "1"
}

event-decoded

mt/gateway/{g}/device/{d}/event-decoded/{identifer-name}

A device fired an event.

This topic is used in decoded mode when the gateway is able to decode.

Note

If the gateway is unable to decode the identifier, it will publish as raw on the event topic.

Payload

  • time: time in ISO-8601 format.

  • seq: sequence number (0-255)

  • value: value associated with event (JSON, optional)

  • ext: value extensions (JSON object, optional)

Example

Button press:

mt/gateway/e4ebc3f77f09/device/da51bdeef18c/event-decoded/button-0
{
  "time": "2025-10-19T12:35:38.479Z",
  "seq": "1"
}

timestamped

mt/gateway/{g}/device/{d}/timestamped/{identifer}

A device reported a device-timestamped measurement/event sample.

Sample should be ACKed using ack if payload property ack is true.

Note

Added in version 2.4.0

Note

Timestamped data for all backfill-enabled identifiers must be subscribed to and ACKed. For example, if backfill is enabled for temperature and humidity but only temperature is subscribed to and ACKed, the device will continuously send the latest un-ACKed humidity sample, thus causing the backfill process to get stuck.

Payload

Property

Type

Optional

Default Value

Description

time

string

No

-

UTC timestamp in iso-8601 format (milliseconds resolution)

value

string

No

-

Value as hex string

flags

string

No

-

Flags as single-byte hex string

backfillCount

number

Yes

0

Total number of backfill samples (not acked)

prevTime

string

No

-

UTC timestamp in iso-8601 format (milliseconds resolution) (added in v2.5.0)

flags bit

Name

Description

6

TIME_SYNC

Set if this is first sample after time sync

5:4

TS_ACCURACY

Timestamp accuracy. See table below.

3

ACK

Set if ACK is possible. False during firmware update/download.

2

ERROR_CODE

Set if value is an errorcode

1

TS_SHIFTED

Set if timestamp was shifted (set to previous_sample + 1ms)

0

BACKFILL

Set if this is a backfill sample

TS_ACCURACY

Description

0

In sync, low accuracy

1

In sync, high accuracy

2

Out of sync

3

Estimated

prevTime is used to detect dropped samples. prevTime should match time of the previous sample. If this is not the case, one or more samples were dropped. This typically happens when samples are not ACKed and the write buffer overflows, or the device is reset. The first sample has prevTime = "1970-01-01T00:00:00.000Z.

Example

mt/gateway/ef6d7dd1d9ed/device/cd10a7eff81f/timestamped/8800
{
  "time": "2025-11-04T10:15:00.000Z",
  "value": "0A8B",
  "flags": "01",
  "prevTime": "2025-11-04T10:00:00.000Z"
}

ErrorCode: 255, ErrorMetadata: 0xAABB:

{
  "time": "2025-11-04T10:15:00.000Z",
  "value": "00FFAABB",
  "flags": "05",
  "prevTime": "2025-11-04T10:00:00.000Z"
}

timestamped-decoded

mt/gateway/{g}/device/{d}/timestamped-decoded/{identifer-name}

A device reported a device-timestamped measurement/event sample.

Sample should be ACKed using ack-decoded if payload property ack is true.

Note

Added in version 2.4.0

Note

Timestamped data for all backfill-enabled identifiers must be subscribed to and ACKed. For example, if backfill is enabled for temperature and humidity but only temperature is subscribed to and ACKed, the device will continuously send the latest un-ACKed humidity sample, thus causing the backfill process to get stuck.

Payload

Property

Type

Optional

Default Value

Description

time

string

No

-

UTC timestamp in iso-8601 format (milliseconds resolution)

value

JSON

Yes

null

Value

ext

object

Yes

null

Value extensions

errorCode

number

Yes

null

Error code. Used instead of value when there’s an error.

errorMeta

string

Yes

“”

Error metadata as hex string. Optional, more info. related to error.

ack

boolean

Yes

false

True when sample can be acked

backfill

boolean

Yes

false

True when sample is backfilled

backfillCount

number

Yes

0

Total number of backfill samples (not acked)

tsShifted

boolean

Yes

false

Timestamp was shifted (set to previous_sample + 1ms)

tsAccuracy

number

Yes

0

Timestamp accuracy (always included in v2.5.0+)

prevTime

string

No

-

UTC timestamp in iso-8601 format (milliseconds resolution) (added in v2.5.0)

timeSync

boolean

No

-

First sample after time sync (added in v2.5.0)

prevTime is used to detect dropped samples. prevTime should match time of the previous sample. If this is not the case, one or more samples were dropped. This typically happens when samples are not ACKed and the write buffer overflows, or the device is reset. The first sample has prevTime = "1970-01-01T00:00:00.000Z.

Example

mt/gateway/ef6d7dd1d9ed/device/cd10a7eff81f/timestamped-decoded/temperature
{
  "time": "2025-11-04T10:15:00.000Z",
  "value": 22.4,
  "ack": true,
  "backfill": true,
  "backfillCount": 3,
  "prevTime": "2025-11-04T10:00:00.000Z"
}

ErrorCode: 255, ErrorMetadata: 0xAABB:

{
  "time": "2025-11-04T10:15:00.000Z",
  "errorCode": 255,
  "errorMeta": "AABB",
  "prevTime": "2025-11-04T10:00:00.000Z"
}