denon-mqtt 0.0.2-beta.14665195558.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.
Files changed (48) hide show
  1. package/README.md +219 -0
  2. package/dist/CliParser.d.ts +11 -0
  3. package/dist/CliParser.js +80 -0
  4. package/dist/CliParser.js.map +1 -0
  5. package/dist/CommandMessage.d.ts +6 -0
  6. package/dist/CommandMessage.js +3 -0
  7. package/dist/CommandMessage.js.map +1 -0
  8. package/dist/ListenerConfig.d.ts +5 -0
  9. package/dist/ListenerConfig.js +3 -0
  10. package/dist/ListenerConfig.js.map +1 -0
  11. package/dist/MqttBroadcaster.d.ts +22 -0
  12. package/dist/MqttBroadcaster.js +72 -0
  13. package/dist/MqttBroadcaster.js.map +1 -0
  14. package/dist/MqttListener.d.ts +19 -0
  15. package/dist/MqttListener.js +65 -0
  16. package/dist/MqttListener.js.map +1 -0
  17. package/dist/MqttManager.d.ts +24 -0
  18. package/dist/MqttManager.js +45 -0
  19. package/dist/MqttManager.js.map +1 -0
  20. package/dist/MqttUpdate.d.ts +6 -0
  21. package/dist/MqttUpdate.js +3 -0
  22. package/dist/MqttUpdate.js.map +1 -0
  23. package/dist/Orchestrator.d.ts +22 -0
  24. package/dist/Orchestrator.js +143 -0
  25. package/dist/Orchestrator.js.map +1 -0
  26. package/dist/ParserResult.d.ts +6 -0
  27. package/dist/ParserResult.js +3 -0
  28. package/dist/ParserResult.js.map +1 -0
  29. package/dist/ReceiverConfig.d.ts +7 -0
  30. package/dist/ReceiverConfig.js +3 -0
  31. package/dist/ReceiverConfig.js.map +1 -0
  32. package/dist/ReceiverManager.d.ts +16 -0
  33. package/dist/ReceiverManager.js +44 -0
  34. package/dist/ReceiverManager.js.map +1 -0
  35. package/dist/TelnetBroadcaster.d.ts +7 -0
  36. package/dist/TelnetBroadcaster.js +22 -0
  37. package/dist/TelnetBroadcaster.js.map +1 -0
  38. package/dist/TelnetListener.d.ts +12 -0
  39. package/dist/TelnetListener.js +84 -0
  40. package/dist/TelnetListener.js.map +1 -0
  41. package/dist/ZoneConfig.d.ts +5 -0
  42. package/dist/ZoneConfig.js +3 -0
  43. package/dist/ZoneConfig.js.map +1 -0
  44. package/dist/entryPoint.d.ts +1 -0
  45. package/dist/entryPoint.js +46 -0
  46. package/dist/entryPoint.js.map +1 -0
  47. package/dist/tsconfig.tsbuildinfo +1 -0
  48. package/package.json +53 -0
package/README.md ADDED
@@ -0,0 +1,219 @@
1
+ # denon-mqtt
2
+
3
+ ## Getting Started
4
+
5
+ ### AVR Configuration
6
+
7
+ While it is possible to get the interface up and running with only command-line options, accessing all features requires
8
+ a configuration file to configure each AVR controlled by the interface. The interface will look for a file named
9
+ `receivers.json` using the following format(see `receivers.json.sample` for an example). In the example below, "Home
10
+ Theater" is the configuration for a Denon X4500H and "Office" is the configuration for a Denon S950H.
11
+
12
+ ```JSON
13
+ [
14
+ {
15
+ "name": "Home Theater",
16
+ "ip": "192.168.0.1234",
17
+ "id": "home_theater",
18
+ "sources": [
19
+ {"code": "SAT/CBL", "display": "Fire TV"},
20
+ {"code": "DVD", "display": "AppleTV"},
21
+ {"code": "BD", "display": "Blu-ray"},
22
+ {"code": "GAME", "display": "XBox"},
23
+ {"code": "MPLAY", "display": "Karaoke"},
24
+ {"code": "TV", "display": "TV Audio"},
25
+ {"code": "AUX1", "display": "pi"},
26
+ {"code": "AUX2", "display": "AUX2"},
27
+ {"code": "CD", "display": "Alexa"},
28
+ {"code": "PHONO", "display": "Phono"},
29
+ {"code": "TUNER", "display": "Tuner"},
30
+ {"code": "NET", "display": "HEOS Music"}
31
+ ],
32
+ "zones": [
33
+ {
34
+ "index": "1",
35
+ "name": "Living Room",
36
+ "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
37
+ },
38
+ {
39
+ "index": "2",
40
+ "name": "Rumpus Room",
41
+ "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
42
+ },
43
+ {
44
+ "index": "3",
45
+ "name": "Back Porch",
46
+ "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
47
+ }
48
+ ]
49
+ },
50
+ {
51
+ "name": "Office",
52
+ "ip": "192.168.0.5678",
53
+ "id": "office_avr",
54
+ "sources": [
55
+ {"code": "SAT/CBL", "display": "Xbox One"},
56
+ {"code": "DVD", "display": "DVD"},
57
+ {"code": "BD", "display": "Blu-ray"},
58
+ {"code": "GAME", "display": "Xbox One"},
59
+ {"code": "MPLAY", "display": "Media Player"},
60
+ {"code": "TV", "display": "TV Audio"},
61
+ {"code": "AUX1", "display": "AUX1"},
62
+ {"code": "AUX2", "display": "AUX2"},
63
+ {"code": "CD", "display": "Alexa"},
64
+ {"code": "PHONO", "display": "Phono"},
65
+ {"code": "TUNER", "display": "Tuner"},
66
+ {"code": "NET", "display": "HEOS Music"}
67
+ ],
68
+ "zones": [
69
+ {
70
+ "index": "1",
71
+ "name": "Living Room",
72
+ "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
73
+ },
74
+ {
75
+ "index": "2",
76
+ "name": "Rumpus Room",
77
+ "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
78
+ },
79
+ {
80
+ "index": "3",
81
+ "name": "Back Porch",
82
+ "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
83
+ }
84
+ ]
85
+ }
86
+ ]
87
+ ```
88
+
89
+ ### Install with yarn orn npm
90
+
91
+ This method requires [installing Node.js first](https://nodejs.org/en/download).
92
+
93
+ ```bash
94
+ # Install:
95
+ yarn global add denon-mqtt
96
+ # OR
97
+ npm i -g denon-mqtt
98
+
99
+ # Run:
100
+ yarn denon-mqtt
101
+ # OR
102
+ npm run denon-mqtt
103
+ ```
104
+
105
+ ### Run with Docker
106
+
107
+ Docker run:
108
+
109
+ ```bash
110
+ docker run douglampe/denon-mqtt:latest -v ./receivers.json:/app/receivers.json
111
+ ```
112
+
113
+ Docker compose:
114
+
115
+ ```yaml
116
+ services:
117
+ denon-mqtt:
118
+ container_name: denon-mqtt
119
+ image: douglampe/denon-mqtt:latest
120
+ volumes:
121
+ - ./receivers.json:/app/receivers.json
122
+ ```
123
+
124
+ ### Command Line Options
125
+
126
+ Options:
127
+
128
+ ```
129
+ -i, --info Display current version number
130
+ -f, --file <file> Get configuration from JSON file
131
+ -m, --mqtt <url> MQTT URL (default: "localhost")
132
+ -u, --username <username> MQTT Username (default: "user")
133
+ -p, --password <password> MQTT Password (default: "password")
134
+ --port MQTT Port <port>
135
+ --prefix MQTT Topic Prefix <prefix>
136
+ -a, --avr <list> Comma-separated list of AVR IP addresses
137
+ --name <list> Comma-separated list of AVR friendly names (default: "Home Theater")
138
+ --id <list> Comma-separated list of AVR unique IDs (default: "denon")
139
+ --zones <list> Comma-separated list of | separated AVR zone names (default: "Main|Zone 2")
140
+ -h, --help display help for command
141
+ ```
142
+
143
+ ### Running MQTT
144
+
145
+ You can use the below Docker compose configuration to run MQTT. Reference the mosquitto documentation for more details.
146
+
147
+ ```yaml
148
+ services:
149
+ eclipse-mosquitto:
150
+ container_name: mosquitto
151
+ image: eclipse-mosquitto:latest
152
+ restart: always
153
+ ports:
154
+ - 9001:9001
155
+ - 1883:1883
156
+ volumes:
157
+ - ./mosquitto.conf:/mosquitto/config/mosquitto.conf
158
+ - ./mosquitto-users.txt:/mosquitto/config/mosquitto-users.txt
159
+ ```
160
+
161
+ ## Contributing
162
+
163
+ ### Clone the repository
164
+
165
+ ```bash
166
+ git clone https://github.com/douglampe/denon-state-manager.git
167
+ ```
168
+
169
+ ### Install dependencies
170
+
171
+ ```bash
172
+ yarn
173
+ # OR
174
+ npm i
175
+ ```
176
+
177
+ ### Start eclipse mosquito MQTT and Home Assistant via docker
178
+
179
+ ```bash
180
+ docker compose up -d
181
+ ```
182
+
183
+ ### Start the interface in dev mode
184
+
185
+ ```bash
186
+ yarn dev
187
+ # OR
188
+ npm run dev
189
+ ```
190
+
191
+ ### Start the interface in dev mode using `receivers.json` to configure AVRs
192
+
193
+ ```bash
194
+ yarn dev:file
195
+ # OR
196
+ npm run dev:file
197
+ ```
198
+
199
+ ## What is This?
200
+
201
+ This project provides MQTT support Denon and Marantz Audio Video Receivers (AVRs). While it does not provide 100%
202
+ compatibility with the protocol, it has been developed in line with documentation for version ("Application model")
203
+ AVR-3312CI/AVR-3312 and version 0.06 of the specification for AVR-S700, S900, X1100, X3100, X4100, X5200, and X7200. It
204
+ has been tested with the following receiver models:
205
+
206
+ - S950H
207
+ - X4500H
208
+
209
+ ## Why Does This Exist?
210
+
211
+ Denon AVRs support both RS-232C and Ethernet interfaces. The Ethernet interface is a TCP interface which does not
212
+ require any authentication or authorization. The interface is bi-directional meaning that changes made to the reciever
213
+ by other sources (ex: using the remote control) are broadcasted to the interface. This makes the interface ideal for
214
+ integrating with systems which operate best while maitaining accurate state such as the Home Automation platform
215
+ Home Assistant. While integrating directly with Home Assistant has advantages such as reduced latency, there are
216
+ disadvantages such as platform lock-in. Existing Denon integrations also have limitations. By creating an MQTT
217
+ interface, multiple Denon AVRs can be integrated with Home Assistant using the supported MQTT integration while
218
+ also providing direct support for any platform that supports MQTT such as Node Red. I also get to write this in
219
+ Node.js instead of python which is a win for me IMHO.
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ export declare class CliParser {
3
+ static isTest: boolean;
4
+ static log: (message: any) => void;
5
+ static run(options: {
6
+ name: string;
7
+ version: string;
8
+ args: string[];
9
+ }): Promise<void>;
10
+ static start(_opts: any, command: Command): Promise<void>;
11
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CliParser = void 0;
7
+ const commander_1 = require("commander");
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const Orchestrator_1 = require("./Orchestrator");
11
+ class CliParser {
12
+ static async run(options) {
13
+ const program = new commander_1.Command();
14
+ if (CliParser.isTest) {
15
+ program.exitOverride().configureOutput({
16
+ writeOut: CliParser.log,
17
+ writeErr: CliParser.log,
18
+ getOutHelpWidth: () => 160,
19
+ getErrHelpWidth: () => 160,
20
+ });
21
+ }
22
+ program.name(options.name).version(options.version, '-i, --info', 'Display current version number');
23
+ program
24
+ .option('-f, --file <file>', 'Get configuration from JSON file')
25
+ .option('-m, --mqtt <url>', 'MQTT URL', 'localhost')
26
+ .option('-u, --username <username>', 'MQTT Username', 'user')
27
+ .option('-p, --password <password>', 'MQTT Password', 'password')
28
+ .option('--port', 'MQTT Port <port>', '1883')
29
+ .option('--prefix', 'MQTT Topic Prefix <prefix>', 'denon')
30
+ .option('-a, --avr <list>', 'Comma-separated list of AVR IP addresses')
31
+ .option('--name <list>', 'Comma-separated list of AVR friendly names', 'Home Theater')
32
+ .option('--id <list>', 'Comma-separated list of AVR unique IDs', 'denon')
33
+ .option('--zones <list>', 'Comma-separated list of | separated AVR zone names', 'Main|Zone 2')
34
+ .action(CliParser.start);
35
+ await program.parseAsync(options.args);
36
+ }
37
+ static async start(_opts, command) {
38
+ const opts = command.optsWithGlobals();
39
+ const options = Object.assign(Object.assign({}, opts), { receivers: [] });
40
+ if (opts.file) {
41
+ const file = path_1.default.resolve(opts.file);
42
+ const stat = await promises_1.default.stat(file);
43
+ if (!stat.isFile()) {
44
+ throw new Error(`File ${opts.file} not found (path: ${file})`);
45
+ }
46
+ try {
47
+ const json = await promises_1.default.readFile(file);
48
+ const fileConfig = JSON.parse(json.toString());
49
+ for (const config of fileConfig) {
50
+ options.receivers.push(config);
51
+ }
52
+ }
53
+ catch (err) {
54
+ throw new Error(`Error parsing file ${opts.file}: ${err}`);
55
+ }
56
+ }
57
+ else {
58
+ const avrHosts = opts.avr.split(',');
59
+ const avrNames = opts.name.split(',');
60
+ const avrIds = opts.id.split(',');
61
+ const zonesLists = opts.zones.split(',');
62
+ const zones = zonesLists.map((z) => z.split('|'));
63
+ if (avrHosts.length + avrNames.length + avrIds.length + zones.length !== avrHosts.length * 4) {
64
+ throw new Error('--avr, --name, --id, and --zones lists must be the same length.');
65
+ }
66
+ for (let i = 0; i < avrHosts.length; i++) {
67
+ options.receivers.push({
68
+ id: avrIds[i],
69
+ name: avrNames[i],
70
+ ip: avrHosts[i],
71
+ zones: zones[i],
72
+ });
73
+ }
74
+ }
75
+ return Orchestrator_1.Orchestrator.run(options);
76
+ }
77
+ }
78
+ exports.CliParser = CliParser;
79
+ CliParser.log = console.log;
80
+ //# sourceMappingURL=CliParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CliParser.js","sourceRoot":"","sources":["../src/CliParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { ReceiverSettings, StateValue } from 'denon-state-manager';
2
+ export interface CommandMessage {
3
+ command: ReceiverSettings;
4
+ value?: StateValue;
5
+ zone?: number;
6
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=CommandMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandMessage.js","sourceRoot":"","sources":["../src/CommandMessage.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ import { ReceiverSettings } from 'denon-state-manager';
2
+ export interface ListenerConfig {
3
+ command: ReceiverSettings;
4
+ zone: number;
5
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ListenerConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListenerConfig.js","sourceRoot":"","sources":["../src/ListenerConfig.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { ReceiverSettings, ReceiverState, StateValue } from 'denon-state-manager';
2
+ import { MqttClient } from 'mqtt/*';
3
+ import { MqttUpdate } from './MqttUpdate';
4
+ export interface MqttBroadcasterOptions {
5
+ prefix: string;
6
+ id: string;
7
+ client: MqttClient;
8
+ }
9
+ export declare class MqttBroadcaster {
10
+ private options;
11
+ static DefaultOptions: {
12
+ prefix: string;
13
+ id: string;
14
+ };
15
+ constructor(options: MqttBroadcasterOptions);
16
+ getTopic(component: string, id: string, zone: number): string;
17
+ getStateWithKeys(state: {
18
+ [key in ReceiverSettings]?: StateValue;
19
+ }): Record<string, string | number | Record<string, string>>;
20
+ publish(update: MqttUpdate): Promise<void>;
21
+ publishState(state: ReceiverState, zone: number): Promise<void>;
22
+ }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MqttBroadcaster = void 0;
4
+ const denon_state_manager_1 = require("denon-state-manager");
5
+ class MqttBroadcaster {
6
+ constructor(options) {
7
+ this.options = options;
8
+ }
9
+ getTopic(component, id, zone) {
10
+ const zonePrefix = zone == 1 ? 'main_zone' : `zone${zone}`;
11
+ return `${this.options.prefix}/${component}/${this.options.id}_${zonePrefix}_${id}/state`;
12
+ }
13
+ getStateWithKeys(state) {
14
+ var _a, _b, _c;
15
+ const stateWithKeys = {};
16
+ for (const [key, value] of Object.entries(state)) {
17
+ const name = denon_state_manager_1.ReceiverSettings[key];
18
+ const processedValue = (_c = (_b = (_a = value.dictionary) !== null && _a !== void 0 ? _a : value.numeric) !== null && _b !== void 0 ? _b : value.text) !== null && _c !== void 0 ? _c : value.raw;
19
+ if (processedValue) {
20
+ stateWithKeys[name] = processedValue;
21
+ }
22
+ }
23
+ return stateWithKeys;
24
+ }
25
+ async publish(update) {
26
+ var _a, _b, _c, _d, _e;
27
+ let component;
28
+ let message;
29
+ const key = (_a = update.key) !== null && _a !== void 0 ? _a : denon_state_manager_1.ReceiverSettings.None;
30
+ const id = denon_state_manager_1.ReceiverSettings[key].toLowerCase();
31
+ if (!update.value) {
32
+ console.error('update.value is undefined');
33
+ return;
34
+ }
35
+ switch (update.key) {
36
+ case denon_state_manager_1.ReceiverSettings.Power:
37
+ case denon_state_manager_1.ReceiverSettings.Mute:
38
+ component = 'switch';
39
+ message = (_b = update.value.text) !== null && _b !== void 0 ? _b : '';
40
+ break;
41
+ case denon_state_manager_1.ReceiverSettings.Source:
42
+ component = 'select';
43
+ message = (_c = update.value.text) !== null && _c !== void 0 ? _c : '';
44
+ break;
45
+ case denon_state_manager_1.ReceiverSettings.Volume:
46
+ component = 'volume';
47
+ message = (_e = (_d = update.value.numeric) === null || _d === void 0 ? void 0 : _d.toString()) !== null && _e !== void 0 ? _e : '';
48
+ break;
49
+ }
50
+ if (message === '') {
51
+ throw new Error(`Could not parse message payload from value for setting ${denon_state_manager_1.ReceiverSettings[key]}: ${JSON.stringify(update.value)}`);
52
+ }
53
+ if (component && message) {
54
+ const topic = this.getTopic(component, id, update.zone);
55
+ console.debug(`Sending message to topic ${topic}: ${message}`);
56
+ this.options.client.publish(topic, message);
57
+ }
58
+ }
59
+ async publishState(state, zone) {
60
+ const message = JSON.stringify(this.getStateWithKeys(state.state));
61
+ const topic = this.getTopic('sensor', 'state', zone);
62
+ console.debug(`Sending message to topic ${topic}: ${message}`);
63
+ this.options.client.publish(topic, message);
64
+ return Promise.resolve();
65
+ }
66
+ }
67
+ exports.MqttBroadcaster = MqttBroadcaster;
68
+ MqttBroadcaster.DefaultOptions = {
69
+ prefix: 'denon',
70
+ id: 'denon',
71
+ };
72
+ //# sourceMappingURL=MqttBroadcaster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MqttBroadcaster.js","sourceRoot":"","sources":["../src/MqttBroadcaster.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { ReceiverSettings } from 'denon-state-manager';
2
+ import { MqttClient } from 'mqtt';
3
+ import { ReceiverManager } from './ReceiverManager';
4
+ export interface MqttListenerOptions {
5
+ prefix: string;
6
+ id: string;
7
+ client: MqttClient;
8
+ receiver: ReceiverManager;
9
+ }
10
+ export declare class MqttListener {
11
+ private options;
12
+ private listenerConfigs;
13
+ constructor(options: MqttListenerOptions);
14
+ getTopic(component: string, id: string, zone: number): string;
15
+ listenToZone(component: string, command: ReceiverSettings, zone: number): Promise<void>;
16
+ listenToTopic(topic: string): Promise<void>;
17
+ listen(): Promise<void>;
18
+ handleMessage(command: ReceiverSettings, body: string, zone: number): Promise<void>;
19
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MqttListener = void 0;
4
+ const denon_state_manager_1 = require("denon-state-manager");
5
+ class MqttListener {
6
+ constructor(options) {
7
+ this.options = options;
8
+ this.listenerConfigs = {};
9
+ }
10
+ getTopic(component, id, zone) {
11
+ const zonePrefix = zone == 1 ? 'main_zone' : `zone${zone}`;
12
+ return `${this.options.prefix}/${component}/${this.options.id}_${zonePrefix}_${id}/command`;
13
+ }
14
+ async listenToZone(component, command, zone) {
15
+ const topic = this.getTopic(component, denon_state_manager_1.ReceiverSettings[command].toLowerCase(), zone);
16
+ this.listenerConfigs[topic] = { command, zone };
17
+ await this.listenToTopic(topic);
18
+ }
19
+ async listenToTopic(topic) {
20
+ await this.options.client.subscribeAsync(topic);
21
+ console.debug(`Listening to topic ${topic}`);
22
+ }
23
+ async listen() {
24
+ for (let i = 1; i <= this.options.receiver.options.zones.length; i++) {
25
+ const zone = this.options.receiver.options.zones[i - 1];
26
+ console.debug(`Configuring receiver ${this.options.receiver.options.name} zone ${zone}`);
27
+ const promises = [];
28
+ promises.push(this.listenToTopic(`${this.options.prefix}/device/command`));
29
+ promises.push(this.listenToZone('switch', denon_state_manager_1.ReceiverSettings.Power, i));
30
+ promises.push(this.listenToZone('switch', denon_state_manager_1.ReceiverSettings.Mute, i));
31
+ promises.push(this.listenToZone('select', denon_state_manager_1.ReceiverSettings.Source, i));
32
+ promises.push(this.listenToZone('volume', denon_state_manager_1.ReceiverSettings.Volume, i));
33
+ await Promise.allSettled(promises);
34
+ }
35
+ this.options.client.on('message', async (topic, message) => {
36
+ const body = message.toString();
37
+ console.debug(`MQTT Message on topic ${topic}:`, body);
38
+ if (topic === `${this.options.prefix}/device/command` && body === 'REFRESH') {
39
+ await this.options.receiver.query();
40
+ return;
41
+ }
42
+ const config = this.listenerConfigs[topic];
43
+ if (config) {
44
+ this.handleMessage(config.command, body, config.zone)
45
+ .then()
46
+ .catch((error) => console.error(error));
47
+ }
48
+ else {
49
+ console.debug(`No configuration found for topic ${topic}`);
50
+ }
51
+ });
52
+ }
53
+ async handleMessage(command, body, zone) {
54
+ const value = JSON.parse(body);
55
+ const avrCommand = zone === 1 ? denon_state_manager_1.MessageFormatter.getCommand(command, value) : denon_state_manager_1.MessageFormatter.getCommand(command, value, zone);
56
+ if (avrCommand) {
57
+ await this.options.receiver.send(avrCommand);
58
+ }
59
+ else {
60
+ console.debug(`No message translation found for command ${denon_state_manager_1.ReceiverSettings[command]} for zone ${zone} or error parsing value:`, value);
61
+ }
62
+ }
63
+ }
64
+ exports.MqttListener = MqttListener;
65
+ //# sourceMappingURL=MqttListener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MqttListener.js","sourceRoot":"","sources":["../src/MqttListener.ts"],"names":[],"mappings":";;;AAAA,6DAAqF;AAarF,MAAa,YAAY;IAGvB,YAAoB,OAA4B;QAA5B,YAAO,GAAP,OAAO,CAAqB;QAFxC,oBAAe,GAAmC,EAAE,CAAC;IAEV,CAAC;IAE7C,QAAQ,CAAC,SAAiB,EAAE,EAAU,EAAE,IAAY;QACzD,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;QAC3D,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,UAAU,IAAI,EAAE,UAAU,CAAC;IAC9F,CAAC;IAEM,KAAK,CAAC,YAAY,CAAC,SAAiB,EAAE,OAAyB,EAAE,IAAY;QAClF,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,sCAAgB,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CAAC;QACtF,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAEhD,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAEM,KAAK,CAAC,aAAa,CAAC,KAAa;QACtC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC;IAEM,KAAK,CAAC,MAAM;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAExD,OAAO,CAAC,KAAK,CAAC,wBAAwB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,SAAS,IAAI,EAAE,CAAC,CAAC;YAEzF,MAAM,QAAQ,GAAG,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,iBAAiB,CAAC,CAAC,CAAC;YAC3E,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,sCAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;YACtE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,sCAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,sCAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;YACvE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,sCAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;YAEvE,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACzD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;YAChC,OAAO,CAAC,KAAK,CAAC,yBAAyB,KAAK,GAAG,EAAE,IAAI,CAAC,CAAC;YAEvD,IAAI,KAAK,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,iBAAiB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5E,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACpC,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAE3C,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;qBAClD,IAAI,EAAE;qBACN,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAyB,EAAE,IAAY,EAAE,IAAY;QACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;QAE7C,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,sCAAgB,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,sCAAgB,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAEhI,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,4CAA4C,sCAAgB,CAAC,OAAO,CAAC,aAAa,IAAI,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACzI,CAAC;IACH,CAAC;CACF;AAtED,oCAsEC"}
@@ -0,0 +1,24 @@
1
+ import { ReceiverState } from 'denon-state-manager';
2
+ import { MqttClient } from 'mqtt/*';
3
+ import { MqttUpdate } from './MqttUpdate';
4
+ import { ReceiverConfig } from './ReceiverConfig';
5
+ import { ReceiverManager } from './ReceiverManager';
6
+ export interface MqttManagerOptions {
7
+ host: string;
8
+ port: number;
9
+ username: string;
10
+ password: string;
11
+ prefix: string;
12
+ id: string;
13
+ receiver: ReceiverConfig;
14
+ }
15
+ export declare class MqttManager {
16
+ private mqttClient;
17
+ private options;
18
+ private broadcaster;
19
+ constructor(mqttClient: MqttClient, options: MqttManagerOptions);
20
+ connect(receiver: ReceiverManager): Promise<void>;
21
+ publish(update: MqttUpdate): Promise<void>;
22
+ publishState(state: ReceiverState, zone: number): Promise<void>;
23
+ disconnect(): Promise<void>;
24
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MqttManager = void 0;
4
+ const MqttBroadcaster_1 = require("./MqttBroadcaster");
5
+ const MqttListener_1 = require("./MqttListener");
6
+ class MqttManager {
7
+ constructor(mqttClient, options) {
8
+ this.mqttClient = mqttClient;
9
+ this.options = options;
10
+ }
11
+ async connect(receiver) {
12
+ this.broadcaster = new MqttBroadcaster_1.MqttBroadcaster({
13
+ prefix: this.options.prefix,
14
+ id: this.options.receiver.id,
15
+ client: this.mqttClient,
16
+ });
17
+ const mqttListener = new MqttListener_1.MqttListener({
18
+ prefix: this.options.prefix,
19
+ id: this.options.id,
20
+ client: this.mqttClient,
21
+ receiver,
22
+ });
23
+ await mqttListener.listen();
24
+ }
25
+ publish(update) {
26
+ return this.broadcaster.publish(update);
27
+ }
28
+ publishState(state, zone) {
29
+ return this.broadcaster.publishState(state, zone);
30
+ }
31
+ disconnect() {
32
+ return new Promise((resolve, reject) => {
33
+ this.mqttClient.end((error) => {
34
+ if (error) {
35
+ reject(error);
36
+ }
37
+ else {
38
+ resolve();
39
+ }
40
+ });
41
+ });
42
+ }
43
+ }
44
+ exports.MqttManager = MqttManager;
45
+ //# sourceMappingURL=MqttManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MqttManager.js","sourceRoot":"","sources":["../src/MqttManager.ts"],"names":[],"mappings":";;;AAGA,uDAAoD;AACpD,iDAA8C;AAe9C,MAAa,WAAW;IAGtB,YACU,UAAsB,EACtB,OAA2B;QAD3B,eAAU,GAAV,UAAU,CAAY;QACtB,YAAO,GAAP,OAAO,CAAoB;IAClC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,QAAyB;QACrC,IAAI,CAAC,WAAW,GAAG,IAAI,iCAAe,CAAC;YACrC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;YAC5B,MAAM,EAAE,IAAI,CAAC,UAAU;SACxB,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,IAAI,2BAAY,CAAC;YACpC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;YACnB,MAAM,EAAE,IAAI,CAAC,UAAU;YACvB,QAAQ;SACT,CAAC,CAAC;QACH,MAAM,YAAY,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,CAAC,MAAkB;QACxB,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,YAAY,CAAC,KAAoB,EAAE,IAAY;QAC7C,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,UAAU;QACR,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC5B,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC;qBAAM,CAAC;oBACN,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AA3CD,kCA2CC"}
@@ -0,0 +1,6 @@
1
+ import { ReceiverSettings, StateValue } from 'denon-state-manager';
2
+ export interface MqttUpdate {
3
+ key: ReceiverSettings;
4
+ value: StateValue;
5
+ zone: number;
6
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=MqttUpdate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MqttUpdate.js","sourceRoot":"","sources":["../src/MqttUpdate.ts"],"names":[],"mappings":""}