UNPKG

ifc

Version:

A Javascript client for Infinite Flight simulator API

233 lines (183 loc) 6.47 kB
var dgram = require('dgram'); var net = require('net'); var IFC = { host: null, port: null, enableLog: false, name: "IF Connect", isConnected: false, foreFlight: { socket: false, broadcastPort: 49002, dataModels: { // GPS "XGPSInfinite Flight": { "name": "GPS", "fields": ["lat", "lng", "alt", "hdg", "gs"] }, // Attitude "XATTInfinite Flight": { "name": "attitude", "fields": ["hdg", "pitch", "roll"] }, // Traffic "XTRAFFICInfinite Flight": { "name": "traffic", "fields": ["icao", "lat", "lng", "alt", "vs", "gnd", "hdg", "spd", "callsign"] } } }, infiniteFlight: { broadcastPort: 15000, serverPort: 0, discoverSocket: false, clientSocket: false }, initSocketOnHostDiscovered: true, closeUDPSocketOnHostDiscovered: true, log: function(msg) { if (IFC.enableLog) console.log(IFC.name, msg); }, beforeInitSocket: function() { IFC.log("Connecting..."); }, onHostUndefined: function() { IFC.log("Host Undefined"); }, onHostSearchStarted: function() { IFC.log("Searching for host"); }, onSocketConnected: function() { IFC.log("Connected"); }, onSocketConnectionError: function() { IFC.log("Connection error"); }, onHostDiscovered: function(host, port, callback) { IFC.log("Host Discovered"); }, onDataReceived: function(data) {}, onHostSearchFailed: function() {}, // SHORTCUTS FUNCTIONS // init: function(successCallback, errorCallback) { if (successCallback) IFC.onSocketConnected = successCallback; if (errorCallback) IFC.onSocketConnectionError = errorCallback; IFC.searchHost(successCallback, errorCallback); }, initForeFlight: function(onForeFlightDataReceived) { IFC.initForeFlightReceiver(onForeFlightDataReceived); }, // FORE FLIGHT // onForeFlightDataReceived: function(data) { IFC.log(data); }, initForeFlightReceiver: function(onForeFlightDataReceived) { if (onForeFlightDataReceived) IFC.onForeFlightDataReceived = onForeFlightDataReceived; if (IFC.foreFlight.socket) IFC.foreFlight.socket.close(function() { IFC.foreFlight.socket = false; }); IFC.foreFlight.socket = dgram.createSocket('udp4'); IFC.foreFlight.socket.on('message', function (msg, info){ msg = IFC._ab2str(msg); var data = {}; var dataParts = msg.split(","); var dataType = dataParts.shift(); var dataModel = IFC.foreFlight.dataModels[dataType]; if (!dataModel) return IFC.log("No format found for ", dataType); var name = dataModel.name; var fields = dataModel.fields; var log = [name]; data._name = name; for (var i = 0; i < fields.length; i++) { log.push(fields[i] + ' : ' + dataParts[i]); data[fields[i]] = dataParts[i]; IFC.onForeFlightDataReceived(data); } //IFC.log(log.join(' ')); }); IFC.foreFlight.socket.on('listening', function() { var address = IFC.foreFlight.socket.address(); IFC.log("listening on :", address.address, ":" , address.port); }); IFC.foreFlight.socket.bind(IFC.foreFlight.broadcastPort); }, searchHost: function(successCallback, errorCallback) { if (IFC.infiniteFlight.discoverSocket) return; IFC.infiniteFlight.discoverSocket = dgram.createSocket('udp4'); IFC.infiniteFlight.discoverSocket.on('message', function (info){ IFC.log("Discover socket : data received"); var dataStr = info; IFC.log(dataStr); var data = {}; try { data = JSON.parse(IFC._ab2str(dataStr)); IFC.log() IFC.log(data); } catch(e) { IFC.log("Discover socket : parsing error"); } if (data.Address && data.Port) { IFC.log("Host Discovered"); IFC.isConnected = true; IFC.infiniteFlight.serverAddress = data.Address; IFC.infiniteFlight.serverPort = data.Port; IFC.initIFClient(data.Address, data.Port); IFC.infiniteFlight.discoverSocket.close(function() { IFC.infiniteFlight.discoverSocket = false; }); } else { IFC.onDataReceived(data); } }); IFC.infiniteFlight.discoverSocket.on('listening', function(){ var address = IFC.infiniteFlight.discoverSocket.address(); IFC.log("IF discoverer listening on :" + address.address + ":" + address.port); }); IFC.infiniteFlight.discoverSocket.bind(IFC.infiniteFlight.broadcastPort); }, initIFClient: function(host, port) { IFC.log('initializing socket'); if (IFC.infiniteFlight.clientSocket) IFC.infiniteFlight.clientSocket.close(); IFC.beforeInitSocket(); if (!host) { return IFC.onHostUndefined(); } IFC.infiniteFlight.clientSocket = new net.Socket(); IFC.infiniteFlight.clientSocket.connect(port, host, function() { IFC.log('Connected to IF server'); IFC.onSocketConnected(); }); IFC.infiniteFlight.clientSocket.on('data', function(data) { IFC.log('Received: ' + data); try { IFC.onDataReceived(JSON.parse(IFC._ab2str(data))); } catch(e) { IFC.log(e); } }); IFC.infiniteFlight.clientSocket.on('close', function() { IFC.infiniteFlight.clientSocket = false; }); }, cmd: function(cmd) { IFC.sendCommand({ "Command": "Commands." + cmd, "Parameters": [] }) }, getAirplaneState: function(onDataReceived) { if (onDataReceived) IFC.onDataReceived = onDataReceived; IFC.sendCommand({ "Command": "Airplane.GetState", "Parameters": []}); }, sendCommand: function(cmd) { try { var jsonStr = JSON.stringify(cmd); var data = new Uint8Array(jsonStr.length + 4); data[0] = jsonStr.length; for (var i = 0; i < jsonStr.length; i++) { data[i+4] = jsonStr.charCodeAt(i); } var buffer = new Buffer(data); IFC.infiniteFlight.clientSocket.write(buffer); } catch(e) { IFC.log(e); } }, // Converters from https://developer.chrome.com/trunk/apps/app_hardware.html // String to ArrayBuffer _str2ab: function(str) { var buf=new ArrayBuffer(str.length); var bufView=new Uint8Array(buf); for (var i=0; i<str.length; i++) { bufView[i]=str.charCodeAt(i); } return buf; }, // ArrayBuffer to String _ab2str: function(buf) { return String.fromCharCode.apply(null, new Uint8Array(buf)); }, }; module.exports = IFC;