yoto-nodejs-client 0.0.1

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 (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +736 -0
  3. package/bin/auth.d.ts +3 -0
  4. package/bin/auth.d.ts.map +1 -0
  5. package/bin/auth.js +130 -0
  6. package/bin/content.d.ts +3 -0
  7. package/bin/content.d.ts.map +1 -0
  8. package/bin/content.js +117 -0
  9. package/bin/devices.d.ts +3 -0
  10. package/bin/devices.d.ts.map +1 -0
  11. package/bin/devices.js +239 -0
  12. package/bin/groups.d.ts +3 -0
  13. package/bin/groups.d.ts.map +1 -0
  14. package/bin/groups.js +80 -0
  15. package/bin/icons.d.ts +3 -0
  16. package/bin/icons.d.ts.map +1 -0
  17. package/bin/icons.js +100 -0
  18. package/bin/lib/cli-helpers.d.ts +21 -0
  19. package/bin/lib/cli-helpers.d.ts.map +1 -0
  20. package/bin/lib/cli-helpers.js +140 -0
  21. package/bin/lib/token-helpers.d.ts +14 -0
  22. package/bin/lib/token-helpers.d.ts.map +1 -0
  23. package/bin/lib/token-helpers.js +151 -0
  24. package/bin/refresh-token.d.ts +3 -0
  25. package/bin/refresh-token.d.ts.map +1 -0
  26. package/bin/refresh-token.js +168 -0
  27. package/bin/token-info.d.ts +3 -0
  28. package/bin/token-info.d.ts.map +1 -0
  29. package/bin/token-info.js +351 -0
  30. package/index.d.ts +218 -0
  31. package/index.d.ts.map +1 -0
  32. package/index.js +689 -0
  33. package/lib/api-endpoints/auth.d.ts +56 -0
  34. package/lib/api-endpoints/auth.d.ts.map +1 -0
  35. package/lib/api-endpoints/auth.js +209 -0
  36. package/lib/api-endpoints/auth.test.js +27 -0
  37. package/lib/api-endpoints/constants.d.ts +6 -0
  38. package/lib/api-endpoints/constants.d.ts.map +1 -0
  39. package/lib/api-endpoints/constants.js +31 -0
  40. package/lib/api-endpoints/content.d.ts +275 -0
  41. package/lib/api-endpoints/content.d.ts.map +1 -0
  42. package/lib/api-endpoints/content.js +518 -0
  43. package/lib/api-endpoints/content.test.js +250 -0
  44. package/lib/api-endpoints/devices.d.ts +202 -0
  45. package/lib/api-endpoints/devices.d.ts.map +1 -0
  46. package/lib/api-endpoints/devices.js +404 -0
  47. package/lib/api-endpoints/devices.test.js +483 -0
  48. package/lib/api-endpoints/family-library-groups.d.ts +75 -0
  49. package/lib/api-endpoints/family-library-groups.d.ts.map +1 -0
  50. package/lib/api-endpoints/family-library-groups.js +247 -0
  51. package/lib/api-endpoints/family-library-groups.test.js +272 -0
  52. package/lib/api-endpoints/family.d.ts +39 -0
  53. package/lib/api-endpoints/family.d.ts.map +1 -0
  54. package/lib/api-endpoints/family.js +166 -0
  55. package/lib/api-endpoints/family.test.js +184 -0
  56. package/lib/api-endpoints/helpers.d.ts +29 -0
  57. package/lib/api-endpoints/helpers.d.ts.map +1 -0
  58. package/lib/api-endpoints/helpers.js +104 -0
  59. package/lib/api-endpoints/icons.d.ts +62 -0
  60. package/lib/api-endpoints/icons.d.ts.map +1 -0
  61. package/lib/api-endpoints/icons.js +201 -0
  62. package/lib/api-endpoints/icons.test.js +118 -0
  63. package/lib/api-endpoints/media.d.ts +37 -0
  64. package/lib/api-endpoints/media.d.ts.map +1 -0
  65. package/lib/api-endpoints/media.js +155 -0
  66. package/lib/api-endpoints/test-helpers.d.ts +7 -0
  67. package/lib/api-endpoints/test-helpers.d.ts.map +1 -0
  68. package/lib/api-endpoints/test-helpers.js +64 -0
  69. package/lib/mqtt/client.d.ts +124 -0
  70. package/lib/mqtt/client.d.ts.map +1 -0
  71. package/lib/mqtt/client.js +558 -0
  72. package/lib/mqtt/commands.d.ts +69 -0
  73. package/lib/mqtt/commands.d.ts.map +1 -0
  74. package/lib/mqtt/commands.js +238 -0
  75. package/lib/mqtt/factory.d.ts +12 -0
  76. package/lib/mqtt/factory.d.ts.map +1 -0
  77. package/lib/mqtt/factory.js +107 -0
  78. package/lib/mqtt/index.d.ts +5 -0
  79. package/lib/mqtt/index.d.ts.map +1 -0
  80. package/lib/mqtt/index.js +81 -0
  81. package/lib/mqtt/mqtt.test.js +168 -0
  82. package/lib/mqtt/topics.d.ts +34 -0
  83. package/lib/mqtt/topics.d.ts.map +1 -0
  84. package/lib/mqtt/topics.js +295 -0
  85. package/lib/pkg.cjs +3 -0
  86. package/lib/pkg.d.cts +70 -0
  87. package/lib/pkg.d.cts.map +1 -0
  88. package/lib/token.d.ts +29 -0
  89. package/lib/token.d.ts.map +1 -0
  90. package/lib/token.js +240 -0
  91. package/package.json +91 -0
  92. package/yoto.png +0 -0
@@ -0,0 +1,404 @@
1
+ /**
2
+ * @import { YotoVolumeCommand, YotoAmbientCommand, YotoSleepTimerCommand, YotoCardStartCommand, YotoBluetoothCommand, YotoDisplayPreviewCommand } from '../mqtt/commands.js'
3
+ * @import { RequestOptions } from './helpers.js'
4
+ */
5
+
6
+ import { request } from 'undici'
7
+ import { defaultAuthHeaders, handleBadResponse, mergeRequestOptions } from './helpers.js'
8
+ import { YOTO_API_URL } from './constants.js'
9
+
10
+ // ============================================================================
11
+ // Devices: Device endpoints for managing Yoto players
12
+ // ============================================================================
13
+
14
+ /**
15
+ * @see https://yoto.dev/api/getdevices/
16
+ * @typedef {Object} YotoDevicesResponse
17
+ * @property {YotoDevice[]} devices
18
+ */
19
+
20
+ /**
21
+ * @see https://yoto.dev/api/getdevices/
22
+ * @typedef {Object} YotoDevice
23
+ * @property {string} deviceId - The unique identifier for the device
24
+ * @property {string} name - The name of the device
25
+ * @property {string} description - A brief description of the device
26
+ * @property {boolean} online - Indicates whether the device is currently online
27
+ * @property {string} releaseChannel - The release channel of the device
28
+ * @property {string} deviceType - The type of the device
29
+ * @property {string} deviceFamily - The family to which the device belongs
30
+ * @property {string} deviceGroup - The group classification of the device
31
+ * @property {string} [generation] - Device generation (e.g., 'gen3')
32
+ * @property {string} [formFactor] - Device form factor (e.g., 'standard', 'mini')
33
+ */
34
+
35
+ /**
36
+ * Retrieves the list of devices associated with the authenticated user.
37
+ * @see https://yoto.dev/api/getdevices/
38
+ * @param {object} options
39
+ * @param {string} options.accessToken The API token to request with
40
+ * @param {string} [options.userAgent] Optional user agent string
41
+ * @param {RequestOptions} [options.requestOptions] Additional undici request options
42
+ * @return {Promise<YotoDevicesResponse>} The user's devices
43
+ */
44
+ export async function getDevices ({
45
+ accessToken,
46
+ userAgent,
47
+ requestOptions
48
+ }) {
49
+ const requestUrl = new URL('/device-v2/devices/mine', YOTO_API_URL)
50
+
51
+ const response = await request(requestUrl, mergeRequestOptions({
52
+ method: 'GET',
53
+ headers: defaultAuthHeaders({ accessToken, userAgent })
54
+ }, requestOptions))
55
+
56
+ await handleBadResponse(response)
57
+
58
+ const responseBody = /** @type {YotoDevicesResponse} */ (await response.body.json())
59
+ return responseBody
60
+ }
61
+
62
+ /**
63
+ * @see https://yoto.dev/api/getdevicestatus/
64
+ * @typedef {Object} YotoDeviceStatusResponse
65
+ * @property {string} deviceId - Unique identifier of the device
66
+ * @property {string} [activeCard] - Active card on the device (can be 'none')
67
+ * @property {number} [ambientLightSensorReading] - Reading from ambient light sensor
68
+ * @property {number} [averageDownloadSpeedBytesSecond] - Average download speed in bytes per second
69
+ * @property {number} [batteryLevelPercentage] - Battery level in percentage
70
+ * @property {number} [batteryLevelPercentageRaw] - Raw battery level percentage
71
+ * @property {number} [buzzErrors] - Number of buzz errors
72
+ * @property {0 | 1 | 2} [cardInsertionState] - Card insertion state (0=none, 1=physical, 2=remote)
73
+ * @property {-1 | 0 | 1} [dayMode] - Day mode status (-1=unknown, 0=night, 1=day)
74
+ * @property {number} [errorsLogged] - Number of errors logged
75
+ * @property {string} [firmwareVersion] - Firmware version (e.g., 'v2.23.2')
76
+ * @property {number} [freeDiskSpaceBytes] - Free disk space in bytes
77
+ * @property {boolean} [isAudioDeviceConnected] - Whether audio device is connected
78
+ * @property {boolean} [isBackgroundDownloadActive] - Whether background download is active
79
+ * @property {boolean} [isBluetoothAudioConnected] - Whether Bluetooth audio is connected
80
+ * @property {boolean} [isCharging] - Whether device is currently charging
81
+ * @property {number} [isNfcLocked] - NFC lock status
82
+ * @property {boolean} [isOnline] - Whether device is currently online
83
+ * @property {string} [networkSsid] - Network SSID device is connected to
84
+ * @property {string} [nightlightMode] - Nightlight mode (hex code or 'off')
85
+ * @property {number} [playingSource] - Currently playing source
86
+ * @property {string | null} [powerCapabilities] - Power capabilities (e.g., '0x02')
87
+ * @property {0 | 1 | 2 | 3} [powerSource] - Power source (0=battery, 1=V2 dock, 2=USB-C, 3=Qi)
88
+ * @property {number} [systemVolumePercentage] - System volume in percentage
89
+ * @property {number} [taskWatchdogTimeoutCount] - Task watchdog timeout count
90
+ * @property {number | string} [temperatureCelcius] - Temperature in Celsius (can be number, string like "0", or "notSupported")
91
+ * @property {number} [totalDiskSpaceBytes] - Total disk space in bytes
92
+ * @property {string} [updatedAt] - Timestamp of last update
93
+ * @property {number} [uptime] - Uptime of the device in seconds
94
+ * @property {number} [userVolumePercentage] - User volume in percentage
95
+ * @property {number} [utcOffsetSeconds] - UTC offset in seconds
96
+ * @property {number} [utcTime] - UTC time as Unix timestamp
97
+ * @property {number} [wifiStrength] - WiFi connection strength in decibels
98
+ */
99
+
100
+ /**
101
+ * Retrieves the current status of a specific device.
102
+ * @see https://yoto.dev/api/getdevicestatus/
103
+ * @param {object} options
104
+ * @param {string} options.accessToken The API token to request with
105
+ * @param {string} options.deviceId The device ID to get status for
106
+ * @param {string} [options.userAgent] Optional user agent string
107
+ * @param {RequestOptions} [options.requestOptions] Additional undici request options
108
+ * @return {Promise<YotoDeviceStatusResponse>} The device status
109
+ */
110
+ export async function getDeviceStatus ({
111
+ accessToken,
112
+ userAgent,
113
+ deviceId,
114
+ requestOptions
115
+ }) {
116
+ const requestUrl = new URL(`/device-v2/${deviceId}/status`, YOTO_API_URL)
117
+
118
+ const response = await request(requestUrl, mergeRequestOptions({
119
+ method: 'GET',
120
+ headers: defaultAuthHeaders({ accessToken, userAgent })
121
+ }, requestOptions))
122
+
123
+ await handleBadResponse(response, { deviceId })
124
+
125
+ const responseBody = /** @type {YotoDeviceStatusResponse} */ (await response.body.json())
126
+ return responseBody
127
+ }
128
+
129
+ /**
130
+ * @see https://yoto.dev/api/getdeviceconfig/
131
+ * @typedef {Object} YotoDeviceConfigResponse
132
+ * @property {YotoDeviceConfigDevice} device
133
+ */
134
+
135
+ /**
136
+ * @see https://yoto.dev/api/getdeviceconfig/
137
+ * @typedef {Object} YotoDeviceConfigDevice
138
+ * @property {YotoDeviceConfig} config - Device configuration settings
139
+ * @property {string} deviceFamily - Device family (e.g., 'v2', 'v3', 'mini')
140
+ * @property {string} deviceGroup - Device group classification
141
+ * @property {string} deviceId - Unique identifier for the device
142
+ * @property {string} deviceType - Type of device
143
+ * @property {any} errorCode - Error code (null if no error)
144
+ * @property {string} geoTimezone - Geographic timezone (e.g., 'Europe/London')
145
+ * @property {string} getPosix - POSIX timezone string
146
+ * @property {string} mac - MAC address
147
+ * @property {string} name - Device name (undocumented)
148
+ * @property {boolean} online - Whether device is online
149
+ * @property {string} registrationCode - Device registration code
150
+ * @property {string} activationPopCode - Activation POP code (undocumented)
151
+ * @property {string} popCode - POP code (undocumented)
152
+ * @property {string} releaseChannelId - Release channel identifier
153
+ * @property {string} releaseChannelVersion - Release channel version
154
+ * @property {string} fwVersion - Firmware version (undocumented)
155
+ * @property {any} [status] - Device status object (undocumented)
156
+ * @property {YotoDeviceShortcuts} [shortcuts] - Button shortcuts configuration (beta feature)
157
+ */
158
+
159
+ /**
160
+ * @see https://yoto.dev/api/getdeviceconfig/
161
+ * @typedef {Object} YotoDeviceConfig
162
+ * @property {string[]} [alarms] - Array of alarm strings in comma-separated format (e.g., '1111111,1100,5WsQg,,,8')
163
+ * @property {string} ambientColour - Ambient light color (hex code)
164
+ * @property {string} bluetoothEnabled - Bluetooth enabled state ('0' or '1')
165
+ * @property {boolean} btHeadphonesEnabled - Bluetooth headphones enabled
166
+ * @property {string} [clockFace] - Clock face style (e.g., 'digital-sun')
167
+ * @property {string} dayDisplayBrightness - Day display brightness (e.g., 'auto')
168
+ * @property {string} dayTime - Day mode start time (e.g., '07:30')
169
+ * @property {string} dayYotoDaily - Day mode Yoto Daily card path
170
+ * @property {string} dayYotoRadio - Day mode Yoto Radio card path
171
+ * @property {string} [daySoundsOff] - Day sounds off setting (undocumented)
172
+ * @property {string} [displayDimBrightness] - Display dim brightness level
173
+ * @property {string} displayDimTimeout - Display dim timeout in seconds
174
+ * @property {boolean} headphonesVolumeLimited - Whether headphones volume is limited
175
+ * @property {string} [hourFormat] - Hour format ('12' or '24')
176
+ * @property {string} [logLevel] - Log level (e.g., 'none') (undocumented)
177
+ * @property {string} [locale] - Device locale (e.g., 'en') (undocumented)
178
+ * @property {string} maxVolumeLimit - Maximum volume limit
179
+ * @property {string} nightAmbientColour - Night ambient light color (hex code)
180
+ * @property {string} nightDisplayBrightness - Night display brightness
181
+ * @property {string} nightMaxVolumeLimit - Night maximum volume limit
182
+ * @property {string} nightTime - Night mode start time (e.g., '19:30')
183
+ * @property {string} nightYotoDaily - Night mode Yoto Daily card path
184
+ * @property {string} nightYotoRadio - Night mode Yoto Radio card path
185
+ * @property {string} [nightSoundsOff] - Night sounds off setting (undocumented)
186
+ * @property {boolean} [pausePowerButton] - Pause on power button press (undocumented)
187
+ * @property {boolean} [pauseVolumeDown] - Pause on volume down (undocumented)
188
+ * @property {boolean} repeatAll - Whether repeat all is enabled
189
+ * @property {boolean} [showDiagnostics] - Show diagnostics (undocumented)
190
+ * @property {string} shutdownTimeout - Shutdown timeout in seconds
191
+ * @property {string} [systemVolume] - System volume level (undocumented)
192
+ * @property {string} [timezone] - Timezone setting (undocumented)
193
+ * @property {string} [volumeLevel] - Volume level preset (e.g., 'safe')
194
+ */
195
+
196
+ /**
197
+ * @see https://yoto.dev/api/getdeviceconfig/
198
+ * @typedef {Object} YotoDeviceShortcuts
199
+ * @property {YotoShortcutModes} modes - Shortcut modes for day and night
200
+ * @property {string} versionId - Shortcuts configuration version ID
201
+ */
202
+
203
+ /**
204
+ * @see https://yoto.dev/api/getdeviceconfig/
205
+ * @typedef {Object} YotoShortcutModes
206
+ * @property {YotoShortcutMode} day - Day mode shortcuts
207
+ * @property {YotoShortcutMode} night - Night mode shortcuts
208
+ */
209
+
210
+ /**
211
+ * @see https://yoto.dev/api/getdeviceconfig/
212
+ * @typedef {Object} YotoShortcutMode
213
+ * @property {YotoShortcutContent[]} content - Array of shortcut content commands
214
+ */
215
+
216
+ /**
217
+ * @see https://yoto.dev/api/getdeviceconfig/
218
+ * @typedef {Object} YotoShortcutContent
219
+ * @property {string} cmd - Command type (e.g., 'track-play')
220
+ * @property {YotoShortcutParams} params - Command parameters
221
+ */
222
+
223
+ /**
224
+ * @see https://yoto.dev/api/getdeviceconfig/
225
+ * @typedef {Object} YotoShortcutParams
226
+ * @property {string} card - Card ID
227
+ * @property {string} chapter - Chapter identifier
228
+ * @property {string} track - Track identifier
229
+ */
230
+
231
+ /**
232
+ * Retrieves the configuration details for a specific device.
233
+ * @see https://yoto.dev/api/getdeviceconfig/
234
+ * @param {object} options
235
+ * @param {string} options.accessToken The API token to request with
236
+ * @param {string} options.deviceId The device ID to get config for
237
+ * @param {string} [options.userAgent] Optional user agent string
238
+ * @param {RequestOptions} [options.requestOptions] Additional undici request options
239
+ * @return {Promise<YotoDeviceConfigResponse>} The device configuration
240
+ */
241
+ export async function getDeviceConfig ({
242
+ accessToken,
243
+ userAgent,
244
+ deviceId,
245
+ requestOptions
246
+ }) {
247
+ const requestUrl = new URL(`/device-v2/${deviceId}/config`, YOTO_API_URL)
248
+
249
+ const response = await request(requestUrl, mergeRequestOptions({
250
+ method: 'GET',
251
+ headers: defaultAuthHeaders({ accessToken, userAgent })
252
+ }, requestOptions))
253
+
254
+ await handleBadResponse(response, { deviceId })
255
+
256
+ const responseBody = /** @type {YotoDeviceConfigResponse} */ (await response.body.json())
257
+ return responseBody
258
+ }
259
+
260
+ /**
261
+ * @see https://yoto.dev/api/updatedeviceconfig/
262
+ * @typedef {Object} YotoUpdateDeviceConfigRequest
263
+ * @property {string} [name] - Device name
264
+ * @property {Partial<YotoDeviceConfig>} config - Configuration settings to update (all fields optional)
265
+ */
266
+
267
+ /**
268
+ * @see https://yoto.dev/api/updatedeviceconfig/
269
+ * @typedef {Object} YotoUpdateDeviceConfigResponse
270
+ * @property {string} status - Status of the update operation (e.g., 'ok')
271
+ */
272
+
273
+ /**
274
+ * Updates the configuration settings for a specific device.
275
+ * @see https://yoto.dev/api/updatedeviceconfig/
276
+ * @param {object} options
277
+ * @param {string} options.accessToken The API token to request with
278
+ * @param {string} options.deviceId The device ID to update config for
279
+ * @param {YotoUpdateDeviceConfigRequest} options.configUpdate The configuration updates to apply (all config fields are optional)
280
+ * @param {string} [options.userAgent] Optional user agent string
281
+ * @param {RequestOptions} [options.requestOptions] Additional undici request options
282
+ * @return {Promise<YotoUpdateDeviceConfigResponse>} The update response
283
+ */
284
+ export async function updateDeviceConfig ({
285
+ accessToken,
286
+ userAgent,
287
+ deviceId,
288
+ configUpdate,
289
+ requestOptions
290
+ }) {
291
+ const requestUrl = new URL(`/device-v2/${deviceId}/config`, YOTO_API_URL)
292
+
293
+ const response = await request(requestUrl, mergeRequestOptions({
294
+ method: 'PUT',
295
+ headers: {
296
+ ...defaultAuthHeaders({ accessToken, userAgent }),
297
+ 'Content-Type': 'application/json'
298
+ },
299
+ body: JSON.stringify(configUpdate)
300
+ }, requestOptions))
301
+
302
+ await handleBadResponse(response, { deviceId })
303
+
304
+ const responseBody = /** @type {YotoUpdateDeviceConfigResponse} */ (await response.body.json())
305
+ return responseBody
306
+ }
307
+
308
+ /**
309
+ * @see https://yoto.dev/api/updateshortcutsbeta/
310
+ * @typedef {Object} YotoUpdateShortcutsRequest
311
+ * @property {YotoDeviceShortcuts} shortcuts - Shortcuts configuration to update
312
+ */
313
+
314
+ /**
315
+ * @see https://yoto.dev/api/updateshortcutsbeta/
316
+ * @typedef {Object} YotoUpdateShortcutsResponse
317
+ * @property {string} status - Status of the update operation (e.g., 'ok')
318
+ */
319
+
320
+ /**
321
+ * Updates the shortcuts configuration for a specific device (beta feature).
322
+ * @see https://yoto.dev/api/updateshortcutsbeta/
323
+ * @param {object} options
324
+ * @param {string} options.accessToken The API token to request with
325
+ * @param {string} options.deviceId The device ID to update shortcuts for
326
+ * @param {YotoUpdateShortcutsRequest} options.shortcutsUpdate The shortcuts configuration to update
327
+ * @param {string} [options.userAgent] Optional user agent string
328
+ * @param {RequestOptions} [options.requestOptions] Additional undici request options
329
+ * @return {Promise<YotoUpdateShortcutsResponse>} The update response
330
+ */
331
+ export async function updateDeviceShortcuts ({
332
+ accessToken,
333
+ userAgent,
334
+ deviceId,
335
+ shortcutsUpdate,
336
+ requestOptions
337
+ }) {
338
+ const requestUrl = new URL(`/device-v2/${deviceId}/shortcuts`, YOTO_API_URL)
339
+
340
+ const response = await request(requestUrl, mergeRequestOptions({
341
+ method: 'PUT',
342
+ headers: {
343
+ ...defaultAuthHeaders({ accessToken, userAgent }),
344
+ 'Content-Type': 'application/json'
345
+ },
346
+ body: JSON.stringify(shortcutsUpdate)
347
+ }, requestOptions))
348
+
349
+ await handleBadResponse(response, { deviceId })
350
+
351
+ const responseBody = /** @type {YotoUpdateShortcutsResponse} */ (await response.body.json())
352
+ return responseBody
353
+ }
354
+
355
+ /**
356
+ * @see https://yoto.dev/api/senddevicecommand/
357
+ * @see https://yoto.dev/players-mqtt/mqtt-docs/
358
+ * @typedef {Object} YotoDeviceCommandResponse
359
+ * @property {string} status - Status of the command (e.g., 'ok')
360
+ */
361
+
362
+ /**
363
+ * MQTT command types that can be sent to a device.
364
+ * Uses command types from the mqtt module.
365
+ * @see https://yoto.dev/players-mqtt/mqtt-docs/
366
+ * @typedef {YotoVolumeCommand | YotoAmbientCommand | YotoSleepTimerCommand | YotoCardStartCommand | YotoBluetoothCommand | YotoDisplayPreviewCommand | {}} YotoDeviceCommand
367
+ */
368
+
369
+ /**
370
+ * Sends an MQTT command to a device.
371
+ * This is a mutation endpoint that controls device behavior.
372
+ * @see https://yoto.dev/api/senddevicecommand/
373
+ * @see https://yoto.dev/players-mqtt/mqtt-docs/
374
+ * @param {object} options
375
+ * @param {string} options.accessToken The API token to request with
376
+ * @param {string} options.deviceId The device ID to send command to
377
+ * @param {YotoDeviceCommand} options.command The MQTT command payload to send
378
+ * @param {string} [options.userAgent] Optional user agent string
379
+ * @param {RequestOptions} [options.requestOptions] Additional undici request options
380
+ * @return {Promise<YotoDeviceCommandResponse>} The command response
381
+ */
382
+ export async function sendDeviceCommand ({
383
+ accessToken,
384
+ userAgent,
385
+ deviceId,
386
+ command,
387
+ requestOptions
388
+ }) {
389
+ const requestUrl = new URL(`/device-v2/${deviceId}/command/status`, YOTO_API_URL)
390
+
391
+ const response = await request(requestUrl, mergeRequestOptions({
392
+ method: 'POST',
393
+ headers: {
394
+ ...defaultAuthHeaders({ accessToken, userAgent }),
395
+ 'Content-Type': 'application/json'
396
+ },
397
+ body: JSON.stringify(command)
398
+ }, requestOptions))
399
+
400
+ await handleBadResponse(response, { deviceId })
401
+
402
+ const responseBody = /** @type {YotoDeviceCommandResponse} */ (await response.body.json())
403
+ return responseBody
404
+ }