@nolag/iot 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # @nolag/iot
2
+
3
+ IoT device SDK for [NoLag](https://nolag.app) — telemetry, command dispatch, and device management.
4
+
5
+ ## How It Works with NoLag
6
+
7
+ NoLag is a real-time messaging platform that handles WebSocket connections, message routing, persistence, and scaling. This SDK wraps the low-level [@nolag/js-sdk](https://www.npmjs.com/package/@nolag/js-sdk) and gives you a purpose-built IoT API — publish telemetry, send commands to devices, and track acknowledgements — without managing topics or subscriptions yourself.
8
+
9
+ ### Getting Your Token
10
+
11
+ 1. Sign up at [nolag.app](https://nolag.app)
12
+ 2. Create a new **project** in the portal
13
+ 3. Choose the **IoT** blueprint when creating an app — this pre-configures the topics (`telemetry`, `commands`, `_cmd_ack`) and settings your IoT system needs
14
+ 4. Go to the app's **Tokens** page and generate an **actor token**
15
+ 5. Use that token when connecting with this SDK
16
+
17
+ Each token identifies a unique device or controller (actor) in NoLag. The blueprint handles all the infrastructure setup — you just build your device logic or dashboard.
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ npm install @nolag/js-sdk @nolag/iot
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```typescript
28
+ import { NoLagIoT } from "@nolag/iot";
29
+
30
+ // --- Device: sends telemetry, receives commands ---
31
+ const device = new NoLagIoT("DEVICE_TOKEN", {
32
+ deviceName: "Sensor #7",
33
+ role: "device",
34
+ });
35
+
36
+ await device.connect();
37
+
38
+ const group = device.joinGroup("warehouse-a");
39
+
40
+ // Publish sensor readings
41
+ setInterval(() => {
42
+ group.sendTelemetry("temperature", 22.5, { unit: "°C" });
43
+ group.sendTelemetry("humidity", 65, { unit: "%" });
44
+ }, 5000);
45
+
46
+ // Respond to commands
47
+ group.on("command", (cmd) => {
48
+ console.log(`Command: ${cmd.command}`, cmd.params);
49
+ group.ackCommand(cmd.id, "completed", { success: true });
50
+ });
51
+
52
+ // --- Controller: monitors telemetry, sends commands ---
53
+ const controller = new NoLagIoT("CONTROLLER_TOKEN", {
54
+ deviceName: "Dashboard",
55
+ role: "controller",
56
+ });
57
+
58
+ await controller.connect();
59
+
60
+ const controlGroup = controller.joinGroup("warehouse-a");
61
+
62
+ // Monitor telemetry
63
+ controlGroup.on("telemetry", (reading) => {
64
+ console.log(`${reading.deviceId}/${reading.sensorId}: ${reading.value}${reading.unit}`);
65
+ });
66
+
67
+ // Send a command to a device
68
+ const cmd = await controlGroup.sendCommand("sensor-7", "calibrate", {
69
+ offset: 0.5,
70
+ });
71
+
72
+ controlGroup.on("commandAck", (ack) => {
73
+ console.log(`Command ${ack.id}: ${ack.status}`);
74
+ });
75
+ ```
76
+
77
+ ## API Reference
78
+
79
+ ### `NoLagIoT`
80
+
81
+ #### Constructor
82
+
83
+ ```typescript
84
+ const iot = new NoLagIoT(token: string, options?: NoLagIoTOptions);
85
+ ```
86
+
87
+ **Options:**
88
+
89
+ | Option | Type | Default | Description |
90
+ |--------|------|---------|-------------|
91
+ | `deviceId` | `string` | auto-generated | Unique device ID |
92
+ | `deviceName` | `string` | — | Display name |
93
+ | `role` | `DeviceRole` | `'device'` | `'device'` or `'controller'` |
94
+ | `metadata` | `Record<string, unknown>` | — | Custom device data |
95
+ | `groups` | `string[]` | — | Auto-join these groups on connect |
96
+ | `maxTelemetryPoints` | `number` | `1000` | Max telemetry points in memory |
97
+ | `commandTimeout` | `number` | `30000` | Command ack timeout (ms) |
98
+ | `debug` | `boolean` | `false` | Enable debug logging |
99
+ | `reconnect` | `boolean` | `true` | Auto-reconnect on disconnect |
100
+
101
+ #### Methods
102
+
103
+ | Method | Returns | Description |
104
+ |--------|---------|-------------|
105
+ | `connect()` | `Promise<void>` | Connect to NoLag |
106
+ | `disconnect()` | `void` | Disconnect |
107
+ | `joinGroup(name)` | `DeviceGroup` | Join a device group |
108
+ | `leaveGroup(name)` | `void` | Leave a group |
109
+ | `getGroups()` | `DeviceGroup[]` | Get all joined groups |
110
+ | `getOnlineDevices()` | `Device[]` | Get online devices |
111
+
112
+ #### Events
113
+
114
+ | Event | Payload | Description |
115
+ |-------|---------|-------------|
116
+ | `connected` | — | Connected |
117
+ | `disconnected` | — | Disconnected |
118
+ | `reconnected` | — | Reconnected |
119
+ | `error` | `Error` | Error |
120
+ | `deviceOnline` | `Device` | Device came online |
121
+ | `deviceOffline` | `Device` | Device went offline |
122
+
123
+ ### `DeviceGroup`
124
+
125
+ #### Methods
126
+
127
+ | Method | Returns | Description |
128
+ |--------|---------|-------------|
129
+ | `sendTelemetry(sensorId, value, opts?)` | `TelemetryReading` | Publish a sensor reading |
130
+ | `getTelemetry(deviceId?, sensorId?)` | `TelemetryReading[]` | Get cached telemetry |
131
+ | `sendCommand(targetDeviceId, command, params?)` | `Promise<DeviceCommand>` | Send a command |
132
+ | `ackCommand(commandId, status, result?)` | `void` | Acknowledge a command |
133
+ | `getDevices()` | `Device[]` | Get devices in this group |
134
+ | `getDevice(deviceId)` | `Device \| undefined` | Get a specific device |
135
+
136
+ #### Events
137
+
138
+ | Event | Payload | Description |
139
+ |-------|---------|-------------|
140
+ | `telemetry` | `TelemetryReading` | Telemetry received |
141
+ | `command` | `DeviceCommand` | Command received (devices) |
142
+ | `commandAck` | `DeviceCommand` | Command acknowledged |
143
+ | `deviceJoined` | `Device` | Device joined group |
144
+ | `deviceLeft` | `Device` | Device left group |
145
+ | `replayStart` / `replayEnd` | — | Telemetry replay |
146
+
147
+ ## Types
148
+
149
+ ```typescript
150
+ interface TelemetryReading {
151
+ id: string;
152
+ deviceId: string;
153
+ sensorId: string;
154
+ value: number | string | boolean | Record<string, unknown>;
155
+ unit?: string;
156
+ tags?: Record<string, string>;
157
+ timestamp: number;
158
+ isReplay: boolean;
159
+ }
160
+
161
+ interface DeviceCommand {
162
+ id: string;
163
+ targetDeviceId: string;
164
+ command: string;
165
+ params?: Record<string, unknown>;
166
+ status: CommandStatus;
167
+ sentBy: string;
168
+ sentAt: number;
169
+ ackedAt?: number;
170
+ completedAt?: number;
171
+ result?: unknown;
172
+ error?: string;
173
+ }
174
+
175
+ type CommandStatus = "pending" | "acked" | "completed" | "failed" | "timeout";
176
+
177
+ interface Device {
178
+ deviceId: string;
179
+ actorTokenId: string;
180
+ deviceName?: string;
181
+ role: DeviceRole;
182
+ metadata?: Record<string, unknown>;
183
+ joinedAt: number;
184
+ isLocal: boolean;
185
+ }
186
+
187
+ type DeviceRole = "device" | "controller";
188
+ ```
189
+
190
+ ## License
191
+
192
+ MIT
@@ -0,0 +1,41 @@
1
+ import type { DeviceCommand } from './types';
2
+ /**
3
+ * Command dispatch with ack tracking and per-command timeout.
4
+ *
5
+ * Controllers call `send()` to dispatch a command and await the result.
6
+ * Devices call `ack()` to acknowledge receipt and report completion/failure.
7
+ */
8
+ export declare class CommandManager {
9
+ private _pending;
10
+ private _commands;
11
+ private _defaultTimeout;
12
+ constructor(defaultTimeout: number);
13
+ /**
14
+ * Dispatch a command to a target device.
15
+ *
16
+ * Returns a Promise that resolves once the device acks with 'acked' or
17
+ * 'completed', or rejects on 'failed' status or timeout.
18
+ */
19
+ send(targetDeviceId: string, command: string, params: Record<string, unknown> | undefined, sentBy: string, timeout?: number): Promise<DeviceCommand>;
20
+ /**
21
+ * Acknowledge a command from the device side.
22
+ *
23
+ * `status` must be one of 'acked', 'completed', or 'failed'.
24
+ * Returns the updated DeviceCommand, or null if the command is unknown or
25
+ * already settled.
26
+ */
27
+ ack(commandId: string, status: 'acked' | 'completed' | 'failed', result?: unknown): DeviceCommand | null;
28
+ /**
29
+ * Get a command by id (includes settled commands).
30
+ */
31
+ get(commandId: string): DeviceCommand | undefined;
32
+ /**
33
+ * Get all commands currently in 'pending' status.
34
+ */
35
+ getPending(): DeviceCommand[];
36
+ /**
37
+ * Clear all pending timers and reject all outstanding promises.
38
+ * Call this when the group or client is torn down.
39
+ */
40
+ dispose(): void;
41
+ }
@@ -0,0 +1,68 @@
1
+ import type { RoomContext } from '@nolag/js-sdk';
2
+ import { EventEmitter } from './EventEmitter';
3
+ import type { DeviceGroupEvents, TelemetryReading, SendTelemetryOptions, DeviceCommand, Device, IoTPresenceData, ResolvedIoTOptions } from './types';
4
+ /**
5
+ * DeviceGroup — a single IoT group for telemetry streaming and command dispatch.
6
+ *
7
+ * Created via `NoLagIoT.joinGroup(name)`. Do not instantiate directly.
8
+ */
9
+ export declare class DeviceGroup extends EventEmitter<DeviceGroupEvents> {
10
+ /** Group name */
11
+ readonly name: string;
12
+ private _roomContext;
13
+ private _localDevice;
14
+ private _options;
15
+ private _presenceManager;
16
+ private _telemetryStore;
17
+ private _commandManager;
18
+ private _receivedCommands;
19
+ private _log;
20
+ /** @internal */
21
+ constructor(name: string, roomContext: RoomContext, localDevice: Device, options: ResolvedIoTOptions, log: (...args: unknown[]) => void);
22
+ /** All remote devices currently in this group */
23
+ get devices(): Map<string, Device>;
24
+ /**
25
+ * Publish a telemetry reading from this device.
26
+ */
27
+ sendTelemetry(sensorId: string, value: TelemetryReading['value'], opts?: SendTelemetryOptions): TelemetryReading;
28
+ /**
29
+ * Retrieve buffered telemetry readings, optionally filtered by device/sensor.
30
+ */
31
+ getTelemetry(deviceId?: string, sensorId?: string): TelemetryReading[];
32
+ /**
33
+ * Dispatch a command to a target device.
34
+ * Resolves when the device acks the command, rejects on failure or timeout.
35
+ */
36
+ sendCommand(targetDeviceId: string, command: string, params?: Record<string, unknown>): Promise<DeviceCommand>;
37
+ /**
38
+ * Acknowledge a command on the device side.
39
+ * Typically called by the device after receiving a command event.
40
+ */
41
+ ackCommand(commandId: string, status: 'acked' | 'completed' | 'failed', result?: unknown): void;
42
+ /**
43
+ * Get all remote devices in this group.
44
+ */
45
+ getDevices(): Device[];
46
+ /**
47
+ * Get a specific device by deviceId.
48
+ */
49
+ getDevice(deviceId: string): Device | undefined;
50
+ /** @internal Subscribe to all group topics and attach listeners */
51
+ _subscribe(): void;
52
+ /** @internal Set presence and fetch existing group members */
53
+ _activate(): void;
54
+ /** @internal Re-set presence after reconnect */
55
+ _updateLocalPresence(): void;
56
+ /** @internal Handle a presence:join event */
57
+ _handlePresenceJoin(actorTokenId: string, presenceData: IoTPresenceData): void;
58
+ /** @internal Handle a presence:leave event */
59
+ _handlePresenceLeave(actorTokenId: string): void;
60
+ /** @internal Handle a presence:update event */
61
+ _handlePresenceUpdate(actorTokenId: string, presenceData: IoTPresenceData): void;
62
+ /** @internal Unsubscribe and clean up */
63
+ _cleanup(): void;
64
+ private _handleIncomingTelemetry;
65
+ private _handleIncomingCommand;
66
+ private _handleIncomingCmdAck;
67
+ private _setPresence;
68
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Tiny typed event emitter — framework-agnostic base for NoLag SDKs.
3
+ *
4
+ * EventMap is a record of event name → tuple of handler arguments.
5
+ */
6
+ export declare class EventEmitter<EventMap extends {
7
+ [K in keyof EventMap]: unknown[];
8
+ }> {
9
+ private _handlers;
10
+ on<K extends keyof EventMap>(event: K, handler: (...args: EventMap[K]) => void): this;
11
+ off<K extends keyof EventMap>(event: K, handler?: (...args: EventMap[K]) => void): this;
12
+ removeAllListeners(): this;
13
+ protected emit<K extends keyof EventMap>(event: K, ...args: EventMap[K]): void;
14
+ listenerCount<K extends keyof EventMap>(event: K): number;
15
+ }
@@ -0,0 +1,86 @@
1
+ import { EventEmitter } from './EventEmitter';
2
+ import { DeviceGroup } from './DeviceGroup';
3
+ import type { NoLagIoTOptions, IoTClientEvents, Device } from './types';
4
+ /**
5
+ * NoLagIoT — high-level IoT telemetry and command dispatch SDK built on @nolag/js-sdk.
6
+ *
7
+ * Provides device presence, real-time telemetry streaming, and command dispatch
8
+ * with ack tracking — all framework-agnostic via events.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { NoLagIoT } from '@nolag/iot';
13
+ *
14
+ * const iot = new NoLagIoT(token, { deviceId: 'sensor-01', role: 'device', debug: true });
15
+ *
16
+ * iot.on('connected', () => console.log('Connected!'));
17
+ * await iot.connect();
18
+ *
19
+ * const group = iot.joinGroup('factory-floor');
20
+ * group.on('command', (cmd) => {
21
+ * console.log('Received command:', cmd.command);
22
+ * group.ackCommand(cmd.id, 'completed', { ok: true });
23
+ * });
24
+ *
25
+ * // Send telemetry every second
26
+ * setInterval(() => {
27
+ * group.sendTelemetry('temperature', 22.5, { unit: '°C' });
28
+ * }, 1000);
29
+ * ```
30
+ */
31
+ export declare class NoLagIoT extends EventEmitter<IoTClientEvents> {
32
+ private _token;
33
+ private _options;
34
+ private _client;
35
+ private _localDevice;
36
+ private _groups;
37
+ private _lobby;
38
+ private _onlineDevices;
39
+ private _actorToDeviceId;
40
+ private _deviceId;
41
+ private _log;
42
+ constructor(token: string, options?: NoLagIoTOptions);
43
+ /** Whether the underlying connection is established */
44
+ get connected(): boolean;
45
+ /** The local device info (available after connect) */
46
+ get localDevice(): Device | null;
47
+ /** All currently joined groups */
48
+ get groups(): Map<string, DeviceGroup>;
49
+ /**
50
+ * Connect to NoLag and set up global presence.
51
+ */
52
+ connect(): Promise<void>;
53
+ /**
54
+ * Disconnect from NoLag and clean up all groups.
55
+ */
56
+ disconnect(): void;
57
+ /**
58
+ * Join a device group. Creates, subscribes, and activates it.
59
+ * Returns an existing group if already joined.
60
+ */
61
+ joinGroup(name: string): DeviceGroup;
62
+ /**
63
+ * Leave a device group. Fully unsubscribes and removes it.
64
+ */
65
+ leaveGroup(name: string): void;
66
+ /**
67
+ * Get all joined groups.
68
+ */
69
+ getGroups(): DeviceGroup[];
70
+ /**
71
+ * Get all devices currently online across all groups.
72
+ */
73
+ getOnlineDevices(): Device[];
74
+ private _subscribeGroup;
75
+ private _handleRoomPresenceJoin;
76
+ private _handleRoomPresenceLeave;
77
+ private _handleRoomPresenceUpdate;
78
+ private _setupLobby;
79
+ private _handleLobbyJoin;
80
+ private _handleLobbyLeave;
81
+ private _handleLobbyUpdate;
82
+ private _hydrateOnlineDevices;
83
+ private _presenceToDevice;
84
+ private _findDeviceIdByActorId;
85
+ private _restoreGroups;
86
+ }
@@ -0,0 +1,40 @@
1
+ import type { Device, IoTPresenceData } from './types';
2
+ /**
3
+ * Maps actorTokenId ↔ Device, filtering self.
4
+ */
5
+ export declare class PresenceManager {
6
+ private _devices;
7
+ private _actorToDeviceId;
8
+ private _localActorId;
9
+ constructor(localActorId: string);
10
+ /**
11
+ * Add or update a device from presence data.
12
+ * Returns the Device if it's a remote device, null if it's self.
13
+ */
14
+ addFromPresence(actorTokenId: string, presence: IoTPresenceData, joinedAt?: number): Device | null;
15
+ /**
16
+ * Remove a device by actorTokenId.
17
+ * Returns the removed device, or null if not found / is self.
18
+ */
19
+ removeByActorId(actorTokenId: string): Device | null;
20
+ /**
21
+ * Get a device by deviceId.
22
+ */
23
+ getDevice(deviceId: string): Device | undefined;
24
+ /**
25
+ * Get a device by actorTokenId.
26
+ */
27
+ getDeviceByActorId(actorTokenId: string): Device | undefined;
28
+ /**
29
+ * Get all remote devices.
30
+ */
31
+ getAll(): Device[];
32
+ /**
33
+ * Get the devices Map (readonly view).
34
+ */
35
+ get devices(): Map<string, Device>;
36
+ /**
37
+ * Clear all tracked devices.
38
+ */
39
+ clear(): void;
40
+ }
@@ -0,0 +1,43 @@
1
+ import type { TelemetryReading } from './types';
2
+ /**
3
+ * Per-device, per-sensor time-series buffer.
4
+ *
5
+ * Readings are stored under a composite key `${deviceId}:${sensorId}` and
6
+ * bounded to `maxPoints` entries per key (oldest entries are dropped first).
7
+ */
8
+ export declare class TelemetryStore {
9
+ private _store;
10
+ private _ids;
11
+ private _maxPoints;
12
+ constructor(maxPoints: number);
13
+ /**
14
+ * Add a telemetry reading to the store.
15
+ * Returns false if the reading id is a duplicate (idempotent).
16
+ */
17
+ add(reading: TelemetryReading): boolean;
18
+ /**
19
+ * Retrieve readings, optionally filtered by deviceId and/or sensorId.
20
+ *
21
+ * - No args → all readings across all devices and sensors
22
+ * - deviceId only → all readings for that device across all sensors
23
+ * - deviceId + sensorId → readings for that exact device/sensor pair
24
+ */
25
+ getAll(deviceId?: string, sensorId?: string): TelemetryReading[];
26
+ /**
27
+ * Get the most recent reading for a specific device/sensor pair.
28
+ */
29
+ getLatest(deviceId: string, sensorId: string): TelemetryReading | undefined;
30
+ /**
31
+ * Check whether a reading id already exists in the store.
32
+ */
33
+ has(id: string): boolean;
34
+ /**
35
+ * Total number of readings across all device/sensor buckets.
36
+ */
37
+ get size(): number;
38
+ /**
39
+ * Clear all stored readings and ids.
40
+ */
41
+ clear(): void;
42
+ private _key;
43
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @nolag/iot — Browser entry point
3
+ */
4
+ export { NoLagIoT } from './NoLagIoT';
5
+ export { DeviceGroup } from './DeviceGroup';
6
+ export { TelemetryStore } from './TelemetryStore';
7
+ export { CommandManager } from './CommandManager';
8
+ export { PresenceManager } from './PresenceManager';
9
+ export { EventEmitter } from './EventEmitter';
10
+ export type { NoLagIoTOptions, ResolvedIoTOptions, DeviceRole, CommandStatus, TelemetryReading, SendTelemetryOptions, DeviceCommand, Device, IoTPresenceData, IoTClientEvents, DeviceGroupEvents, } from './types';
@@ -0,0 +1,2 @@
1
+ import{NoLag as e}from"@nolag/js-sdk";class t{constructor(){this._handlers=new Map}on(e,t){return this._handlers.has(e)||this._handlers.set(e,new Set),this._handlers.get(e).add(t),this}off(e,t){return t?this._handlers.get(e)?.delete(t):this._handlers.delete(e),this}removeAllListeners(){return this._handlers.clear(),this}emit(e,...t){const i=this._handlers.get(e);if(i)for(const s of i)try{s(...t)}catch(t){console.error(`Error in ${String(e)} handler:`,t)}}listenerCount(e){return this._handlers.get(e)?.size??0}}class i{constructor(e){this._devices=new Map,this._actorToDeviceId=new Map,this._localActorId=e}addFromPresence(e,t,i){if(e===this._localActorId)return null;const s=this._actorToDeviceId.get(e),o=t.deviceId||s||e,n={deviceId:o,actorTokenId:e,deviceName:t.deviceName,role:t.role,metadata:t.metadata,joinedAt:i??Date.now(),isLocal:!1};return this._devices.set(o,n),this._actorToDeviceId.set(e,o),n}removeByActorId(e){if(e===this._localActorId)return null;const t=this._actorToDeviceId.get(e);if(!t)return null;const i=this._devices.get(t)??null;return this._devices.delete(t),this._actorToDeviceId.delete(e),i}getDevice(e){return this._devices.get(e)}getDeviceByActorId(e){const t=this._actorToDeviceId.get(e);return t?this._devices.get(t):void 0}getAll(){return Array.from(this._devices.values())}get devices(){return this._devices}clear(){this._devices.clear(),this._actorToDeviceId.clear()}}class s{constructor(e){this._store=new Map,this._ids=new Set,this._maxPoints=e}add(e){if(this._ids.has(e.id))return!1;const t=this._key(e.deviceId,e.sensorId);this._store.has(t)||this._store.set(t,[]);const i=this._store.get(t);return i.push(e),i.length>this._maxPoints&&i.splice(0,i.length-this._maxPoints),this._ids.add(e.id),!0}getAll(e,t){if(void 0!==e&&void 0!==t)return[...this._store.get(this._key(e,t))??[]];const i=[];for(const[t,s]of this._store.entries())(void 0===e||t.startsWith(`${e}:`))&&i.push(...s);return i}getLatest(e,t){const i=this._store.get(this._key(e,t));if(i&&0!==i.length)return i[i.length-1]}has(e){return this._ids.has(e)}get size(){let e=0;for(const t of this._store.values())e+=t.length;return e}clear(){this._store.clear(),this._ids.clear()}_key(e,t){return`${e}:${t}`}}function o(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():"xxxx-xxxx-xxxx-xxxx".replace(/x/g,()=>Math.floor(16*Math.random()).toString(16))}function n(e,t){return t?(...t)=>{console.log(`[${e}]`,...t)}:(...e)=>{}}class c{constructor(e){this._pending=new Map,this._commands=new Map,this._defaultTimeout=e}send(e,t,i,s,n){const c=o(),r=Date.now(),a={id:c,targetDeviceId:e,command:t,params:i,status:"pending",sentBy:s,sentAt:r};this._commands.set(c,a);const d=new Promise((e,i)=>{const s=n??this._defaultTimeout,o=setTimeout(()=>{const e=this._pending.get(c);e&&(e.command.status="timeout",this._commands.set(c,e.command),this._pending.delete(c),i(new Error(`Command "${t}" (${c}) timed out after ${s}ms`)))},s);this._pending.set(c,{command:a,resolve:e,reject:i,timer:o})});return d.catch(()=>{}),d}ack(e,t,i){const s=this._pending.get(e);if(!s)return null;clearTimeout(s.timer),this._pending.delete(e);const o=Date.now(),n=s.command;return n.status=t,"acked"===t?n.ackedAt=o:"completed"===t?(n.ackedAt=n.ackedAt??o,n.completedAt=o,n.result=i):"failed"===t&&(n.ackedAt=n.ackedAt??o,n.error="string"==typeof i?i:"Command failed"),this._commands.set(e,n),"acked"===t||"completed"===t?s.resolve(n):s.reject(new Error(n.error??"Command failed")),n}get(e){return this._commands.get(e)}getPending(){return Array.from(this._pending.values()).map(e=>e.command)}dispose(){for(const[e,t]of this._pending.entries())clearTimeout(t.timer),t.command.status="timeout",this._commands.set(e,t.command),t.reject(new Error(`Command "${t.command.command}" (${e}) was disposed`));this._pending.clear()}}const r="telemetry",a="commands",d="_cmd_ack";class h extends t{constructor(e,t,o,n,r){super(),this._receivedCommands=new Map,this.name=e,this._roomContext=t,this._localDevice=o,this._options=n,this._log=r,this._presenceManager=new i(o.actorTokenId),this._telemetryStore=new s(n.maxTelemetryPoints),this._commandManager=new c(n.commandTimeout)}get devices(){return this._presenceManager.devices}sendTelemetry(e,t,i={}){const s={id:o(),deviceId:this._localDevice.deviceId,sensorId:e,value:t,unit:i.unit,tags:i.tags,timestamp:Date.now(),isReplay:!1};return this._log("Sending telemetry:",e,"=",t),this._roomContext.emit(r,s,{echo:!1}),this._telemetryStore.add(s),s}getTelemetry(e,t){return this._telemetryStore.getAll(e,t)}sendCommand(e,t,i){this._log("Sending command:",t,"→",e);const s=this._commandManager.send(e,t,i,this._localDevice.deviceId,this._options.commandTimeout),o=this._commandManager.getPending(),n=o[o.length-1];return n&&this._roomContext.emit(a,n,{echo:!1,filter:e}),s}ackCommand(e,t,i){this._log("Acking command:",e,t);const s={commandId:e,status:t,result:i,ackedBy:this._localDevice.deviceId,ackedAt:Date.now()},o=this._receivedCommands.get(e)||this._commandManager.get(e),n=o?.sentBy;this._receivedCommands.delete(e),this._roomContext.emit(d,s,{echo:!1,...n?{filter:n}:{}}),this._commandManager.ack(e,t,i)}getDevices(){return this._presenceManager.getAll()}getDevice(e){return this._presenceManager.getDevice(e)}_subscribe(){this._log("Group subscribe:",this.name),this._roomContext.subscribe(r),"device"===this._options.role?this._roomContext.subscribe(a,{filters:[this._localDevice.deviceId]}):this._roomContext.subscribe(a),"controller"===this._options.role?this._roomContext.subscribe(d,{filters:[this._localDevice.deviceId]}):this._roomContext.subscribe(d),this._roomContext.on(r,e=>{this._handleIncomingTelemetry(e)}),this._roomContext.on(a,e=>{this._handleIncomingCommand(e)}),this._roomContext.on(d,e=>{this._handleIncomingCmdAck(e)})}_activate(){this._log("Group activate:",this.name),this._setPresence(),this._roomContext.fetchPresence().then(e=>{this._log("Group presence fetched:",this.name,e.length,"actors");for(const t of e)if(t.presence){const e=this._presenceManager.addFromPresence(t.actorTokenId,t.presence,t.joinedAt);e&&this.emit("deviceJoined",e)}}).catch(e=>{this._log("Failed to fetch group presence:",e)})}_updateLocalPresence(){this._setPresence()}_handlePresenceJoin(e,t){const i=this._presenceManager.addFromPresence(e,t);i&&(this._log("Device joined group:",this.name,i.deviceId),this.emit("deviceJoined",i))}_handlePresenceLeave(e){const t=this._presenceManager.removeByActorId(e);t&&(this._log("Device left group:",this.name,t.deviceId),this.emit("deviceLeft",t))}_handlePresenceUpdate(e,t){this._presenceManager.addFromPresence(e,t)}_cleanup(){this._log("Group cleanup:",this.name),this._roomContext.unsubscribe(r),this._roomContext.unsubscribe(a),this._roomContext.unsubscribe(d),this._roomContext.off(r),this._roomContext.off(a),this._roomContext.off(d),this._commandManager.dispose(),this._receivedCommands.clear(),this._presenceManager.clear(),this.removeAllListeners()}_handleIncomingTelemetry(e){const t=e;this._log("Received telemetry:",t.sensorId,"=",t.value,"from",t.deviceId);this._telemetryStore.add(t)&&this.emit("telemetry",t)}_handleIncomingCommand(e){const t=e;"controller"!==this._options.role&&(this._log("Received command:",t.command,"from",t.sentBy),this._receivedCommands.set(t.id,t),this.emit("command",t))}_handleIncomingCmdAck(e){const t=e;this._log("Received command ack:",t.commandId,t.status);const i=this._commandManager.ack(t.commandId,t.status,t.result);i&&this.emit("commandAck",i)}_setPresence(){const e={deviceId:this._localDevice.deviceId,deviceName:this._localDevice.deviceName,role:this._localDevice.role,metadata:this._localDevice.metadata};this._roomContext.setPresence(e)}}class l extends t{constructor(e,t={}){super(),this._client=null,this._localDevice=null,this._groups=new Map,this._lobby=null,this._onlineDevices=new Map,this._actorToDeviceId=new Map,this._token=e,this._deviceId=t.deviceId??o(),this._options={deviceId:this._deviceId,deviceName:t.deviceName,role:t.role??"device",metadata:t.metadata,appName:t.appName??"iot",url:t.url,maxTelemetryPoints:t.maxTelemetryPoints??1e3,commandTimeout:t.commandTimeout??3e4,debug:t.debug??!1,reconnect:t.reconnect??!0,groups:t.groups??[]},this._log=n("NoLagIoT",this._options.debug)}get connected(){return this._client?.connected??!1}get localDevice(){return this._localDevice}get groups(){return this._groups}async connect(){this._log("Connecting...");const t={debug:this._options.debug,reconnect:this._options.reconnect};this._options.url&&(t.url=this._options.url),this._client=e(this._token,t),this._client.on("connect",()=>{this._log("Connected"),this._groups.size>0&&(this._log("Reconnected — restoring groups..."),this._restoreGroups(),this.emit("reconnected"))}),this._client.on("disconnect",e=>{this._log("Disconnected:",e),this.emit("disconnected",e)}),this._client.on("reconnect",()=>{this._log("Reconnecting...")}),this._client.on("error",e=>{this._log("Error:",e),this.emit("error",e)}),await this._client.connect(),this._client.on("presence:join",e=>{this._handleRoomPresenceJoin(e)}),this._client.on("presence:leave",e=>{this._handleRoomPresenceLeave(e)}),this._client.on("presence:update",e=>{this._handleRoomPresenceUpdate(e)}),this._localDevice={deviceId:this._deviceId,actorTokenId:this._client.actorId,deviceName:this._options.deviceName,role:this._options.role,metadata:this._options.metadata,joinedAt:Date.now(),isLocal:!0},this._log("Local device:",this._localDevice.deviceId,"→",this._localDevice.actorTokenId),await this._setupLobby(),this.emit("connected");for(const e of this._options.groups)this.joinGroup(e);setTimeout(()=>{this._lobby&&this._client?.connected&&this._lobby.fetchPresence().then(e=>{this._hydrateOnlineDevices(e)}).catch(()=>{})},2e3)}disconnect(){this._log("Disconnecting...");for(const e of[...this._groups.keys()])this.leaveGroup(e);this._lobby?.unsubscribe(),this._lobby=null,this._client?.disconnect(),this._client=null,this._onlineDevices.clear(),this._actorToDeviceId.clear(),this._localDevice=null}joinGroup(e){if(!this._client||!this._localDevice)throw new Error("Not connected — call connect() first");let t=this._groups.get(e);return t||(t=this._subscribeGroup(e),t._activate()),t}leaveGroup(e){const t=this._groups.get(e);t&&(this._log("Leaving group:",e),t._cleanup(),this._groups.delete(e))}getGroups(){return Array.from(this._groups.values())}getOnlineDevices(){return Array.from(this._onlineDevices.values())}_subscribeGroup(e){if(!this._client||!this._localDevice)throw new Error("Not connected — call connect() first");this._log("Subscribing group:",e);const t=this._client.setApp(this._options.appName).setRoom(e),i=new h(e,t,this._localDevice,this._options,n(`DeviceGroup:${e}`,this._options.debug));return this._groups.set(e,i),i._subscribe(),i}_handleRoomPresenceJoin(e){if(e.actorTokenId===this._localDevice?.actorTokenId)return;const t=e.presence;if(!t?.deviceId)return;const i=this._presenceToDevice(e.actorTokenId,t);this._actorToDeviceId.set(e.actorTokenId,i.deviceId),this._onlineDevices.has(i.deviceId)||(this._onlineDevices.set(i.deviceId,i),this.emit("deviceOnline",i));for(const i of this._groups.values())i._handlePresenceJoin(e.actorTokenId,t)}_handleRoomPresenceLeave(e){if(e.actorTokenId!==this._localDevice?.actorTokenId)for(const t of this._groups.values())t._handlePresenceLeave(e.actorTokenId)}_handleRoomPresenceUpdate(e){if(e.actorTokenId===this._localDevice?.actorTokenId)return;const t=e.presence;if(t?.deviceId){if(this._onlineDevices.has(t.deviceId)){const i=this._presenceToDevice(e.actorTokenId,t);this._onlineDevices.set(i.deviceId,i)}for(const i of this._groups.values())i._handlePresenceUpdate(e.actorTokenId,t)}}async _setupLobby(){if(!this._client)return;this._lobby=this._client.setApp(this._options.appName).setLobby("online");const e=e=>t=>{const i=t;"join"===e?this._handleLobbyJoin(i):"leave"===e?this._handleLobbyLeave(i):this._handleLobbyUpdate(i)};this._client.on("lobbyPresence:join",e("join")),this._client.on("lobbyPresence:leave",e("leave")),this._client.on("lobbyPresence:update",e("update"));try{const e=await this._lobby.subscribe();this._hydrateOnlineDevices(e),this._log("Lobby subscribed, online devices:",this._onlineDevices.size)}catch(e){this._log("Lobby subscription failed:",e)}}_handleLobbyJoin(e){const{actorId:t,data:i}=e;if(t===this._localDevice?.actorTokenId)return;const s=i;if(!s.deviceId)return;const o=this._presenceToDevice(t,s);this._actorToDeviceId.set(t,o.deviceId),this._onlineDevices.has(o.deviceId)||(this._onlineDevices.set(o.deviceId,o),this.emit("deviceOnline",o))}_handleLobbyLeave(e){const{actorId:t,data:i}=e;if(t===this._localDevice?.actorTokenId)return;const s=i,o=s?.deviceId||this._actorToDeviceId.get(t)||this._findDeviceIdByActorId(t);if(o){const e=this._onlineDevices.get(o);e&&(this._onlineDevices.delete(o),this._actorToDeviceId.delete(t),this.emit("deviceOffline",e))}}_handleLobbyUpdate(e){const{actorId:t,data:i}=e;if(t===this._localDevice?.actorTokenId)return;const s=i;if(!s.deviceId)return;const o=this._presenceToDevice(t,s);this._onlineDevices.set(o.deviceId,o)}_hydrateOnlineDevices(e){for(const t of Object.keys(e)){const i=e[t];for(const e of Object.keys(i)){if(e===this._localDevice?.actorTokenId)continue;const t=i[e],s=t?.presence??t;if(s?.deviceId){const t=this._presenceToDevice(e,s);this._actorToDeviceId.set(e,t.deviceId),this._onlineDevices.has(t.deviceId)||(this._onlineDevices.set(t.deviceId,t),this.emit("deviceOnline",t))}}}}_presenceToDevice(e,t){return{deviceId:t.deviceId,actorTokenId:e,deviceName:t.deviceName,role:t.role,metadata:t.metadata,joinedAt:Date.now(),isLocal:!1}}_findDeviceIdByActorId(e){for(const t of this._onlineDevices.values())if(t.actorTokenId===e)return t.deviceId}_restoreGroups(){for(const e of this._groups.values())e._updateLocalPresence();this._lobby?.fetchPresence().then(e=>{this._onlineDevices.clear(),this._actorToDeviceId.clear(),this._hydrateOnlineDevices(e)}).catch(e=>{this._log("Failed to re-fetch lobby presence:",e)})}}export{c as CommandManager,h as DeviceGroup,t as EventEmitter,l as NoLagIoT,i as PresenceManager,s as TelemetryStore};
2
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sources":["../src/EventEmitter.ts","../src/PresenceManager.ts","../src/TelemetryStore.ts","../src/utils.ts","../src/CommandManager.ts","../src/constants.ts","../src/DeviceGroup.ts","../src/NoLagIoT.ts"],"sourcesContent":[null,null,null,null,null,null,null,null],"names":["EventEmitter","constructor","this","_handlers","Map","on","event","handler","has","set","Set","get","add","off","delete","removeAllListeners","clear","emit","args","handlers","e","console","error","String","listenerCount","size","PresenceManager","localActorId","_devices","_actorToDeviceId","_localActorId","addFromPresence","actorTokenId","presence","joinedAt","existing","deviceId","device","deviceName","role","metadata","Date","now","isLocal","removeByActorId","getDevice","getDeviceByActorId","undefined","getAll","Array","from","values","devices","TelemetryStore","maxPoints","_store","_ids","_maxPoints","reading","id","key","_key","sensorId","bucket","push","length","splice","results","entries","startsWith","getLatest","total","generateId","crypto","randomUUID","replace","Math","floor","random","toString","createLogger","prefix","enabled","log","_args","CommandManager","defaultTimeout","_pending","_commands","_defaultTimeout","send","targetDeviceId","command","params","sentBy","timeout","cmd","status","sentAt","promise","Promise","resolve","reject","ms","timer","setTimeout","entry","Error","catch","ack","commandId","result","clearTimeout","ackedAt","completedAt","getPending","map","dispose","TOPIC_TELEMETRY","TOPIC_COMMANDS","TOPIC_CMD_ACK","DeviceGroup","name","roomContext","localDevice","options","super","_receivedCommands","_roomContext","_localDevice","_options","_log","_presenceManager","_telemetryStore","maxTelemetryPoints","_commandManager","commandTimeout","sendTelemetry","value","opts","unit","tags","timestamp","isReplay","echo","getTelemetry","sendCommand","pending","filter","ackCommand","ackedBy","ackFilter","getDevices","_subscribe","subscribe","filters","data","_handleIncomingTelemetry","_handleIncomingCommand","_handleIncomingCmdAck","_activate","_setPresence","fetchPresence","then","actors","actor","err","_updateLocalPresence","_handlePresenceJoin","presenceData","_handlePresenceLeave","_handlePresenceUpdate","_cleanup","unsubscribe","setPresence","NoLagIoT","token","_client","_groups","_lobby","_onlineDevices","_token","_deviceId","appName","url","debug","reconnect","groups","connected","connect","clientOptions","NoLag","_restoreGroups","reason","_handleRoomPresenceJoin","_handleRoomPresenceLeave","_handleRoomPresenceUpdate","actorId","_setupLobby","groupName","joinGroup","state","_hydrateOnlineDevices","disconnect","keys","leaveGroup","group","_subscribeGroup","getGroups","getOnlineDevices","setApp","setRoom","_presenceToDevice","setLobby","lobbyHandler","type","_handleLobbyJoin","_handleLobbyLeave","_handleLobbyUpdate","initialState","_findDeviceIdByActorId","roomId","Object","roomPresence","raw"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /** Default app name for NoLag IoT SDK */
2
+ export declare const DEFAULT_APP_NAME = "iot";
3
+ /** Maximum telemetry readings to retain per device/sensor key */
4
+ export declare const DEFAULT_MAX_TELEMETRY_POINTS = 1000;
5
+ /** Default command acknowledgement timeout in milliseconds */
6
+ export declare const DEFAULT_COMMAND_TIMEOUT = 30000;
7
+ /** Topic name for telemetry readings */
8
+ export declare const TOPIC_TELEMETRY = "telemetry";
9
+ /** Topic name for dispatched commands */
10
+ export declare const TOPIC_COMMANDS = "commands";
11
+ /** Topic name for command acknowledgements */
12
+ export declare const TOPIC_CMD_ACK = "_cmd_ack";
13
+ /** Lobby ID for global online presence */
14
+ export declare const LOBBY_ID = "online";