UNPKG

react-native-androidtv-remote

Version:

Port of AndroidTV Remote to react native

207 lines (182 loc) 8.84 kB
import { RemoteMessageManager } from "./RemoteMessageManager.js"; import EventEmitter from "events"; import {Buffer} from "buffer"; import TcpSockets from 'react-native-tcp-socket'; class RemoteManager extends EventEmitter { constructor(host, port, certs, systeminfo) { super(); this.host = host; this.port = port; this.certs = certs; this.chunks = Buffer.from([]); this.error = null; this.remoteMessageManager = new RemoteMessageManager(systeminfo); this.isManualStop = false; } async start() { return new Promise((resolve, reject) => { let options = { port: this.port, host : this.host, key: this.certs.key, cert: this.certs.cert, rejectUnauthorized: false, // Specific to react-native-tcp-socket (patched) androidKeyStore: this.certs.androidKeyStore, certAlias: this.certs.certAlias, keyAlias: this.certs.keyAlias, //ca: require('../../../../client-selfsigned.crt'), }; console.debug("Start Remote Connect"); this.isManualStop = false; //console.debug('RemoteManager.start(): before connectTLS'); this.client = TcpSockets.connectTLS(options, () => { console.debug("Remote connected") }); this.client.on('timeout', () => { console.debug('timeout'); this.client.destroy(); }); // Le ping est reçu toutes les 5 secondes this.client.setTimeout(10000); this.client.on("secureConnect", () => { console.debug(this.host + " Remote secureConnect"); resolve(true); }); this.client.on('data', (data) => { let buffer = Buffer.from(data); this.chunks = Buffer.concat([this.chunks, buffer]); if(this.chunks.length > 0 && this.chunks.readInt8(0) === this.chunks.length - 1){ let message = this.remoteMessageManager.parse(this.chunks); if(!message.remotePingRequest){ //console.debug(this.host + " Receive : " + Array.from(this.chunks)); console.debug(this.host + " Receive : " + JSON.stringify(message.toJSON())); } if(message.remoteConfigure){ this.client.write(this.remoteMessageManager.createRemoteConfigure( 622, "Build.MODEL", "Build.MANUFACTURER", 1, "Build.VERSION.RELEASE", )); this.emit('ready'); } else if(message.remoteSetActive){ this.client.write(this.remoteMessageManager.createRemoteSetActive(622)); } else if(message.remotePingRequest){ this.client.write(this.remoteMessageManager.createRemotePingResponse(message.remotePingRequest.val1)); } else if(message.remoteImeKeyInject){ this.emit('current_app', message.remoteImeKeyInject.appInfo.appPackage); } else if(message.remoteImeBatchEdit){ console.debug("Receive IME BATCH EDIT" + message.remoteImeBatchEdit); } else if(message.remoteImeShowRequest){ console.debug("Receive IME SHOW REQUEST" + message.remoteImeShowRequest); } else if(message.remoteVoiceBegin){ //console.debug("Receive VOICE BEGIN" + message.remoteVoiceBegin); } else if(message.remoteVoicePayload){ //console.debug("Receive VOICE PAYLOAD" + message.remoteVoicePayload); } else if(message.remoteVoiceEnd){ //console.debug("Receive VOICE END" + message.remoteVoiceEnd); } else if(message.remoteStart){ this.emit('powered', message.remoteStart.started); } else if(message.remoteSetVolumeLevel){ this.emit('volume', { level : message.remoteSetVolumeLevel.volumeLevel, maximum : message.remoteSetVolumeLevel.volumeMax, muted : message.remoteSetVolumeLevel.volumeMuted, }); //console.debug("Receive SET VOLUME LEVEL" + message.remoteSetVolumeLevel.toJSON().toString()); } else if(message.remoteSetPreferredAudioDevice){ //console.debug("Receive SET PREFERRED AUDIO DEVICE" + message.remoteSetPreferredAudioDevice); } else if(message.remoteError){ console.debug("Receive REMOTE ERROR"); this.emit('error', {error : message.remoteError}); } else{ console.log("What else ?"); } this.chunks = Buffer.from([]); } }); this.client.on('close', async (hasError) => { console.info(this.host + " Remote Connection closed ", hasError); // Don't restart if it was manually stopped if (this.isManualStop) { console.log('RemoteManager.close() after manual stop - not restarting'); this.isManualStop = false; // Reset flag for future connections return; } if(hasError){ console.log('RemoteManager.close() hasError'); reject(this.error.code); if(this.error.code === "ECONNRESET"){ console.log('RemoteManager.close() hasError ECONNRESET'); this.emit('unpaired'); } else if(this.error.code === "ECONNREFUSED"){ console.log('RemoteManager.close() hasError ECONNREFUSED'); // L'appareil n'est pas encore prêt : on relance await new Promise(resolve => setTimeout(resolve, 1000)); await this.start().catch((error) => { console.error(error); }); } else if(this.error.code === "EHOSTDOWN"){ // L'appareil est down, on ne fait rien console.log('RemoteManager.close() hasError EHOSTDOWN'); } else{ // Dans le doute on redémarre console.log('RemoteManager.close() unknown error => start again'); await new Promise(resolve => setTimeout(resolve, 1000)); await this.start().catch((error) => { console.error(error); }); } } else { // Si pas d'erreur on relance. Si elle s'est éteinte alors une erreur empéchera de relancer encore console.log('RemoteManager.close() no error => start again'); await new Promise(resolve => setTimeout(resolve, 1000)); await this.start().catch((error) => { console.error(error); }); } }); this.client.on('error', (error) => { console.error(this.host, error); this.error = error; }); }); } sendPower(){ this.client.write(this.remoteMessageManager.createRemoteKeyInject( this.remoteMessageManager.RemoteDirection.SHORT, this.remoteMessageManager.RemoteKeyCode.KEYCODE_POWER)); } sendKey(key, direction){ this.client.write(this.remoteMessageManager.createRemoteKeyInject( direction, key)); } sendAppLink(app_link){ this.client.write(this.remoteMessageManager.createRemoteRemoteAppLinkLaunchRequest(app_link)); } stop(){ this.isManualStop = true; this.client.destroy(); } } export { RemoteManager };