Skip to content

Commit

Permalink
release 4.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
grzegorz914 committed Jan 14, 2024
1 parent f65a3eb commit b3c4289
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 52 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## The properties *inputs.displayType* and *surrounds.displayType* are removed.
## Note - after update to 3.15.x need remove the accessory frome Home app and add it again.

## [4.6.0] - (14.01.2024)
## Changes
- added support for new API of AVR like AVC-X4800H or Marantz PM7000N, closes [#211](https://github.com/grzegorz914/homebridge-denon-tv/issues/211)
- replaced properties *supportOldAvr* with *generation*
- bump dependencies
- config schema updated
- cleanup

## [4.5.0] - (02.01.2024)
## Changes
- added possibility to disable prefix name for buttons and sensors [#215](https://github.com/grzegorz914/homebridge-denon-tv/issues/215)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
[![GitHub issues](https://img.shields.io/github/issues/grzegorz914/homebridge-denon-tv.svg)](https://github.com/grzegorz914/homebridge-denon-tv/issues)

Homebridge plugin for Denon/Marantz AV Receivers series X/SR.
Tested with Denon AVR-X6300H, Denon AVR-X2700H, Denon AVR-3311CI, Marantz SR8012, Marantz SR6013, Marantz M-CR611.
Tested with Denon AVR-3311CI, AVR-X6300H, AVR-X2700H, AVC-X4800H, Marantz SR8012, SR6013, M-CR611, PM7000N.

</span>

Expand Down Expand Up @@ -68,7 +68,7 @@ Tested with Denon AVR-X6300H, Denon AVR-X2700H, Denon AVR-3311CI, Marantz SR8012
| `host` | Here set the *Hostname or Address IP* of AVR. |
| `port` | Here set the API communication port, if `8080` is not working try to use port `80` which some receivers use alternatively. |
| `zoneControl` | Selects which zone will be controlled by this section `0 - Main Zone`, `1 - Zone 2`, `2 - Zone 3`, `3 - Surround Mode`. |
| `supportOldAvr` | This enable support for old AVR like AVR-3311CI. |
| `generation` | Here select generation of Your device, old `0 - AVR-3311CI`, middle `1 - AVR-X6300H`, new `2 - AVC-X4800H`. |
| `getInputsFromDevice` | If enabled, source *Inputs* will be loaded direct from device. |
| `getFavoritesFromDevice` | If enabled, *Favorites* will be loaded to the inputs list if exist. |
| `getQuickSmartSelectFromDevice` | If enabled, *Quick/Smart Select* will be loaded to the inputs list if exist. |
Expand Down
38 changes: 31 additions & 7 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,35 @@
"placeholder": 8080,
"required": true
},
"generation": {
"title": "Generatin",
"type": "integer",
"minimum": 0,
"maximum": 2,
"default": 1,
"description": "Here select generation of Your device.",
"oneOf": [
{
"title": "Old like AVR-3311CI",
"enum": [
0
]
},
{
"title": "Middle like AVR-X6300H",
"enum": [
1
]
},
{
"title": "New like AVC-X4800H",
"enum": [
2
]
}
],
"required": true
},
"zoneControl": {
"title": "Zone/Mode Control",
"type": "integer",
Expand Down Expand Up @@ -4569,13 +4598,6 @@
"description": "This disable logging device connect error.",
"required": false
},
"supportOldAvr": {
"title": "Support old AVR",
"type": "boolean",
"default": false,
"description": "If enabled, old AVR like AVR-3311CI will be supported.",
"required": false
},
"masterPower": {
"title": "Master Power Control",
"type": "boolean",
Expand Down Expand Up @@ -4787,6 +4809,7 @@
"devices[].name",
"devices[].host",
"devices[].port",
"devices[].generation",
"devices[].zoneControl",
{
"key": "devices[]",
Expand Down Expand Up @@ -4903,6 +4926,7 @@
"title": "Device",
"items": [
"devices[].supportOldAvr",
"devices[].supportNewAvr",
"devices[].masterPower",
"devices[].masterVolume",
"devices[].masterMute",
Expand Down
8 changes: 4 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@ class DenonPlatform {
fs.mkdirSync(prefDir);
};

api.on('didFinishLaunching', () => {
api.on('didFinishLaunching', async () => {
for (const device of config.devices) {
if (!device.name || !device.host || !device.port || !(device.zoneControl >= 0 && device.zoneControl <= 3)) {
log.warn(`Name: ${device.name ? 'OK' : device.name}, host: ${device.host ? 'OK' : device.host}, port: ${device.port ? 'OK' : device.port}, zone: ${(device.zoneControl >= 0 && device.zoneControl <= 3) ? 'OK' : device.zoneControl} ,n config wrong or missing.`);
log.warn(`Name: ${device.name ? 'OK' : device.name}, host: ${device.host ? 'OK' : device.host}, port: ${device.port ? 'OK' : device.port}, zone: ${(device.zoneControl >= 0 && device.zoneControl <= 3) ? 'OK' : device.zoneControl} ,in config wrong or missing.`);
return;
}
await new Promise(resolve => setTimeout(resolve, 250))

//debug config
const debug = device.enableDebugMode ? log(`Device: ${device.host} ${device.name}, did finish launching.`) : false;
const debug1 = device.enableDebugMode ? log(`Device: ${device.host} ${device.name}, Config: ${JSON.stringify(device, null, 2)}`) : false;

//denon device
const zone = device.zoneControl;
const denonDevice = new DenonDevice(api, prefDir, zone, device);
const denonDevice = new DenonDevice(api, prefDir, device);
denonDevice.on('publishAccessory', (accessory) => {
api.publishExternalAccessories(CONSTANS.PluginName, [accessory]);
const debug = device.enableDebugMode ? log(`Device: ${device.host} ${device.name}, published as external accessory.`) : false;
Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"displayName": "Denon TV",
"name": "homebridge-denon-tv",
"version": "4.5.13",
"version": "4.6.0",
"description": "Homebridge plugin to control Denon/Marantz AV Receivers.",
"license": "MIT",
"author": "grzegorz914",
Expand Down Expand Up @@ -30,7 +30,7 @@
"dependencies": {
"async-mqtt": "^2.6.3",
"axios": "^1.6.5",
"fast-xml-parser": "^4.3.2",
"fast-xml-parser": "^4.3.3",
"express": "^4.18.2"
},
"keywords": [
Expand Down
7 changes: 4 additions & 3 deletions sample-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"name": "AV Main Zone",
"host": "192.168.1.5",
"port": 8080,
"generation": 1,
"zoneControl": 0,
"supportOldAvr": false,
"getInputsFromDevice": false,
"getFavoritesFromDevice": false,
"getQuickSmartSelectFromDevice": false,
Expand Down Expand Up @@ -92,8 +92,8 @@
"name": "AV Zone 1",
"host": "192.168.1.5",
"port": 8080,
"generation": 1,
"zoneControl": 1,
"supportOldAvr": false,
"getInputsFromDevice": false,
"getFavoritesFromDevice": false,
"getQuickSmartSelectFromDevice": false,
Expand Down Expand Up @@ -153,8 +153,8 @@
"name": "AV Zone 2",
"host": "192.168.1.5",
"port": 8080,
"generation": 1,
"zoneControl": 2,
"supportOldAvr": false,
"getInputsFromDevice": false,
"getFavoritesFromDevice": false,
"getQuickSmartSelectFromDevice": false,
Expand Down Expand Up @@ -214,6 +214,7 @@
"name": "AV Surround Mode",
"host": "192.168.1.5",
"port": 8080,
"generation": 1,
"zoneControl": 3,
"surrounds": [
{
Expand Down
45 changes: 28 additions & 17 deletions src/denon.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';
const fs = require('fs');
const fsPromises = fs.promises;
const https = require('https');
const axios = require('axios');
const EventEmitter = require('events');
const { XMLParser, XMLBuilder, XMLValidator } = require('fast-xml-parser');
Expand All @@ -11,12 +12,12 @@ class DENON extends EventEmitter {
super();
const host = config.host;
const port = config.port;
const generation = config.generation;
const zone = config.zone;
const inputs = config.inputs;
const surrounds = config.surrounds;
const devInfoFile = config.devInfoFile;
const inputsFile = config.inputsFile;
const supportOldAvr = config.supportOldAvr;
const getInputsFromDevice = config.getInputsFromDevice;
const getFavoritesFromDevice = config.getFavoritesFromDevice;
const getQuickSmartSelectFromDevice = config.getQuickSmartSelectFromDevice;
Expand All @@ -25,6 +26,7 @@ class DENON extends EventEmitter {
const refreshInterval = config.refreshInterval;
const restFulEnabled = config.restFulEnabled;
const mqttEnabled = config.mqttEnabled;
const deviceInfoUrl = generation === 0 ? CONSTANS.ApiUrls.MainZone : CONSTANS.ApiUrls.DeviceInfo;

this.inputs = inputs;
this.surrounds = surrounds;
Expand All @@ -36,13 +38,27 @@ class DENON extends EventEmitter {
this.refreshInterval = refreshInterval;

const baseUrl = `http://${host}:${port}`;
this.axiosInstance = axios.create({
this.axiosInstance = generation === 2 ? axios.create({
method: 'GET',
baseURL: baseUrl,
timeout: 10000,
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
}) : axios.create({
method: 'GET',
baseURL: baseUrl,
timeout: 10000
});

this.axiosInstancePost = axios.create({
this.axiosInstancePost = generation === 2 ? axios.create({
method: 'POST',
baseURL: baseUrl,
timeout: 10000,
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
}) : axios.create({
method: 'POST',
baseURL: baseUrl,
timeout: 10000
Expand All @@ -55,7 +71,6 @@ class DENON extends EventEmitter {
};
const parseString = new XMLParser(options);

this.connected = false;
this.startPrepareAccessory = true;
this.emitDeviceInfo = true;
this.power = false;
Expand All @@ -69,10 +84,10 @@ class DENON extends EventEmitter {

this.on('checkDeviceInfo', async () => {
try {
const deviceUrl = supportOldAvr ? CONSTANS.ApiUrls.MainZone : CONSTANS.ApiUrls.DeviceInfo;
const deviceInfo = await this.axiosInstance(deviceUrl);
const parseDeviceInfo = parseString.parse(deviceInfo.data);
const devInfo = supportOldAvr ? parseDeviceInfo.item : parseDeviceInfo.Device_Info;
//get device info
const deviceInfo = await this.axiosInstance(deviceInfoUrl);
const parseData = parseString.parse(deviceInfo.data);
const devInfo = generation === 0 ? parseData.item : parseData.Device_Info;
const debug = debugLog ? this.emit('debug', `Info: ${JSON.stringify(devInfo, null, 2)}`) : false;

//device info
Expand All @@ -87,7 +102,7 @@ class DENON extends EventEmitter {
const manualModelName = deviceInfoKeys.includes('ManualModelName') ? devInfo.ManualModelName : 'Unknown';
const deliveryCode = deviceInfoKeys.includes('DeliveryCode') ? devInfo.DeliveryCode : 0;
const modelName = deviceInfoKeys.includes('ModelName') ? devInfo.ModelName : 'AV Receiver';
const serialNumber = deviceInfoKeys.includes('MacAddress') ? devInfo.MacAddress.toString() : supportOldAvr ? `1234567654321` : false;
const serialNumber = deviceInfoKeys.includes('MacAddress') ? devInfo.MacAddress.toString() : generation === 0 ? `1234567654321` : false;
const firmwareRevision = deviceInfoKeys.includes('UpgradeVersion') ? devInfo.UpgradeVersion.toString() : '00';
const reloadDeviceInfo = deviceInfoKeys.includes('ReloadDeviceInfo') ? devInfo.ReloadDeviceInfo : 0;
const deviceZones = deviceInfoKeys.includes('DeviceZones') ? devInfo.DeviceZones : 1;
Expand Down Expand Up @@ -187,7 +202,7 @@ class DENON extends EventEmitter {
const saveDevInfo = zone === 0 ? await this.saveDevInfo(devInfoFile, devInfo) : false;

//save inputs to the file
await this.saveInputs(inputsFile, devInfo, zone, zoneCapabilities, supportFavorites, supportShortcut, supportInputSource, supportQuickSmartSelect);
await this.saveInputs(inputsFile, devInfo, generation, zone, zoneCapabilities, supportFavorites, supportShortcut, supportInputSource, supportQuickSmartSelect);

//emit device info
const emitDeviceInfo = this.emitDeviceInfo ? this.emit('deviceInfo', manufacturer, modelName, serialNumber, firmwareRevision, deviceZones, apiVersion, supportPictureMode) : false;
Expand Down Expand Up @@ -267,9 +282,6 @@ class DENON extends EventEmitter {
this.pictureMode = pictureMode;
this.soundMode = soundMode;

const emitConnected = !this.connected ? this.emit('message', `Connected.`) : false;
this.connected = true;

//emit state changed
this.emit('stateChanged', power, reference, volume, volumeDisplay, mute, pictureMode);

Expand All @@ -292,7 +304,6 @@ class DENON extends EventEmitter {
.on('disconnect', () => {
this.emit('stateChanged', false, this.reference, this.volume, this.volumeDisplay, this.mute, this.pictureMode);
this.emit('disconnected', 'Disconnected.');
this.connected = false;
this.checkState();
});

Expand Down Expand Up @@ -323,16 +334,16 @@ class DENON extends EventEmitter {
});
};

saveInputs(path, devInfo, zone, zoneCapabilities, supportFavorites, supportShortcut, supportInputSource, supportQuickSmartSelect) {
saveInputs(path, devInfo, generation, zone, zoneCapabilities, supportFavorites, supportShortcut, supportInputSource, supportQuickSmartSelect) {
return new Promise(async (resolve, reject) => {
try {
const referenceConversionKeys = Object.keys(CONSTANS.InputConversion);
const inputsArr = [];
const referencesArray = [];

//old AVR
const inputsReferenceOldAvr = this.supportOldAvr ? devInfo.InputFuncList.value : [];
const inputsNameOldAvr = this.supportOldAvr ? devInfo.RenameSource.value : [];
const inputsReferenceOldAvr = generation === 0 ? devInfo.InputFuncList.value : [];
const inputsNameOldAvr = generation === 0 ? devInfo.RenameSource.value : [];
const inputsReferenceOldAvrCount = inputsReferenceOldAvr.length;
for (let i = 0; i < inputsReferenceOldAvrCount; i++) {
const renamedInput = inputsNameOldAvr[i].trim();
Expand Down
Loading

0 comments on commit b3c4289

Please sign in to comment.