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,250 @@
1
+ import test from 'node:test'
2
+ import assert from 'node:assert'
3
+ import { getContent, getUserMyoContent } from './content.js'
4
+ import { YotoAPIError } from './helpers.js'
5
+ import { loadTestTokens, logResponse } from './test-helpers.js'
6
+
7
+ const { accessToken } = loadTestTokens()
8
+
9
+ test('getUserMyoContent', async (t) => {
10
+ await t.test('should fetch user MYO cards', async () => {
11
+ const response = await getUserMyoContent({
12
+ accessToken
13
+ })
14
+
15
+ // Log response for type verification and documentation
16
+ logResponse('GET /content/mine', response)
17
+
18
+ // Validate response structure matches YotoMyoContentResponse
19
+ assert.ok(response, 'Response should exist')
20
+ assert.ok(Array.isArray(response.cards), 'Response should have cards array')
21
+ assert.ok(response.cards.length > 0, 'User should have at least one card')
22
+
23
+ // Validate card structure
24
+ const card = response.cards[0]
25
+ assert.ok(card, 'Card should exist')
26
+ assert.ok(typeof card.cardId === 'string', 'Card should have cardId string')
27
+ assert.ok(typeof card.title === 'string', 'Card should have title string')
28
+ assert.ok(typeof card.createdAt === 'string', 'Card should have createdAt string')
29
+ assert.ok(typeof card.updatedAt === 'string', 'Card should have updatedAt string')
30
+ assert.ok(typeof card.userId === 'string', 'Card should have userId string')
31
+ assert.ok(card.content, 'Card should have content object')
32
+ assert.ok(card.metadata, 'Card should have metadata object')
33
+ assert.ok(card.metadata.media, 'Metadata should have media object')
34
+ assert.ok(typeof card.metadata.media.duration === 'number', 'Media should have duration number')
35
+
36
+ // Validate metadata category enum if present and non-empty
37
+ if (card.metadata.category && card.metadata.category.length > 0) {
38
+ const validCategories = ['none', 'stories', 'music', 'radio', 'podcast', 'sfx', 'activities', 'alarms']
39
+ assert.ok(validCategories.includes(card.metadata.category), `Metadata category should be valid: ${card.metadata.category}`)
40
+ }
41
+
42
+ // Validate optional metadata fields if present
43
+ if (card.metadata.languages) {
44
+ const validLanguages = ['en', 'en-gb', 'en-us', 'fr', 'fr-fr', 'es', 'es-es', 'es-419', 'de', 'it']
45
+ assert.ok(Array.isArray(card.metadata.languages), 'Metadata languages should be array')
46
+ card.metadata.languages.forEach(lang => {
47
+ assert.ok(validLanguages.includes(lang), `Language should be valid: ${lang}`)
48
+ })
49
+ }
50
+
51
+ if (card.metadata.status) {
52
+ const validStatuses = ['new', 'inprogress', 'complete', 'live', 'archived']
53
+ assert.ok(validStatuses.includes(card.metadata.status.name), `Status name should be valid: ${card.metadata.status.name}`)
54
+ assert.ok(typeof card.metadata.status.updatedAt === 'string', 'Status should have updatedAt string')
55
+ }
56
+
57
+ if (card.metadata.playbackDirection) {
58
+ assert.ok(['DESC', 'ASC'].includes(card.metadata.playbackDirection), 'Playback direction should be DESC or ASC')
59
+ }
60
+ })
61
+
62
+ await t.test('should accept showDeleted parameter', async () => {
63
+ const response = await getUserMyoContent({
64
+ accessToken,
65
+ showDeleted: true
66
+ })
67
+
68
+ assert.ok(response, 'Response should exist')
69
+ assert.ok(Array.isArray(response.cards), 'Response should have cards array')
70
+ })
71
+
72
+ await t.test('should fail with invalid token', async () => {
73
+ await assert.rejects(
74
+ async () => {
75
+ await getUserMyoContent({
76
+ accessToken: 'invalid-token'
77
+ })
78
+ },
79
+ (err) => {
80
+ assert.ok(err instanceof YotoAPIError, 'Should throw YotoAPIError')
81
+ assert.ok(err.statusCode === 401 || err.statusCode === 403, 'Should return 401 or 403 for invalid token')
82
+ assert.ok(err.body, 'Error should have body')
83
+ return true
84
+ }
85
+ )
86
+ })
87
+ })
88
+
89
+ test('getContent', async (t) => {
90
+ /** @type {string[]} */
91
+ let testCardIds = []
92
+
93
+ // Get real card IDs to test with
94
+ await t.test('setup - get card IDs from user content', async () => {
95
+ const response = await getUserMyoContent({
96
+ accessToken
97
+ })
98
+
99
+ assert.ok(response.cards.length > 0, 'User should have at least one card for getContent tests')
100
+
101
+ testCardIds = response.cards.slice(0, 3).map(card => card.cardId).filter(Boolean)
102
+ assert.ok(testCardIds.length > 0, 'Should have extracted at least one card ID')
103
+ })
104
+
105
+ await t.test('should fetch content for valid card IDs', async () => {
106
+ // Test with multiple cards to ensure consistency
107
+ for (const cardId of testCardIds) {
108
+ const content = await getContent({
109
+ accessToken,
110
+ cardId
111
+ })
112
+
113
+ // Log response for type verification and documentation
114
+ logResponse(`GET /content/${cardId}`, content)
115
+
116
+ // Validate response structure matches YotoContentResponse
117
+ assert.ok(content, 'Response should exist')
118
+ assert.ok(content.card, 'Response should have card property')
119
+ assert.strictEqual(content.card.cardId, cardId, 'Returned card ID should match requested ID')
120
+ assert.ok(typeof content.card.title === 'string', 'Card should have title')
121
+ assert.ok(typeof content.card.createdAt === 'string', 'Card should have createdAt')
122
+ assert.ok(typeof content.card.updatedAt === 'string', 'Card should have updatedAt')
123
+ assert.ok(content.card.content, 'Card should have content property')
124
+ assert.ok(Array.isArray(content.card.content.chapters), 'Content should have chapters array')
125
+ assert.ok(content.card.metadata, 'Card should have metadata')
126
+
127
+ // Validate metadata category enum if present and non-empty
128
+ if (content.card.metadata.category && content.card.metadata.category.length > 0) {
129
+ const validCategories = ['none', 'stories', 'music', 'radio', 'podcast', 'sfx', 'activities', 'alarms']
130
+ assert.ok(validCategories.includes(content.card.metadata.category), `Metadata category should be valid: ${content.card.metadata.category}`)
131
+ }
132
+
133
+ // Validate optional playbackType if present
134
+ if (content.card.content.playbackType) {
135
+ const validPlaybackTypes = ['linear', 'interactive']
136
+ assert.ok(validPlaybackTypes.includes(content.card.content.playbackType), `Playback type should be valid: ${content.card.content.playbackType}`)
137
+ }
138
+ }
139
+ })
140
+
141
+ await t.test('should include chapters in content', async () => {
142
+ const cardId = testCardIds[0]
143
+ assert.ok(cardId, 'Card ID should exist')
144
+
145
+ const content = await getContent({
146
+ accessToken,
147
+ cardId
148
+ })
149
+
150
+ // Chapters array should exist (may be empty for some cards)
151
+ assert.ok(Array.isArray(content.card.content.chapters), 'Should have chapters array')
152
+
153
+ // If chapters exist, validate their structure matches YotoChapter type
154
+ if (content.card.content.chapters.length > 0) {
155
+ const chapter = content.card.content.chapters[0]
156
+ assert.ok(chapter, 'Chapter should exist')
157
+
158
+ // Validate chapter structure
159
+ assert.ok(typeof chapter.key === 'string', 'Chapter should have key string')
160
+ assert.ok(typeof chapter.title === 'string', 'Chapter should have title string')
161
+ assert.ok(typeof chapter.overlayLabel === 'string', 'Chapter should have overlayLabel string')
162
+ assert.ok(Array.isArray(chapter.tracks), 'Chapter should have tracks array')
163
+ assert.ok(chapter.display, 'Chapter should have display object')
164
+ assert.ok(typeof chapter.display.icon16x16 === 'string', 'Chapter display should have icon16x16 string')
165
+ assert.ok(typeof chapter.duration === 'number', 'Chapter should have duration number')
166
+ assert.ok(typeof chapter.fileSize === 'number', 'Chapter should have fileSize number')
167
+ assert.ok('availableFrom' in chapter, 'Chapter should have availableFrom property')
168
+ assert.ok('ambient' in chapter, 'Chapter should have ambient property')
169
+ assert.ok('defaultTrackDisplay' in chapter, 'Chapter should have defaultTrackDisplay property')
170
+ assert.ok('defaultTrackAmbient' in chapter, 'Chapter should have defaultTrackAmbient property')
171
+
172
+ // If tracks exist, validate their structure matches YotoTrack type
173
+ if (chapter.tracks.length > 0) {
174
+ const track = chapter.tracks[0]
175
+ assert.ok(track, 'Track should exist')
176
+
177
+ // Validate track structure
178
+ assert.ok(typeof track.key === 'string', 'Track should have key string')
179
+ assert.ok(typeof track.title === 'string', 'Track should have title string')
180
+ assert.ok(typeof track.trackUrl === 'string', 'Track should have trackUrl string')
181
+ assert.ok(track.trackUrl.startsWith('yoto:#'), 'Track URL should start with "yoto:#"')
182
+ assert.ok(typeof track.format === 'string', 'Track should have format string')
183
+
184
+ // Validate audio format enum
185
+ const validFormats = ['mp3', 'aac', 'opus', 'ogg']
186
+ assert.ok(validFormats.includes(track.format), `Track format should be valid: ${track.format}`)
187
+
188
+ assert.ok(track.type === 'audio' || track.type === 'stream', 'Track type should be "audio" or "stream"')
189
+ assert.ok(typeof track.overlayLabel === 'string', 'Track should have overlayLabel string')
190
+ assert.ok(typeof track.duration === 'number', 'Track should have duration number')
191
+ assert.ok(typeof track.fileSize === 'number', 'Track should have fileSize number')
192
+ assert.ok(track.channels === 'stereo' || track.channels === 'mono', 'Track channels should be "stereo" or "mono"')
193
+ assert.ok('ambient' in track, 'Track should have ambient property')
194
+ assert.ok(track.display, 'Track should have display object')
195
+ assert.ok(typeof track.display.icon16x16 === 'string', 'Track display should have icon16x16 string')
196
+ assert.ok(track.display.icon16x16.startsWith('yoto:#'), 'Track display icon should start with "yoto:#"')
197
+ }
198
+ }
199
+ })
200
+
201
+ await t.test('should accept timezone parameter for podcast content', async () => {
202
+ const cardId = testCardIds[0]
203
+ assert.ok(cardId, 'Card ID should exist')
204
+
205
+ const content = await getContent({
206
+ accessToken,
207
+ cardId,
208
+ timezone: 'Pacific/Auckland'
209
+ })
210
+
211
+ // Log response with timezone parameter
212
+ logResponse('GET /content/{cardId}?timezone=Pacific/Auckland', content)
213
+
214
+ assert.ok(content.card, 'Should return content with timezone parameter')
215
+ assert.strictEqual(content.card.cardId, cardId, 'Should return correct card')
216
+ })
217
+
218
+ await t.test('should accept playable parameter for signed URLs', async () => {
219
+ const cardId = testCardIds[0]
220
+ assert.ok(cardId, 'Card ID should exist')
221
+
222
+ const content = await getContent({
223
+ accessToken,
224
+ cardId,
225
+ playable: true,
226
+ signingType: 's3'
227
+ })
228
+
229
+ // Log response with playable URLs
230
+ logResponse('GET /content/{cardId}?playable=true&signingType=s3', content)
231
+
232
+ assert.ok(content.card, 'Should return content with playable URLs')
233
+ assert.strictEqual(content.card.cardId, cardId, 'Should return correct card')
234
+ })
235
+ })
236
+
237
+ // TODO: Add tests for createOrUpdateContent
238
+ // - should create new content without cardId
239
+ // - should return created card with generated cardId
240
+ // - should update existing content with cardId
241
+ // - should validate response structure matches YotoCreateOrUpdateContentResponse
242
+ // - should fail with invalid token
243
+ // - should accept all content fields (chapters, config, metadata)
244
+
245
+ // TODO: Add tests for deleteContent
246
+ // - should delete content successfully
247
+ // - should return status 'ok'
248
+ // - should fail with 404 for non-existent cardId
249
+ // - should fail with 404 when trying to delete content user didn't create
250
+ // - should fail with invalid token
@@ -0,0 +1,202 @@
1
+ export function getDevices({ accessToken, userAgent, requestOptions }: {
2
+ accessToken: string;
3
+ userAgent?: string | undefined;
4
+ requestOptions?: ({
5
+ dispatcher?: import("undici").Dispatcher;
6
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
7
+ }): Promise<YotoDevicesResponse>;
8
+ export function getDeviceStatus({ accessToken, userAgent, deviceId, requestOptions }: {
9
+ accessToken: string;
10
+ deviceId: string;
11
+ userAgent?: string | undefined;
12
+ requestOptions?: ({
13
+ dispatcher?: import("undici").Dispatcher;
14
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
15
+ }): Promise<YotoDeviceStatusResponse>;
16
+ export function getDeviceConfig({ accessToken, userAgent, deviceId, requestOptions }: {
17
+ accessToken: string;
18
+ deviceId: string;
19
+ userAgent?: string | undefined;
20
+ requestOptions?: ({
21
+ dispatcher?: import("undici").Dispatcher;
22
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
23
+ }): Promise<YotoDeviceConfigResponse>;
24
+ export function updateDeviceConfig({ accessToken, userAgent, deviceId, configUpdate, requestOptions }: {
25
+ accessToken: string;
26
+ deviceId: string;
27
+ configUpdate: YotoUpdateDeviceConfigRequest;
28
+ userAgent?: string | undefined;
29
+ requestOptions?: ({
30
+ dispatcher?: import("undici").Dispatcher;
31
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
32
+ }): Promise<YotoUpdateDeviceConfigResponse>;
33
+ export function updateDeviceShortcuts({ accessToken, userAgent, deviceId, shortcutsUpdate, requestOptions }: {
34
+ accessToken: string;
35
+ deviceId: string;
36
+ shortcutsUpdate: YotoUpdateShortcutsRequest;
37
+ userAgent?: string | undefined;
38
+ requestOptions?: ({
39
+ dispatcher?: import("undici").Dispatcher;
40
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
41
+ }): Promise<YotoUpdateShortcutsResponse>;
42
+ export function sendDeviceCommand({ accessToken, userAgent, deviceId, command, requestOptions }: {
43
+ accessToken: string;
44
+ deviceId: string;
45
+ command: YotoDeviceCommand;
46
+ userAgent?: string | undefined;
47
+ requestOptions?: ({
48
+ dispatcher?: import("undici").Dispatcher;
49
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
50
+ }): Promise<YotoDeviceCommandResponse>;
51
+ export type YotoDevicesResponse = {
52
+ devices: YotoDevice[];
53
+ };
54
+ export type YotoDevice = {
55
+ deviceId: string;
56
+ name: string;
57
+ description: string;
58
+ online: boolean;
59
+ releaseChannel: string;
60
+ deviceType: string;
61
+ deviceFamily: string;
62
+ deviceGroup: string;
63
+ generation?: string;
64
+ formFactor?: string;
65
+ };
66
+ export type YotoDeviceStatusResponse = {
67
+ deviceId: string;
68
+ activeCard?: string;
69
+ ambientLightSensorReading?: number;
70
+ averageDownloadSpeedBytesSecond?: number;
71
+ batteryLevelPercentage?: number;
72
+ batteryLevelPercentageRaw?: number;
73
+ buzzErrors?: number;
74
+ cardInsertionState?: 0 | 1 | 2;
75
+ dayMode?: -1 | 0 | 1;
76
+ errorsLogged?: number;
77
+ firmwareVersion?: string;
78
+ freeDiskSpaceBytes?: number;
79
+ isAudioDeviceConnected?: boolean;
80
+ isBackgroundDownloadActive?: boolean;
81
+ isBluetoothAudioConnected?: boolean;
82
+ isCharging?: boolean;
83
+ isNfcLocked?: number;
84
+ isOnline?: boolean;
85
+ networkSsid?: string;
86
+ nightlightMode?: string;
87
+ playingSource?: number;
88
+ powerCapabilities?: string | null;
89
+ powerSource?: 0 | 1 | 2 | 3;
90
+ systemVolumePercentage?: number;
91
+ taskWatchdogTimeoutCount?: number;
92
+ temperatureCelcius?: number | string;
93
+ totalDiskSpaceBytes?: number;
94
+ updatedAt?: string;
95
+ uptime?: number;
96
+ userVolumePercentage?: number;
97
+ utcOffsetSeconds?: number;
98
+ utcTime?: number;
99
+ wifiStrength?: number;
100
+ };
101
+ export type YotoDeviceConfigResponse = {
102
+ device: YotoDeviceConfigDevice;
103
+ };
104
+ export type YotoDeviceConfigDevice = {
105
+ config: YotoDeviceConfig;
106
+ deviceFamily: string;
107
+ deviceGroup: string;
108
+ deviceId: string;
109
+ deviceType: string;
110
+ errorCode: any;
111
+ geoTimezone: string;
112
+ getPosix: string;
113
+ mac: string;
114
+ name: string;
115
+ online: boolean;
116
+ registrationCode: string;
117
+ activationPopCode: string;
118
+ popCode: string;
119
+ releaseChannelId: string;
120
+ releaseChannelVersion: string;
121
+ fwVersion: string;
122
+ status?: any;
123
+ shortcuts?: YotoDeviceShortcuts;
124
+ };
125
+ export type YotoDeviceConfig = {
126
+ alarms?: string[];
127
+ ambientColour: string;
128
+ bluetoothEnabled: string;
129
+ btHeadphonesEnabled: boolean;
130
+ clockFace?: string;
131
+ dayDisplayBrightness: string;
132
+ dayTime: string;
133
+ dayYotoDaily: string;
134
+ dayYotoRadio: string;
135
+ daySoundsOff?: string;
136
+ displayDimBrightness?: string;
137
+ displayDimTimeout: string;
138
+ headphonesVolumeLimited: boolean;
139
+ hourFormat?: string;
140
+ logLevel?: string;
141
+ locale?: string;
142
+ maxVolumeLimit: string;
143
+ nightAmbientColour: string;
144
+ nightDisplayBrightness: string;
145
+ nightMaxVolumeLimit: string;
146
+ nightTime: string;
147
+ nightYotoDaily: string;
148
+ nightYotoRadio: string;
149
+ nightSoundsOff?: string;
150
+ pausePowerButton?: boolean;
151
+ pauseVolumeDown?: boolean;
152
+ repeatAll: boolean;
153
+ showDiagnostics?: boolean;
154
+ shutdownTimeout: string;
155
+ systemVolume?: string;
156
+ timezone?: string;
157
+ volumeLevel?: string;
158
+ };
159
+ export type YotoDeviceShortcuts = {
160
+ modes: YotoShortcutModes;
161
+ versionId: string;
162
+ };
163
+ export type YotoShortcutModes = {
164
+ day: YotoShortcutMode;
165
+ night: YotoShortcutMode;
166
+ };
167
+ export type YotoShortcutMode = {
168
+ content: YotoShortcutContent[];
169
+ };
170
+ export type YotoShortcutContent = {
171
+ cmd: string;
172
+ params: YotoShortcutParams;
173
+ };
174
+ export type YotoShortcutParams = {
175
+ card: string;
176
+ chapter: string;
177
+ track: string;
178
+ };
179
+ export type YotoUpdateDeviceConfigRequest = {
180
+ name?: string;
181
+ config: Partial<YotoDeviceConfig>;
182
+ };
183
+ export type YotoUpdateDeviceConfigResponse = {
184
+ status: string;
185
+ };
186
+ export type YotoUpdateShortcutsRequest = {
187
+ shortcuts: YotoDeviceShortcuts;
188
+ };
189
+ export type YotoUpdateShortcutsResponse = {
190
+ status: string;
191
+ };
192
+ export type YotoDeviceCommandResponse = {
193
+ status: string;
194
+ };
195
+ export type YotoDeviceCommand = YotoVolumeCommand | YotoAmbientCommand | YotoSleepTimerCommand | YotoCardStartCommand | YotoBluetoothCommand | YotoDisplayPreviewCommand | {};
196
+ import type { YotoVolumeCommand } from '../mqtt/commands.js';
197
+ import type { YotoAmbientCommand } from '../mqtt/commands.js';
198
+ import type { YotoSleepTimerCommand } from '../mqtt/commands.js';
199
+ import type { YotoCardStartCommand } from '../mqtt/commands.js';
200
+ import type { YotoBluetoothCommand } from '../mqtt/commands.js';
201
+ import type { YotoDisplayPreviewCommand } from '../mqtt/commands.js';
202
+ //# sourceMappingURL=devices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devices.d.ts","sourceRoot":"","sources":["devices.js"],"names":[],"mappings":"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"}