homebridge-samsung-smart-tv18
Version:
Homebridge Samsung Smart TV 2018
154 lines (133 loc) • 5.12 kB
JavaScript
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);
}
});
}
};