homebridge-denon-tv 6.2.4 → 6.3.0
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 +12 -0
- package/README.md +1 -0
- package/icons/LICENSE +22 -0
- package/icons/audio-input-rca.png +0 -0
- package/icons/audio-input-stereo-minijack.png +0 -0
- package/icons/bluetooth.png +0 -0
- package/icons/disc-player.png +0 -0
- package/icons/disc.png +0 -0
- package/icons/dock-window.png +0 -0
- package/icons/gamepad-variant.png +0 -0
- package/icons/harddisk.png +0 -0
- package/icons/image-multiple.png +0 -0
- package/icons/import.png +0 -0
- package/icons/lan.png +0 -0
- package/icons/music-circle.png +0 -0
- package/icons/numeric-1-circle.png +0 -0
- package/icons/numeric-2-circle.png +0 -0
- package/icons/numeric-3-circle.png +0 -0
- package/icons/numeric-4-circle.png +0 -0
- package/icons/numeric-5-circle.png +0 -0
- package/icons/play-circle.png +0 -0
- package/icons/radio-tower.png +0 -0
- package/icons/radio.png +0 -0
- package/icons/record-player.png +0 -0
- package/icons/satellite-variant.png +0 -0
- package/icons/server-network.png +0 -0
- package/icons/speaker.png +0 -0
- package/icons/spotify.png +0 -0
- package/icons/star.png +0 -0
- package/icons/television.png +0 -0
- package/icons/usb.png +0 -0
- package/icons/video-input-hdmi.png +0 -0
- package/icons/video-vintage.png +0 -0
- package/package.json +2 -1
- package/src/hadiscovery.js +25 -0
- package/src/inputicons.js +77 -0
- package/src/mainzone.js +9 -2
- package/src/mqtt.js +1 -1
- package/src/passthroughinputs.js +3 -2
- package/src/surrounds.js +3 -2
- package/src/zone2.js +9 -2
- package/src/zone3.js +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -21,6 +21,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
21
21
|
- For plugin < v6.1.0 use Homebridge UI <= v5.5.0
|
|
22
22
|
- For plugin >= v6.1.0 use Homebridge UI >= v5.13.0
|
|
23
23
|
|
|
24
|
+
## [6.3.0] - (25.09.2026)
|
|
25
|
+
|
|
26
|
+
### Changes
|
|
27
|
+
|
|
28
|
+
- added: Home Assistant discovery shows an icon of the current input (TV, Blu-ray, game, tuner, Bluetooth, Spotify, AUX, quick select and more) for Main Zone, Zone 2 and Zone 3. The receiver has no input icons, the plugin bundles icons from Material Design Icons (Apache 2.0), published on the `HA Image` topic
|
|
29
|
+
|
|
30
|
+
## [6.2.5] - (24.09.2026)
|
|
31
|
+
|
|
32
|
+
### Changes
|
|
33
|
+
|
|
34
|
+
- fix: with 85 inputs (the HomeKit limit) the input list from the receiver 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
|
|
35
|
+
|
|
24
36
|
## [6.2.4] - (24.09.2026)
|
|
25
37
|
|
|
26
38
|
### Changes
|
package/README.md
CHANGED
|
@@ -172,6 +172,7 @@
|
|
|
172
172
|
* `homeassistant/media_player/<id>/config` - discovery message.
|
|
173
173
|
* `HA State` - `{"power": true, "volume": 49, "muted": false, "source": "SITV", "sound_mode": "MOVIE"}`.
|
|
174
174
|
* `Availability` - `online`, `offline` (last will).
|
|
175
|
+
* `HA Image` - PNG icon of the current input (TV, Blu-ray, game, tuner, Bluetooth and more), shown by Home Assistant as the source image. The receiver has no input icons, the plugin bundles icons from [Material Design Icons](https://pictogrammers.com/library/mdi/) (Apache 2.0).
|
|
175
176
|
|
|
176
177
|
| Method | Topic | Message | Type |
|
|
177
178
|
| --- | --- | --- | --- |
|
package/icons/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Input icons rendered to PNG from Material Design Icons 7.4.47 by Pictogrammers (https://pictogrammers.com/library/mdi/).
|
|
2
|
+
|
|
3
|
+
Pictogrammers Free License
|
|
4
|
+
--------------------------
|
|
5
|
+
|
|
6
|
+
This icon collection is released as free, open source, and GPL friendly by
|
|
7
|
+
the [Pictogrammers](http://pictogrammers.com/) icon group. You may use it
|
|
8
|
+
for commercial projects, open source projects, or anything really.
|
|
9
|
+
|
|
10
|
+
# Icons: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
|
|
11
|
+
Some of the icons are redistributed under the Apache 2.0 license. All other
|
|
12
|
+
icons are either redistributed under their respective licenses or are
|
|
13
|
+
distributed under the Apache 2.0 license.
|
|
14
|
+
|
|
15
|
+
# Fonts: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
|
|
16
|
+
All web and desktop fonts are distributed under the Apache 2.0 license. Web
|
|
17
|
+
and desktop fonts contain some icons that are redistributed under the Apache
|
|
18
|
+
2.0 license. All other icons are either redistributed under their respective
|
|
19
|
+
licenses or are distributed under the Apache 2.0 license.
|
|
20
|
+
|
|
21
|
+
# Code: MIT (https://opensource.org/licenses/MIT)
|
|
22
|
+
The MIT license applies to all non-font and non-icon files.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/icons/disc.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/icons/import.png
ADDED
|
Binary file
|
package/icons/lan.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/icons/radio.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/icons/star.png
ADDED
|
Binary file
|
|
Binary file
|
package/icons/usb.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "Denon TV",
|
|
3
3
|
"name": "homebridge-denon-tv",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.3.0",
|
|
5
5
|
"description": "Homebridge plugin to control Denon/Marantz AV Receivers.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
"src",
|
|
25
|
+
"icons",
|
|
25
26
|
"index.js",
|
|
26
27
|
"config.schema.json",
|
|
27
28
|
"package.json",
|
package/src/hadiscovery.js
CHANGED
|
@@ -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)) {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
// Icons of the receiver inputs for Home Assistant, the receiver does not provide any.
|
|
4
|
+
// Material Design Icons (Apache 2.0, https://pictogrammers.com) rendered to PNG in /icons
|
|
5
|
+
const IconsDir = new URL('../icons/', import.meta.url);
|
|
6
|
+
|
|
7
|
+
const InputIcons = {
|
|
8
|
+
'PHONO': 'record-player',
|
|
9
|
+
'CD': 'disc',
|
|
10
|
+
'CDR': 'disc',
|
|
11
|
+
'DVD': 'disc-player',
|
|
12
|
+
'BD': 'disc-player',
|
|
13
|
+
'HDP': 'disc-player',
|
|
14
|
+
'TV': 'television',
|
|
15
|
+
'SAT/CBL': 'satellite-variant',
|
|
16
|
+
'SAT': 'satellite-variant',
|
|
17
|
+
'CBL': 'satellite-variant',
|
|
18
|
+
'MPLAY': 'play-circle',
|
|
19
|
+
'OTP': 'play-circle',
|
|
20
|
+
'GAME': 'gamepad-variant',
|
|
21
|
+
'GAME1': 'gamepad-variant',
|
|
22
|
+
'GAME2': 'gamepad-variant',
|
|
23
|
+
'TUNER': 'radio',
|
|
24
|
+
'HDRADIO': 'radio',
|
|
25
|
+
'DVR': 'harddisk',
|
|
26
|
+
'VCR': 'video-vintage',
|
|
27
|
+
'DOCK': 'dock-window',
|
|
28
|
+
'NET/USB': 'usb',
|
|
29
|
+
'USB/IPOD': 'usb',
|
|
30
|
+
'USB': 'usb',
|
|
31
|
+
'IPD': 'usb',
|
|
32
|
+
'NET': 'lan',
|
|
33
|
+
'BT': 'bluetooth',
|
|
34
|
+
'8K': 'video-input-hdmi',
|
|
35
|
+
'DIGITALIN1': 'audio-input-rca',
|
|
36
|
+
'IRADIO': 'radio-tower',
|
|
37
|
+
'IRP': 'radio-tower',
|
|
38
|
+
'SERVER': 'server-network',
|
|
39
|
+
'SPOTIFY': 'spotify',
|
|
40
|
+
'SPOTIFYCONNECT': 'spotify',
|
|
41
|
+
'FLICKR': 'image-multiple',
|
|
42
|
+
'SIRIUS': 'music-circle',
|
|
43
|
+
'SIRIUSXM': 'music-circle',
|
|
44
|
+
'RHAPSODY': 'music-circle',
|
|
45
|
+
'PANDORA': 'music-circle',
|
|
46
|
+
'NAPSTER': 'music-circle',
|
|
47
|
+
'LASTFM': 'music-circle',
|
|
48
|
+
'FAVORITES': 'star',
|
|
49
|
+
'FVP': 'star',
|
|
50
|
+
'SOURCE': 'speaker'
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
class InputIconsStore {
|
|
54
|
+
constructor() {
|
|
55
|
+
this.cache = new Map();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Icon file name of an input reference, AUX and quick / smart / favorite selects by prefix, others the generic input icon
|
|
59
|
+
iconName(reference) {
|
|
60
|
+
const ref = String(reference ?? '').toUpperCase().replace(/ MEMORY$/, '');
|
|
61
|
+
if (InputIcons[ref]) return InputIcons[ref];
|
|
62
|
+
if (/^(AUX|V\.AUX|M-XPORT)/.test(ref)) return 'audio-input-stereo-minijack';
|
|
63
|
+
if (/^FAVORITE\d/.test(ref)) return 'star';
|
|
64
|
+
const select = ref.match(/^(QUICK|SMART)([1-5])$/);
|
|
65
|
+
if (select) return `numeric-${select[2]}-circle`;
|
|
66
|
+
return 'import';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// PNG bytes of the input icon, read once and cached
|
|
70
|
+
async get(reference) {
|
|
71
|
+
const name = this.iconName(reference);
|
|
72
|
+
if (!this.cache.has(name)) this.cache.set(name, await readFile(new URL(`${name}.png`, IconsDir)).catch(() => null));
|
|
73
|
+
return this.cache.get(name);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default new InputIconsStore();
|
package/src/mainzone.js
CHANGED
|
@@ -2,6 +2,7 @@ import EventEmitter from 'events';
|
|
|
2
2
|
import Zone from './zone.js';
|
|
3
3
|
import Functions from './functions.js';
|
|
4
4
|
import HaDiscovery from './hadiscovery.js';
|
|
5
|
+
import InputIcons from './inputicons.js';
|
|
5
6
|
import { PictureModesConversionToHomeKit, PictureModesDenonNumber, PictureModesDenonString, DirectSoundMode, SoundModeConversion, SoundModeDisplayName } from './constants.js';
|
|
6
7
|
let Accessory, Characteristic, Service, Categories, Encode, AccessoryUUID;
|
|
7
8
|
|
|
@@ -227,8 +228,6 @@ class MainZone extends EventEmitter {
|
|
|
227
228
|
let updated = false;
|
|
228
229
|
|
|
229
230
|
for (const input of inputs) {
|
|
230
|
-
if (this.inputsServices.length >= 85 && !remove) continue;
|
|
231
|
-
|
|
232
231
|
const inputReference = input.reference;
|
|
233
232
|
const savedName = this.savedInputsNames[inputReference] ?? input.name;
|
|
234
233
|
const sanitizedName = await this.functions.sanitizeString(savedName);
|
|
@@ -259,6 +258,9 @@ class MainZone extends EventEmitter {
|
|
|
259
258
|
updated = true;
|
|
260
259
|
}
|
|
261
260
|
} else {
|
|
261
|
+
// HomeKit allows at most 85 inputs, the limit applies to new inputs only, existing ones are still updated
|
|
262
|
+
if (this.inputsServices.length >= 85) continue;
|
|
263
|
+
|
|
262
264
|
const identifier = this.inputsServices.length + 1;
|
|
263
265
|
inputService = this.accessory.addService(Service.InputSource, sanitizedName, `Input ${inputReference}`);
|
|
264
266
|
inputService.identifier = identifier;
|
|
@@ -979,6 +981,7 @@ class MainZone extends EventEmitter {
|
|
|
979
981
|
objectId: `denon_${this.savedInfo.serialNumber}_zone${this.zoneControl}`,
|
|
980
982
|
name: this.name,
|
|
981
983
|
deviceClass: 'receiver',
|
|
984
|
+
image: true,
|
|
982
985
|
device: {
|
|
983
986
|
manufacturer: this.savedInfo.manufacturer,
|
|
984
987
|
model: this.savedInfo.modelName,
|
|
@@ -1024,6 +1027,10 @@ class MainZone extends EventEmitter {
|
|
|
1024
1027
|
source: input ? `${input.zonePrefix}${input.reference}` : this.reference,
|
|
1025
1028
|
sound_mode: this.ha.commands.sound_mode ? this.zone.soundMode || undefined : undefined
|
|
1026
1029
|
});
|
|
1030
|
+
|
|
1031
|
+
// Icon of the current input, bundled with the plugin
|
|
1032
|
+
const reference = this.power ? this.reference || null : null;
|
|
1033
|
+
this.ha.updateImage(reference, () => InputIcons.get(reference)).catch(() => { });
|
|
1027
1034
|
} catch (error) {
|
|
1028
1035
|
if (this.logWarn) this.emit('warn', `HA Discovery state error: ${error}`);
|
|
1029
1036
|
}
|
package/src/mqtt.js
CHANGED
|
@@ -110,7 +110,7 @@ class Mqtt extends EventEmitter {
|
|
|
110
110
|
if (this.config.logWarn) this.emit('warn', `MQTT Publish error: ${error.message}`);
|
|
111
111
|
return reject(error);
|
|
112
112
|
}
|
|
113
|
-
if (this.config.logDebug) this.emit('debug', `MQTT Publish retained Topic: ${fullTopic}, Payload: ${payload}`);
|
|
113
|
+
if (this.config.logDebug) this.emit('debug', `MQTT Publish retained Topic: ${fullTopic}, Payload: ${typeof payload === 'string' ? payload : `${payload.length} bytes`}`);
|
|
114
114
|
resolve();
|
|
115
115
|
});
|
|
116
116
|
});
|
package/src/passthroughinputs.js
CHANGED
|
@@ -107,8 +107,6 @@ class PassThroughInputs extends EventEmitter {
|
|
|
107
107
|
let updated = false;
|
|
108
108
|
|
|
109
109
|
for (const input of inputs) {
|
|
110
|
-
if (this.inputsServices.length >= 85 && !remove) continue;
|
|
111
|
-
|
|
112
110
|
const inputReference = input.reference;
|
|
113
111
|
const savedName = this.savedInputsNames[inputReference] ?? input.name;
|
|
114
112
|
const sanitizedName = await this.functions.sanitizeString(savedName);
|
|
@@ -139,6 +137,9 @@ class PassThroughInputs extends EventEmitter {
|
|
|
139
137
|
updated = true;
|
|
140
138
|
}
|
|
141
139
|
} else {
|
|
140
|
+
// HomeKit allows at most 85 inputs, the limit applies to new inputs only, existing ones are still updated
|
|
141
|
+
if (this.inputsServices.length >= 85) continue;
|
|
142
|
+
|
|
142
143
|
const identifier = this.inputsServices.length + 1;
|
|
143
144
|
inputService = this.accessory.addService(Service.InputSource, sanitizedName, `Input ${inputReference}`);
|
|
144
145
|
inputService.identifier = identifier;
|
package/src/surrounds.js
CHANGED
|
@@ -118,8 +118,6 @@ class Surrounds extends EventEmitter {
|
|
|
118
118
|
let updated = false;
|
|
119
119
|
|
|
120
120
|
for (const input of inputs) {
|
|
121
|
-
if (this.inputsServices.length >= 85 && !remove) continue;
|
|
122
|
-
|
|
123
121
|
const inputReference = input.reference;
|
|
124
122
|
const savedName = this.savedInputsNames[inputReference] ?? input.name;
|
|
125
123
|
const sanitizedName = await this.functions.sanitizeString(savedName);
|
|
@@ -150,6 +148,9 @@ class Surrounds extends EventEmitter {
|
|
|
150
148
|
updated = true;
|
|
151
149
|
}
|
|
152
150
|
} else {
|
|
151
|
+
// HomeKit allows at most 85 inputs, the limit applies to new inputs only, existing ones are still updated
|
|
152
|
+
if (this.inputsServices.length >= 85) continue;
|
|
153
|
+
|
|
153
154
|
const identifier = this.inputsServices.length + 1;
|
|
154
155
|
inputService = this.accessory.addService(Service.InputSource, sanitizedName, `Input ${inputReference}`);
|
|
155
156
|
inputService.identifier = identifier;
|
package/src/zone2.js
CHANGED
|
@@ -2,6 +2,7 @@ import EventEmitter from 'events';
|
|
|
2
2
|
import Zone from './zone.js';
|
|
3
3
|
import Functions from './functions.js';
|
|
4
4
|
import HaDiscovery from './hadiscovery.js';
|
|
5
|
+
import InputIcons from './inputicons.js';
|
|
5
6
|
import { PictureModesConversionToHomeKit, PictureModesDenonNumber, SoundModeConversion, SoundModeDisplayName } from './constants.js';
|
|
6
7
|
let Accessory, Characteristic, Service, Categories, Encode, AccessoryUUID;
|
|
7
8
|
|
|
@@ -225,8 +226,6 @@ class Zone2 extends EventEmitter {
|
|
|
225
226
|
let updated = false;
|
|
226
227
|
|
|
227
228
|
for (const input of inputs) {
|
|
228
|
-
if (this.inputsServices.length >= 85 && !remove) continue;
|
|
229
|
-
|
|
230
229
|
const inputReference = input.reference;
|
|
231
230
|
const savedName = this.savedInputsNames[inputReference] ?? input.name;
|
|
232
231
|
const sanitizedName = await this.functions.sanitizeString(savedName);
|
|
@@ -257,6 +256,9 @@ class Zone2 extends EventEmitter {
|
|
|
257
256
|
updated = true;
|
|
258
257
|
}
|
|
259
258
|
} else {
|
|
259
|
+
// HomeKit allows at most 85 inputs, the limit applies to new inputs only, existing ones are still updated
|
|
260
|
+
if (this.inputsServices.length >= 85) continue;
|
|
261
|
+
|
|
260
262
|
const identifier = this.inputsServices.length + 1;
|
|
261
263
|
inputService = this.accessory.addService(Service.InputSource, sanitizedName, `Input ${inputReference}`);
|
|
262
264
|
inputService.identifier = identifier;
|
|
@@ -893,6 +895,7 @@ class Zone2 extends EventEmitter {
|
|
|
893
895
|
objectId: `denon_${this.savedInfo.serialNumber}_zone${this.zoneControl}`,
|
|
894
896
|
name: this.name,
|
|
895
897
|
deviceClass: 'receiver',
|
|
898
|
+
image: true,
|
|
896
899
|
device: {
|
|
897
900
|
manufacturer: this.savedInfo.manufacturer,
|
|
898
901
|
model: this.savedInfo.modelName,
|
|
@@ -938,6 +941,10 @@ class Zone2 extends EventEmitter {
|
|
|
938
941
|
source: input ? `${input.zonePrefix}${input.reference}` : this.reference,
|
|
939
942
|
sound_mode: this.ha.commands.sound_mode ? this.zone.soundMode || undefined : undefined
|
|
940
943
|
});
|
|
944
|
+
|
|
945
|
+
// Icon of the current input, bundled with the plugin
|
|
946
|
+
const reference = this.power ? this.reference || null : null;
|
|
947
|
+
this.ha.updateImage(reference, () => InputIcons.get(reference)).catch(() => { });
|
|
941
948
|
} catch (error) {
|
|
942
949
|
if (this.logWarn) this.emit('warn', `HA Discovery state error: ${error}`);
|
|
943
950
|
}
|
package/src/zone3.js
CHANGED
|
@@ -2,6 +2,7 @@ import EventEmitter from 'events';
|
|
|
2
2
|
import Zone from './zone.js';
|
|
3
3
|
import Functions from './functions.js';
|
|
4
4
|
import HaDiscovery from './hadiscovery.js';
|
|
5
|
+
import InputIcons from './inputicons.js';
|
|
5
6
|
import { PictureModesConversionToHomeKit, PictureModesDenonNumber, SoundModeConversion, SoundModeDisplayName } from './constants.js';
|
|
6
7
|
let Accessory, Characteristic, Service, Categories, Encode, AccessoryUUID;
|
|
7
8
|
|
|
@@ -225,8 +226,6 @@ class Zone3 extends EventEmitter {
|
|
|
225
226
|
let updated = false;
|
|
226
227
|
|
|
227
228
|
for (const input of inputs) {
|
|
228
|
-
if (this.inputsServices.length >= 85 && !remove) continue;
|
|
229
|
-
|
|
230
229
|
const inputReference = input.reference;
|
|
231
230
|
const savedName = this.savedInputsNames[inputReference] ?? input.name;
|
|
232
231
|
const sanitizedName = await this.functions.sanitizeString(savedName);
|
|
@@ -257,6 +256,9 @@ class Zone3 extends EventEmitter {
|
|
|
257
256
|
updated = true;
|
|
258
257
|
}
|
|
259
258
|
} else {
|
|
259
|
+
// HomeKit allows at most 85 inputs, the limit applies to new inputs only, existing ones are still updated
|
|
260
|
+
if (this.inputsServices.length >= 85) continue;
|
|
261
|
+
|
|
260
262
|
const identifier = this.inputsServices.length + 1;
|
|
261
263
|
inputService = this.accessory.addService(Service.InputSource, sanitizedName, `Input ${inputReference}`);
|
|
262
264
|
inputService.identifier = identifier;
|
|
@@ -893,6 +895,7 @@ class Zone3 extends EventEmitter {
|
|
|
893
895
|
objectId: `denon_${this.savedInfo.serialNumber}_zone${this.zoneControl}`,
|
|
894
896
|
name: this.name,
|
|
895
897
|
deviceClass: 'receiver',
|
|
898
|
+
image: true,
|
|
896
899
|
device: {
|
|
897
900
|
manufacturer: this.savedInfo.manufacturer,
|
|
898
901
|
model: this.savedInfo.modelName,
|
|
@@ -938,6 +941,10 @@ class Zone3 extends EventEmitter {
|
|
|
938
941
|
source: input ? `${input.zonePrefix}${input.reference}` : this.reference,
|
|
939
942
|
sound_mode: this.ha.commands.sound_mode ? this.zone.soundMode || undefined : undefined
|
|
940
943
|
});
|
|
944
|
+
|
|
945
|
+
// Icon of the current input, bundled with the plugin
|
|
946
|
+
const reference = this.power ? this.reference || null : null;
|
|
947
|
+
this.ha.updateImage(reference, () => InputIcons.get(reference)).catch(() => { });
|
|
941
948
|
} catch (error) {
|
|
942
949
|
if (this.logWarn) this.emit('warn', `HA Discovery state error: ${error}`);
|
|
943
950
|
}
|