yoto-nodejs-client 0.0.6 → 0.0.8
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 +52 -36
- package/bin/content.js +0 -0
- package/bin/devices.js +0 -0
- package/bin/groups.js +0 -0
- package/bin/icons.js +0 -0
- package/bin/refresh-token.js +0 -0
- package/lib/test-helpers/device-model-test-helpers.d.ts +29 -0
- package/lib/test-helpers/device-model-test-helpers.d.ts.map +1 -0
- package/lib/test-helpers/device-model-test-helpers.js +116 -0
- package/lib/yoto-account.d.ts +339 -9
- package/lib/yoto-account.d.ts.map +1 -1
- package/lib/yoto-account.js +411 -39
- package/lib/yoto-account.test.js +139 -0
- package/lib/yoto-device.d.ts +62 -18
- package/lib/yoto-device.d.ts.map +1 -1
- package/lib/yoto-device.js +62 -19
- package/lib/yoto-device.test.js +6 -111
- package/package.json +14 -12
package/lib/yoto-device.d.ts
CHANGED
|
@@ -171,6 +171,10 @@ export const YotoPlaybackStateType: {};
|
|
|
171
171
|
* MQTT disconnect event metadata (from MQTT disconnect packet)
|
|
172
172
|
* @typedef {YotoMqttClientDisconnectMetadata} YotoMqttDisconnectMetadata
|
|
173
173
|
*/
|
|
174
|
+
/**
|
|
175
|
+
* MQTT connect event metadata (from MQTT CONNACK)
|
|
176
|
+
* @typedef {IConnackPacket} YotoMqttConnectMetadata
|
|
177
|
+
*/
|
|
174
178
|
/**
|
|
175
179
|
* MQTT close event metadata (from connection close)
|
|
176
180
|
* @typedef {YotoMqttClientCloseMetadata} YotoMqttCloseMetadata
|
|
@@ -196,12 +200,17 @@ export const YotoPlaybackStateType: {};
|
|
|
196
200
|
* 'playbackUpdate': [YotoPlaybackState, Set<keyof YotoPlaybackState>],
|
|
197
201
|
* 'online': [YotoDeviceOnlineMetadata],
|
|
198
202
|
* 'offline': [YotoDeviceOfflineMetadata],
|
|
199
|
-
* 'mqttConnect': [],
|
|
203
|
+
* 'mqttConnect': [YotoMqttConnectMetadata],
|
|
200
204
|
* 'mqttDisconnect': [YotoMqttDisconnectMetadata],
|
|
201
205
|
* 'mqttClose': [YotoMqttCloseMetadata],
|
|
202
206
|
* 'mqttReconnect': [],
|
|
203
207
|
* 'mqttOffline': [],
|
|
204
208
|
* 'mqttEnd': [],
|
|
209
|
+
* 'mqttStatus': [string, YotoStatusMessage],
|
|
210
|
+
* 'mqttEvents': [string, YotoEventsMessage],
|
|
211
|
+
* 'mqttStatusLegacy': [string, YotoStatusLegacyMessage],
|
|
212
|
+
* 'mqttResponse': [string, YotoResponseMessage],
|
|
213
|
+
* 'mqttUnknown': [string, unknown],
|
|
205
214
|
* 'error': [Error]
|
|
206
215
|
* }} YotoDeviceModelEventMap
|
|
207
216
|
*/
|
|
@@ -223,12 +232,17 @@ export const YotoPlaybackStateType: {};
|
|
|
223
232
|
* - 'playbackUpdate' - Emitted when playback state changes, passes (playback, changedFields)
|
|
224
233
|
* - 'online' - Emitted when device comes online, passes metadata with reason and optional upTime
|
|
225
234
|
* - 'offline' - Emitted when device goes offline, passes metadata with reason and optional shutDownReason or timeSinceLastSeen
|
|
226
|
-
* - 'mqttConnect' - Emitted when MQTT client connects
|
|
235
|
+
* - 'mqttConnect' - Emitted when MQTT client connects, passes CONNACK metadata
|
|
227
236
|
* - 'mqttDisconnect' - Emitted when MQTT disconnect packet received, passes metadata with disconnect packet
|
|
228
237
|
* - 'mqttClose' - Emitted when MQTT connection closes, passes metadata with close reason
|
|
229
238
|
* - 'mqttReconnect' - Emitted when MQTT client is reconnecting
|
|
230
239
|
* - 'mqttOffline' - Emitted when MQTT client goes offline
|
|
231
240
|
* - 'mqttEnd' - Emitted when MQTT client end is called
|
|
241
|
+
* - 'mqttStatus' - Emitted with raw MQTT status messages, passes (topic, message)
|
|
242
|
+
* - 'mqttEvents' - Emitted with raw MQTT events messages, passes (topic, message)
|
|
243
|
+
* - 'mqttStatusLegacy' - Emitted with raw legacy MQTT status messages, passes (topic, message)
|
|
244
|
+
* - 'mqttResponse' - Emitted with raw MQTT response messages, passes (topic, message)
|
|
245
|
+
* - 'mqttUnknown' - Emitted with unknown MQTT messages, passes (topic, message)
|
|
232
246
|
* - 'error' - Emitted when an error occurs, passes error
|
|
233
247
|
*
|
|
234
248
|
* @extends {EventEmitter<YotoDeviceModelEventMap>}
|
|
@@ -375,23 +389,10 @@ export class YotoDeviceModel extends EventEmitter<YotoDeviceModelEventMap> {
|
|
|
375
389
|
reboot(): Promise<void>;
|
|
376
390
|
/**
|
|
377
391
|
* Start card playback over MQTT
|
|
378
|
-
* @param {
|
|
379
|
-
* @param {string} options.uri - Card URI (e.g., "https://yoto.io/<cardID>")
|
|
380
|
-
* @param {string} [options.chapterKey] - Chapter to start from
|
|
381
|
-
* @param {string} [options.trackKey] - Track to start from
|
|
382
|
-
* @param {number} [options.secondsIn] - Playback start offset in seconds
|
|
383
|
-
* @param {number} [options.cutOff] - Playback stop offset in seconds
|
|
384
|
-
* @param {boolean} [options.anyButtonStop] - Whether button press stops playback
|
|
392
|
+
* @param {YotoCardStartOptions} options - Card start options
|
|
385
393
|
* @returns {Promise<void>}
|
|
386
394
|
*/
|
|
387
|
-
startCard(options:
|
|
388
|
-
uri: string;
|
|
389
|
-
chapterKey?: string | undefined;
|
|
390
|
-
trackKey?: string | undefined;
|
|
391
|
-
secondsIn?: number | undefined;
|
|
392
|
-
cutOff?: number | undefined;
|
|
393
|
-
anyButtonStop?: boolean | undefined;
|
|
394
|
-
}): Promise<void>;
|
|
395
|
+
startCard(options: YotoCardStartOptions): Promise<void>;
|
|
395
396
|
/**
|
|
396
397
|
* Stop card playback over MQTT
|
|
397
398
|
* @returns {Promise<void>}
|
|
@@ -508,6 +509,35 @@ export type DayMode = "unknown" | "night" | "day";
|
|
|
508
509
|
* Power source state
|
|
509
510
|
*/
|
|
510
511
|
export type PowerSource = "battery" | "dock" | "usb-c" | "wireless";
|
|
512
|
+
/**
|
|
513
|
+
* Card start options for Yoto playback.
|
|
514
|
+
*/
|
|
515
|
+
export type YotoCardStartOptions = {
|
|
516
|
+
/**
|
|
517
|
+
* - Card ID (used when uri is not provided)
|
|
518
|
+
*/
|
|
519
|
+
cardId: string;
|
|
520
|
+
/**
|
|
521
|
+
* - Chapter to start from
|
|
522
|
+
*/
|
|
523
|
+
chapterKey?: string;
|
|
524
|
+
/**
|
|
525
|
+
* - Track to start from
|
|
526
|
+
*/
|
|
527
|
+
trackKey?: string;
|
|
528
|
+
/**
|
|
529
|
+
* - Playback start offset in seconds
|
|
530
|
+
*/
|
|
531
|
+
secondsIn?: number;
|
|
532
|
+
/**
|
|
533
|
+
* - Playback stop offset in seconds
|
|
534
|
+
*/
|
|
535
|
+
cutOff?: number;
|
|
536
|
+
/**
|
|
537
|
+
* - Whether button press stops playback
|
|
538
|
+
*/
|
|
539
|
+
anyButtonStop?: boolean;
|
|
540
|
+
};
|
|
511
541
|
/**
|
|
512
542
|
* Canonical device status - normalized format for both HTTP and MQTT sources
|
|
513
543
|
*
|
|
@@ -946,6 +976,10 @@ export type YotoDeviceOfflineMetadata = {
|
|
|
946
976
|
* MQTT disconnect event metadata (from MQTT disconnect packet)
|
|
947
977
|
*/
|
|
948
978
|
export type YotoMqttDisconnectMetadata = YotoMqttClientDisconnectMetadata;
|
|
979
|
+
/**
|
|
980
|
+
* MQTT connect event metadata (from MQTT CONNACK)
|
|
981
|
+
*/
|
|
982
|
+
export type YotoMqttConnectMetadata = IConnackPacket;
|
|
949
983
|
/**
|
|
950
984
|
* MQTT close event metadata (from connection close)
|
|
951
985
|
*/
|
|
@@ -994,12 +1028,17 @@ export type YotoDeviceModelEventMap = {
|
|
|
994
1028
|
"playbackUpdate": [YotoPlaybackState, Set<keyof YotoPlaybackState>];
|
|
995
1029
|
"online": [YotoDeviceOnlineMetadata];
|
|
996
1030
|
"offline": [YotoDeviceOfflineMetadata];
|
|
997
|
-
"mqttConnect": [];
|
|
1031
|
+
"mqttConnect": [YotoMqttConnectMetadata];
|
|
998
1032
|
"mqttDisconnect": [YotoMqttDisconnectMetadata];
|
|
999
1033
|
"mqttClose": [YotoMqttCloseMetadata];
|
|
1000
1034
|
"mqttReconnect": [];
|
|
1001
1035
|
"mqttOffline": [];
|
|
1002
1036
|
"mqttEnd": [];
|
|
1037
|
+
"mqttStatus": [string, YotoStatusMessage];
|
|
1038
|
+
"mqttEvents": [string, YotoEventsMessage];
|
|
1039
|
+
"mqttStatusLegacy": [string, YotoStatusLegacyMessage];
|
|
1040
|
+
"mqttResponse": [string, YotoResponseMessage];
|
|
1041
|
+
"mqttUnknown": [string, unknown];
|
|
1003
1042
|
"error": [Error];
|
|
1004
1043
|
};
|
|
1005
1044
|
import { EventEmitter } from 'events';
|
|
@@ -1012,5 +1051,10 @@ import type { YotoClient } from './api-client.js';
|
|
|
1012
1051
|
import type { PlaybackStatus } from './mqtt/client.js';
|
|
1013
1052
|
import type { YotoMqttOptions } from './mqtt/factory.js';
|
|
1014
1053
|
import type { YotoMqttClientDisconnectMetadata } from './mqtt/client.js';
|
|
1054
|
+
import type { IConnackPacket } from 'mqtt';
|
|
1015
1055
|
import type { YotoMqttClientCloseMetadata } from './mqtt/client.js';
|
|
1056
|
+
import type { YotoStatusMessage } from './mqtt/client.js';
|
|
1057
|
+
import type { YotoEventsMessage } from './mqtt/client.js';
|
|
1058
|
+
import type { YotoStatusLegacyMessage } from './mqtt/client.js';
|
|
1059
|
+
import type { YotoResponseMessage } from './mqtt/client.js';
|
|
1016
1060
|
//# sourceMappingURL=yoto-device.d.ts.map
|
package/lib/yoto-device.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yoto-device.d.ts","sourceRoot":"","sources":["yoto-device.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"yoto-device.d.ts","sourceRoot":"","sources":["yoto-device.js"],"names":[],"mappings":"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"}
|
package/lib/yoto-device.js
CHANGED
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
+
* @import { IConnackPacket } from 'mqtt'
|
|
10
11
|
* @import { YotoClient } from './api-client.js'
|
|
11
12
|
* @import { YotoDevice, YotoDeviceConfig, YotoDeviceShortcuts, YotoDeviceFullStatus, YotoDeviceStatusResponse, YotoDeviceCommand, YotoDeviceCommandResponse } from './api-endpoints/devices.js'
|
|
12
|
-
* @import { YotoMqttClient, YotoMqttStatus, YotoEventsMessage, YotoLegacyStatus, YotoMqttClientDisconnectMetadata, YotoMqttClientCloseMetadata, PlaybackStatus } from './mqtt/client.js'
|
|
13
|
+
* @import { YotoMqttClient, YotoMqttStatus, YotoEventsMessage, YotoLegacyStatus, YotoStatusMessage, YotoStatusLegacyMessage, YotoResponseMessage, YotoMqttClientDisconnectMetadata, YotoMqttClientCloseMetadata, PlaybackStatus } from './mqtt/client.js'
|
|
13
14
|
* @import { YotoMqttOptions } from './mqtt/factory.js'
|
|
15
|
+
* @import { YotoCardStartCommand } from './mqtt/commands.js'
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
import { EventEmitter } from 'events'
|
|
@@ -80,6 +82,17 @@ function convertPowerSource (numericSource) {
|
|
|
80
82
|
* @typedef {'battery' | 'dock' | 'usb-c' | 'wireless'} PowerSource
|
|
81
83
|
*/
|
|
82
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Card start options for Yoto playback.
|
|
87
|
+
* @typedef {Object} YotoCardStartOptions
|
|
88
|
+
* @property {string} cardId - Card ID (used when uri is not provided)
|
|
89
|
+
* @property {string} [chapterKey] - Chapter to start from
|
|
90
|
+
* @property {string} [trackKey] - Track to start from
|
|
91
|
+
* @property {number} [secondsIn] - Playback start offset in seconds
|
|
92
|
+
* @property {number} [cutOff] - Playback stop offset in seconds
|
|
93
|
+
* @property {boolean} [anyButtonStop] - Whether button press stops playback
|
|
94
|
+
*/
|
|
95
|
+
|
|
83
96
|
/**
|
|
84
97
|
* Normalize "0"/"1" booleans from config to true/false.
|
|
85
98
|
* @param {string | boolean} value
|
|
@@ -459,6 +472,11 @@ export const YotoPlaybackStateType = {}
|
|
|
459
472
|
* @typedef {YotoMqttClientDisconnectMetadata} YotoMqttDisconnectMetadata
|
|
460
473
|
*/
|
|
461
474
|
|
|
475
|
+
/**
|
|
476
|
+
* MQTT connect event metadata (from MQTT CONNACK)
|
|
477
|
+
* @typedef {IConnackPacket} YotoMqttConnectMetadata
|
|
478
|
+
*/
|
|
479
|
+
|
|
462
480
|
/**
|
|
463
481
|
* MQTT close event metadata (from connection close)
|
|
464
482
|
* @typedef {YotoMqttClientCloseMetadata} YotoMqttCloseMetadata
|
|
@@ -486,12 +504,17 @@ export const YotoPlaybackStateType = {}
|
|
|
486
504
|
* 'playbackUpdate': [YotoPlaybackState, Set<keyof YotoPlaybackState>],
|
|
487
505
|
* 'online': [YotoDeviceOnlineMetadata],
|
|
488
506
|
* 'offline': [YotoDeviceOfflineMetadata],
|
|
489
|
-
* 'mqttConnect': [],
|
|
507
|
+
* 'mqttConnect': [YotoMqttConnectMetadata],
|
|
490
508
|
* 'mqttDisconnect': [YotoMqttDisconnectMetadata],
|
|
491
509
|
* 'mqttClose': [YotoMqttCloseMetadata],
|
|
492
510
|
* 'mqttReconnect': [],
|
|
493
511
|
* 'mqttOffline': [],
|
|
494
512
|
* 'mqttEnd': [],
|
|
513
|
+
* 'mqttStatus': [string, YotoStatusMessage],
|
|
514
|
+
* 'mqttEvents': [string, YotoEventsMessage],
|
|
515
|
+
* 'mqttStatusLegacy': [string, YotoStatusLegacyMessage],
|
|
516
|
+
* 'mqttResponse': [string, YotoResponseMessage],
|
|
517
|
+
* 'mqttUnknown': [string, unknown],
|
|
495
518
|
* 'error': [Error]
|
|
496
519
|
* }} YotoDeviceModelEventMap
|
|
497
520
|
*/
|
|
@@ -518,12 +541,17 @@ export const YotoPlaybackStateType = {}
|
|
|
518
541
|
* - 'playbackUpdate' - Emitted when playback state changes, passes (playback, changedFields)
|
|
519
542
|
* - 'online' - Emitted when device comes online, passes metadata with reason and optional upTime
|
|
520
543
|
* - 'offline' - Emitted when device goes offline, passes metadata with reason and optional shutDownReason or timeSinceLastSeen
|
|
521
|
-
* - 'mqttConnect' - Emitted when MQTT client connects
|
|
544
|
+
* - 'mqttConnect' - Emitted when MQTT client connects, passes CONNACK metadata
|
|
522
545
|
* - 'mqttDisconnect' - Emitted when MQTT disconnect packet received, passes metadata with disconnect packet
|
|
523
546
|
* - 'mqttClose' - Emitted when MQTT connection closes, passes metadata with close reason
|
|
524
547
|
* - 'mqttReconnect' - Emitted when MQTT client is reconnecting
|
|
525
548
|
* - 'mqttOffline' - Emitted when MQTT client goes offline
|
|
526
549
|
* - 'mqttEnd' - Emitted when MQTT client end is called
|
|
550
|
+
* - 'mqttStatus' - Emitted with raw MQTT status messages, passes (topic, message)
|
|
551
|
+
* - 'mqttEvents' - Emitted with raw MQTT events messages, passes (topic, message)
|
|
552
|
+
* - 'mqttStatusLegacy' - Emitted with raw legacy MQTT status messages, passes (topic, message)
|
|
553
|
+
* - 'mqttResponse' - Emitted with raw MQTT response messages, passes (topic, message)
|
|
554
|
+
* - 'mqttUnknown' - Emitted with unknown MQTT messages, passes (topic, message)
|
|
527
555
|
* - 'error' - Emitted when an error occurs, passes error
|
|
528
556
|
*
|
|
529
557
|
* @extends {EventEmitter<YotoDeviceModelEventMap>}
|
|
@@ -925,17 +953,26 @@ export class YotoDeviceModel extends EventEmitter {
|
|
|
925
953
|
|
|
926
954
|
/**
|
|
927
955
|
* Start card playback over MQTT
|
|
928
|
-
* @param {
|
|
929
|
-
* @param {string} options.uri - Card URI (e.g., "https://yoto.io/<cardID>")
|
|
930
|
-
* @param {string} [options.chapterKey] - Chapter to start from
|
|
931
|
-
* @param {string} [options.trackKey] - Track to start from
|
|
932
|
-
* @param {number} [options.secondsIn] - Playback start offset in seconds
|
|
933
|
-
* @param {number} [options.cutOff] - Playback stop offset in seconds
|
|
934
|
-
* @param {boolean} [options.anyButtonStop] - Whether button press stops playback
|
|
956
|
+
* @param {YotoCardStartOptions} options - Card start options
|
|
935
957
|
* @returns {Promise<void>}
|
|
936
958
|
*/
|
|
937
959
|
async startCard (options) {
|
|
938
|
-
|
|
960
|
+
const uri = `https://yoto.io/${options.cardId}`
|
|
961
|
+
|
|
962
|
+
if (!uri) {
|
|
963
|
+
throw new Error('Card URI or cardId is required')
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/** @type {YotoCardStartCommand} */
|
|
967
|
+
const payload = { uri }
|
|
968
|
+
|
|
969
|
+
if (typeof options.chapterKey === 'string') payload.chapterKey = options.chapterKey
|
|
970
|
+
if (typeof options.trackKey === 'string') payload.trackKey = options.trackKey
|
|
971
|
+
if (typeof options.secondsIn === 'number') payload.secondsIn = options.secondsIn
|
|
972
|
+
if (typeof options.cutOff === 'number') payload.cutOff = options.cutOff
|
|
973
|
+
if (typeof options.anyButtonStop === 'boolean') payload.anyButtonStop = options.anyButtonStop
|
|
974
|
+
|
|
975
|
+
return await this.#mqttClient?.startCard(payload)
|
|
939
976
|
}
|
|
940
977
|
|
|
941
978
|
/**
|
|
@@ -1144,8 +1181,8 @@ export class YotoDeviceModel extends EventEmitter {
|
|
|
1144
1181
|
if (!this.#mqttClient) return
|
|
1145
1182
|
|
|
1146
1183
|
// Connection events
|
|
1147
|
-
this.#mqttClient.on('connect', () => {
|
|
1148
|
-
this.emit('mqttConnect')
|
|
1184
|
+
this.#mqttClient.on('connect', (metadata) => {
|
|
1185
|
+
this.emit('mqttConnect', metadata)
|
|
1149
1186
|
|
|
1150
1187
|
// Request status and events after settling period
|
|
1151
1188
|
this.#scheduleMqttRequests()
|
|
@@ -1186,8 +1223,9 @@ export class YotoDeviceModel extends EventEmitter {
|
|
|
1186
1223
|
})
|
|
1187
1224
|
|
|
1188
1225
|
// Status updates - PRIMARY source for status after initialization
|
|
1189
|
-
this.#mqttClient.on('status', (
|
|
1226
|
+
this.#mqttClient.on('status', (topic, message) => {
|
|
1190
1227
|
this.#recordDeviceActivity()
|
|
1228
|
+
this.emit('mqttStatus', topic, message)
|
|
1191
1229
|
this.#updateStatusFromDocumentedMqtt(message.status)
|
|
1192
1230
|
})
|
|
1193
1231
|
|
|
@@ -1195,20 +1233,25 @@ export class YotoDeviceModel extends EventEmitter {
|
|
|
1195
1233
|
// This does NOT respond to requestStatus() - only emits on real-time events or 5-minute periodic updates
|
|
1196
1234
|
// NOTE: Don't call #recordDeviceActivity() here - #handleLegacyStatus handles online/offline transitions
|
|
1197
1235
|
// based on actual power state (shutdown/startup) which is more reliable than just "activity"
|
|
1198
|
-
this.#mqttClient.on('status-legacy', (
|
|
1236
|
+
this.#mqttClient.on('status-legacy', (topic, message) => {
|
|
1237
|
+
this.emit('mqttStatusLegacy', topic, message)
|
|
1199
1238
|
this.#handleLegacyStatus(message.status)
|
|
1200
1239
|
})
|
|
1201
1240
|
|
|
1202
1241
|
// Events updates (playback, volume, etc.)
|
|
1203
|
-
this.#mqttClient.on('events', (
|
|
1242
|
+
this.#mqttClient.on('events', (topic, message) => {
|
|
1204
1243
|
this.#recordDeviceActivity()
|
|
1244
|
+
this.emit('mqttEvents', topic, message)
|
|
1205
1245
|
this.#handleEventMessage(message)
|
|
1206
1246
|
})
|
|
1207
1247
|
|
|
1208
1248
|
// Response messages (for debugging/logging)
|
|
1209
|
-
this.#mqttClient.on('response', (
|
|
1210
|
-
|
|
1211
|
-
|
|
1249
|
+
this.#mqttClient.on('response', (topic, message) => {
|
|
1250
|
+
this.emit('mqttResponse', topic, message)
|
|
1251
|
+
})
|
|
1252
|
+
|
|
1253
|
+
this.#mqttClient.on('unknown', (topic, message) => {
|
|
1254
|
+
this.emit('mqttUnknown', topic, message)
|
|
1212
1255
|
})
|
|
1213
1256
|
}
|
|
1214
1257
|
|
package/lib/yoto-device.test.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
/** @import { YotoDeviceModelConfig, YotoPlaybackState } from './yoto-device.js' */
|
|
2
1
|
/** @import { YotoDevice } from './api-endpoints/devices.js' */
|
|
3
2
|
|
|
4
3
|
import test from 'node:test'
|
|
5
4
|
import assert from 'node:assert/strict'
|
|
6
|
-
import { once } from 'node:events'
|
|
7
|
-
import { setTimeout as sleep } from 'node:timers/promises'
|
|
8
5
|
import { join } from 'node:path'
|
|
9
6
|
import { YotoClient } from './api-client.js'
|
|
10
7
|
import { YotoDeviceModel } from './yoto-device.js'
|
|
11
8
|
import { loadTestTokens } from './api-endpoints/endpoint-test-helpers.js'
|
|
12
9
|
import { saveTokensToEnv } from '../bin/lib/token-helpers.js'
|
|
10
|
+
import {
|
|
11
|
+
assertConfigShape,
|
|
12
|
+
assertPlaybackShape,
|
|
13
|
+
toLower,
|
|
14
|
+
waitForModelReady
|
|
15
|
+
} from './test-helpers/device-model-test-helpers.js'
|
|
13
16
|
|
|
14
17
|
const envPath = join(import.meta.dirname, '..', '.env')
|
|
15
18
|
|
|
@@ -41,109 +44,6 @@ function createTestClient () {
|
|
|
41
44
|
})
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
/**
|
|
45
|
-
* @param {Promise<unknown>} promise
|
|
46
|
-
* @param {number} timeoutMs
|
|
47
|
-
* @param {string} label
|
|
48
|
-
* @returns {Promise<unknown>}
|
|
49
|
-
*/
|
|
50
|
-
function withTimeout (promise, timeoutMs, label) {
|
|
51
|
-
return Promise.race([
|
|
52
|
-
promise,
|
|
53
|
-
sleep(timeoutMs).then(() => {
|
|
54
|
-
throw new Error(`${label} timed out after ${timeoutMs}ms`)
|
|
55
|
-
})
|
|
56
|
-
])
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @param {YotoDeviceModel} model
|
|
61
|
-
* @returns {Promise<void>}
|
|
62
|
-
*/
|
|
63
|
-
async function waitForModelReady (model) {
|
|
64
|
-
const started = withTimeout(once(model, 'started'), 15000, 'started')
|
|
65
|
-
const statusUpdated = withTimeout(once(model, 'statusUpdate'), 15000, 'statusUpdate')
|
|
66
|
-
const configUpdated = withTimeout(once(model, 'configUpdate'), 15000, 'configUpdate')
|
|
67
|
-
|
|
68
|
-
await model.start()
|
|
69
|
-
await Promise.all([started, statusUpdated, configUpdated])
|
|
70
|
-
await sleep(1500)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @param {YotoDeviceModelConfig} config
|
|
75
|
-
*/
|
|
76
|
-
function assertConfigShape (config) {
|
|
77
|
-
assert.ok(Array.isArray(config.alarms), 'alarms should be an array')
|
|
78
|
-
assert.equal(typeof config.ambientColour, 'string', 'ambientColour should be string')
|
|
79
|
-
assert.equal(typeof config.bluetoothEnabled, 'boolean', 'bluetoothEnabled should be boolean')
|
|
80
|
-
assert.equal(typeof config.btHeadphonesEnabled, 'boolean', 'btHeadphonesEnabled should be boolean')
|
|
81
|
-
assert.equal(typeof config.clockFace, 'string', 'clockFace should be string')
|
|
82
|
-
assert.equal(typeof config.dayDisplayBrightnessAuto, 'boolean', 'dayDisplayBrightnessAuto should be boolean')
|
|
83
|
-
if (config.dayDisplayBrightnessAuto) {
|
|
84
|
-
assert.equal(config.dayDisplayBrightness, null, 'dayDisplayBrightness should be null when auto')
|
|
85
|
-
} else {
|
|
86
|
-
assert.equal(typeof config.dayDisplayBrightness, 'number', 'dayDisplayBrightness should be number when not auto')
|
|
87
|
-
}
|
|
88
|
-
assert.equal(typeof config.dayTime, 'string', 'dayTime should be string')
|
|
89
|
-
assert.equal(typeof config.dayYotoDaily, 'string', 'dayYotoDaily should be string')
|
|
90
|
-
assert.equal(typeof config.dayYotoRadio, 'string', 'dayYotoRadio should be string')
|
|
91
|
-
assert.equal(typeof config.daySoundsOff, 'boolean', 'daySoundsOff should be boolean')
|
|
92
|
-
assert.equal(typeof config.displayDimBrightness, 'number', 'displayDimBrightness should be number')
|
|
93
|
-
assert.equal(typeof config.displayDimTimeout, 'number', 'displayDimTimeout should be number')
|
|
94
|
-
assert.equal(typeof config.headphonesVolumeLimited, 'boolean', 'headphonesVolumeLimited should be boolean')
|
|
95
|
-
assert.ok(config.hourFormat === 12 || config.hourFormat === 24, 'hourFormat should be 12 or 24')
|
|
96
|
-
assert.equal(typeof config.locale, 'string', 'locale should be string')
|
|
97
|
-
assert.equal(typeof config.logLevel, 'string', 'logLevel should be string')
|
|
98
|
-
assert.equal(typeof config.maxVolumeLimit, 'number', 'maxVolumeLimit should be number')
|
|
99
|
-
assert.equal(typeof config.nightAmbientColour, 'string', 'nightAmbientColour should be string')
|
|
100
|
-
assert.equal(typeof config.nightDisplayBrightnessAuto, 'boolean', 'nightDisplayBrightnessAuto should be boolean')
|
|
101
|
-
if (config.nightDisplayBrightnessAuto) {
|
|
102
|
-
assert.equal(config.nightDisplayBrightness, null, 'nightDisplayBrightness should be null when auto')
|
|
103
|
-
} else {
|
|
104
|
-
assert.equal(typeof config.nightDisplayBrightness, 'number', 'nightDisplayBrightness should be number when not auto')
|
|
105
|
-
}
|
|
106
|
-
assert.equal(typeof config.nightMaxVolumeLimit, 'number', 'nightMaxVolumeLimit should be number')
|
|
107
|
-
assert.equal(typeof config.nightTime, 'string', 'nightTime should be string')
|
|
108
|
-
assert.equal(typeof config.nightYotoDaily, 'string', 'nightYotoDaily should be string')
|
|
109
|
-
assert.equal(typeof config.nightYotoRadioEnabled, 'boolean', 'nightYotoRadioEnabled should be boolean')
|
|
110
|
-
if (config.nightYotoRadioEnabled) {
|
|
111
|
-
assert.equal(typeof config.nightYotoRadio, 'string', 'nightYotoRadio should be string when enabled')
|
|
112
|
-
} else {
|
|
113
|
-
assert.equal(config.nightYotoRadio, null, 'nightYotoRadio should be null when disabled')
|
|
114
|
-
}
|
|
115
|
-
assert.equal(typeof config.nightSoundsOff, 'boolean', 'nightSoundsOff should be boolean')
|
|
116
|
-
assert.equal(typeof config.pausePowerButton, 'boolean', 'pausePowerButton should be boolean')
|
|
117
|
-
assert.equal(typeof config.pauseVolumeDown, 'boolean', 'pauseVolumeDown should be boolean')
|
|
118
|
-
assert.equal(typeof config.repeatAll, 'boolean', 'repeatAll should be boolean')
|
|
119
|
-
assert.equal(typeof config.showDiagnostics, 'boolean', 'showDiagnostics should be boolean')
|
|
120
|
-
assert.equal(typeof config.shutdownTimeout, 'number', 'shutdownTimeout should be number')
|
|
121
|
-
assert.equal(typeof config.systemVolume, 'number', 'systemVolume should be number')
|
|
122
|
-
assert.equal(typeof config.timezone, 'string', 'timezone should be string')
|
|
123
|
-
assert.equal(typeof config.volumeLevel, 'string', 'volumeLevel should be string')
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @param {YotoPlaybackState} playback
|
|
128
|
-
*/
|
|
129
|
-
function assertPlaybackShape (playback) {
|
|
130
|
-
assert.ok(playback, 'playback should exist')
|
|
131
|
-
assert.equal(typeof playback.updatedAt, 'string', 'playback.updatedAt should be string')
|
|
132
|
-
|
|
133
|
-
assert.ok(playback.cardId === null || typeof playback.cardId === 'string', 'playback.cardId should be string or null')
|
|
134
|
-
assert.ok(playback.source === null || typeof playback.source === 'string', 'playback.source should be string or null')
|
|
135
|
-
assert.ok(playback.playbackStatus === null || typeof playback.playbackStatus === 'string', 'playback.playbackStatus should be string or null')
|
|
136
|
-
assert.ok(playback.trackTitle === null || typeof playback.trackTitle === 'string', 'playback.trackTitle should be string or null')
|
|
137
|
-
assert.ok(playback.trackKey === null || typeof playback.trackKey === 'string', 'playback.trackKey should be string or null')
|
|
138
|
-
assert.ok(playback.chapterTitle === null || typeof playback.chapterTitle === 'string', 'playback.chapterTitle should be string or null')
|
|
139
|
-
assert.ok(playback.chapterKey === null || typeof playback.chapterKey === 'string', 'playback.chapterKey should be string or null')
|
|
140
|
-
assert.ok(playback.position === null || typeof playback.position === 'number', 'playback.position should be number or null')
|
|
141
|
-
assert.ok(playback.trackLength === null || typeof playback.trackLength === 'number', 'playback.trackLength should be number or null')
|
|
142
|
-
assert.ok(playback.streaming === null || typeof playback.streaming === 'boolean', 'playback.streaming should be boolean or null')
|
|
143
|
-
assert.ok(playback.sleepTimerActive === null || typeof playback.sleepTimerActive === 'boolean', 'playback.sleepTimerActive should be boolean or null')
|
|
144
|
-
assert.ok(playback.sleepTimerSeconds === null || typeof playback.sleepTimerSeconds === 'number', 'playback.sleepTimerSeconds should be number or null')
|
|
145
|
-
}
|
|
146
|
-
|
|
147
47
|
/**
|
|
148
48
|
* @param {YotoClient} client
|
|
149
49
|
* @param {YotoDevice} device
|
|
@@ -169,11 +69,6 @@ test('YotoDeviceModel - online devices', async (t) => {
|
|
|
169
69
|
const client = createTestClient()
|
|
170
70
|
const response = await client.getDevices()
|
|
171
71
|
|
|
172
|
-
/**
|
|
173
|
-
* @param {string | undefined} value
|
|
174
|
-
* @returns {string}
|
|
175
|
-
*/
|
|
176
|
-
const toLower = (value) => typeof value === 'string' ? value.toLowerCase() : ''
|
|
177
72
|
const onlineMini = response.devices.find(device =>
|
|
178
73
|
device.online && (toLower(device.deviceFamily) === 'mini' || toLower(device.deviceType).includes('mini'))
|
|
179
74
|
)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yoto-nodejs-client",
|
|
3
3
|
"description": "(Unofficial) Node.js client for the Yoto API with automatic token refresh, MQTT device communication, and TypeScript support",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.8",
|
|
5
5
|
"author": "Bret Comnes <bcomnes@gmail.com> (https://bret.io)",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/bcomnes/yoto-nodejs-client/issues"
|
|
@@ -69,17 +69,9 @@
|
|
|
69
69
|
"type": "git",
|
|
70
70
|
"url": "https://github.com/bcomnes/yoto-nodejs-client.git"
|
|
71
71
|
},
|
|
72
|
-
"funding": {
|
|
73
|
-
"type": "individual",
|
|
74
|
-
"url": "https://github.com/sponsors/bcomnes"
|
|
75
|
-
},
|
|
76
|
-
"c8": {
|
|
77
|
-
"reporter": [
|
|
78
|
-
"lcov",
|
|
79
|
-
"text"
|
|
80
|
-
]
|
|
81
|
-
},
|
|
82
72
|
"scripts": {
|
|
73
|
+
"prepublishOnly": "npm run build && git push --follow-tags && gh-release -y",
|
|
74
|
+
"postpublish": "npm run clean",
|
|
83
75
|
"test": "run-s test:*",
|
|
84
76
|
"test:lint": "eslint",
|
|
85
77
|
"test:tsc": "tsc",
|
|
@@ -93,5 +85,15 @@
|
|
|
93
85
|
"clean:declarations-top": "rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*' -o -name '*.d.cts*' -o -name '*.d.mts*')",
|
|
94
86
|
"clean:declarations-lib": "rm -rf $(find lib -type f \\( -name '*.d.ts*' -o -name '*.d.cts*' -o -name '*.d.mts*' \\) ! -name '*-types.d.ts')",
|
|
95
87
|
"clean:declarations-bin": "rm -rf $(find bin -type f \\( -name '*.d.ts*' -o -name '*.d.cts*' -o -name '*.d.mts*' \\) ! -name '*-types.d.ts')"
|
|
88
|
+
},
|
|
89
|
+
"funding": {
|
|
90
|
+
"type": "individual",
|
|
91
|
+
"url": "https://github.com/sponsors/bcomnes"
|
|
92
|
+
},
|
|
93
|
+
"c8": {
|
|
94
|
+
"reporter": [
|
|
95
|
+
"lcov",
|
|
96
|
+
"text"
|
|
97
|
+
]
|
|
96
98
|
}
|
|
97
|
-
}
|
|
99
|
+
}
|