MQTT Migration Guide

This guide describes the recommended process for migrating MQTT integrations from the PANS PRO RTLS stack to the LEAPS RTLS stack. Teams may modernise their existing applications to speak the LEAPS topics directly or deploy a temporary/permanent bridge that performs the translation on their behalf. It consolidates the documentation found in:


1. Scope & Inventory

The table below consolidates the MQTT traffic described in the PANS PRO and LEAPS RTLS connector guides. Use it as a baseline when planning migrations or validating completeness.

Domain

PANS PRO topics (QoS / retain)

Payload focus

LEAPS RTLS topics (QoS / retain)

Payload focus

Notes

Server lifecycle

{prefix}/server server status (QoS 1 / retained ✓)<br>`{prefix}/server` requests (QoS 1 / retained ✗)

Server status (empty/min JSON)<br> ServerMessage requests

{prefix}/server/status (QoS 1 / retained ✗)<br>`{prefix}/server/request` (QoS 1 / retained ✗)

leaps_api.server_message (state, version, nodeList, request, networks)

Consumers subscribe to {prefix}/server/status; server LWT publishes {“state”:”DISCONNECTED”}.

Gateway status & config

{prefix}/gateway/{deviceId}/uplink (QoS 1 / retained ✓)<br>`{prefix}/gateway/{deviceId}/downlink` (QoS 1 / retained ✗)

GatewayStatusAndConfig (networkId, bridgeNodeId, configuration)

{prefix}/{networkId}/gateway/uplink/status/{deviceId} (QoS 1 / retained ✗)<br>`{prefix}/{networkId}/gateway/uplink/config/{deviceId}` (QoS 1 / retained ✗)<br>`{prefix}/{networkId}/gateway/downlink/config/{deviceId}` (QoS 1 / retained ✗)

leaps_api.status <br> leaps_api.node_config

Insert {networkId} from legacy networkId; split status vs configuration topics.

Node status & config

{prefix}/node/{deviceId}/uplink/status (QoS 1 / retained ✓)<br>`{prefix}/node/{deviceId}/uplink/config` (QoS 1 / retained ✓)<br>`{prefix}/node/{deviceId}/downlink/config` (QoS 1 / retained ✗)

NodeStatusUplink <br> NodeConfiguration

{prefix}/{networkId}/{nodegateway}/uplink/status/{deviceId} (QoS 1 / retained ✗)<br>`{prefix}/{networkId}/{nodegateway}/uplink/config/{deviceId}` (QoS 1 / retained ✗)<br>`{prefix}/{networkId}/{nodegateway}/downlink/config/{deviceId}` (QoS 1 / retained ✗)

leaps_api.status <br> leaps_api.node_config

Map nodeType into anchor_config/tag_config; remove redundant networkId.

Data & service channels

{prefix}/node/{deviceId}/uplink/data (QoS 1 / retained ✗)<br>`{prefix}/node/{deviceId}/downlink/data` (QoS 1 / retained ✗)<br>`{prefix}/node/{deviceId}/uplink/service` (QoS 1 / retained ✗)<br>`{prefix}/node/{deviceId}/downlink/service` (QoS 1 / retained ✗)

NodeDataUplink with Base64 payloads with optional superFrameNumber <br> NodeDataDownlink with Base64 payloads with optional overwrite <br> NodeServiceUplink / NodeServiceDownlink TLV messages

{prefix}/{networkId}/{nodegateway}/uplink/data/{deviceId} (QoS 1 / retained ✗)<br>`{prefix}/{networkId}/{nodegateway}/downlink/data/{deviceId}` (QoS 1 / retained ✗)<br>`{prefix}/{networkId}/{nodegateway}/uplink/service/{deviceId}` (QoS 1 / retained ✗)<br>`{prefix}/{networkId}/{nodegateway}/downlink/service/{deviceId}` (QoS 1 / retained ✗)

leaps_api.user_data <br> leaps_api.service_data

LEAPS omits superFrameNumber; keep timestamps and overwrite flags.

Location streams

{prefix}/node/{deviceId}/uplink/location (QoS 0 / retained ✓)

NodeLocationUplink (Position), superFrameNumber)

{prefix}/{networkId}/node/uplink/location/{deviceId} (QoS 0 / retained ✗)

leaps_api.location (node_location, statistics)

Wrap coordinates inside location and drop superFrameNumber.


1. Schema Alignment and Translation Recipes

The following sections document the translation requirements for each domain. Use them when refactoring publishers/consumers or building an adapter.

2.1 Server Lifecycle

  • PANS topics:

    • Uplink server status: {prefix}/server (retained, QoS 1) publishing an empty or minimal JSON payload when the server is online; broker LWT sends the same topic with an empty payload on disconnect (see Description).

    • Downlink commands: {prefix}/server carrying ServerMessage requests such as {"request":"REFRESH_TOPICS"} (see Description).

  • LEAPS topics:

    • Uplink status: {prefix}/server/status (not retained, QoS 1) conveying leaps_api.server_message payloads (see Description and leaps_api.server_message).

    • Downlink requests: {prefix}/server/request (not retained, QoS 1) using the same leaps_api.server_message schema for requests (See Description).

  • Translation steps:

    1. Subscriber change: Update consumers to subscribe to {prefix}/server/status (uplink) instead of {prefix}/server. Expect JSON payloads with at least state and handle disconnect events when {"state":"DISCONNECTED"} is received.

    2. Publisher change: Configure the server (or bridge) to emit a server status payloads such as {"state":"CONNECTED"} to {prefix}/server/status and set the broker LWT on that topic to publish {"state":"DISCONNECTED"}.

    3. Request routing: Move any command publications to {prefix}/server/request and encode them as {"request":"PUBLISH_ALL_TOPICS"} with optional networks filters.

  • Before / After:

    // PANS server status
    {}
    
    // LEAPS server status
    {
      "state": "CONNECTED",
      "version": "2.2.8"
    }
    

2.2 Gateway Status and Configuration

  • PANS topics:

    • {prefix}/gateway/{deviceId}/uplink (retained, QoS 1) reporting GatewayStatusAndConfig payloads with fields such as networkId, bridgeNodeId, version, uwb, and nested configuration (see Description).

    • {prefix}/gateway/{deviceId}/downlink for configuration updates (see Description).

  • LEAPS topics:

    • {prefix}/{networkId}/gateway/uplink/status/{deviceId} (not retained, QoS 1) carrying leaps_api.status (see Description).

    • {prefix}/{networkId}/gateway/uplink/config/{deviceId} and {prefix}/{networkId}/gateway/downlink/config/{deviceId} using leaps_api.node_config (Description and Description).

  • Translation steps:

    1. Introduce the {networkId} path segment (using the value previously found in the PANS networkId field). Remove the now-duplicate networkId field from the payload.

    2. Map gateway health indicators: present, downlink, uwb, batt, and temp can be copied directly into leaps_api.status. If PANS included bridgeNodeId or routing diagnostics, log or expose them via observability channels because LEAPS does not have one-to-one fields.

    3. Restructure configuration into the leaps_api.node_config shape:

      • ipAddress[], ipMask[], ipGateway[]inet.ip[].addr, inet.ip[].mask, inet.ip[].gateway

      • dns[]inet.dns

      • interfaceinet.iface

      • tlsinet.tls

      • server / portinet.server.host / inet.server.port

      • dhcpinet.dhcp

      • Optional Wi-Fi fields → wifi

    4. If firmware version details are required, subscribe them through {prefix}/server/status or a management database; LEAPS gateway config/topic does not transport release metadata.

  • Before / After:

    // PANS gateway uplink
    {
      "networkId": 1,
      "uwb": "CONNECTED_BH",
      "configuration": {
        "ipAddress": ["10.0.1.10"],
        "ipMask": ["255.255.255.0"],
        "dns": ["8.8.8.8"],
        "interface": "ETHERNET",
        "tls": "OFF",
        "server": "10.0.1.13",
        "port": 7777
      }
    }
    
    // LEAPS gateway uplink (status + config pair)
    {
      "present": true,
      "downlink": true,
      "uwb": "CONNECTED_BH",
      "timestamp": "1681398574409278"
    }
    
    {
      "label": "DW590F-nWIFI",
      "uwb_mode": "UWB_MODE_ACTIVE",
      "fw_update": true,
      "inet": {
        "ip": [
          {"addr": "10.0.1.10", "mask": "255.255.255.0"}
        ],
        "dns": ["8.8.8.8"],
        "iface": "ETHERNET",
        "tls": "OFF",
        "dhcp": true,
        "server": {"host": "10.0.1.13", "port": 7777}
      }
    }
    

2.3 Node Configuration and Status

  • PANS topics:

    • {prefix}/node/{deviceId}/uplink/status (retained, QoS 1) with NodeStatusUplink payloads (See Description).

    • {prefix}/node/{deviceId}/uplink/config and {prefix}/node/{deviceId}/downlink/config sharing NodeConfiguration structures (see Description and and see Description).

  • LEAPS topics:

    • {prefix}/{networkId}/{node\|gateway}/uplink/status/{deviceId} carrying leaps_api.status (See Description).

    • {prefix}/{networkId}/{node\|gateway}/{uplink|downlink}/config/{deviceId} using leaps_api.node_config (See Description).

  • Translation steps:

    1. Insert {networkId} and the device role (node or gateway) into the topic path; remove redundant networkId or nodeType identifiers from the payload.

    2. Map shared fields directly: present, downlink, uwb, batt, batt_state, temp, and timestamp match one-to-one in leaps_api.status.

    3. Convert configuration objects:

      • configuration.labellabel

      • nodeType → choose between populating anchor (for anchors/gateways) or tag (for tags); absence of a section implies the other role

      • ble, leds, uwbFirmwareUpdateble, leds, fw_update

      • anchor.position (x/y/z/quality) → anchor.location

      • anchor.routingConfig (ROUTING_CFG_*) → anchor.routing (ROUTING_* enum)

      • anchor.routingStatus has no LEAPS equivalent; surface via monitoring or drop

      • anchor.initiatoranchor.initiator

      • Tag settings (TagConfiguration) → tag fields (location_engine, low_power, stationary_detection, update_rate_*)

    4. Carry timestamps forward; ensure they are strings or integers consistent with LEAPS examples (microseconds).

  • Before / After:

    // PANS node config
    {
      "configuration": {
        "label": "DW0F07",
        "nodeType": "ANCHOR",
        "ble": true,
        "leds": true,
        "uwbFirmwareUpdate": true,
        "anchor": {
          "initiator": true,
          "position": {"x": 0, "y": 0, "z": 0, "quality": 0},
          "routingConfig": "ROUTING_CFG_OFF"
        }
      }
    }
    
    // LEAPS node config
    {
      "label": "DW0F07",
      "uwb_mode": "UWB_MODE_ACTIVE",
      "ble": true,
      "leds": true,
      "fw_update": true,
      "anchor": {
        "initiator": true,
        "location": {"x": 0.0, "y": 0.0, "z": 0.0, "quality": 0},
        "routing": "ROUTING_OFF"
      }
    }
    


2.5 Location Streams

  • PANS topics: {prefix}/node/{deviceId}/uplink/location with NodeLocationUplink payloads (see Description).

  • LEAPS topics: {prefix}/{networkId}/node/uplink/location/{deviceId} publishing leaps_api.location payloads (see Description).

  • Translation steps:

    1. Add {networkId} to the topic and remove networkId fields from the body.

    2. Nest position coordinates inside the location object expected by LEAPS: position.xlocation.x, etc. If PANS supplied KernelPosition bytes, convert them to floating-point meters before publishing.

    3. Move optional quality metrics into LEAPS statistics fields when available (sd_x, sd_y, sd_z, r95, toa). Values without direct equivalents can be stored in application-specific telemetry streams.

    4. Drop superFrameNumber or repurpose it within analytics; LEAPS does not define that field in leaps_api.location.

  • Before / After:

    // PANS location
    {
      "position": {
        "x": 3.25238609,
        "y": -0.00895162672,
        "z": 0.42510426,
        "quality": 21
      },
      "superFrameNumber": 1144,
      "timestamp": "1679495047880989"
    }
    
    // LEAPS location
    {
      "location": {
        "x": 3.25238609,
        "y": -0.00895162672,
        "z": 0.42510426,
        "quality": 21
      },
      "timestamp": "1679495047880989"
    }
    

1. Environment Updates

  • Broker configuration: Update topic ACLs, retained flags, and LWT settings to accommodate the LEAPS namespace. Ensure {prefix}/server/status and {prefix}/server/request are available and that QoS requirements match the LEAPS documentation.

  • Client endpoints: Point gateways and management tools to the LEAPS server endpoints. Adjust client-side MQTT settings (QoS, retain) to match the new specifications.

  • Documentation: Record any broker-level changes so that future deployments reference the LEAPS expectations instead of the legacy ones.


4. Cutover & Validation

  • Staging rehearsal: Run the full traffic set through a staging LEAPS deployment. Confirm that consumers process the new topics without schema errors.

  • Production cutover: Schedule the switch once staging passes. Monitor the broker, adapter logs, and downstream applications for discrepancies.

  • Fallback plan: Maintain the adapter or dual-publish strategy until metrics show stable consumption on the LEAPS topics.

  • Alerting updates: Modify monitoring rules to inspect the new topics (e.g., checking state != "CONNECTED" on {prefix}/server/status).

5. Post-Migration Cleanup

  1. Retire PANS PRO topic publishers and remove obsolete ACLs from the broker.

  2. Decommission temporary adapters once every producer and consumer speaks native LEAPS.

  3. Archive the translation recipes and sample payloads. They remain valuable for onboarding and audits.

  4. Update team runbooks and diagrams to reflect the LEAPS RTLS architecture.


Appendices

A. Reference Tables

Domain

Source docs

Target docs

Server lifecycle

MQTT Connector

Base MQTT messages

Gateway status/config

MQTT Connector

LEAPS MQTT Connector

Node status/config

MQTT Connector

LEAPS MQTT Connector

Data/service

MQTT Connector

LEAPS MQTT Connector

Location

MQTT Connector

LEAPS MQTT Connector