homebridge-philips-hue-sync-box
Version:
Homebridge plugin for the Philips Hue Sync Box.
277 lines • 12.5 kB
JavaScript
import { SyncBoxDevice } from './base.js';
import { PASSTHROUGH, POWER_SAVE } from '../lib/constants.js';
export class BaseTvDevice extends SyncBoxDevice {
platform;
accessory;
state;
primaryAccessory;
lightbulbService;
inputServices = [];
mainAccessory;
intensityToNumber = new Map([
['subtle', 1],
['moderate', 2],
['high', 3],
['intense', 4],
]);
numberToIntensity = new Map([
[1, 'subtle'],
[2, 'moderate'],
[3, 'high'],
[4, 'intense'],
]);
modeToNumber = new Map([
['video', 1],
['music', 2],
['game', 3],
['passthrough', 4],
['powersave', 5],
]);
numberToMode = new Map([
[1, 'video'],
[2, 'music'],
[3, 'game'],
[4, 'passthrough'],
[5, 'powersave'],
]);
constructor(platform, accessory, state, primaryAccessory) {
super(platform, accessory, state);
this.platform = platform;
this.accessory = accessory;
this.state = state;
this.primaryAccessory = primaryAccessory;
this.mainAccessory = primaryAccessory;
this.createInputServices();
this.createLightbulbService();
this.service.setCharacteristic(this.platform.api.hap.Characteristic.SleepDiscoveryMode, this.platform.api.hap.Characteristic.SleepDiscoveryMode
.ALWAYS_DISCOVERABLE);
this.service
.getCharacteristic(this.platform.api.hap.Characteristic.RemoteKey)
.onSet(this.handleRemoteButton.bind(this));
let name;
if (this.platform.config[this.getConfiguredNamePropertyName()]) {
name = this.platform.config[this.getConfiguredNamePropertyName()];
}
else if (this.mainAccessory?.context[this.getConfiguredNamePropertyName()]) {
name = this.mainAccessory?.context[this.getConfiguredNamePropertyName()];
}
else {
name = this.state.device.name;
}
this.service
.getCharacteristic(this.platform.api.hap.Characteristic.ConfiguredName)
.onSet(this.handleConfiguredNameChange.bind(this));
this.service.updateCharacteristic(this.platform.api.hap.Characteristic.ConfiguredName, name);
}
handleConfiguredNameChange(value) {
if (this.platform.config[this.getConfiguredNamePropertyName()]) {
this.platform.log.warn(this.getConfiguredNamePropertyName() +
' is set in the config, therefore it cannot be changed by HomeKit.' +
' Please change it in the Homebridge config. Alternatively remove the' +
' config and manually configure in HomeKit (not recommended).');
return;
}
this.platform.log.debug(this.getConfiguredNamePropertyName() + ' name changed to ' + value);
if (this.mainAccessory) {
this.mainAccessory.context[this.getConfiguredNamePropertyName()] = value;
}
}
shouldBeOn() {
return this.state.execution.mode !== POWER_SAVE;
}
createLightbulbService() {
if (!this.isLightbulbEnabled()) {
return;
}
this.lightbulbService =
this.accessory.getService(this.platform.api.hap.Service.Lightbulb) ||
this.accessory.addService(this.platform.api.hap.Service.Lightbulb);
// Stores the light bulb service
// Subscribes for changes of the on characteristic
this.lightbulbService
.getCharacteristic(this.platform.api.hap.Characteristic.On)
.onSet(this.setOnLightbulb.bind(this));
// Subscribes for changes of the brightness characteristic
this.lightbulbService
.getCharacteristic(this.platform.api.hap.Characteristic.Brightness)
.onSet(this.setBrightness.bind(this));
}
setOnLightbulb(value) {
if (!this.lightbulbService) {
return;
}
this.platform.log.debug('Set On ->', value);
const currentVal = this.lightbulbService.getCharacteristic(this.platform.api.hap.Characteristic.On).value;
return this.updateMode(currentVal, value);
}
getServiceType() {
return this.platform.api.hap.Service.Television;
}
handleRemoteButton(value) {
this.platform.log.debug('Remote key pressed: ' + value);
let mode;
switch (value) {
case this.platform.api.hap.Characteristic.RemoteKey.ARROW_UP:
this.platform.log.debug('Increase brightness by 25%');
this.updateExecution({
brightness: Math.min(200, this.state.execution.brightness + 50),
});
break;
case this.platform.api.hap.Characteristic.RemoteKey.ARROW_DOWN:
this.platform.log.debug('Decrease brightness by 25%');
this.updateExecution({
brightness: Math.max(0, this.state.execution.brightness - 50),
});
break;
case this.platform.api.hap.Characteristic.RemoteKey.ARROW_LEFT: {
// Gets the current mode or the last sync mode to set the intensity
mode = this.getMode();
this.platform.log.debug('Toggle intensity');
if (!this.state.execution[mode]) {
this.platform.log.debug('Current mode ' + mode + ' does not have an intensity to update');
break;
}
const currentIntensity = this.state.execution[mode].intensity;
const nextLowestIntensity = (this.intensityToNumber.get(currentIntensity) ?? 4) - 1;
if (nextLowestIntensity < 1) {
break;
}
const nextIntensity = this.numberToIntensity.get(nextLowestIntensity);
const body = {};
body[mode] = {
intensity: nextIntensity,
};
this.updateExecution(body);
break;
}
case this.platform.api.hap.Characteristic.RemoteKey.ARROW_RIGHT: {
// Gets the current mode or the last sync mode to set the intensity
mode = this.getMode();
this.platform.log.debug('Toggle intensity');
if (!this.state.execution[mode]) {
this.platform.log.debug('Current mode ' + mode + ' does not have an intensity to update');
break;
}
const currentIntensity = this.state.execution[mode].intensity;
const nextHighestIntensity = (this.intensityToNumber.get(currentIntensity) ?? 1) + 1;
if (nextHighestIntensity > 4) {
break;
}
const nextIntensity = this.numberToIntensity.get(nextHighestIntensity);
const body = {};
body[mode] = {
intensity: nextIntensity,
};
this.updateExecution(body);
break;
}
case this.platform.api.hap.Characteristic.RemoteKey.SELECT: {
this.platform.log.debug('Toggle mode');
const currentMode = this.state.execution.mode;
const nextMode = ((this.modeToNumber.get(currentMode) ?? 4) % 4) + 1;
this.updateExecution({
mode: this.numberToMode.get(nextMode),
});
break;
}
case this.platform.api.hap.Characteristic.RemoteKey.PLAY_PAUSE:
this.platform.log.debug('Toggle switch state');
if (this.state.execution.mode !== POWER_SAVE &&
this.state.execution.mode !== PASSTHROUGH) {
this.updateExecution({
mode: this.platform.config.defaultOffMode,
});
}
else {
let onMode = this.platform.config.defaultOnMode;
if (onMode === 'lastSyncMode') {
onMode = this?.state?.execution?.lastSyncMode ?? 'video';
}
this.updateExecution({
mode: onMode,
});
}
break;
case this.platform.api.hap.Characteristic.RemoteKey.INFORMATION: {
this.platform.log.debug('Toggle hdmi source');
const hdmiSource = this.state.execution.hdmiSource;
const currentSourcePosition = parseInt(hdmiSource.replace('input', ''));
const nextSourcePosition = (currentSourcePosition % 4) + 1;
this.updateExecution({
hdmiSource: 'input' + nextSourcePosition,
});
break;
}
}
}
updateSources(services) {
// Handles showing/hiding of sources
for (const service of services) {
service
.getCharacteristic(this.platform.api.hap.Characteristic.TargetVisibilityState)
.onSet(this.setVisibility(service));
}
}
update(state) {
super.update(state);
if (!state) {
this.setLightbulbUnresponsive();
return;
}
this.updateTv();
this.updateLightbulb();
}
updateLightbulb() {
if (!this.lightbulbService) {
return;
}
this.platform.log.debug('Updated state to ' + this.state.execution.mode);
this.lightbulbService.updateCharacteristic(this.platform.api.hap.Characteristic.On, this.state.execution.mode !== POWER_SAVE &&
this.state.execution.mode !== PASSTHROUGH);
this.platform.log.debug('Updated brightness to ' + this.state.execution.brightness);
this.lightbulbService.updateCharacteristic(this.platform.api.hap.Characteristic.Brightness, Math.round((this.state.execution.brightness / 200.0) * 100));
}
setLightbulbUnresponsive() {
if (!this.lightbulbService) {
return;
}
this.platform.log.debug('Updated state to ' + this.state.execution.mode);
this.lightbulbService.updateCharacteristic(this.platform.api.hap.Characteristic.On, new this.platform.api.hap.HapStatusError(-70402 /* HAPStatus.SERVICE_COMMUNICATION_FAILURE */));
}
getInputService(name, position) {
if (!name) {
throw new Error('Name is required');
}
const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
this.platform.log.debug('Creating input service for ' + capitalizedName);
const inputService = this.accessory.getServiceById(this.platform.api.hap.Service.InputSource, position) ||
this.accessory.addService(this.platform.api.hap.Service.InputSource, position.toLowerCase().replace(' ', ''), position);
// Sets the TV name
inputService
.setCharacteristic(this.platform.api.hap.Characteristic.ConfiguredName, capitalizedName)
.setCharacteristic(this.platform.api.hap.Characteristic.IsConfigured, this.platform.api.hap.Characteristic.IsConfigured.CONFIGURED)
.setCharacteristic(this.platform.api.hap.Characteristic.CurrentVisibilityState, this.platform.api.hap.Characteristic.CurrentVisibilityState.SHOWN)
.setCharacteristic(this.platform.api.hap.Characteristic.TargetVisibilityState, this.platform.api.hap.Characteristic.TargetVisibilityState.SHOWN);
inputService
.setCharacteristic(this.platform.api.hap.Characteristic.Identifier, position[position.length - 1])
.setCharacteristic(this.platform.api.hap.Characteristic.InputSourceType, this.platform.api.hap.Characteristic.InputSourceType.HDMI);
return inputService;
}
setVisibility(service) {
return (value) => {
service.setCharacteristic(this.platform.api.hap.Characteristic.CurrentVisibilityState, value);
};
}
getMode() {
let mode = 'video';
if (this.state.execution.mode !== POWER_SAVE &&
this.state.execution.mode !== PASSTHROUGH) {
mode = this.state.execution.mode;
}
else if (this.state.execution.lastSyncMode) {
mode = this.state.execution.lastSyncMode;
}
return mode;
}
}
//# sourceMappingURL=baseTv.js.map