homebridge-denon-v3
Version:
Denon and Marantz AVR support for Homebridge: https://github.com/nfarina/homebridge
194 lines • 9.72 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DenonMarantzAVRAccessory = void 0;
const types_js_1 = require("./types.js");
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
class DenonMarantzAVRAccessory {
constructor(log, platform, accessory, zone, controller) {
this.platform = platform;
this.accessory = accessory;
this.controller = controller;
this.inputServices = [];
this.state = {
isPlaying: true,
inputs: [],
connectionError: false,
};
this.log = log;
// set the AVR accessory information
this.accessory
.getService(this.platform.Service.AccessoryInformation)
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Denon/Marantz');
this.log.info("adding television service");
this.service = this.accessory.getService(this.platform.Service.Television) || this.accessory.addService(this.platform.Service.Television);
this.zone = zone;
this.init();
// regularly ping the AVR to keep power/input state syncronised
setInterval(this.updateAVRState.bind(this), 60000);
}
async init() {
try {
await this.updateInputSources();
await this.createTVService();
await this.createTVSpeakerService();
await this.createInputSourceServices();
}
catch (err) {
this.platform.log.error(err);
}
}
async updateInputSources() {
let inputs = this.accessory.context.device.availableInputs || types_js_1.INPUTS;
inputs.forEach((input) => { this.state.inputs.push(input); });
}
async createTVService() {
// Set Television Service Name & Discovery Mode
this.log.info("display name is ", this.accessory.context.device.display);
this.service
.setCharacteristic(this.platform.Characteristic.Name, this.accessory.context.device.displayName)
// .setCharacteristic(this.platform.Characteristic.ConfiguredName, this.accessory.context.device.displayName)
.setCharacteristic(this.platform.Characteristic.SleepDiscoveryMode, this.platform.Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE);
// Power State Get/Set
this.service
.getCharacteristic(this.platform.Characteristic.Active)
.onSet(this.setPowerState.bind(this))
.onGet(this.getPowerState.bind(this));
// Input Source Get/Set
this.service
.getCharacteristic(this.platform.Characteristic.ActiveIdentifier)
.onSet(this.setInputState.bind(this))
.onGet(this.getInputState.bind(this));
// Remote Key Set
this.service.getCharacteristic(this.platform.Characteristic.RemoteKey).onSet(this.setRemoteKey.bind(this));
return;
}
async createTVSpeakerService() {
this.log.info("adding television speaker service");
const speakerService = this.accessory.getService(this.platform.Service.TelevisionSpeaker) || this.accessory.addService(this.platform.Service.TelevisionSpeaker);
speakerService
.setCharacteristic(this.platform.Characteristic.Name, `${this.accessory.context.device.displayName} Speaker`)
.setCharacteristic(this.platform.Characteristic.Active, this.platform.Characteristic.Active.ACTIVE)
.setCharacteristic(this.platform.Characteristic.VolumeControlType, this.platform.Characteristic.VolumeControlType.ABSOLUTE);
speakerService.getCharacteristic(this.platform.Characteristic.Mute).onGet(this.getMute.bind(this)).onSet(this.setMute.bind(this));
// handle volume control
speakerService.getCharacteristic(this.platform.Characteristic.Volume).onGet(this.getVolume.bind(this)).onSet(this.setVolume.bind(this));
speakerService.getCharacteristic(this.platform.Characteristic.VolumeSelector).onSet(this.setVolumeSelector.bind(this));
return;
}
async createInputSourceServices() {
this.state.inputs.forEach(async (input, i) => {
try {
this.log.info(`adding television input service with name ${input} `);
const inputService = this.accessory.getServiceById(this.platform.Service.InputSource, input) || this.accessory.addService(this.platform.Service.InputSource, input, input);
inputService
.setCharacteristic(this.platform.Characteristic.Identifier, i)
.setCharacteristic(this.platform.Characteristic.ConfiguredName, input)
.setCharacteristic(this.platform.Characteristic.Name, `${this.accessory.context.device.displayName} input ${input}`)
.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);
this.service.addLinkedService(inputService);
this.inputServices.push(inputService);
}
catch (err) {
this.platform.log.error(`
Failed to add input service ${input}:
${err}
`);
}
});
}
async setRemoteKey(remoteKey) {
try {
this.log.info("trying to set key", remoteKey);
}
catch (error) {
this.platform.log.error(error.message);
}
}
async updateAVRState() {
try {
await this.controller.refresh();
let power = this.controller.GetPowerState(this.zone);
let source = this.controller.GetInputSource(this.zone);
this.platform.log.debug(`AVR PING`, { power: power, input: source });
this.service.updateCharacteristic(this.platform.Characteristic.Active, power);
this.service.updateCharacteristic(this.platform.Characteristic.ActiveIdentifier, this.state.inputs.findIndex((input) => input === source));
if (this.state.connectionError) {
this.state.connectionError = false;
this.platform.log.info(`Communication with Yamaha AVR at ${this.platform.config.ip} restored`);
}
}
catch (error) {
if (this.state.connectionError) {
return;
}
this.state.connectionError = true;
this.platform.log.error(`
Cannot communicate with Yamaha AVR at ${this.platform.config.ip}.
Connection will be restored automatically when the AVR begins responding.
`);
}
}
async getPowerState() {
this.log.info(`Get power state ${this.controller.ipaddress} zone ${this.zone} power ${this.controller.GetPowerState(this.zone)} `);
return this.controller.GetPowerState(this.zone);
}
async setPowerState(state) {
await this.controller.SetPowerState(this.zone, state);
if (state && this.zone === 'main') {
this.log.info(`setting default values input:${this.accessory.context.device.defaultInput} volume:${this.accessory.context.device.defaultVolume}`);
await sleep(5000); // sleep needed between powwer on otherwise volume set to 0
this.setInputState(this.accessory.context.device.defaultInput);
await sleep(1000);
this.setVolume(this.accessory.context.device.defaultVolume);
}
}
async getMute() {
this.log.info(`Get mute state ${this.controller.GetMuteState(this.zone)} `);
return this.controller.GetMuteState(this.zone);
}
async setMute(state) {
await this.controller.SetMuteSate(this.zone, state);
}
async setVolumeSelector(direction) {
try {
const currentVolume = this.controller.GetVolume(this.zone);
const volumeStep = 5;
if (direction === this.platform.Characteristic.VolumeSelector.INCREMENT) {
this.platform.log.info('Volume Up', currentVolume + volumeStep);
await this.controller.SetVolume(this.zone, currentVolume + volumeStep);
}
else {
this.platform.log.info('Volume Down', currentVolume - volumeStep);
await this.controller.SetVolume(this.zone, currentVolume - volumeStep);
}
}
catch (error) {
this.platform.log.error(error.message);
}
}
async setVolume(value) {
await this.controller.SetVolume(this.zone, value);
}
async getVolume() {
return this.controller.GetVolume(this.zone);
}
async getInputState() {
this.log.info(`Get input state ${this.controller.GetInputSource(this.zone)} `);
let source = this.controller.GetInputSource(this.zone);
return this.state.inputs.findIndex((input) => input === source);
}
async setInputState(inputIndex) {
try {
const setInputResponse = await this.controller.SetInputSource(this.zone, this.state.inputs[inputIndex]);
this.platform.log.info(`Set input: ${this.state.inputs[inputIndex]}`);
}
catch (error) {
this.platform.log.error(error.message);
}
}
}
exports.DenonMarantzAVRAccessory = DenonMarantzAVRAccessory;
//# sourceMappingURL=accessory.js.map