@mdjhnson/homebridge-yoto 0.1.5 → 0.1.6
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 +1 -1
- package/config.schema.json +12 -8
- package/homebridge-ui/public/client.js +22 -10
- package/homebridge-ui/public/index.html +2 -0
- package/homebridge-ui/public/logo.png +0 -0
- package/homebridge-ui/server.js +3 -0
- package/lib/settings.js +5 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<img src="https://github.com/homebridge/branding/raw/latest/logos/homebridge-wordmark-logo-vertical.png" width="150">
|
|
4
4
|
|
|
5
|
-
<img src="https://raw.githubusercontent.com/mdjhnson/homebridge-yoto/master/logo.png" width="
|
|
5
|
+
<img src="https://raw.githubusercontent.com/mdjhnson/homebridge-yoto/master/homebridge-ui/public/logo.png" width="100">
|
|
6
6
|
|
|
7
7
|
</p>
|
|
8
8
|
|
package/config.schema.json
CHANGED
|
@@ -8,11 +8,16 @@
|
|
|
8
8
|
"schema": {
|
|
9
9
|
"type": "object",
|
|
10
10
|
"properties": {
|
|
11
|
+
"name": {
|
|
12
|
+
"title": "Name",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"default": "Yoto",
|
|
15
|
+
"description": "Name used for this plugin in the Homebridge log."
|
|
16
|
+
},
|
|
11
17
|
"clientId": {
|
|
12
18
|
"title": "OAuth Client ID",
|
|
13
19
|
"type": "string",
|
|
14
20
|
"default": "tpc_ot5BY24FLyZoCX9MnykipB",
|
|
15
|
-
"required": false,
|
|
16
21
|
"description": "OAuth client ID for Yoto API authentication. The default works for most users. Only change if you've created your own OAuth app at yoto.dev.",
|
|
17
22
|
"x-schema-form": {
|
|
18
23
|
"hidden": false
|
|
@@ -21,7 +26,6 @@
|
|
|
21
26
|
"accessToken": {
|
|
22
27
|
"title": "Access Token",
|
|
23
28
|
"type": "string",
|
|
24
|
-
"required": false,
|
|
25
29
|
"description": "Automatically managed by the authentication flow. Do not edit manually.",
|
|
26
30
|
"x-schema-form": {
|
|
27
31
|
"type": "password"
|
|
@@ -30,7 +34,6 @@
|
|
|
30
34
|
"refreshToken": {
|
|
31
35
|
"title": "Refresh Token",
|
|
32
36
|
"type": "string",
|
|
33
|
-
"required": false,
|
|
34
37
|
"description": "Automatically managed by the authentication flow. Do not edit manually.",
|
|
35
38
|
"x-schema-form": {
|
|
36
39
|
"type": "password"
|
|
@@ -39,7 +42,6 @@
|
|
|
39
42
|
"tokenExpiresAt": {
|
|
40
43
|
"title": "Token Expiration",
|
|
41
44
|
"type": "number",
|
|
42
|
-
"required": false,
|
|
43
45
|
"description": "Automatically managed by the authentication flow. Do not edit manually.",
|
|
44
46
|
"x-schema-form": {
|
|
45
47
|
"hidden": true
|
|
@@ -50,7 +52,6 @@
|
|
|
50
52
|
"type": "integer",
|
|
51
53
|
"default": 60000,
|
|
52
54
|
"minimum": 10000,
|
|
53
|
-
"required": false,
|
|
54
55
|
"description": "How often to poll the Yoto API for device status and config as a fallback to MQTT updates. Defaults to 60000 (1 minute)."
|
|
55
56
|
},
|
|
56
57
|
"services": {
|
|
@@ -116,13 +117,11 @@
|
|
|
116
117
|
"label": {
|
|
117
118
|
"title": "Label",
|
|
118
119
|
"type": "string",
|
|
119
|
-
"required": true,
|
|
120
120
|
"description": "Name shown in HomeKit for this card control."
|
|
121
121
|
},
|
|
122
122
|
"cardId": {
|
|
123
123
|
"title": "Card ID",
|
|
124
124
|
"type": "string",
|
|
125
|
-
"required": true,
|
|
126
125
|
"description": "The Yoto card ID to play."
|
|
127
126
|
},
|
|
128
127
|
"playOnAll": {
|
|
@@ -131,7 +130,11 @@
|
|
|
131
130
|
"default": false,
|
|
132
131
|
"description": "Create a separate accessory that plays this card on every Yoto."
|
|
133
132
|
}
|
|
134
|
-
}
|
|
133
|
+
},
|
|
134
|
+
"required": [
|
|
135
|
+
"label",
|
|
136
|
+
"cardId"
|
|
137
|
+
]
|
|
135
138
|
}
|
|
136
139
|
},
|
|
137
140
|
"shortcuts": {
|
|
@@ -250,6 +253,7 @@
|
|
|
250
253
|
"expandable": true,
|
|
251
254
|
"expanded": false,
|
|
252
255
|
"items": [
|
|
256
|
+
"name",
|
|
253
257
|
"httpPollIntervalMs",
|
|
254
258
|
{
|
|
255
259
|
"type": "help",
|
|
@@ -16,6 +16,7 @@ const homebridge = window.homebridge
|
|
|
16
16
|
/**
|
|
17
17
|
* @typedef {Object} YotoConfig
|
|
18
18
|
* @property {string} [platform] - Platform alias (always "Yoto")
|
|
19
|
+
* @property {string} [name] - Name used in the Homebridge log
|
|
19
20
|
* @property {string} [clientId] - OAuth client ID (only stored when not the default)
|
|
20
21
|
* @property {string} [refreshToken] - Stored refresh token
|
|
21
22
|
* @property {string} [accessToken] - Stored access token
|
|
@@ -31,6 +32,8 @@ let authorizeUrl = null
|
|
|
31
32
|
let pluginConfig = []
|
|
32
33
|
/** @type {string | null} */
|
|
33
34
|
let defaultClientId = null
|
|
35
|
+
/** @type {string | null} */
|
|
36
|
+
let defaultName = null
|
|
34
37
|
/** @type {string[]} */
|
|
35
38
|
let legacyClientIds = []
|
|
36
39
|
|
|
@@ -153,14 +156,13 @@ function getErrorMessage (error, fallback) {
|
|
|
153
156
|
async function loadAuthConfig () {
|
|
154
157
|
try {
|
|
155
158
|
pluginConfig = await homebridge.getPluginConfig()
|
|
156
|
-
if (!pluginConfig.length) {
|
|
157
|
-
pluginConfig.push({ platform: 'Yoto' })
|
|
158
|
-
}
|
|
159
159
|
|
|
160
160
|
/** @type {AuthConfigResponse} */
|
|
161
161
|
const config = await homebridge.request('/auth/config')
|
|
162
162
|
defaultClientId = config.defaultClientId
|
|
163
|
+
defaultName = config.defaultName
|
|
163
164
|
legacyClientIds = config.legacyClientIds
|
|
165
|
+
getPlatformBlock()
|
|
164
166
|
|
|
165
167
|
const redirectUriDisplay = document.getElementById('redirectUriDisplay')
|
|
166
168
|
if (redirectUriDisplay) redirectUriDisplay.textContent = config.redirectUri
|
|
@@ -178,6 +180,18 @@ async function loadAuthConfig () {
|
|
|
178
180
|
}
|
|
179
181
|
}
|
|
180
182
|
|
|
183
|
+
/**
|
|
184
|
+
* The plugin's config block, created if missing. Also fills in the name,
|
|
185
|
+
* which blocks saved by older versions don't have.
|
|
186
|
+
* @returns {YotoConfig}
|
|
187
|
+
*/
|
|
188
|
+
function getPlatformBlock () {
|
|
189
|
+
if (!pluginConfig[0]) pluginConfig[0] = { platform: 'Yoto' }
|
|
190
|
+
const config = pluginConfig[0]
|
|
191
|
+
if (!config.name && defaultName) config.name = defaultName
|
|
192
|
+
return config
|
|
193
|
+
}
|
|
194
|
+
|
|
181
195
|
/**
|
|
182
196
|
* The client ID saved in config, ignoring retired ones
|
|
183
197
|
* @returns {string | undefined}
|
|
@@ -265,8 +279,7 @@ async function finishAuthorization () {
|
|
|
265
279
|
response: pasted,
|
|
266
280
|
})
|
|
267
281
|
|
|
268
|
-
|
|
269
|
-
const config = pluginConfig[0]
|
|
282
|
+
const config = getPlatformBlock()
|
|
270
283
|
config.refreshToken = result.refreshToken
|
|
271
284
|
config.accessToken = result.accessToken
|
|
272
285
|
config.tokenExpiresAt = result.tokenExpiresAt
|
|
@@ -306,11 +319,10 @@ async function logout () {
|
|
|
306
319
|
try {
|
|
307
320
|
homebridge.showSpinner()
|
|
308
321
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
322
|
+
const config = getPlatformBlock()
|
|
323
|
+
delete config.refreshToken
|
|
324
|
+
delete config.accessToken
|
|
325
|
+
delete config.tokenExpiresAt
|
|
314
326
|
|
|
315
327
|
await homebridge.updatePluginConfig(pluginConfig)
|
|
316
328
|
await homebridge.savePluginConfig()
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
<script type="module" src="client.js"></script>
|
|
3
3
|
|
|
4
4
|
<div class="card card-body">
|
|
5
|
+
<img src="logo.png" alt="Homebridge Yoto" width="80" height="80" class="d-block mx-auto mb-3" />
|
|
6
|
+
|
|
5
7
|
<!-- Authentication Status -->
|
|
6
8
|
<div id="authStatus">
|
|
7
9
|
<h4>Authentication Status</h4>
|
|
Binary file
|
package/homebridge-ui/server.js
CHANGED
|
@@ -11,6 +11,7 @@ import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-ut
|
|
|
11
11
|
import { YotoClient } from 'yoto-nodejs-client'
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_CLIENT_ID,
|
|
14
|
+
DEFAULT_NAME,
|
|
14
15
|
LEGACY_CLIENT_IDS,
|
|
15
16
|
OAUTH_REDIRECT_URI,
|
|
16
17
|
OAUTH_SCOPES,
|
|
@@ -59,6 +60,7 @@ class YotoUiServer extends HomebridgePluginUiServer {
|
|
|
59
60
|
* Response from /auth/config endpoint
|
|
60
61
|
* @typedef {Object} AuthConfigResponse
|
|
61
62
|
* @property {string} defaultClientId - The default OAuth client ID
|
|
63
|
+
* @property {string} defaultName - The default plugin name, filled into config blocks that have none
|
|
62
64
|
* @property {string[]} legacyClientIds - Client IDs that no longer support sign-in
|
|
63
65
|
* @property {string} redirectUri - Redirect URI to register on a custom Yoto app
|
|
64
66
|
*/
|
|
@@ -70,6 +72,7 @@ class YotoUiServer extends HomebridgePluginUiServer {
|
|
|
70
72
|
async function getAuthConfig () {
|
|
71
73
|
return {
|
|
72
74
|
defaultClientId: DEFAULT_CLIENT_ID,
|
|
75
|
+
defaultName: DEFAULT_NAME,
|
|
73
76
|
legacyClientIds: LEGACY_CLIENT_IDS,
|
|
74
77
|
redirectUri: OAUTH_REDIRECT_URI,
|
|
75
78
|
}
|
package/lib/settings.js
CHANGED
|
@@ -15,6 +15,11 @@ export const PLUGIN_NAME = '@mdjhnson/homebridge-yoto'
|
|
|
15
15
|
*/
|
|
16
16
|
export const DEFAULT_CLIENT_ID = configSchema.schema.properties.clientId.default
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Default plugin name (shown in the Homebridge log) from config schema
|
|
20
|
+
*/
|
|
21
|
+
export const DEFAULT_NAME = configSchema.schema.properties.name.default
|
|
22
|
+
|
|
18
23
|
/**
|
|
19
24
|
* OAuth redirect URI registered on the Yoto developer app. Nothing listens here:
|
|
20
25
|
* the user copies the resulting address back into the plugin settings.
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@mdjhnson/homebridge-yoto",
|
|
3
3
|
"displayName": "Homebridge Yoto",
|
|
4
4
|
"description": "Control your Yoto players through Apple HomeKit with real-time MQTT updates",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.6",
|
|
6
6
|
"author": "mdjhnson (https://github.com/mdjhnson)",
|
|
7
7
|
"contributors": [
|
|
8
8
|
"Bret Comnes <bcomnes@gmail.com> (https://bret.io)"
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node": "^25.9.8",
|
|
24
24
|
"@voxpelli/tsconfig": "^16.2.1",
|
|
25
|
+
"ajv": "^8.20.0",
|
|
25
26
|
"auto-changelog": "^2.0.0",
|
|
26
27
|
"c8": "^10.0.0",
|
|
27
28
|
"eslint": "^9.39.2",
|