UNPKG

homebridge-lgtv-fork-tvkit

Version:

Homebridge plugin for LG 2012 series TVs that uses the new homekit TV service

210 lines (181 loc) 7.33 kB
'use strict'; var false_run = false; // https://github.com/g30r93g/homebridge-panasonic/blob/master/index.js var Service, Characteristic; var ping = require('ping'); var inherits = require('util').inherits; var lgtv = require('lgtv-2012').lgtv; function lgtv_2012_accessory(log, config, api) { this.log = function(msg) { if(this.host) msg = `TV [${this.host}]: ${msg}`; log(msg); } this.api = api; this.powered = false; if (config) { // import the user configuration this.name = config.name; this.key = config.pairingKey; this.host = config.ip; this.port = parseInt(config.port) || 8080; // set up tv object and debug flags this.tv = new lgtv({ 'host': this.host, 'port': this.port}); this.tv.debug = (config.debug === true || config.debug == "true") this.tv.min_volume = config.min_volume || 2 this.max_volume = 100 / (parseInt(config.max_volume) || 20); this.on_command = String(config.on_command).toUpperCase() || 'MUTE'; this.tv.false_run = config.false_run == "true" } this.deviceInformation = new Service.AccessoryInformation(); this.deviceInformation.setCharacteristic(Characteristic.Name, 'LG TV 2012') .setCharacteristic(Characteristic.Manufacturer, 'LG Electronics Inc.') .setCharacteristic(Characteristic.Model, '1.0'); // Configure HomeKit TV Accessory this.tvService = new Service.Television(this.name, "Television"); this.tvService .setCharacteristic(Characteristic.ConfiguredName, this.name) .setCharacteristic(Characteristic.SleepDiscoveryMode, 1); this.tvService.getCharacteristic(Characteristic.Active) .on("get", this.getState.bind(this)) .on("set", this.setState.bind(this)); // Configure HomeKit TV Accessory Remote Control this.tvService .getCharacteristic(Characteristic.RemoteKey) .on("set", this.remoteControl.bind(this)); // Configure HomeKit TV Volume Control this.speakerService = new Service.TelevisionSpeaker(this.name + " Volume", "volumeService"); this.speakerService .setCharacteristic(Characteristic.Active, Characteristic.Active.ACTIVE) .setCharacteristic(Characteristic.VolumeControlType, Characteristic.VolumeControlType.ABSOLUTE); this.speakerService .getCharacteristic(Characteristic.VolumeSelector) .on("set", (newValue, callback) => { this.tv.setVolume(newValue); callback(null, newValue); }); this.speakerService .getCharacteristic(Characteristic.Mute) .on("get", this.getMute.bind(this)) .on("set", this.setMute.bind(this)); this.speakerService .addCharacteristic(Characteristic.Volume) .on("get", this.getVolume.bind(this)) .on("set", this.setVolume.bind(this)); this.tvService.addLinkedService(this.speakerService); // this.service = new Service.Lightbulb(this.name) // this.service.getCharacteristic(Characteristic.On) // .on('get', this.getState.bind(this)) // .on('set', this.setState.bind(this)); // // this.service.getCharacteristic(Characteristic.Brightness) // .on('get', this.getVolume.bind(this)) // .on('set', this.setVolume.bind(this)); // // this.service.getCharacteristic(Characteristic.Hue) // .on('get', this.getChannel.bind(this)) // .on('set', this.setChannel.bind(this)); this.getServices = function() { return [this.deviceInformation, this.tvService, this.speakerService]; } } lgtv_2012_accessory.prototype.connect = function(cb) { if (this.host && this.host.length && this.port) { this.tv.new_session(this.key, (tv) => { this.powered = Boolean(tv); cb(tv); }); } else { this.log('Does not appear to be powered on'); this.powered = false; cb(null); } } lgtv_2012_accessory.prototype.getState = function(cb) { if (!this.host || !this.host.length) cb(null, false) else ping.sys.probe(this.host, (isAlive) => { this.powered = isAlive; this.log(' is' + isAlive?'On':'Off'); cb(null, isAlive); }, { timeout: 1, min_reply: 1 }) } lgtv_2012_accessory.prototype.setState = function(toggle, cb) { if(!this.powered || this.tv.locked) { this.log('Unable to change power settings at this time') cb(null, false) } else { this.getState((error, alive) => { this.connect((tv) => { this.log('Turning ' + toggle?'On':'Off') if(toggle) tv.send_command(this.on_command, (err) => { cb(null, true) }); else tv.send_command('POWER', (err) => { cb(null, true) }); }) }) } } lgtv_2012_accessory.prototype.getVolume = function(cb) { this.connect((tv) => { tv.get_volume( (volume) => { this.log('Volume is ' +volume.level+ ' and Mute is ' + volume.mute?'On':'Off'); cb(null, Math.round(volume.level * this.max_volume)); }) }) } lgtv_2012_accessory.prototype.setVolume = function(to, cb) { this.connect((tv) => { tv.set_volume(Math.round(to / this.max_volume), (err) => { this.log('Setting Volume to ' +to+ '... ' + err?'Success':'Failure'); cb(null, true); }) }) } lgtv_2012_accessory.prototype.getChannel = function(cb) { if (!this.host || !this.host.length) cb(null, false) else { this.connect((tv) => { tv.get_channel( (channel) => { this.log(`On Channel: #${channel.number} ${channel.title}`); cb(null, channel.number) }) }) } } lgtv_2012_accessory.prototype.setChannel = function(channel, cb) { this.connect((tv) => { channel = parseInt(channel); if(channel) tv.set_channel(channel, (err) => { if(!err) this.log(`Set channel to ${channel}`); cb(true, err); }); }) } lgtv_2012_accessory.prototype.getChannelName = function(cb) { this.connect((tv) => { tv.get_channel( (channel) => { this.log(`Channel: ${channel.title}`); cb(null, channel.title); }) }) } lgtv_2012_accessory.prototype.identify = function(cb) { if (this.host && this.host.length) { if(this.powered) { if(this.key && this.key.length) this.connect((tv) => { tv.send_command('APPS', (success) => { this.log('Identifying by launching LG App menu'); cb(null, success); }) }); else tv.pair_request((success) => { this.log('Performing request for TV key'); cb(null, success); }); } else this.checkInterval((alive) => { cb(null, alive) }) } else cb(null, false) } lgtv_2012_accessory.prototype.checkInterval = function(cb) { this.getState((err, state) => { cb(state) }); //setTimeout(cb, this.checkInterval.bind(this, cb), 2000) } module.exports = function (homebridge) { Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic; homebridge.registerAccessory('homebridge-lgtv-2012', 'lgtv-2012', lgtv_2012_accessory); }