homebridge-xbox-tv 4.2.1 → 4.2.2

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/CHANGELOG.md CHANGED
@@ -18,6 +18,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
18
18
  - For plugin < v4.1.0 use Homebridge UI <= v5.5.0
19
19
  - For plugin >= v4.1.0 use Homebridge UI >= v5.13.0
20
20
 
21
+ ## [4.2.2] - (24.09.2026)
22
+
23
+ ### Changes
24
+
25
+ - fix: with 85 inputs (the HomeKit limit) the input list from the console no longer updated existing inputs, the limit skipped every input instead of only new ones, so names of existing inputs were never refreshed. The limit now applies to new inputs only
26
+
21
27
  ## [4.2.1] - (24.09.2026)
22
28
 
23
29
  ### Changes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Xbox TV",
3
3
  "name": "homebridge-xbox-tv",
4
- "version": "4.2.1",
4
+ "version": "4.2.2",
5
5
  "description": "Homebridge plugin to control Xbox game consoles.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -20,12 +20,14 @@ class HaDiscovery {
20
20
  this.configTopic = `${mqtt.haPrefix}/media_player/${this.objectId}/config`;
21
21
  this.stateTopic = `${mqtt.config.prefix}/HA State`;
22
22
  this.commandTopic = `${mqtt.config.prefix}/Set`;
23
+ this.imageTopic = config.image ? `${mqtt.config.prefix}/HA Image` : null;
23
24
 
24
25
  this.sources = [];
25
26
  this.soundModes = [];
26
27
  this.state = {};
27
28
  this.lastConfig = '';
28
29
  this.lastState = '';
30
+ this.lastImageKey = undefined;
29
31
  }
30
32
 
31
33
  // Publish (or republish when changed) the retained discovery message
@@ -45,6 +47,7 @@ class HaDiscovery {
45
47
  state_topic: this.stateTopic,
46
48
  command_topic: this.commandTopic,
47
49
  availability_topic: this.mqtt.availabilityTopic,
50
+ ...(this.imageTopic ? { image_topic: this.imageTopic } : {}),
48
51
  device,
49
52
  commands: this.commands,
50
53
  sources: this.sources,
@@ -58,6 +61,28 @@ class HaDiscovery {
58
61
  return true;
59
62
  }
60
63
 
64
+ // Publish the image of the current source (app icon, channel picon) once per source.
65
+ // key identifies the image, fetchImage returns a Buffer or null, null clears the image
66
+ async updateImage(key, fetchImage) {
67
+ if (!this.imageTopic || key === this.lastImageKey) return false;
68
+ this.lastImageKey = key;
69
+
70
+ let image = null;
71
+ try {
72
+ image = key ? await fetchImage() : null;
73
+ } catch {
74
+ // Network or device error, allow a retry on the next state update
75
+ image = null;
76
+ if (key === this.lastImageKey) this.lastImageKey = undefined;
77
+ return false;
78
+ }
79
+
80
+ // The source changed again while fetching, a newer call publishes its own image
81
+ if (key !== this.lastImageKey) return false;
82
+ await this.mqtt.publishRetained(this.imageTopic, image ?? '');
83
+ return true;
84
+ }
85
+
61
86
  // Merge a partial state and publish it retained when something changed
62
87
  async updateState(partial) {
63
88
  for (const [key, value] of Object.entries(partial)) {
package/src/mqtt.js CHANGED
@@ -116,7 +116,7 @@ class Mqtt extends EventEmitter {
116
116
  if (this.config.logWarn) this.emit('warn', `MQTT Publish error: ${error.message}`);
117
117
  return reject(error);
118
118
  }
119
- if (this.config.logDebug) this.emit('debug', `MQTT Publish retained Topic: ${fullTopic}, Payload: ${payload}`);
119
+ if (this.config.logDebug) this.emit('debug', `MQTT Publish retained Topic: ${fullTopic}, Payload: ${typeof payload === 'string' ? payload : `${payload.length} bytes`}`);
120
120
  resolve();
121
121
  });
122
122
  });
package/src/xboxdevice.js CHANGED
@@ -227,8 +227,6 @@ class XboxDevice extends EventEmitter {
227
227
  let updated = false;
228
228
 
229
229
  for (const input of inputs) {
230
- if (this.inputsServices.length >= 85 && !remove) continue;
231
-
232
230
  // Filter
233
231
  const contentType = input.contentType;
234
232
  const filterGames = this.filterGames && contentType === 'Game';
@@ -268,6 +266,9 @@ class XboxDevice extends EventEmitter {
268
266
  updated = true;
269
267
  }
270
268
  } else {
269
+ // HomeKit allows at most 85 inputs, the limit applies to new inputs only, existing ones are still updated
270
+ if (this.inputsServices.length >= 85) continue;
271
+
271
272
  const identifier = this.inputsServices.length + 1;
272
273
  inputService = this.accessory.addService(Service.InputSource, sanitizedName, `Input ${inputReference}`);
273
274
  inputService.identifier = identifier;