homebridge-yoto 0.0.13 → 0.0.14

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/lib/platform.js CHANGED
@@ -56,6 +56,10 @@ export class YotoPlatform {
56
56
  // Status polling interval
57
57
  this.statusPollInterval = null
58
58
 
59
+ // Cache of user's owned MYO card IDs
60
+ /** @type {Set<string>} */
61
+ this.ownedCardIds = new Set()
62
+
59
63
  // Initialize API clients
60
64
  this.auth = new YotoAuth(log, this.config.clientId)
61
65
  this.yotoApi = new YotoApi(log, this.auth)
@@ -108,6 +112,9 @@ export class YotoPlatform {
108
112
  throw error
109
113
  }
110
114
 
115
+ // Fetch user's owned cards for lookup optimization
116
+ await this.fetchOwnedCards()
117
+
111
118
  // Start platform-level status polling (every 60 seconds)
112
119
  this.startStatusPolling()
113
120
  } catch (error) {
@@ -173,6 +180,40 @@ export class YotoPlatform {
173
180
  }
174
181
 
175
182
  /**
183
+ * Fetch user's owned MYO cards and cache their IDs
184
+ * @returns {Promise<void>}
185
+ */
186
+ async fetchOwnedCards () {
187
+ try {
188
+ this.log.debug(LOG_PREFIX.PLATFORM, 'Fetching user\'s owned cards...')
189
+ const myContent = await this.yotoApi.getMyContent()
190
+
191
+ // Cache card IDs
192
+ if (myContent.cards && Array.isArray(myContent.cards)) {
193
+ this.ownedCardIds.clear()
194
+ for (const card of myContent.cards) {
195
+ if (card.cardId) {
196
+ this.ownedCardIds.add(card.cardId)
197
+ }
198
+ }
199
+ this.log.info(LOG_PREFIX.PLATFORM, `✓ Cached ${this.ownedCardIds.size} owned card(s)`)
200
+ }
201
+ } catch (error) {
202
+ this.log.warn(LOG_PREFIX.PLATFORM, 'Failed to fetch owned cards, card details may be limited:', error)
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Check if a card is owned by the user
208
+ * @param {string} cardId - Card ID to check
209
+ * @returns {boolean}
210
+ */
211
+ isCardOwned (cardId) {
212
+ return this.ownedCardIds.has(cardId)
213
+ }
214
+
215
+ /**
216
+ * Handle token refresh - update config
176
217
  * Perform device authorization flow
177
218
  * @returns {Promise<void>}
178
219
  */
@@ -1536,10 +1536,18 @@ export class YotoPlayerAccessory {
1536
1536
  return
1537
1537
  }
1538
1538
 
1539
+ // Check if we own this card before attempting to fetch details
1540
+ if (!this.platform.isCardOwned(cardId)) {
1541
+ this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Playing card ${cardId} (store content - details not available)`)
1542
+ this.activeContentInfo = null
1543
+ this.accessory.context.activeContentInfo = null
1544
+ return
1545
+ }
1546
+
1539
1547
  this.log.info(LOG_PREFIX.ACCESSORY, `[${this.device.name}] Active card changed: ${cardId}`)
1540
1548
 
1541
1549
  try {
1542
- // Fetch card details
1550
+ // Fetch card details for owned cards
1543
1551
  const content = await this.platform.yotoApi.getContent(cardId)
1544
1552
  this.activeContentInfo = content
1545
1553
 
package/lib/yotoApi.js CHANGED
@@ -114,7 +114,6 @@ export class YotoApi {
114
114
 
115
115
  if (!response.ok) {
116
116
  const errorText = await response.text()
117
- this.log.error(LOG_PREFIX.API, `Request failed: ${response.status} ${errorText}`)
118
117
 
119
118
  // Handle 401 by attempting token refresh once
120
119
  if (response.status === 401 && !options._retried) {
@@ -124,6 +123,13 @@ export class YotoApi {
124
123
  return this.request(endpoint, { ...options, _retried: true })
125
124
  }
126
125
 
126
+ // Reduce noise for expected errors (403/404 on content endpoints)
127
+ if ((response.status === 403 || response.status === 404) && endpoint.startsWith('/content/')) {
128
+ this.log.debug(LOG_PREFIX.API, `Request failed: ${response.status} ${errorText}`)
129
+ } else {
130
+ this.log.error(LOG_PREFIX.API, `Request failed: ${response.status} ${errorText}`)
131
+ }
132
+
127
133
  throw new Error(`API request failed: ${response.status} ${errorText}`)
128
134
  }
129
135
 
@@ -134,7 +140,10 @@ export class YotoApi {
134
140
 
135
141
  return await response.json()
136
142
  } catch (error) {
137
- this.log.error(LOG_PREFIX.API, `${ERROR_MESSAGES.API_ERROR}:`, error)
143
+ // Only log non-API errors (network issues, etc.)
144
+ if (!(error instanceof Error && error.message.startsWith('API request failed'))) {
145
+ this.log.error(LOG_PREFIX.API, `${ERROR_MESSAGES.API_ERROR}:`, error)
146
+ }
138
147
  throw error
139
148
  }
140
149
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-yoto",
3
3
  "description": "Control your Yoto players through Apple HomeKit with real-time MQTT updates",
4
- "version": "0.0.13",
4
+ "version": "0.0.14",
5
5
  "author": "Bret Comnes <bcomnes@gmail.com> (https://bret.io)",
6
6
  "bugs": {
7
7
  "url": "https://github.com/bcomnes/homebridge-yoto/issues"