UNPKG

homebridge-skyq-tvremote

Version:

Exposes and Sky Q Box as a TV Accessory in HomeBridge, allow you to use the Remote UI in Control Centre

250 lines 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SkyTVPlugin = void 0; const settings_1 = require("./settings"); const SkyRemote = require("sky-remote"); const SkyQCheck = require("sky-q"); class SkyTVPlugin { constructor(log, config, api) { this.names = []; this.getActive = async (boxCheck) => { return new Promise((resolve, reject) => { boxCheck.getPowerState().then(isOn => { if (isOn) { resolve(this.api.hap.Characteristic.Active.ACTIVE); } else { resolve(this.api.hap.Characteristic.Active.INACTIVE); } }).catch(error => { this.log.error(error); reject(error); }); }); }; this.send = async (remoteControl, command) => { try { remoteControl.press(command); } catch (error) { this.log.error(error); return Promise.reject(error); } }; this.log = log; this.api = api; if (config.devices) { config.devices.forEach((deviceConfig, key) => { deviceConfig = this.prepareDeviceConfig(key, deviceConfig); this.publishExternalAccessory(deviceConfig); this.names = []; }); } else { const deviceConfig = this.prepareDeviceConfig(null, config); this.publishExternalAccessory(deviceConfig); } log.info('Sky TV platform finished initializing!'); } prepareDeviceConfig(key, config) { if (!config.name) { if (key === null) { config.name = 'TV'; } else { config.name = `TV ${key + 1}`; if (this.names.includes(config.name)) { this.log.error(`Duplicate name at device ${key + 1}.`); } } } if (!config.ipAddress) { if (key === null) { if (!config.ipAddress) { this.log.error('IP address not set.'); } } else { if (!config.ipAddress) { this.log.error(`IP address not set at device ${key + 1}.`); } } } return config; } publishExternalAccessory(config) { if (!config.name) { return; } if (!config.ipAddress) { return; } const remoteControl = new SkyRemote(config.ipAddress); const boxCheck = new SkyQCheck({ ip: config.ipAddress }); // Generate a UUID const uuid = this.api.hap.uuid.generate(`homebridge:${settings_1.PLUGIN_NAME}:` + config.ipAddress); // Create the accessory const accessory = new this.api.platformAccessory(config.name, uuid); // Set the accessory category accessory.category = 35 /* TV_SET_TOP_BOX */; // Add the accessory information service const accessoryInfoService = accessory.getService(this.api.hap.Service.AccessoryInformation); accessoryInfoService.setCharacteristic(this.api.hap.Characteristic.Manufacturer, 'Sky'); boxCheck._getSystemInformation({}).then(info => { if (info.manufacturer) { accessoryInfoService.setCharacteristic(this.api.hap.Characteristic.Manufacturer, info.manufacturer); } if (info.deviceType) { accessoryInfoService.setCharacteristic(this.api.hap.Characteristic.Model, info.deviceType); } if (info.serialNumber) { accessoryInfoService.setCharacteristic(this.api.hap.Characteristic.SerialNumber, info.serialNumber); } }); // Add the TV service const tvService = accessory.addService(this.api.hap.Service.Television); // Set the TV name tvService.setCharacteristic(this.api.hap.Characteristic.ConfiguredName, config.name); // Set sleep discovery characteristic tvService.setCharacteristic(this.api.hap.Characteristic.SleepDiscoveryMode, this.api.hap.Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE); boxCheck._request('as/services/favourites').then(favoritesData => { if (favoritesData.favourites) { boxCheck._request('as/services').then(servicesData => { if (servicesData.services) { tvService.getCharacteristic(this.api.hap.Characteristic.ActiveIdentifier) .on("set" /* SET */, (value, callback) => { const input = value.toString(); this.log.info(`[${config.name}]`, 'Set Input:', value); this.send(remoteControl, ['backup', 'backup', 'backup', ...input]).then(() => callback()).catch((error) => { this.log.error(error); callback(error); }); }); favoritesData.favourites.forEach(favorite => { const service = servicesData.services.filter(service => service.sid === favorite.sid)[0]; if (!service || !service.t || !service.c) { return; } const inputService = accessory.addService(this.api.hap.Service.InputSource, service.c, service.t); inputService.setCharacteristic(this.api.hap.Characteristic.Identifier, parseInt(service.c)); inputService.setCharacteristic(this.api.hap.Characteristic.ConfiguredName, service.t); inputService.setCharacteristic(this.api.hap.Characteristic.IsConfigured, this.api.hap.Characteristic.IsConfigured.CONFIGURED); inputService.setCharacteristic(this.api.hap.Characteristic.InputSourceType, this.api.hap.Characteristic.InputSourceType.TUNER); inputService.setCharacteristic(this.api.hap.Characteristic.InputDeviceType, this.api.hap.Characteristic.InputDeviceType.TUNER); tvService.addLinkedService(inputService); }); } }); } }); // Handle on / off events using the active characteristic tvService.getCharacteristic(this.api.hap.Characteristic.Active) .on("get" /* GET */, (callback) => { this.getActive(boxCheck).then((activeState) => { this.log.debug(`[${config.name}]`, 'Get Active: ' + (activeState ? 'ACTIVE' : 'INACTIVE')); callback(undefined, activeState); }).catch((error) => { this.log.error(`[${config.name}]`, 'Perhaps looking at this error will help you figure out why'); this.log.error(error); callback(error); }); }) .on("set" /* SET */, (value, callback) => { this.getActive(boxCheck).then((activeState) => { if (!!value === !!activeState) { this.log.info(`[${config.name}]`, 'Skipping Active: new value is equal to current value'); return callback(); } this.log.info(`[${config.name}]`, 'Set Active: ' + (value ? 'ACTIVE' : 'INACTIVE')); this.send(remoteControl, 'power').then(() => { activeState = value ? this.api.hap.Characteristic.Active.ACTIVE : this.api.hap.Characteristic.Active.INACTIVE; tvService.updateCharacteristic(this.api.hap.Characteristic.Active, activeState); callback(); }).catch((error) => { this.log.error(error); callback(error); }); }).catch((error) => { this.log.error(`[${config.name}]`, 'Perhaps looking at this error will help you figure out why'); this.log.error(error); callback(error); }); }); // Handle remote control input tvService.getCharacteristic(this.api.hap.Characteristic.RemoteKey) .on("set" /* SET */, (value, callback) => { const command = (() => { switch (value) { case this.api.hap.Characteristic.RemoteKey.REWIND: return 'rewind'; case this.api.hap.Characteristic.RemoteKey.FAST_FORWARD: return 'fastforward'; case this.api.hap.Characteristic.RemoteKey.ARROW_UP: return 'up'; case this.api.hap.Characteristic.RemoteKey.ARROW_DOWN: return 'down'; case this.api.hap.Characteristic.RemoteKey.ARROW_LEFT: return 'left'; case this.api.hap.Characteristic.RemoteKey.ARROW_RIGHT: return 'right'; case this.api.hap.Characteristic.RemoteKey.SELECT: return 'select'; case this.api.hap.Characteristic.RemoteKey.BACK: return 'backup'; case this.api.hap.Characteristic.RemoteKey.PLAY_PAUSE: return 'play'; case this.api.hap.Characteristic.RemoteKey.INFORMATION: return 'tvguide'; case this.api.hap.Characteristic.RemoteKey.EXIT: } })(); if (!command) { this.log.error(`[${config.name}]`, `Skipping Remote Key: unknown new value: ${value}`); return callback(); } this.log.info(`[${config.name}]`, 'Set Remote Key: ' + command); this.send(remoteControl, command).then(() => callback()).catch((error) => { this.log.error(error); callback(error); }); }); // Add the speaker service const speakerService = accessory.addService(this.api.hap.Service.TelevisionSpeaker); speakerService.setCharacteristic(this.api.hap.Characteristic.Active, this.api.hap.Characteristic.Active.ACTIVE); speakerService.setCharacteristic(this.api.hap.Characteristic.VolumeControlType, this.api.hap.Characteristic.VolumeControlType.RELATIVE); // Handle volume control speakerService.getCharacteristic(this.api.hap.Characteristic.VolumeSelector) .on("set" /* SET */, (value, callback) => { const command = (() => { switch (value) { case this.api.hap.Characteristic.VolumeSelector.INCREMENT: return 'channelup'; case this.api.hap.Characteristic.VolumeSelector.DECREMENT: return 'channeldown'; } })(); if (!command) { this.log.error(`[${config.name}]`, `Skipping Volume Selector: unknown newValue: ${value}`); return callback(); } this.log.info(`[${config.name}]`, 'Set Volume Selector: ' + command); this.send(remoteControl, command).then(() => callback()).catch((error) => { this.log.error(error); callback(error); }); }); // will be exposed as an additional accessory and must be paired separately with the pincode of homebridge this.api.publishExternalAccessories(settings_1.PLUGIN_NAME, [accessory]); setInterval(() => { this.getActive(boxCheck).then((activeState) => { this.log.debug(`[${config.name}]`, 'Update Active: ' + (activeState ? 'ACTIVE' : 'INACTIVE')); tvService.updateCharacteristic(this.api.hap.Characteristic.Active, activeState); }).catch((error) => { this.log.error(`[${config.name}]`, 'Perhaps looking at this error will help you figure out why'); this.log.error(error); }); }, 10000); } } exports.SkyTVPlugin = SkyTVPlugin; //# sourceMappingURL=platform.js.map