yoto-nodejs-client 0.0.5 → 0.0.7

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.
Files changed (52) hide show
  1. package/README.md +73 -40
  2. package/bin/auth.js +4 -3
  3. package/bin/device-model.js +25 -5
  4. package/bin/device-tui.js +25 -3
  5. package/bin/devices.js +25 -9
  6. package/bin/lib/cli-helpers.d.ts.map +1 -1
  7. package/bin/lib/cli-helpers.js +3 -1
  8. package/bin/lib/token-helpers.d.ts +4 -2
  9. package/bin/lib/token-helpers.d.ts.map +1 -1
  10. package/bin/lib/token-helpers.js +9 -8
  11. package/bin/refresh-token.js +4 -2
  12. package/bin/token-info.js +2 -2
  13. package/lib/api-client.d.ts +11 -10
  14. package/lib/api-client.d.ts.map +1 -1
  15. package/lib/api-client.js +12 -14
  16. package/lib/api-endpoints/auth.test.js +4 -4
  17. package/lib/api-endpoints/content.test.js +32 -32
  18. package/lib/api-endpoints/devices.d.ts +4 -4
  19. package/lib/api-endpoints/devices.js +2 -2
  20. package/lib/api-endpoints/devices.test.js +45 -45
  21. package/lib/api-endpoints/endpoint-test-helpers.d.ts +3 -4
  22. package/lib/api-endpoints/endpoint-test-helpers.d.ts.map +1 -1
  23. package/lib/api-endpoints/endpoint-test-helpers.js +21 -5
  24. package/lib/api-endpoints/family-library-groups.d.ts +3 -3
  25. package/lib/api-endpoints/family-library-groups.d.ts.map +1 -1
  26. package/lib/api-endpoints/family-library-groups.js +3 -3
  27. package/lib/api-endpoints/family-library-groups.test.js +29 -29
  28. package/lib/api-endpoints/family.test.js +11 -11
  29. package/lib/api-endpoints/icons.test.js +14 -14
  30. package/lib/mqtt/client.d.ts +123 -48
  31. package/lib/mqtt/client.d.ts.map +1 -1
  32. package/lib/mqtt/client.js +131 -49
  33. package/lib/mqtt/factory.d.ts +12 -5
  34. package/lib/mqtt/factory.d.ts.map +1 -1
  35. package/lib/mqtt/factory.js +39 -11
  36. package/lib/mqtt/index.js +2 -1
  37. package/lib/mqtt/mqtt.test.js +25 -22
  38. package/lib/test-helpers/device-model-test-helpers.d.ts +29 -0
  39. package/lib/test-helpers/device-model-test-helpers.d.ts.map +1 -0
  40. package/lib/test-helpers/device-model-test-helpers.js +116 -0
  41. package/lib/token.d.ts +44 -2
  42. package/lib/token.d.ts.map +1 -1
  43. package/lib/token.js +142 -2
  44. package/lib/yoto-account.d.ts +339 -9
  45. package/lib/yoto-account.d.ts.map +1 -1
  46. package/lib/yoto-account.js +411 -39
  47. package/lib/yoto-account.test.js +139 -0
  48. package/lib/yoto-device.d.ts +418 -30
  49. package/lib/yoto-device.d.ts.map +1 -1
  50. package/lib/yoto-device.js +670 -104
  51. package/lib/yoto-device.test.js +88 -0
  52. package/package.json +1 -1
@@ -1,21 +1,27 @@
1
1
  /**
2
2
  * Yoto MQTT Client class
3
- * @extends EventEmitter
3
+ * @extends {EventEmitter<YotoMqttClientEventMap>}
4
4
  *
5
5
  * Device automatically publishes status updates every 5 minutes when connected.
6
6
  * Status can also be requested on-demand via requestStatus() and requestEvents().
7
7
  *
8
- * @fires YotoMqttClient#events - Emits (topic, payload) when device sends events
9
- * @fires YotoMqttClient#status - Emits (topic, payload) when device sends status (automatic every 5 min, or on-demand)
10
- * @fires YotoMqttClient#status-legacy - Emits (topic, payload) when device sends legacy status with lifecycle events
11
- * @fires YotoMqttClient#response - Emits (topic, payload) when device responds to commands
12
- * @fires YotoMqttClient#unknown - Emits (topic, payload) when receiving unknown message type
13
- * @fires YotoMqttClient#connected
14
- * @fires YotoMqttClient#disconnected
15
- * @fires YotoMqttClient#reconnecting
16
- * @fires YotoMqttClient#error
8
+ * Events:
9
+ * - 'connect' - Emitted on successful (re)connection (connack rc=0). Passes connack packet; when sessionPresent is true and clean is false, you can rely on stored session and avoid re-subscribing. Auto-subscribe (if enabled) runs after connect and may emit errors.
10
+ * - 'disconnect' - Emitted after receiving disconnect packet from broker. MQTT 5.0 feature. Passes metadata with disconnect packet.
11
+ * - 'close' - Emitted after a disconnection, passes metadata with close reason.
12
+ * - 'reconnect' - Emitted when a reconnect starts.
13
+ * - 'offline' - Emitted when the client goes offline.
14
+ * - 'end' - Emitted when mqttClient.end() is called (after its callback returns).
15
+ * - 'error' - Emitted when the client cannot connect (connack rc != 0) or when a parsing error occurs.
16
+ * - 'packetsend' - Emitted when the client sends any packet (including publish and subscription packets).
17
+ * - 'packetreceive' - Emitted when the client receives any packet.
18
+ * - 'events' - Device sends events, passes (topic, payload).
19
+ * - 'status' - Device sends status, passes (topic, payload).
20
+ * - 'status-legacy' - Device sends legacy status with lifecycle events, passes (topic, payload).
21
+ * - 'response' - Device responds to commands, passes (topic, payload).
22
+ * - 'unknown' - Unknown message type received, passes (topic, payload).
17
23
  */
18
- export class YotoMqttClient extends EventEmitter<any> {
24
+ export class YotoMqttClient extends EventEmitter<YotoMqttClientEventMap> {
19
25
  /**
20
26
  * Create a Yoto MQTT client
21
27
  * @param {MqttClient} mqttClient - Underlying MQTT client
@@ -26,20 +32,9 @@ export class YotoMqttClient extends EventEmitter<any> {
26
32
  constructor(mqttClient: MqttClient, deviceId: string, options?: {
27
33
  autoSubscribe?: boolean | undefined;
28
34
  });
29
- mqttClient: MqttClient;
30
- deviceId: string;
31
- autoSubscribe: boolean;
32
- commands: {
33
- volume: typeof import("./commands.js").createVolumeCommand;
34
- ambient: typeof import("./commands.js").createAmbientCommand;
35
- ambientFromHex: typeof import("./commands.js").createAmbientCommandFromHex;
36
- sleepTimer: typeof import("./commands.js").createSleepTimerCommand;
37
- cardStart: typeof import("./commands.js").createCardStartCommand;
38
- bluetoothOn: typeof import("./commands.js").createBluetoothOnCommand;
39
- bluetoothSpeaker: typeof import("./commands.js").createBluetoothSpeakerCommand;
40
- bluetoothAudioSource: typeof import("./commands.js").createBluetoothAudioSourceCommand;
41
- displayPreview: typeof import("./commands.js").createDisplayPreviewCommand;
42
- };
35
+ /** @type {typeof commands} */ commands: typeof commands;
36
+ /** @type {MqttClient} */ mqttClient: MqttClient;
37
+ /** @type {string} */ deviceId: string;
43
38
  /**
44
39
  * Get current connection state
45
40
  * @returns {YotoMqttConnectionState}
@@ -218,6 +213,44 @@ export class YotoMqttClient extends EventEmitter<any> {
218
213
  }): Promise<void>;
219
214
  #private;
220
215
  }
216
+ export type PlaybackStatus = "playing" | "paused" | "stopped" | "loading";
217
+ /**
218
+ * MQTT disconnect event metadata (from MQTT disconnect packet)
219
+ */
220
+ export type YotoMqttClientDisconnectMetadata = {
221
+ /**
222
+ * - MQTT disconnect packet
223
+ */
224
+ packet: IDisconnectPacket;
225
+ };
226
+ /**
227
+ * MQTT close event metadata (from connection close)
228
+ */
229
+ export type YotoMqttClientCloseMetadata = {
230
+ /**
231
+ * - Close reason
232
+ */
233
+ reason: "close";
234
+ };
235
+ /**
236
+ * Event map for YotoMqttClient
237
+ */
238
+ export type YotoMqttClientEventMap = {
239
+ "connect": [IConnackPacket];
240
+ "disconnect": [YotoMqttClientDisconnectMetadata];
241
+ "close": [YotoMqttClientCloseMetadata];
242
+ "reconnect": [];
243
+ "offline": [];
244
+ "end": [];
245
+ "error": [Error];
246
+ "events": [string, YotoEventsMessage];
247
+ "status": [string, YotoStatusMessage];
248
+ "status-legacy": [string, YotoStatusLegacyMessage];
249
+ "response": [string, YotoResponseMessage];
250
+ "unknown": [string, any];
251
+ "packetsend": [Packet];
252
+ "packetreceive": [Packet];
253
+ };
221
254
  /**
222
255
  * Events message from device
223
256
  * Note: Messages are partial - only changed fields are included
@@ -266,7 +299,7 @@ export type YotoEventsMessage = {
266
299
  /**
267
300
  * - Source of playback (e.g., "card", "remote", "MQTT")
268
301
  */
269
- source?: string;
302
+ source?: "card" | "remote" | "MQTT";
270
303
  /**
271
304
  * - ISO8601 format timestamp
272
305
  */
@@ -290,7 +323,7 @@ export type YotoEventsMessage = {
290
323
  /**
291
324
  * - Playback status
292
325
  */
293
- playbackStatus?: "playing" | "paused" | "stopped" | "loading" | string;
326
+ playbackStatus?: PlaybackStatus;
294
327
  /**
295
328
  * - Seconds remaining on sleep timer
296
329
  */
@@ -334,7 +367,7 @@ export type YotoMqttStatus = {
334
367
  */
335
368
  batteryLevel: number;
336
369
  /**
337
- * - Ambient light sensor reading
370
+ * - Ambient light sensor reading TODO: Find range/units
338
371
  */
339
372
  als: number;
340
373
  /**
@@ -374,11 +407,11 @@ export type YotoMqttStatus = {
374
407
  */
375
408
  dnowBrightness: number;
376
409
  /**
377
- * - Day brightness setting (Integer 0-100)
410
+ * - Day brightness setting (Integer 0-100, 255 when 'auto')
378
411
  */
379
412
  dayBright: number;
380
413
  /**
381
- * - Night brightness setting (Integer 0-100)
414
+ * - Night brightness setting (Integer 0-100, 255 when 'auto')
382
415
  */
383
416
  nightBright: number;
384
417
  /**
@@ -402,7 +435,7 @@ export type YotoMqttStatus = {
402
435
  */
403
436
  nightlightMode?: string;
404
437
  /**
405
- * - Temperature reading (format varies: 'value1:value2:value3' or 'value1:notSupported') - only in requested status
438
+ * - Temperature reading (format varies: 'value1:value2:value3' or 'value1:notSupported') - only in requested status. value2, when a number, is the temp in Celcius
406
439
  */
407
440
  temp?: string;
408
441
  /**
@@ -410,6 +443,55 @@ export type YotoMqttStatus = {
410
443
  */
411
444
  day: -1 | 0 | 1;
412
445
  };
446
+ /**
447
+ * Response message from device
448
+ */
449
+ export type YotoResponseStatusKnown = {
450
+ /**
451
+ * - Volume command result
452
+ */
453
+ volume?: "OK" | "FAIL";
454
+ /**
455
+ * - Ambients command result
456
+ */
457
+ ambients?: "OK" | "FAIL";
458
+ /**
459
+ * - Card command result
460
+ */
461
+ card?: "OK" | "FAIL";
462
+ /**
463
+ * - Events request result (alternate key to 'events/request')
464
+ */
465
+ events?: "OK" | "FAIL";
466
+ /**
467
+ * - Status request result (alternate key to 'status/request')
468
+ */
469
+ status?: "OK" | "FAIL";
470
+ /**
471
+ * - Bluetooth command result
472
+ */
473
+ bluetooth?: "OK" | "FAIL";
474
+ /**
475
+ * - Display command result
476
+ */
477
+ display?: "OK" | "FAIL";
478
+ /**
479
+ * - Reboot command result
480
+ */
481
+ reboot?: "OK" | "FAIL";
482
+ /**
483
+ * - Stringified JSON from original request
484
+ */
485
+ req_body: string;
486
+ /**
487
+ * - Sleep timer command result (alternate key to 'sleep-timer')
488
+ */
489
+ sleepTimer?: "OK" | "FAIL";
490
+ };
491
+ /**
492
+ * Response message from device
493
+ */
494
+ export type YotoResponseStatus = YotoResponseStatusKnown & Record<string, "OK" | "FAIL" | string | undefined> & Partial<Record<"status/request" | "events/request" | "sleep-timer", "OK" | "FAIL">>;
413
495
  /**
414
496
  * Response message from device
415
497
  */
@@ -417,18 +499,7 @@ export type YotoResponseMessage = {
417
499
  /**
418
500
  * - Status object with dynamic resource keys
419
501
  */
420
- status: {
421
- volume?: "OK" | "FAIL" | undefined;
422
- ambients?: "OK" | "FAIL" | undefined;
423
- card?: "OK" | "FAIL" | undefined;
424
- events?: "OK" | "FAIL" | undefined;
425
- status?: "OK" | "FAIL" | undefined;
426
- bluetooth?: "OK" | "FAIL" | undefined;
427
- display?: "OK" | "FAIL" | undefined;
428
- reboot?: "OK" | "FAIL" | undefined;
429
- req_body: string;
430
- sleepTimer: "OK" | "FAIL";
431
- };
502
+ status: YotoResponseStatus;
432
503
  };
433
504
  /**
434
505
  * Legacy status message from device (MQTT /status)
@@ -622,15 +693,15 @@ export type YotoLegacyStatus = {
622
693
  */
623
694
  buzzErrors: number;
624
695
  /**
625
- * - Current display brightness
696
+ * - Current display brightness (0-100, act)
626
697
  */
627
698
  dnowBrightness: number;
628
699
  /**
629
- * - Day brightness setting
700
+ * - Day brightness setting (0-100, 255 when configed to 'auto')
630
701
  */
631
702
  dayBright: number;
632
703
  /**
633
- * - Night brightness setting
704
+ * - Night brightness setting (0-100, 255 when configed to 'auto')
634
705
  */
635
706
  nightBright: number;
636
707
  /**
@@ -662,11 +733,11 @@ export type YotoLegacyStatus = {
662
733
  */
663
734
  day: -1 | 0 | 1;
664
735
  /**
665
- * - Temperature readings (format: 'val1:val2:val3')
736
+ * - Temperature reading (format varies: 'value1:value2:value3' or 'value1:notSupported') - only in requested status. value2, when a number, is the temp in Celcius
666
737
  */
667
738
  temp: string;
668
739
  /**
669
- * - Ambient light sensor reading
740
+ * - Ambient light sensor reading TODO: Find range/units
670
741
  */
671
742
  als: number;
672
743
  /**
@@ -723,5 +794,9 @@ export type ResponseCallback = (topic: string, payload: YotoResponseMessage) =>
723
794
  */
724
795
  export type UnknownCallback = (topic: string, payload: any) => any;
725
796
  import { EventEmitter } from 'events';
797
+ import { commands } from './commands.js';
726
798
  import type { MqttClient } from 'mqtt';
799
+ import type { IDisconnectPacket } from 'mqtt';
800
+ import type { IConnackPacket } from 'mqtt';
801
+ import type { Packet } from 'mqtt';
727
802
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["client.js"],"names":[],"mappings":"AA6PA;;;;;;;;;;;;;;;;GAgBG;AACH;IACE;;;;;;OAMG;IACH,wBALW,UAAU,YACV,MAAM,YAEd;QAA0B,aAAa;KACzC,EAaA;IATC,uBAA4B;IAC5B,iBAAwB;IACxB,uBAAoD;IAMpD;;;;;;;;;;MAAwB;IAG1B;;;OAGG;IACH,aAFa,uBAAuB,CAMnC;IAED;;;OAGG;IACH,iBAFa,OAAO,CAInB;IA2CD;;;;;;;;;;;;OAYG;IACH,kBAXW,KAAK,CAAC,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC,GAAG,KAAK,GAC7C,OAAO,CAAC,IAAI,CAAC,CAiDzB;IA8CD;;;OAGG;IACH,WAFa,OAAO,CAAC,IAAI,CAAC,CA8BzB;IAED;;;OAGG;IACH,cAFa,OAAO,CAAC,IAAI,CAAC,CAiBzB;IAwBD;;;;OAIG;IACH,qBAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;;OAIG;IACH,qBAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;;OAIG;IACH,kBAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;;;;OAMG;IACH,cALW,MAAM,KACN,MAAM,KACN,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;;OAIG;IACH,wBAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;;OAIG;IACH,uBAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;OAGG;IACH,UAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;;;;;;;;OAUG;IACH,mBARG;QAAwB,GAAG,EAAnB,MAAM;QACW,UAAU;QACV,QAAQ;QACR,SAAS;QACT,MAAM;QACL,aAAa;KACvC,GAAU,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;OAGG;IACH,YAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,aAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,cAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;;;;;;;OASG;IACH,sBAPG;QAAyB,MAAM;QACI,IAAI;QACd,IAAI;QACJ,IAAI;QACJ,GAAG;KAC5B,GAAU,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;OAGG;IACH,gBAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,wBAFa,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;OAGG;IACH,4BAFa,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;OAGG;IACH,wBAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,uBAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,qBAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;;;;;OAOG;IACH,wBALG;QAAwB,GAAG,EAAnB,MAAM;QACU,OAAO,EAAvB,MAAM;QACW,QAAQ,EAAzB,OAAO;KACf,GAAU,OAAO,CAAC,IAAI,CAAC,CAMzB;;CACF;;;;;;;;;gBA/sBa,OAAO;;;;gBACP,OAAO;;;;aACP,MAAM;;;;gBACN,MAAM;;;;mBACN,OAAO;;;;uBACP,OAAO;;;;eACP,MAAM;;;;kBACN,MAAM;;;;eACN,MAAM;;;;aACN,MAAM;;;;aACN,MAAM;;;;oBACN,MAAM;;;;mBACN,MAAM;;;;iBACN,MAAM;;;;iBACN,MAAM;;;;eACN,MAAM;;;;qBACN,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM;;;;wBACrD,MAAM;;;;;;;;;;;;;;YAYN,cAAc;;;;;;;;;;;;mBAUd,MAAM;;;;eACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;SACN,MAAM;;;;cACN,MAAM;;;;qBACN,MAAM;;;;iBACN,MAAM;;;;cACN,MAAM;;;;gBACN,MAAM;;;;kBACN,CAAC,GAAG,CAAC,GAAG,CAAC;;;;mBACT,MAAM;;;;gBACN,OAAO;;;;oBACP,MAAM;;;;eACN,MAAM;;;;iBACN,MAAM;;;;iBACN,OAAO;;;;YACP,MAAM;;;;gBACN,MAAM;;;;gBACN,IAAI,GAAG,IAAI;;;;qBACX,MAAM;;;;WACN,MAAM;;;;SACN,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;;;;;;;;;YAQrB;QAAkC,MAAM;QACN,QAAQ;QACR,IAAI;QACJ,MAAM;QACN,MAAM;QACN,SAAS;QACT,OAAO;QACP,MAAM;QACd,QAAQ,EAAvB,MAAM;QACgB,UAAU,EAAhC,IAAI,GAAG,MAAM;KAE1B;;;;;;;;;;;;;;;;;YAca,gBAAgB;;;;;;;;;;;mBAShB,MAAM;;;;eACN,MAAM;;;;cACN,MAAM;;;;eACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;UACN,MAAM;;;;uBACN,MAAM;;;;uBACN,MAAM;;;;oBACN,MAAM;;;;oBACN,MAAM;;;;aACN,MAAM;;;;aACN,MAAM;;;;eACN,MAAM;;;;kBACN,MAAM;;;;iBACN,MAAM;;;;iBACN,MAAM;;;;qBACN,MAAM;;;;UACN,MAAM;;;;aACN,MAAM;;;;YACN,MAAM;;;;YACN,MAAM;;;;aACN,MAAM;;;;eACN,MAAM;;;;eACN,MAAM;;;;oBACN,MAAM;;;;cACN,MAAM;;;;gBACN,MAAM;;;;cACN,MAAM;;;;qBACN,MAAM;;;;eACN,MAAM;;;;aACN,MAAM;;;;iBACN,MAAM;;;;cACN,MAAM;;;;cACN,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;;;;gBACb,MAAM;;;;kBACN,CAAC,GAAG,CAAC,GAAG,CAAC;;;;mBACT,MAAM;;;;gBACN,MAAM;;;;kBACN,MAAM;;;;WACN,MAAM;;;;gBACN,MAAM;;;;oBACN,MAAM;;;;eACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;UACN,MAAM;;;;iBACN,MAAM;;;;oBACN,MAAM;;;;gBACN,MAAM;;;;aACN,MAAM;;;;SACN,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;;;;UACV,MAAM;;;;SACN,MAAM;;;;YACN,MAAM;;;;gBACN,MAAM;;;;gBACN,IAAI,GAAG,IAAI;;;;kBACX,MAAM;;;;gBACN,MAAM;;;;aACN,MAAM;;;;oBACN,MAAM;;;;;sCAKP,cAAc,GAAG,WAAW,GAAG,cAAc;;;;qCAM/C,MAAM,WACN,iBAAiB;;;;qCAMjB,MAAM,WACN,iBAAiB;;;;2CAMjB,MAAM,WACN,uBAAuB;;;;uCAMvB,MAAM,WACN,mBAAmB;;;;sCAMnB,MAAM,WACN,GAAG;6BAGe,QAAQ;gCAtNN,MAAM"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["client.js"],"names":[],"mappings":"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"}
@@ -10,7 +10,43 @@
10
10
  // ============================================================================
11
11
 
12
12
  /**
13
- * @import { MqttClient } from 'mqtt'
13
+ * @import { MqttClient, IConnackPacket, IDisconnectPacket, Packet } from 'mqtt'
14
+ */
15
+
16
+ /**
17
+ * @typedef {'playing' | 'paused' | 'stopped' | 'loading'} PlaybackStatus
18
+ */
19
+
20
+ /**
21
+ * MQTT disconnect event metadata (from MQTT disconnect packet)
22
+ * @typedef {Object} YotoMqttClientDisconnectMetadata
23
+ * @property {IDisconnectPacket} packet - MQTT disconnect packet
24
+ */
25
+
26
+ /**
27
+ * MQTT close event metadata (from connection close)
28
+ * @typedef {Object} YotoMqttClientCloseMetadata
29
+ * @property {'close'} reason - Close reason
30
+ */
31
+
32
+ /**
33
+ * Event map for YotoMqttClient
34
+ * @typedef {{
35
+ * 'connect': [IConnackPacket],
36
+ * 'disconnect': [YotoMqttClientDisconnectMetadata],
37
+ * 'close': [YotoMqttClientCloseMetadata],
38
+ * 'reconnect': [],
39
+ * 'offline': [],
40
+ * 'end': [],
41
+ * 'error': [Error],
42
+ * 'events': [string, YotoEventsMessage],
43
+ * 'status': [string, YotoStatusMessage],
44
+ * 'status-legacy': [string, YotoStatusLegacyMessage],
45
+ * 'response': [string, YotoResponseMessage],
46
+ * 'unknown': [string, any],
47
+ * 'packetsend': [Packet],
48
+ * 'packetreceive': [Packet]
49
+ * }} YotoMqttClientEventMap
14
50
  */
15
51
 
16
52
  /**
@@ -28,13 +64,13 @@
28
64
  * @property {number} [trackLength] - Track duration in seconds
29
65
  * @property {number} [position] - Current position in seconds
30
66
  * @property {string} [cardId] - Currently playing card ID
31
- * @property {string} [source] - Source of playback (e.g., "card", "remote", "MQTT")
67
+ * @property {'card' | 'remote' | 'MQTT' } [source] - Source of playback (e.g., "card", "remote", "MQTT")
32
68
  * @property {string} [cardUpdatedAt] - ISO8601 format timestamp
33
69
  * @property {string} [chapterTitle] - Current chapter title
34
70
  * @property {string} [chapterKey] - Current chapter key
35
71
  * @property {string} [trackTitle] - Current track title
36
72
  * @property {string} [trackKey] - Current track key
37
- * @property {'playing' | 'paused' | 'stopped' | 'loading' | string} [playbackStatus] - Playback status
73
+ * @property {PlaybackStatus} [playbackStatus] - Playback status
38
74
  * @property {number} [sleepTimerSeconds] - Seconds remaining on sleep timer
39
75
  */
40
76
 
@@ -61,7 +97,7 @@
61
97
  * @property {string} fwVersion - Firmware version
62
98
  * @property {string} productType - Product type identifier
63
99
  * @property {number} batteryLevel - Battery level percentage
64
- * @property {number} als - Ambient light sensor reading
100
+ * @property {number} als - Ambient light sensor reading TODO: Find range/units
65
101
  * @property {number} freeDisk - Free disk space in bytes
66
102
  * @property {number} shutdownTimeout - Shutdown timeout in seconds
67
103
  * @property {number} dbatTimeout - DBAT timeout
@@ -71,33 +107,46 @@
71
107
  * @property {number} playingStatus - Playing status code
72
108
  * @property {boolean} headphones - Headphones connected
73
109
  * @property {number} dnowBrightness - Current display brightness (Integer 0-100)
74
- * @property {number} dayBright - Day brightness setting (Integer 0-100)
75
- * @property {number} nightBright - Night brightness setting (Integer 0-100)
110
+ * @property {number} dayBright - Day brightness setting (Integer 0-100, 255 when 'auto')
111
+ * @property {number} nightBright - Night brightness setting (Integer 0-100, 255 when 'auto')
76
112
  * @property {boolean} bluetoothHp - Bluetooth headphones enabled
77
113
  * @property {number} volume - System/max volume level (0-100 percentage, represents 0-16 hardware scale, maps to volumeMax in events)
78
114
  * @property {number} userVolume - User volume setting (0-100 percentage, represents 0-16 hardware scale, maps to volume in events)
79
115
  * @property {'12' | '24'} timeFormat - Time format preference
80
116
  * @property {string} [nightlightMode] - Current nightlight color (actual hex color like '0xff5733' or 'off') - only in requested status, most accurate source
81
- * @property {string} [temp] - Temperature reading (format varies: 'value1:value2:value3' or 'value1:notSupported') - only in requested status
117
+ * @property {string} [temp] - Temperature reading (format varies: 'value1:value2:value3' or 'value1:notSupported') - only in requested status. value2, when a number, is the temp in Celcius
82
118
  * @property {-1 | 0 | 1} day - Day mode (0=night, 1=day, -1=unknown)
83
119
  */
84
120
 
85
121
  /**
86
122
  * Response message from device
87
123
  * @see https://yoto.dev/players-mqtt/mqtt-docs/#deviceidresponse
124
+ *
125
+ * Note: `status` contains dynamic keys and some keys may include slashes/dashes.
126
+ * Known (observed) non-identifier keys:
127
+ * - 'status/request' - Status request result
128
+ * - 'events/request' - Events request result
129
+ * - 'sleep-timer' - Sleep timer command result
130
+ *
131
+ * @typedef {Object} YotoResponseStatusKnown
132
+ * @property {'OK' | 'FAIL'} [volume] - Volume command result
133
+ * @property {'OK' | 'FAIL'} [ambients] - Ambients command result
134
+ * @property {'OK' | 'FAIL'} [card] - Card command result
135
+ * @property {'OK' | 'FAIL'} [events] - Events request result (alternate key to 'events/request')
136
+ * @property {'OK' | 'FAIL'} [status] - Status request result (alternate key to 'status/request')
137
+ * @property {'OK' | 'FAIL'} [bluetooth] - Bluetooth command result
138
+ * @property {'OK' | 'FAIL'} [display] - Display command result
139
+ * @property {'OK' | 'FAIL'} [reboot] - Reboot command result
140
+ * @property {string} req_body - Stringified JSON from original request
141
+ * @property {'OK' | 'FAIL'} [sleepTimer] - Sleep timer command result (alternate key to 'sleep-timer')
142
+ *
143
+ * @typedef {YotoResponseStatusKnown
144
+ * & Record<string, 'OK' | 'FAIL' | string | undefined>
145
+ * & Partial<Record<'status/request' | 'events/request' | 'sleep-timer', 'OK' | 'FAIL'>>
146
+ * } YotoResponseStatus
147
+ *
88
148
  * @typedef {Object} YotoResponseMessage
89
- * @property {Object} status - Status object with dynamic resource keys
90
- * @property {'OK' | 'FAIL'} [status.volume] - Volume command result
91
- * @property {'OK' | 'FAIL'} [status.ambients] - Ambients command result
92
- * @property {'OK' | 'FAIL'} [status.card] - Card command result
93
- * @property {'OK' | 'FAIL'} [status.events] - Events request result
94
- * @property {'OK' | 'FAIL'} [status.status] - Status request result
95
- * @property {'OK' | 'FAIL'} [status.bluetooth] - Bluetooth command result
96
- * @property {'OK' | 'FAIL'} [status.display] - Display command result
97
- * @property {'OK' | 'FAIL'} [status.reboot] - Reboot command result
98
- * @property {string} status.req_body - Stringified JSON from original request
99
- * @property {'OK' | 'FAIL'} status.sleepTimer - Sleep timer command result (note: actual field name is 'sleep-timer')
100
-
149
+ * @property {YotoResponseStatus} status - Status object with dynamic resource keys
101
150
  */
102
151
 
103
152
  /**
@@ -163,9 +212,9 @@
163
212
  * @property {number} wifiRestarts - WiFi restart count
164
213
  * @property {number} qiOtp - Qi OTP value
165
214
  * @property {number} buzzErrors - Buzzer error count
166
- * @property {number} dnowBrightness - Current display brightness
167
- * @property {number} dayBright - Day brightness setting
168
- * @property {number} nightBright - Night brightness setting
215
+ * @property {number} dnowBrightness - Current display brightness (0-100, act)
216
+ * @property {number} dayBright - Day brightness setting (0-100, 255 when configed to 'auto')
217
+ * @property {number} nightBright - Night brightness setting (0-100, 255 when configed to 'auto')
169
218
  * @property {number} errorsLogged - Number of errors logged
170
219
  * @property {number} twdt - Task watchdog timer value
171
220
  * @property {number} bluetoothHp - Bluetooth headphones state (0 or 1)
@@ -173,8 +222,8 @@
173
222
  * @property {number} bgDownload - Background download state
174
223
  * @property {number} bytesPS - Bytes per second
175
224
  * @property {-1 | 0 | 1} day - Day mode (0=night, 1=day, -1=unknown)
176
- * @property {string} temp - Temperature readings (format: 'val1:val2:val3')
177
- * @property {number} als - Ambient light sensor reading
225
+ * @property {string} temp - Temperature reading (format varies: 'value1:value2:value3' or 'value1:notSupported') - only in requested status. value2, when a number, is the temp in Celcius
226
+ * @property {number} als - Ambient light sensor reading TODO: Find range/units
178
227
  * @property {number} volume - System/max volume level (0-100 percentage, represents 0-16 hardware scale, maps to volumeMax in events)
179
228
  * @property {number} userVolume - User volume setting (0-100 percentage, represents 0-16 hardware scale, maps to volume in events)
180
229
  * @property {'12' | '24'} timeFormat - Time format preference
@@ -253,22 +302,33 @@ import { commands } from './commands.js'
253
302
 
254
303
  /**
255
304
  * Yoto MQTT Client class
256
- * @extends EventEmitter
305
+ * @extends {EventEmitter<YotoMqttClientEventMap>}
257
306
  *
258
307
  * Device automatically publishes status updates every 5 minutes when connected.
259
308
  * Status can also be requested on-demand via requestStatus() and requestEvents().
260
309
  *
261
- * @fires YotoMqttClient#events - Emits (topic, payload) when device sends events
262
- * @fires YotoMqttClient#status - Emits (topic, payload) when device sends status (automatic every 5 min, or on-demand)
263
- * @fires YotoMqttClient#status-legacy - Emits (topic, payload) when device sends legacy status with lifecycle events
264
- * @fires YotoMqttClient#response - Emits (topic, payload) when device responds to commands
265
- * @fires YotoMqttClient#unknown - Emits (topic, payload) when receiving unknown message type
266
- * @fires YotoMqttClient#connected
267
- * @fires YotoMqttClient#disconnected
268
- * @fires YotoMqttClient#reconnecting
269
- * @fires YotoMqttClient#error
310
+ * Events:
311
+ * - 'connect' - Emitted on successful (re)connection (connack rc=0). Passes connack packet; when sessionPresent is true and clean is false, you can rely on stored session and avoid re-subscribing. Auto-subscribe (if enabled) runs after connect and may emit errors.
312
+ * - 'disconnect' - Emitted after receiving disconnect packet from broker. MQTT 5.0 feature. Passes metadata with disconnect packet.
313
+ * - 'close' - Emitted after a disconnection, passes metadata with close reason.
314
+ * - 'reconnect' - Emitted when a reconnect starts.
315
+ * - 'offline' - Emitted when the client goes offline.
316
+ * - 'end' - Emitted when mqttClient.end() is called (after its callback returns).
317
+ * - 'error' - Emitted when the client cannot connect (connack rc != 0) or when a parsing error occurs.
318
+ * - 'packetsend' - Emitted when the client sends any packet (including publish and subscription packets).
319
+ * - 'packetreceive' - Emitted when the client receives any packet.
320
+ * - 'events' - Device sends events, passes (topic, payload).
321
+ * - 'status' - Device sends status, passes (topic, payload).
322
+ * - 'status-legacy' - Device sends legacy status with lifecycle events, passes (topic, payload).
323
+ * - 'response' - Device responds to commands, passes (topic, payload).
324
+ * - 'unknown' - Unknown message type received, passes (topic, payload).
270
325
  */
271
326
  export class YotoMqttClient extends EventEmitter {
327
+ /** @type {typeof commands} */ commands = commands
328
+ /** @type {MqttClient} */ mqttClient
329
+ /** @type {string} */ deviceId
330
+ /** @type {boolean} */ #autoSubscribe = true
331
+
272
332
  /**
273
333
  * Create a Yoto MQTT client
274
334
  * @param {MqttClient} mqttClient - Underlying MQTT client
@@ -281,13 +341,10 @@ export class YotoMqttClient extends EventEmitter {
281
341
 
282
342
  this.mqttClient = mqttClient
283
343
  this.deviceId = deviceId
284
- this.autoSubscribe = options.autoSubscribe !== false
344
+ this.#autoSubscribe = options.autoSubscribe !== false
285
345
 
286
346
  // Bind MQTT event handlers
287
347
  this.#setupEventHandlers()
288
-
289
- // Export command builders for convenience
290
- this.commands = commands
291
348
  }
292
349
 
293
350
  /**
@@ -313,29 +370,44 @@ export class YotoMqttClient extends EventEmitter {
313
370
  */
314
371
  #setupEventHandlers () {
315
372
  // Connection established
316
- this.mqttClient.on('connect', async () => {
317
- // Auto-subscribe to device topics if enabled
318
- if (this.autoSubscribe) {
319
- await this.#subscribe()
320
- }
373
+ this.mqttClient.on('connect', (connack) => {
374
+ this.emit('connect', connack)
321
375
 
322
- // Only emit connected after subscriptions are ready
323
- this.emit('connected')
376
+ // Auto-subscribe to device topics if enabled and no prior session
377
+ if (this.#autoSubscribe && !connack.sessionPresent) {
378
+ this.#subscribe().catch((error) => {
379
+ this.emit('error', error)
380
+ })
381
+ }
324
382
  })
325
383
 
326
384
  // Connection lost
327
- this.mqttClient.on('disconnect', () => {
328
- this.emit('disconnected')
385
+ this.mqttClient.on('disconnect', (packet) => {
386
+ /** @type {YotoMqttClientDisconnectMetadata} */
387
+ const metadata = { packet }
388
+ this.emit('disconnect', metadata)
329
389
  })
330
390
 
331
391
  // Connection closed
332
392
  this.mqttClient.on('close', () => {
333
- this.emit('disconnected')
393
+ /** @type {YotoMqttClientCloseMetadata} */
394
+ const metadata = { reason: 'close' }
395
+ this.emit('close', metadata)
334
396
  })
335
397
 
336
398
  // Reconnecting
337
399
  this.mqttClient.on('reconnect', () => {
338
- this.emit('reconnecting')
400
+ this.emit('reconnect')
401
+ })
402
+
403
+ // Client went offline
404
+ this.mqttClient.on('offline', () => {
405
+ this.emit('offline')
406
+ })
407
+
408
+ // Client end requested
409
+ this.mqttClient.on('end', () => {
410
+ this.emit('end')
339
411
  })
340
412
 
341
413
  // Error occurred
@@ -343,6 +415,16 @@ export class YotoMqttClient extends EventEmitter {
343
415
  this.emit('error', error)
344
416
  })
345
417
 
418
+ // Packet sent
419
+ this.mqttClient.on('packetsend', (packet) => {
420
+ this.emit('packetsend', packet)
421
+ })
422
+
423
+ // Packet received
424
+ this.mqttClient.on('packetreceive', (packet) => {
425
+ this.emit('packetreceive', packet)
426
+ })
427
+
346
428
  // Message received
347
429
  this.mqttClient.on('message', (topic, message) => {
348
430
  this.#handleMessage(topic, message)
@@ -10,7 +10,8 @@
10
10
  *
11
11
  * const client = createYotoMqttClient({
12
12
  * deviceId: 'abc123',
13
- * accessToken: 'eyJhbGc...'
13
+ * token,
14
+ * clientId: 'my-unique-client-id'
14
15
  * })
15
16
  *
16
17
  * client.on('events', (message) => {
@@ -25,7 +26,8 @@
25
26
  * // Disable automatic reconnection
26
27
  * const client = createYotoMqttClient({
27
28
  * deviceId: 'abc123',
28
- * accessToken: 'token',
29
+ * token,
30
+ * clientId: 'my-unique-client-id',
29
31
  * mqttOptions: {
30
32
  * reconnectPeriod: 0, // Disable auto-reconnect (default is 5000ms)
31
33
  * connectTimeout: 30000 // 30 second connection timeout
@@ -44,9 +46,13 @@ export type YotoMqttOptions = {
44
46
  */
45
47
  deviceId: string;
46
48
  /**
47
- * - JWT access token for authentication
49
+ * - RefreshableToken instance used to supply the current JWT. Enables auto-updating auth on reconnect via transformWsUrl.
48
50
  */
49
- accessToken: string;
51
+ token: RefreshableToken;
52
+ /**
53
+ * - Stable unique session ID suffix used to avoid collisions across multiple clients/processes. Used to build the MQTT clientId: DASH${deviceId}${sessionId} (non-alphanumeric characters are stripped). (MQTT calls this clientId, but we call it sessionId to not confuse it with the oauth clientId)
54
+ */
55
+ sessionId?: string;
50
56
  /**
51
57
  * - Prefix for MQTT client ID (default: 'DASH')
52
58
  */
@@ -64,10 +70,11 @@ export type YotoMqttOptions = {
64
70
  */
65
71
  autoSubscribe?: boolean;
66
72
  /**
67
- * - Additional MQTT.js client options (defaults: reconnectPeriod=5000, keepalive=300; cannot override: clientId, username, password, protocol, ALPNProtocols)
73
+ * - Additional MQTT.js client options (defaults: reconnectPeriod=5000, reconnectOnConnackError=true, keepalive=300, clean=false; cannot override: clientId, username, password, protocol, ALPNProtocols; transformWsUrl is wrapped to keep auth current)
68
74
  */
69
75
  mqttOptions?: MqttClientOptions;
70
76
  };
71
77
  import { YotoMqttClient } from './client.js';
72
78
  import mqtt from 'mqtt';
79
+ import type { RefreshableToken } from '../token.js';
73
80
  //# sourceMappingURL=factory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["factory.js"],"names":[],"mappings":"AA0CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,8CAjCW,eAAe,GACb,cAAc,CAmF1B;;;;gCA/GY,OAAO,CAAC,mBAAc,CAAC;;;;;cAKtB,MAAM;;;;iBACN,MAAM;;;;qBACN,MAAM;;;;gBACN,MAAM;;;;WACN,MAAM;;;;oBACN,OAAO;;;;kBACP,iBAAiB;;+BAIA,aAAa;iBAD3B,MAAM"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["factory.js"],"names":[],"mappings":"AA6CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,8CAnCW,eAAe,GACb,cAAc,CA4G1B;;;;gCA1IY,OAAO,CAAC,mBAAc,CAAC;;;;;cAKtB,MAAM;;;;WACN,gBAAgB;;;;gBAChB,MAAM;;;;qBACN,MAAM;;;;gBACN,MAAM;;;;WACN,MAAM;;;;oBACN,OAAO;;;;kBACP,iBAAiB;;+BAIA,aAAa;iBAD3B,MAAM;sCAxBc,aAAa"}