homebridge-virtual-accessories
Version:
Virtual HomeKit accessories for Homebridge.
230 lines • 10.4 kB
JavaScript
import { ExternalAccessory } from './externalAccessory.js';
import { InputSource } from './virtualAccessoryInputSource.js';
/**
* Television - Accessory implementation
*/
export class Television extends ExternalAccessory {
static ACCESSORY_TYPE_NAME = 'Television';
static INACTIVE = 0; // Characteristic.Active.INACTIVE
static ACTIVE = 1; // Characteristic.Active.ACTIVE
static NOT_DISCOVERABLE = 0; // Characteristic.SleepDiscoveryMode.NOT_DISCOVERABLE
static ALWAYS_DISCOVERABLE = 1; // Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE
static REWIND = 0; // Characteristic.RemoteKey.REWIND
static FAST_FORWARD = 1; // Characteristic.RemoteKey.FAST_FORWARD
static NEXT_TRACK = 2; // Characteristic.RemoteKey.NEXT_TRACK
static PREVIOUS_TRACK = 3; // Characteristic.RemoteKey.PREVIOUS_TRACK
static ARROW_UP = 4; // Characteristic.RemoteKey.ARROW_UP
static ARROW_DOWN = 5; // Characteristic.RemoteKey.ARROW_DOWN
static ARROW_LEFT = 6; // Characteristic.RemoteKey.ARROW_LEFT
static ARROW_RIGHT = 7; // Characteristic.RemoteKey.ARROW_RIGHT
static SELECT = 8; // Characteristic.RemoteKey.SELECT
static BACK = 9; // Characteristic.RemoteKey.BACK
static EXIT = 10; // Characteristic.RemoteKey.EXIT
static PLAY_PAUSE = 11; // Characteristic.RemoteKey.PLAY_PAUSE
static INFORMATION = 15; // Characteristic.RemoteKey.INFORMATION
stateStorageKey = 'TelevisionState';
inputActiveIdStorageKey = 'TelevisionInputActiveId';
configuredNameStorageKey = 'TelevisionConfiguredName';
inputSources = [];
states = {
TelevisionState: Television.INACTIVE,
TelevisionInputActiveId: 0,
TelevisionConfiguredName: '',
TelevisionSleepDiscoveryMode: Television.ALWAYS_DISCOVERABLE,
};
constructor(platform, accessory, accessoryConfiguration) {
super(platform, accessory, accessoryConfiguration);
this.states.TelevisionConfiguredName = this.accessoryConfiguration.accessoryName;
// If the accessory is stateful retrieve stored state
if (this.accessoryConfiguration.accessoryIsStateful) {
const accessoryState = this.loadAccessoryState(this.storagePath);
const cachedState = accessoryState[this.stateStorageKey];
const cachedInputActiveId = accessoryState[this.inputActiveIdStorageKey];
const cachedConfiguredName = accessoryState[this.configuredNameStorageKey];
if (cachedState !== undefined) {
this.states.TelevisionState = cachedState;
}
if (cachedInputActiveId !== undefined) {
this.states.TelevisionInputActiveId = cachedInputActiveId;
}
if (cachedConfiguredName !== undefined) {
this.states.TelevisionConfiguredName = cachedConfiguredName;
}
}
// set accessory information
this.service = this.accessory.getService(this.platform.Service.Television) || this.accessory.addService(this.platform.Service.Television);
this.service.setCharacteristic(this.platform.Characteristic.Name, this.accessoryConfiguration.accessoryName);
// register handlers
this.service.getCharacteristic(this.platform.Characteristic.Active)
.onSet(this.setActive.bind(this))
.onGet(this.getActive.bind(this));
this.service.getCharacteristic(this.platform.Characteristic.ActiveIdentifier)
.onSet(this.setActiveIdentifier.bind(this))
.onGet(this.getActiveIdentifier.bind(this));
this.service.getCharacteristic(this.platform.Characteristic.ConfiguredName)
.onSet(this.setConfiguredName.bind(this))
.onGet(this.getConfiguredName.bind(this));
this.service.getCharacteristic(this.platform.Characteristic.RemoteKey)
.onSet(this.setRemoteKey.bind(this));
this.service.getCharacteristic(this.platform.Characteristic.SleepDiscoveryMode)
.onGet(this.getSleepDiscoveryMode.bind(this));
/**
* Creating multiple services of the same type.
*
* To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
* when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
* this.accessory.getService('NAME') || this.accessory.addService(this.platform.Service.Lightbulb, 'NAME', 'USER_DEFINED_SUBTYPE_ID');
*
* The USER_DEFINED_SUBTYPE must be unique to the platform accessory (if you platform exposes multiple accessories, each accessory
* can use the same subtype id.)
*/
this.accessoryConfiguration.television.getInputSources().forEach(inputSourceConfig => {
// Enrich configuration with "inputSource" settings
const tempHolder = this.accessoryConfiguration.inputSource;
this.accessoryConfiguration.inputSource = inputSourceConfig;
const inputSource = new InputSource(this.platform, this.accessory, this.accessoryConfiguration);
this.accessory.getService(this.platform.Service.Television).addLinkedService(inputSource.service);
// Remove configuration enrichments
this.accessoryConfiguration.inputSource = tempHolder;
this.inputSources.push(inputSource);
});
}
// Handlers
async setActive(value) {
this.states.TelevisionState = value;
this.storeState();
this.log.info(`[${this.accessoryConfiguration.accessoryName}] Setting State: ${Television.getStateName(this.states.TelevisionState)}`);
}
async getActive() {
const televisionState = this.states.TelevisionState;
this.log.debug(`[${this.accessoryConfiguration.accessoryName}] Getting State: ${Television.getStateName(televisionState)}`);
return televisionState;
}
async setActiveIdentifier(value) {
this.states.TelevisionInputActiveId = value;
this.log.info(`[${this.accessoryConfiguration.accessoryName}] Setting Input Active Identifier: ${this.states.TelevisionInputActiveId}`);
}
async getActiveIdentifier() {
const inputActiveId = this.states.TelevisionInputActiveId;
this.log.debug(`[${this.accessoryConfiguration.accessoryName}] Getting Input Active Identifier: ${inputActiveId}`);
return inputActiveId;
}
async setConfiguredName(value) {
this.states.TelevisionConfiguredName = value;
this.storeState();
this.log.info(`[${this.accessoryConfiguration.accessoryName}] Setting Configured Name: ${this.states.TelevisionConfiguredName}`);
}
async getConfiguredName() {
const televisionConfiguredName = this.states.TelevisionConfiguredName;
this.log.debug(`[${this.accessoryConfiguration.accessoryName}] Getting Configured Name: ${televisionConfiguredName}`);
return televisionConfiguredName;
}
async setRemoteKey(value) {
const remoteKey = value;
this.log.debug(`[${this.accessoryConfiguration.accessoryName}] Setting Remote Key: ${Television.getKeyName(remoteKey)}`);
}
async getSleepDiscoveryMode() {
const sleepDiscoveryMode = this.states.TelevisionSleepDiscoveryMode;
this.log.debug(`[${this.accessoryConfiguration.accessoryName}] Getting Sleep Discovery Mode: ${sleepDiscoveryMode}`);
return sleepDiscoveryMode;
}
getJsonState() {
const jsonState = {
[this.stateStorageKey]: this.states.TelevisionState,
[this.inputActiveIdStorageKey]: this.states.TelevisionInputActiveId,
[this.configuredNameStorageKey]: this.states.TelevisionConfiguredName,
};
const json = JSON.stringify(jsonState);
return json;
}
getAccessoryTypeName() {
return Television.ACCESSORY_TYPE_NAME;
}
static getStateName(state) {
let stateName;
switch (state) {
case undefined: {
stateName = 'undefined';
break;
}
case Television.INACTIVE: {
stateName = 'INACTIVE';
break;
}
case Television.ACTIVE: {
stateName = 'ACTIVE';
break;
}
default: {
stateName = state.toString();
}
}
return stateName;
}
static getKeyName(state) {
let stateName;
switch (state) {
case undefined: {
stateName = 'undefined';
break;
}
case Television.REWIND: {
stateName = 'REWIND';
break;
}
case Television.FAST_FORWARD: {
stateName = 'FAST FORWARD';
break;
}
case Television.NEXT_TRACK: {
stateName = 'NEXT TRACK';
break;
}
case Television.PREVIOUS_TRACK: {
stateName = 'PREVIOUS TRACK';
break;
}
case Television.ARROW_UP: {
stateName = 'ARROW UP';
break;
}
case Television.ARROW_DOWN: {
stateName = 'ARROW DOWN';
break;
}
case Television.ARROW_LEFT: {
stateName = 'ARROW LEFT';
break;
}
case Television.ARROW_RIGHT: {
stateName = 'ARROW RIGHT';
break;
}
case Television.SELECT: {
stateName = 'SELECT';
break;
}
case Television.BACK: {
stateName = 'BACK';
break;
}
case Television.EXIT: {
stateName = 'EXIT';
break;
}
case Television.PLAY_PAUSE: {
stateName = 'PLAY PAUSE';
break;
}
case Television.INFORMATION: {
stateName = 'INFORMATION';
break;
}
default: {
stateName = state.toString();
}
}
return stateName;
}
}
//# sourceMappingURL=virtualAccessoryTelevision.js.map