Skip to content

Commit

Permalink
Catch duplicate input errors, check input name for duplicate when cre…
Browse files Browse the repository at this point in the history
…ating inputs
  • Loading branch information
ACDR committed Oct 22, 2020
1 parent e89b16d commit 3fdd87c
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 83 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"license": "UNLICENSED",
"displayName": "Yamaha AVR",
"name": "homebridge-yamaha-avr",
"version": "2.0.2",
"version": "2.0.3",
"description": "homebridge-plugin - Add a Yamaha AVR as a HomeKit Audio Receiver with Power, Input, Volume & Remote Control",
"author": {
"name": "ACDR",
Expand Down
179 changes: 98 additions & 81 deletions src/accessory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,88 +226,99 @@ export class YamahaAVRAccessory {
`);
}

const inputService = this.accessory.addService(
this.platform.Service.InputSource,
this.platform.api.hap.uuid.generate(input.id),
input.name,
);

inputService
.setCharacteristic(this.platform.Characteristic.Identifier, i)
.setCharacteristic(this.platform.Characteristic.Name, input.name)
.setCharacteristic(this.platform.Characteristic.IsConfigured, this.platform.Characteristic.IsConfigured.CONFIGURED)
.setCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.platform.Characteristic.CurrentVisibilityState.SHOWN)
.setCharacteristic(this.platform.Characteristic.InputSourceType, this.platform.Characteristic.InputSourceType.APPLICATION)
.setCharacteristic(this.platform.Characteristic.InputDeviceType, this.platform.Characteristic.InputDeviceType.TV);

inputService.getCharacteristic(this.platform.Characteristic.ConfiguredName)
.on('set', (name, callback) => {
this.platform.log.debug(`Set input (${input.id}) name to ${name}`);
inputService.updateCharacteristic(this.platform.Characteristic.ConfiguredName, name);

if (cachedService?.ConfiguredName !== name) {
storage.setItem(`input_${i}`, {
ConfiguredName: name,
CurrentVisibilityState: inputService.getCharacteristic(this.platform.Characteristic.CurrentVisibilityState).value,
});
try {
const inputService = this.accessory.addService(
this.platform.Service.InputSource,
this.platform.api.hap.uuid.generate(input.id),
input.name,
);

inputService
.setCharacteristic(this.platform.Characteristic.Identifier, i)
.setCharacteristic(this.platform.Characteristic.Name, input.name)
.setCharacteristic(this.platform.Characteristic.IsConfigured, this.platform.Characteristic.IsConfigured.CONFIGURED)
.setCharacteristic(
this.platform.Characteristic.CurrentVisibilityState,
this.platform.Characteristic.CurrentVisibilityState.SHOWN,
)
.setCharacteristic(this.platform.Characteristic.InputSourceType, this.platform.Characteristic.InputSourceType.APPLICATION)
.setCharacteristic(this.platform.Characteristic.InputDeviceType, this.platform.Characteristic.InputDeviceType.TV);

inputService.getCharacteristic(this.platform.Characteristic.ConfiguredName)
.on('set', (name, callback) => {
this.platform.log.debug(`Set input (${input.id}) name to ${name}`);
inputService.updateCharacteristic(this.platform.Characteristic.ConfiguredName, name);

if (cachedService?.ConfiguredName !== name) {
storage.setItem(`input_${i}`, {
ConfiguredName: name,
CurrentVisibilityState: inputService.getCharacteristic(this.platform.Characteristic.CurrentVisibilityState).value,
});
}

callback(null);
});

inputService.getCharacteristic(this.platform.Characteristic.TargetVisibilityState)
.on('set', (targetVisibilityState, callback) => {
this.platform.log.debug(`
Set input (${input.id}) visibility state to
${targetVisibilityState === this.platform.Characteristic.TargetVisibilityState.HIDDEN ? 'HIDDEN' : 'SHOWN'}
`);
inputService.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, targetVisibilityState);

if (cachedService?.CurrentVisibilityState !== targetVisibilityState) {
storage.setItem(`input_${i}`, {
ConfiguredName: inputService.getCharacteristic(this.platform.Characteristic.ConfiguredName).value,
CurrentVisibilityState: targetVisibilityState,
});
}

callback(null);
});

inputService.getCharacteristic(this.platform.Characteristic.Name)
.on('get', callback => callback(null, input.name));

if (cachedService) {
if (this.platform.Characteristic.CurrentVisibilityState.SHOWN !== cachedService.CurrentVisibilityState) {
this.platform.log.debug(`Restoring input ${input.id} visibility state from cache`);
inputService
.setCharacteristic(this.platform.Characteristic.CurrentVisibilityState, cachedService.CurrentVisibilityState);
}

callback(null);
});

inputService.getCharacteristic(this.platform.Characteristic.TargetVisibilityState)
.on('set', (targetVisibilityState, callback) => {
this.platform.log.debug(`
Set input (${input.id}) visibility state to
${targetVisibilityState === this.platform.Characteristic.TargetVisibilityState.HIDDEN ? 'HIDDEN' : 'SHOWN'}
`);
inputService.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, targetVisibilityState);

if (cachedService?.CurrentVisibilityState !== targetVisibilityState) {
storage.setItem(`input_${i}`, {
ConfiguredName: inputService.getCharacteristic(this.platform.Characteristic.ConfiguredName).value,
CurrentVisibilityState: targetVisibilityState,
});
if (input.name !== cachedService.ConfiguredName) {
this.platform.log.debug(`Restoring input ${input.id} configured name from cache`);
inputService
.setCharacteristic(this.platform.Characteristic.ConfiguredName, cachedService.ConfiguredName);
}

callback(null);
});

inputService.getCharacteristic(this.platform.Characteristic.Name)
.on('get', callback => callback(null, input.name));

if (cachedService) {
if (this.platform.Characteristic.CurrentVisibilityState.SHOWN !== cachedService.CurrentVisibilityState) {
this.platform.log.debug(`Restoring input ${input.id} visibility state from cache`);
inputService
.setCharacteristic(this.platform.Characteristic.CurrentVisibilityState, cachedService.CurrentVisibilityState);
}

if (input.name !== cachedService.ConfiguredName) {
this.platform.log.debug(`Restoring input ${input.id} configured name from cache`);
inputService
.setCharacteristic(this.platform.Characteristic.ConfiguredName, cachedService.ConfiguredName);
}
}

this.service.addLinkedService(inputService);
this.inputServices.push(inputService);
this.service.addLinkedService(inputService);
this.inputServices.push(inputService);

try {
// Cache Data
await storage.setItem(`input_${i}`, {
ConfiguredName: inputService.getCharacteristic(this.platform.Characteristic.ConfiguredName).value,
CurrentVisibilityState: inputService.getCharacteristic(this.platform.Characteristic.CurrentVisibilityState).value,
});
try {
// Cache Data
await storage.setItem(`input_${i}`, {
ConfiguredName: inputService.getCharacteristic(this.platform.Characteristic.ConfiguredName).value,
CurrentVisibilityState: inputService.getCharacteristic(this.platform.Characteristic.CurrentVisibilityState).value,
});

if (this.inputServices.length === this.state.inputs.length) {
resolve();
if (this.inputServices.length === this.state.inputs.length) {
resolve();
}
} catch (err) {
reject(`
Could not write to cache.
Please check your Homebridge instance has permission to write to
"${this.platform.config.cacheDirectory || '../.node-persist'}"
or set a different cache directory using the "cacheDirectory" config property.
`);
}
} catch (err) {
reject(`
Could not write to cache.
Please check your Homebridge instance has permission to write to "${this.platform.config.cacheDirectory || '../.node-persist'}"
or set a different cache directory using the "cacheDirectory" config property.
this.platform.log.error(`
Failed to add input service ${input.name}:
${err}
`);
}
});
Expand All @@ -334,6 +345,11 @@ export class YamahaAVRAccessory {
this.state.inputs = [];

features.forEach((feature, i) => {
if (this.state.inputs.find(input => input.id === feature.replace('_', ' ') || input.name === feature.replace('_', ' '))) {
// Input already exists
return;
}

this.state.inputs.push({
id: feature.replace('_', ' '),
name: feature.replace('_', ' '),
Expand All @@ -348,21 +364,22 @@ export class YamahaAVRAccessory {
// check if the property/key is defined in the object itself, not in parent
if (availableInputs[0].hasOwnProperty(key)) { // eslint-disable-line
let id = String(key).replace('_', '');
const name = availableInputs[0][key][0];

if (key.includes('MusicCast_Link') || key.includes('NET_RADIO')) {
id = String(key).replace('_', ' ');
}

const input: Input = {
if (this.state.inputs.find(input => input.id === id || input.name === name)) {
// Input already exists
return;
}

this.state.inputs.push({
id,
name: availableInputs[0][key][0],
name,
index: i,
};

if (!this.state.inputs.find(input => input.id === id)) {
// add input only if it is not already in inputs
this.state.inputs.push(input);
}
});

i++;
}
Expand Down

0 comments on commit 3fdd87c

Please sign in to comment.