NodeMQTTOrchestrator - Central MQTT orchestration layer for AWS IoT Device Shadow.

Design principles:

  • Node-agnostic: does not depend on the Node class.
  • Single connection: one MQTT client, one message router.
  • Deduplicated subscriptions: 30 nodes → maybe 3 shadows → only 3 MQTT subscriptions.
  • Nodes = dumb consumers, Orchestrator = brain.

Methods

  • Clears the singleton and resets it for re-initialization. Rejects all pending requests, unsubscribes shadow wildcard topics and request-response topics, then drops transport and in-memory state.

    Returns void

  • Returns the current initialization generation. Increments on each initialize. Used by subscription channels to detect a logout→login reset and re-attach stale listeners.

    Returns number

  • Gets params (state.reported.params) for a node.

    Parameters

    • nodeId: string

      The device/node identifier.

    Returns Promise<Record<string, unknown>>

    The reported params map, or {} when absent.

    If node is not registered.

  • Gets the full shadow document (state.reported + state.desired).

    Parameters

    • nodeId: string

      The device/node identifier.

    Returns Promise<unknown>

    The full state object.

    If node is not registered.

  • Initializes the orchestrator with an MQTT transport. Must be called before any other method.

    Parameters

    Returns void

    If already initialized. Call clear first if you truly need to re-init — a silent swap would leave stale in-memory subscriptions pointing at topics that were never subscribed on the new transport.

  • Checks if a node is registered. Returns false if the orchestrator has not been initialized at all (safe read-only check, matches getRegisteredNodeCount — the mutating methods throw instead).

    Parameters

    • nodeId: string

      The device/node identifier.

    Returns boolean

  • Registers a node with the orchestrator. Must be called before subscribeToNode, getParams, getShadow, etc. On shadow rename: clears the old binding, then installs the new name (including shrinks to a shorter membership shadow).

    Parameters

    • nodeId: string

      The device/node identifier.

    • shadowName: string

      The named shadow (e.g. params-groupId-subgroupId).

    Returns void

  • Soft-resets session-scoped state without dropping the singleton. Called from ESPRMNeoUser.logout so the orchestrator is ready for the next login without a public re-initialize step. Rejects pending requests, clears shadow listeners, drops node registrations, and bumps _generation so subscription channels detect the reset and re-attach on next login. Keeps transport, initialized, and _instance intact so getInstance() continues to work.

    Returns void

  • Publishes parameters to the group control MQTT topic (fan-out to all devices in the group or in one subgroup). Does not require a registered node; only a connected MQTT transport (same credentials as unicast setParams).

    Parameters

    • groupId: string

      Primary group id.

    • params: unknown

      Same payload shape as NodeMQTTOrchestrator.setParams.

    • OptionalsubgroupId: string

      Omit for group-wide broadcast; set to target one subgroup.

    Returns Promise<void>

  • Sets params via the RainMaker user params topic (unicast: single node).

    Parameters

    • nodeId: string

      The device/node identifier.

    • params: unknown

      Parameter payload (often { <deviceId>: { <paramId>: value } }).

    Returns Promise<void>

    If node is not registered, MQTT is not connected, or the publish fails.

  • Subscribes to node param updates. Deduplicates MQTT subscriptions by shadow.

    Parameters

    • nodeId: string

      The device/node identifier.

    • callback: (params: unknown) => void

      Callback invoked when shadow update/accepted is received.

    Returns Promise<void>

    If node is not registered, MQTT is not connected, or the underlying transport subscribe fails. On failure no listener is added.

  • Unregisters a node. Removes from nodeMap and cleans up listeners. Unsubscribes from shadow topic if no other nodes use it.

    Parameters

    • nodeId: string

      The device/node identifier.

    Returns void

  • Unsubscribes a callback from a node.

    In-memory listener removal happens even if MQTT is disconnected — otherwise on reconnect the orchestrator would fan messages out to a stale listener (per-disconnect leak). The network topic-unsubscribe inside cleanupSubscriptionIfIdle is best-effort and tolerates a missing connection.

    Parameters

    • nodeId: string

      The device/node identifier.

    • callback: (params: unknown) => void

      The callback to remove.

    Returns Promise<void>

  • Updates shadow state.desired.

    Parameters

    • nodeId: string

      The device/node identifier.

    • params: unknown

      The desired state parameters.

    Returns Promise<void>

    If node is not registered or transport unavailable.