homebridge-androidtv
Version:
Homebridge plugin to control your AndroidTV / Freebox Player Pop / Freemox Mini 4k
293 lines (235 loc) • 15.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.PLUGIN_NAME = exports.PLATFORM_NAME = exports.AndroidTV = void 0;
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
require("core-js/modules/web.url.to-json.js");
require("core-js/modules/es.promise.js");
require("core-js/modules/es.regexp.exec.js");
require("core-js/modules/es.string.split.js");
var _index2 = require("./admin/index.js");
var _DeviceManager = require("./DeviceManager.js");
var _androidtvRemote = require("androidtv-remote");
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
var PLATFORM_NAME = 'HomebridgeAndroidTV';
exports.PLATFORM_NAME = PLATFORM_NAME;
var PLUGIN_NAME = 'homebridge-androidtv';
exports.PLUGIN_NAME = PLUGIN_NAME;
class AndroidTV {
constructor(log, config, api) {
this.log = log;
this.config = config;
this.api = api;
this.keys = {};
this.keys[this.api.hap.Characteristic.RemoteKey.REWIND] = _androidtvRemote.RemoteKeyCode.KEYCODE_MEDIA_REWIND;
this.keys[this.api.hap.Characteristic.RemoteKey.FAST_FORWARD] = _androidtvRemote.RemoteKeyCode.KEYCODE_MEDIA_FAST_FORWARD;
this.keys[this.api.hap.Characteristic.RemoteKey.NEXT_TRACK] = _androidtvRemote.RemoteKeyCode.KEYCODE_MEDIA_NEXT;
this.keys[this.api.hap.Characteristic.RemoteKey.PREVIOUS_TRACK] = _androidtvRemote.RemoteKeyCode.KEYCODE_MEDIA_PREVIOUS;
this.keys[this.api.hap.Characteristic.RemoteKey.ARROW_UP] = _androidtvRemote.RemoteKeyCode.KEYCODE_DPAD_UP;
this.keys[this.api.hap.Characteristic.RemoteKey.ARROW_DOWN] = _androidtvRemote.RemoteKeyCode.KEYCODE_DPAD_DOWN;
this.keys[this.api.hap.Characteristic.RemoteKey.ARROW_LEFT] = _androidtvRemote.RemoteKeyCode.KEYCODE_DPAD_LEFT;
this.keys[this.api.hap.Characteristic.RemoteKey.ARROW_RIGHT] = _androidtvRemote.RemoteKeyCode.KEYCODE_DPAD_RIGHT;
this.keys[this.api.hap.Characteristic.RemoteKey.SELECT] = _androidtvRemote.RemoteKeyCode.KEYCODE_DPAD_CENTER;
this.keys[this.api.hap.Characteristic.RemoteKey.BACK] = _androidtvRemote.RemoteKeyCode.KEYCODE_BACK;
this.keys[this.api.hap.Characteristic.RemoteKey.EXIT] = _androidtvRemote.RemoteKeyCode.KEYCODE_HOME;
this.keys[this.api.hap.Characteristic.RemoteKey.PLAY_PAUSE] = _androidtvRemote.RemoteKeyCode.KEYCODE_MEDIA_PLAY_PAUSE;
this.keys[this.api.hap.Characteristic.RemoteKey.INFORMATION] = _androidtvRemote.RemoteKeyCode.KEYCODE_INFO;
this.channelskeys = {};
this.channelskeys[0] = _androidtvRemote.RemoteKeyCode.KEYCODE_0;
this.channelskeys[1] = _androidtvRemote.RemoteKeyCode.KEYCODE_1;
this.channelskeys[2] = _androidtvRemote.RemoteKeyCode.KEYCODE_2;
this.channelskeys[3] = _androidtvRemote.RemoteKeyCode.KEYCODE_3;
this.channelskeys[4] = _androidtvRemote.RemoteKeyCode.KEYCODE_4;
this.channelskeys[5] = _androidtvRemote.RemoteKeyCode.KEYCODE_5;
this.channelskeys[6] = _androidtvRemote.RemoteKeyCode.KEYCODE_6;
this.channelskeys[7] = _androidtvRemote.RemoteKeyCode.KEYCODE_7;
this.channelskeys[8] = _androidtvRemote.RemoteKeyCode.KEYCODE_8;
this.channelskeys[9] = _androidtvRemote.RemoteKeyCode.KEYCODE_9;
this.deviceManager = new _DeviceManager.DeviceManager(log, config, api);
this.deviceManager.load();
this.deviceManager.on('discover', this.discover.bind(this));
this.adminServer = new _index2.AdminServer(this.config.port ? this.config.port : 8182, this.deviceManager);
this.adminServer.listen().then(port => {
this.log.info("Admin server is running on port ".concat(port));
}).catch(e => {
this.log.error('Failed to launch the admin server:', e.message);
});
api.on("didFinishLaunching", () => {
this.log.info("didFinishLaunching");
this.deviceManager.listen();
this.log.info("end didFinishLaunching");
});
}
discover(device) {
var _this = this;
this.log.info("Discover : ", device.toJSON());
var tvName = device.name;
var uuid = this.api.hap.uuid.generate('homebridge:androidtv-' + tvName);
this.log.info(tvName, 'Registering device', uuid);
this.tvAccessory = new this.api.platformAccessory(tvName, uuid);
this.tvAccessory.category = device.type;
this.infoService = this.tvAccessory.getService(this.api.hap.Service.AccessoryInformation);
this.infoService.setCharacteristic(this.api.hap.Characteristic.Manufacturer, "MANUFACTURER").setCharacteristic(this.api.hap.Characteristic.Model, "MODEL").setCharacteristic(this.api.hap.Characteristic.Name, tvName).setCharacteristic(this.api.hap.Characteristic.SerialNumber, uuid).setCharacteristic(this.api.hap.Characteristic.SoftwareRevision, "VERSION").setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, PLUGIN_NAME).setCharacteristic(this.api.hap.Characteristic.HardwareRevision, "PLUGIN_AUTHOR");
var tvService = this.tvAccessory.addService(this.api.hap.Service.Television);
tvService.setCharacteristic(this.api.hap.Characteristic.ConfiguredName, tvName);
tvService.setCharacteristic(this.api.hap.Characteristic.SleepDiscoveryMode, this.api.hap.Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE);
tvService.setCharacteristic(this.api.hap.Characteristic.PowerModeSelection, this.api.hap.Characteristic.PowerModeSelection.SHOW);
tvService.getCharacteristic(this.api.hap.Characteristic.Active).onSet((newValue, old) => {
this.log.info(tvName, 'set Active => setNewValue: ' + newValue);
if (device.powered !== (newValue === this.api.hap.Characteristic.Active.ACTIVE)) {
device.android_remote.sendPower();
}
tvService.updateCharacteristic(this.api.hap.Characteristic.Active, newValue);
});
tvService.getCharacteristic(this.api.hap.Characteristic.Active).on('get', function (callback) {
this.log.info(tvName, 'get Active', device.powered);
callback(null, device.powered ? this.api.hap.Characteristic.Active.ACTIVE : this.api.hap.Characteristic.Active.INACTIVE); //tvService.updateCharacteristic(this.api.hap.Characteristic.Active, 1);
}.bind(this));
this.deviceManager.on('powered', function (device) {
this.log.info(tvName, 'powered', device.powered);
tvService.updateCharacteristic(this.api.hap.Characteristic.Active, device.powered ? this.api.hap.Characteristic.Active.ACTIVE : this.api.hap.Characteristic.Active.INACTIVE);
}.bind(this));
tvService.getCharacteristic(this.api.hap.Characteristic.RemoteKey).onSet(newValue => {
this.log.info(tvName, 'Set RemoteKey ' + newValue);
device.android_remote.sendKey(this.keys[newValue], _androidtvRemote.RemoteDirection.SHORT);
});
var speakerService = this.tvAccessory.addService(this.api.hap.Service.TelevisionSpeaker);
speakerService.setCharacteristic(this.api.hap.Characteristic.Active, this.api.hap.Characteristic.Active.ACTIVE).setCharacteristic(this.api.hap.Characteristic.VolumeControlType, this.api.hap.Characteristic.VolumeControlType.RELATIVE_WITH_CURRENT);
speakerService.getCharacteristic(this.api.hap.Characteristic.VolumeSelector).onSet(volumeSelector => {
this.log.info(tvName, 'set VolumeSelector => setNewValue: ' + volumeSelector);
if (volumeSelector === this.api.hap.Characteristic.VolumeSelector.INCREMENT) {
device.android_remote.sendKey(_androidtvRemote.RemoteKeyCode.KEYCODE_VOLUME_UP, _androidtvRemote.RemoteDirection.SHORT);
} else if (volumeSelector === this.api.hap.Characteristic.VolumeSelector.DECREMENT) {
device.android_remote.sendKey(_androidtvRemote.RemoteKeyCode.KEYCODE_VOLUME_DOWN, _androidtvRemote.RemoteDirection.SHORT);
}
});
speakerService.getCharacteristic(this.api.hap.Characteristic.Volume).on('get', function (callback) {
var volume = 0;
if (device.volume_max > 0) {
volume = Math.round(device.volume_current * 100 / device.volume_max);
}
this.log.info(tvName, 'get VolumeSelector ' + volume);
callback(null, volume);
}.bind(this));
this.deviceManager.on('volume', function (device) {
var volume = 0;
if (device.volume_max > 0) {
volume = Math.round(device.volume_current * 100 / device.volume_max);
}
this.log.info(tvName, 'Device set Volume', volume);
speakerService.updateCharacteristic(this.api.hap.Characteristic.Volume, volume);
}.bind(this));
speakerService.getCharacteristic(this.api.hap.Characteristic.Mute).onSet(function (muted) {
this.log.info(tvName, 'set Mute => muted: ' + muted);
device.android_remote.sendKey(_androidtvRemote.RemoteKeyCode.KEYCODE_VOLUME_MUTE, _androidtvRemote.RemoteDirection.SHORT);
speakerService.updateCharacteristic(this.api.hap.Characteristic.Mute, muted);
});
this.deviceManager.on('muted', function (device) {
this.log.info(tvName, 'Device set mute', device.volume_muted);
speakerService.updateCharacteristic(this.api.hap.Characteristic.Mute, device.volume_muted);
}.bind(this));
speakerService.getCharacteristic(this.api.hap.Characteristic.Mute).on("get", function (callback) {
var muted = device.volume_muted;
this.log.info(tvName, 'get VolumeMutedSelector');
callback(null, muted);
}.bind(this));
var identifier = 0;
if (this.config.channels) {
for (var channel of this.config.channels) {
var _uuid = this.api.hap.uuid.generate('homebridge:androidtv-' + tvName + '-channel-' + channel.name);
var service = this.tvAccessory.addService(this.api.hap.Service.InputSource, _uuid, channel.name);
this.log.info(tvName, 'Adding channel', channel.name, _uuid);
service.setCharacteristic(this.api.hap.Characteristic.Identifier, identifier);
service.setCharacteristic(this.api.hap.Characteristic.ConfiguredName, channel.name);
service.setCharacteristic(this.api.hap.Characteristic.IsConfigured, this.api.hap.Characteristic.IsConfigured.CONFIGURED);
service.setCharacteristic(this.api.hap.Characteristic.InputSourceType, this.api.hap.Characteristic.InputSourceType.TUNER);
tvService.addLinkedService(service);
identifier++;
}
}
if (this.config.keys) {
for (var key of this.config.keys) {
var _uuid2 = this.api.hap.uuid.generate('homebridge:androidtv-' + tvName + '-key-' + key.name);
var _service = this.tvAccessory.addService(this.api.hap.Service.InputSource, _uuid2, key.name);
this.log.info(tvName, 'Adding key', key.name, _uuid2);
_service.setCharacteristic(this.api.hap.Characteristic.Identifier, identifier);
_service.setCharacteristic(this.api.hap.Characteristic.ConfiguredName, key.name);
_service.setCharacteristic(this.api.hap.Characteristic.IsConfigured, this.api.hap.Characteristic.IsConfigured.CONFIGURED);
_service.setCharacteristic(this.api.hap.Characteristic.InputSourceType, this.api.hap.Characteristic.InputSourceType.TUNER);
tvService.addLinkedService(_service);
identifier++;
}
}
if (this.config.applications) {
for (var application of this.config.applications) {
var _uuid3 = this.api.hap.uuid.generate('homebridge:androidtv-' + tvName + '-application-' + application.name);
var _service2 = this.tvAccessory.addService(this.api.hap.Service.InputSource, _uuid3, application.name);
this.log.info(tvName, 'Adding application', application.name, _uuid3);
_service2.setCharacteristic(this.api.hap.Characteristic.Identifier, identifier);
_service2.setCharacteristic(this.api.hap.Characteristic.ConfiguredName, application.name);
_service2.setCharacteristic(this.api.hap.Characteristic.IsConfigured, this.api.hap.Characteristic.IsConfigured.CONFIGURED);
_service2.setCharacteristic(this.api.hap.Characteristic.InputSourceType, this.api.hap.Characteristic.InputSourceType.APPLICATION);
tvService.addLinkedService(_service2);
identifier++;
}
}
tvService.setCharacteristic(this.api.hap.Characteristic.ActiveIdentifier, 0);
tvService.getCharacteristic(this.api.hap.Characteristic.ActiveIdentifier).onSet( /*#__PURE__*/function () {
var _ref = _asyncToGenerator(function* (newValue) {
var channel_length = 0;
var key_length = 0;
if (_this.config.channels) {
channel_length = _this.config.channels.length;
}
if (_this.config.keys) {
key_length = _this.config.keys.length;
}
if (newValue < channel_length) {
if (_this.config.channels) {
var _channel = _this.config.channels[newValue];
var array = _this.splitChannelNumber(_channel.number);
device.android_remote.sendKey(_androidtvRemote.RemoteKeyCode.KEYCODE_HOME, _androidtvRemote.RemoteDirection.SHORT);
yield new Promise(resolve => setTimeout(resolve, 500));
device.android_remote.sendKey(_androidtvRemote.RemoteKeyCode.KEYCODE_HOME, _androidtvRemote.RemoteDirection.SHORT);
yield new Promise(resolve => setTimeout(resolve, 500));
device.android_remote.sendKey(_androidtvRemote.RemoteKeyCode.KEYCODE_DPAD_CENTER, _androidtvRemote.RemoteDirection.SHORT);
yield new Promise(resolve => setTimeout(resolve, 500));
for (var button of array) {
_this.log.info(tvName, 'Tap on ' + button + ' ' + _this.channelskeys[button]);
device.android_remote.sendKey(_this.channelskeys[button], _androidtvRemote.RemoteDirection.SHORT);
}
}
} else if (newValue < channel_length + key_length) {
if (_this.config.keys) {
var index = newValue - channel_length;
var _key = _this.config.keys[index];
var value = _androidtvRemote.RemoteKeyCode[_key.key];
device.android_remote.sendKey(value, _androidtvRemote.RemoteDirection.SHORT);
_this.log.info(tvName, 'Tap on ' + _key.key + ' ' + _androidtvRemote.RemoteKeyCode[_key.key]);
}
} else {
if (_this.config.applications) {
var _index = newValue - channel_length - key_length;
var _application = _this.config.applications[_index];
_this.log.info(tvName, "Sending link " + _application.link);
device.android_remote.sendAppLink(_application.link);
}
}
_this.log.info(tvName, 'set Active Identifier => setNewValue: ' + newValue);
});
return function (_x) {
return _ref.apply(this, arguments);
};
}());
this.api.publishExternalAccessories(PLUGIN_NAME, [this.tvAccessory]);
}
splitChannelNumber(number) {
var string_number = String(number);
var array = string_number.split('');
return array;
}
}
exports.AndroidTV = AndroidTV;