UNPKG

homebridge-philips-pita-paka

Version:

Homebridge Plugin for Philips Android TV API v6+

325 lines (304 loc) 8.28 kB
const request = require("request"); const wol = require("wake_on_lan"); class PhilipsTV { api = null; channelList = []; powerState = false; // volume = { // min: 0, // max: 0, // current: 0, // muted: false, // }; constructor(config) { const wolURL = config.wol_url; const baseURL = `https://${config.ip_address}:1926/6/`; this.api = (path, body = null) => { return new Promise((success, fail) => { request( { rejectUnauthorized: false, timeout: 3000, auth: { user: config.username, pass: config.password, sendImmediately: false, }, method: body ? "POST" : "GET", body: typeof body === "object" ? JSON.stringify(body) : body, url: `${baseURL}${path}`, }, (error, response, body) => { if (error) { fail(error); } else { if (body && body.indexOf("{") !== -1) { try { success(JSON.parse(body)); } catch (e) { fail(e); } } else { success({}); } } } ); }); }; this.wake = (callback) => { if (!wolURL) { callback(null, "EMPTY"); return; } if (wolURL.substring(0, 3).toUpperCase() === "WOL") { //Wake on lan request const macAddress = wolURL.replace(/^WOL[:]?[\/]?[\/]?/gi, ""); wol.wake(macAddress, function (error) { if (error) { callback(error); } else { callback(null, "OK"); } }); } else { if (wolURL.length > 3) { callback(new Error("Unsupported protocol: ", "ERROR")); } else { callback(null, "EMPTY"); } } }; } getPowerState = (callback) => { this.api("powerstate") .then((data) => { callback && callback(null, data.powerstate === "On"); }) .catch((e) => { callback && callback(null, false); }); }; setPowerState = (value, callback) => { if (value) { this.wake((wolState) => {}); } this.api("powerstate", { powerstate: value ? "On" : "Standby", }) .then((data) => { callback(null, value); }) .catch(() => { callback(null, false); }); }; sendKey = (key) => this.api("input/key", { key }); setChannel = (ccid) => this.api("activities/tv", { channel: { ccid }, channelList: { id: "allsat" }, }); launchApp = (app) => this.api("activities/launch", app); getChannelList = () => this.api("channeldb/tv/channelLists/all").then((response) => { if (response) { return response.Channel; } return []; }); presetToCCid = async (preset) => { if (!this.channelList.length) { this.channelList = await this.getChannelList(); } const channel = this.channelList .filter((item) => parseInt(item.preset) === parseInt(preset)) .pop(); return channel ? channel.ccid : 0; }; getCurrentSource = (inputs) => { return new Promise(async (resolve, reject) => { try { const current = await this.api("activities/current"); const currentPkgname = current.component.packageName; let currentTvPreset = 0; let selected = 0; if ( currentPkgname === "org.droidtv.channels" || currentPkgname === "org.droidtv.playtv" ) { const currentTV = await this.api("activities/tv"); currentTvPreset = parseInt(currentTV.channel.preset, 10); } inputs.forEach((item, index) => { if (currentTvPreset && item.channel === currentTvPreset) { selected = index; } else if ( item.launch && item.launch.intent && item.launch.intent.component.packageName === currentPkgname ) { selected = index; } }); resolve(selected); } catch (e) { resolve(0); } }); }; setSource = async (input, callback) => { if (input.channel) { await this.sendKey("WatchTV"); // await this.sendKey("Digit" + input.channel); // await this.sendKey("Confirm"); const ccid = await this.presetToCCid(input.channel); await this.setChannel(ccid); } else if (input.launch) { await this.launchApp(input.launch); } else { await this.sendKey("WatchTV"); } callback(null); }; getAmbilightState = (callback) => { this.api("ambilight/power") .then((data) => { callback(null, data.power === "On"); }) .catch(() => { callback(null, false); }); }; getAmbilightBrightness = (callback) => { this.api("ambilight/lounge") .then((data) => { callback(null, data.color.brightness); }) .catch(() => { callback(null, false); }); }; // getVolumeState = (callback) => { // this.api("audio/volume") // .then((data) => { // this.volume = { // ...this.volume, // ...data, // }; // const volume = Math.floor( // ((this.volume.current - this.volume.min) / // (this.volume.max - this.volume.min)) * // 100 // ); // callback(null, volume); // }) // .catch(() => { // callback(null, false); // }); // }; // setVolumeState = (value, callback) => { // this.volume.current = Math.round( // this.volume.min + (this.volume.max - this.volume.min) * (value / 100) // ); // this.api("audio/volume", this.volume) // .then(() => { // callback(null, value); // }) // .catch(() => { // callback(null, false); // }); // }; // getMuteState = (callback) => { // this.api("audio/volume") // .then((data) => { // this.volume = { // ...this.volume, // ...data, // }; // callback(null, this.volume.muted); // }) // .catch(() => { // callback(null, false); // }); // }; // setMuteState = (value, callback) => { // this.volume.muted = !value; // this.api("audio/volume", this.volume) // .then(() => { // callback(null, value); // }) // .catch(() => { // callback(null, false); // }); // }; setAmbilightState = (value, callback) => { if (value) { this.api("ambilight/currentconfiguration", { styleName: "FOLLOW_VIDEO", isExpert: false, menuSetting: "STANDARD", }) .then(() => { this.api("screenstate", { screenstate: "On" }); }) .then((data) => { callback(null, true); }) .catch(() => { callback(null, false); }); } else { this.api("ambilight/power", { power: "Off", }) .then((data) => { callback(null, false); }) .catch(() => { callback(null, false); }); } }; setAmbilightLounge = (value, callback) => { if (value) { this.api("ambilight/lounge", { color: { hue: 15, saturation: 255, brightness: Math.round(value), }, colordelta: { hue: 15, saturation: 0, brightness: 0 }, speed: 0, mode: "A", }) .then(() => { this.api("screenstate", { screenstate: "Off" }); }) .then((data) => { callback(null, true); }) .catch(() => { callback(null, false); }); } else { this.api("ambilight/power", { power: "Off", }) .then(() => { this.getPowerState((error, powerState) => { if (powerState === true) { this.api("screenstate", { screenstate: "On" }); } }); }) .then((data) => { callback(null, false); }) .catch(() => { callback(null, false); }); } }; } module.exports = PhilipsTV;