UNPKG

homebridge-samsung-smart-tv18

Version:
154 lines (133 loc) 5.12 kB
const wol = require('wake_on_lan'); const request = require('request'); const WebSocket = require('ws'); var Service, Characteristic; module.exports = function (homebridge) { Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic; homebridge.registerAccessory("homebridge-samsung-smart-tv18", "SamsungSmartTV2018", AccessorySamsungSmartTV2018); }; //--------------------------------------------------------- // | // Samsung SmartTV NU Series 2018 Accessory | // | //--------------------------------------------------------- function AccessorySamsungSmartTV2018(log, config) { var accessory = this; this.log = log; this.config = config; this.name = config["name"]; this.mac_address = config["mac_address"]; this.ip_address = config["ip_address"]; this.api_timeout = 2000; if (this.ip_address == null) throw new Error("No IP Address"); if (this.mac_address == null) throw new Error("No MAC Address"); this.is_powering_off = false; this.service = new Service.Switch(this.name); this.wakeOnLan = function (callbackWol) { wol.wake(this.mac_address, function (error) { if (error) { accessory.log(error) callbackWol(true) } else { accessory.log("Wake On Lan Successful") callbackWol(false) } }); }; this.sendPowerCommand = function (callbackCmd) { var ws = new WebSocket('wss://' + this.ip_address + ':8002/api/v2/channels/samsung.remote.control?name=' + (new Buffer("homebridge")).toString('base64'), {rejectUnauthorized: false}, function (error) { accessory.log(error); }); ws.on('error', function (e) { accessory.log('Error in websocket'); callbackCmd(e) }); ws.on('message', function (data) { var cmd = { "method": "ms.remote.control", "params": {"Cmd": "Click", "DataOfCmd": "KEY_POWER", "Option": "false", "TypeOfRemote": "SendRemoteKey"} }; data = JSON.parse(data); if (data.event == "ms.channel.connect") { accessory.log('WebSocket Connected'); ws.send(JSON.stringify(cmd)); setTimeout(function () { ws.close(); accessory.log('WebSocket Closed'); callbackCmd(false) }, 1000); } }); }; //Since wake on lan its used to turn on the tv, verification for an online API is // used to check if the TV is On or Off. this.checkOnline = function (callback) { request.get({ url: 'http://' + this.ip_address + ':8001/api/v2/', timeout: this.api_timeout }, function (err, res, body) { if (!err && res.statusCode === 200) { accessory.log('TV API Active'); callback(true); } else { accessory.log('No response from TV'); callback(false); } }); }; this.service .getCharacteristic(Characteristic.On) .on('get', this._getOn.bind(this)) .on('set', this._setOn.bind(this)); } AccessorySamsungSmartTV2018.prototype.getInformationService = function () { var informationService = new Service.AccessoryInformation(); informationService .setCharacteristic(Characteristic.Name, this.name) .setCharacteristic(Characteristic.Manufacturer, 'Samsung SmartTV 2018') .setCharacteristic(Characteristic.Model, '1.0.0') .setCharacteristic(Characteristic.SerialNumber, this.ip_address); return informationService; }; AccessorySamsungSmartTV2018.prototype.getServices = function () { return [this.service, this.getInformationService()]; }; AccessorySamsungSmartTV2018.prototype._getOn = function (callback) { var accessory = this; if (accessory.is_powering_off) { accessory.log('Powering OFF'); callback(null, false); } else { this.checkOnline(function (isOnline) { callback(null, isOnline); }); } }; AccessorySamsungSmartTV2018.prototype._setOn = function (on, callback) { var accessory = this; accessory.log('Received ON Command: ' + on); if (on) { accessory.log('Attempting Wake'); accessory.wakeOnLan(function (err) { if (err) { callback(new Error(err)); } else { callback(null); } }); } else { accessory.sendPowerCommand(function (err) { if (err) { callback(new Error(err)); } else { accessory.is_powering_off = true; setTimeout(function () { accessory.is_powering_off = false; }, 3000) callback(null); } }); } };