/// <summary>
 /// Scans the registered plugins for one that handles the named API string
 /// </summary>
 /// <param name="APIname">The API string to handle, excluding any parameters</param>
 /// <returns>An API-processing delegate, or null if none were found</returns>
 public APIDelegate GetAPIDelegate(string APIname)
 {
     lock (_dataLock)
     {
         // Check our handler cache first.
         if (handlers.ContainsKey(APIname))
         {
             return(handlers[APIname]);
         }
         foreach (var plugin in registeredPlugins)
         {
             // Does this match the api at all?
             if (plugin.commands.Contains(APIname) || plugin.regexCommands.Any(x => x.IsMatch(APIname)))
             {
                 try
                 {
                     var del = plugin.apiHandler(APIname);
                     if (del != null)
                     {
                         // Add to the handling cache and the plugin response list
                         handlers[APIname] = del;
                         plugin.known_handlers.Add(APIname);
                         return(del);
                     }
                 }
                 catch (Exception ex)
                 {
                     PluginLogger.print("Got Exception processing plugin " + plugin.instance.ToString() + ", " + ex.ToString());
                 }
             }
         }
     }
     return(null);
 }
        static private void readConfiguration()
        {
            config.load();

            // Read the port out of the config file
            int port = config.GetValue <int>("PORT");

            if (port != 0 && port.IsPortNumber())
            {
                serverConfig.port = port;
            }
            else if (!port.IsPortNumber())
            {
                PluginLogger.print("Port specified in configuration file '" + serverConfig.port + "' must be a value between 1 and 65535 inclusive");
            }
            else
            {
                PluginLogger.print("No port in configuration file - using default of " + serverConfig.port.ToString());
            }

            // Read a specific IP address to bind to
            string ip = config.GetValue <String>("IPADDRESS");

            if (ip != null)
            {
                IPAddress ipAddress = null;
                if (IPAddress.TryParse(ip, out ipAddress))
                {
                    serverConfig.ipAddress = ipAddress;
                }
                else
                {
                    PluginLogger.print("Invalid IP address in configuration file, falling back to default");
                }
            }
            else
            {
                PluginLogger.print("No IP address in configuration file.");
            }

            // Fill the serverconfig list of addresses.... if IPAddress.Any, then enumerate them
            if (serverConfig.ipAddress == IPAddress.Any)
            {
                // Build a list of addresses we will be able to recieve at
                serverConfig.ValidIpAddresses.Add(IPAddress.Loopback);
                serverConfig.ValidIpAddresses.AddRange(Dns.GetHostAddresses(Dns.GetHostName()));
            }
            else
            {
                serverConfig.ValidIpAddresses.Add(serverConfig.ipAddress);
            }

            serverConfig.version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
            serverConfig.name    = "Telemachus";

            isPartless = config.GetValue <int>("PARTLESS") == 0 ? false : true;
            PluginLogger.print("Partless:" + isPartless);
        }
 static private void stopDataLink()
 {
     if (webServer != null)
     {
         PluginLogger.print("Telemachus data link shutting down.");
         webServer.Stop();
         webServer = null;
     }
 }
Beispiel #4
0
 private void updateHasTelemachusPart(Vessel vessel)
 {
     try
     {
         hasTelemachusPart = vessel.parts.FindAll(p => p.Modules.Contains("TelemachusDataLink")).Count > 0;
     }
     catch (Exception e)
     {
         PluginLogger.debug(e.Message + " " + e.StackTrace);
     }
 }
Beispiel #5
0
 static private void stopDataLink()
 {
     if (server != null)
     {
         PluginLogger.print("Telemachus data link shutting down.");
         server.stopServing();
         server = null;
         webSocketServer.stopServing();
         webSocketServer = null;
     }
 }
Beispiel #6
0
        static private void readConfiguration()
        {
            config.load();

            int port = config.GetValue <int>("PORT");

            if (port != 0)
            {
                serverConfig.port = port;
            }
            else
            {
                PluginLogger.print("No port in configuration file.");
            }

            String ip = config.GetValue <String>("IPADDRESS");

            if (ip != null)
            {
                try
                {
                    serverConfig.addIPAddressAsString(ip);
                }
                catch
                {
                    PluginLogger.print("Invalid IP address in configuration file, falling back to find.");
                }
            }
            else
            {
                PluginLogger.print("No IP address in configuration file.");
            }


            serverConfig.maxRequestLength = config.GetValue <int>("MAXREQUESTLENGTH");

            if (serverConfig.maxRequestLength < 8000)
            {
                PluginLogger.print("No max request length specified, setting to 8000.");
                serverConfig.maxRequestLength = 10000;
            }
            else
            {
                PluginLogger.print("Max request length set to:" + serverConfig.maxRequestLength);
            }

            serverConfig.version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            serverConfig.name    = "Telemachus";
            serverConfig.backLog = 1000;

            isPartless = config.GetValue <int>("PARTLESS") == 0 ? false : true;
            PluginLogger.print("Partless:" + isPartless);
        }
        public void Update()
        {
            delayedAPIRunner.execute();

            if (FlightGlobals.fetch != null)
            {
                vesselChangeDetector.update(FlightGlobals.ActiveVessel);
            }
            else
            {
                PluginLogger.debug("Flight globals was null during start up; skipping update of vessel change.");
            }
        }
 /// <summary>
 /// Deregisters an API plugin handler instance via handler reference
 /// </summary>
 /// <param name="handler">The plugin handler for the plugin</param>
 private void Deregister(PluginHandler handler)
 {
     PluginLogger.print("Removing registered plugin " + handler.instance.ToString());
     // Remove the handler caches
     lock (_dataLock)
     {
         foreach (var api in handler.known_handlers)
         {
             handlers.Remove(api);
         }
         registeredPlugins.Remove(handler);
     }
 }
 public void openBrowser()
 {
     try
     {
         Application.OpenURL("http://" + TelemachusBehaviour.getServerPrimaryIPAddress() + ":"
                             + TelemachusBehaviour.getServerPort() + "/telemachus/information.html");
     }
     catch
     {
         PluginLogger.print(
             "Unable to open the data link. Please try to edit the Telemachus configuration file manually");
     }
 }
        static private void startDataLink()
        {
            if (webServer == null)
            {
                try
                {
                    PluginLogger.print("Telemachus data link starting");

                    readConfiguration();

                    // Data access tools
                    vesselChangeDetector = new VesselChangeDetector(isPartless);
                    apiInstance          = new KSPAPI(JSONFormatterProvider.Instance, vesselChangeDetector, serverConfig, pluginManager);

                    // Create the dispatcher and handlers. Handlers added in reverse priority order so that new ones are not ignored.
                    webDispatcher = new KSPWebServerDispatcher();
                    webDispatcher.AddResponder(new ElseResponsibility());
                    webDispatcher.AddResponder(new IOPageResponsibility());
                    var cameraLink = new CameraResponsibility(apiInstance, rateTracker);
                    webDispatcher.AddResponder(cameraLink);
                    var dataLink = new DataLinkResponsibility(apiInstance, rateTracker);
                    webDispatcher.AddResponder(dataLink);

                    // Create the server and associate the dispatcher
                    webServer         = new HttpServer(serverConfig.ipAddress, serverConfig.port);
                    webServer.OnGet  += webDispatcher.DispatchRequest;
                    webServer.OnPost += webDispatcher.DispatchRequest;

                    // Create the websocket server and attach to the web server
                    webServer.AddWebSocketService("/datalink", () => new KSPWebSocketService(apiInstance, rateTracker));

                    // Finally, start serving requests!
                    try {
                        webServer.Start();
                    } catch (Exception ex)
                    {
                        PluginLogger.print("Error starting web server: " + ex.ToString());
                        throw;
                    }

                    PluginLogger.print("Telemachus data link listening for requests on the following addresses: ("
                                       + string.Join(", ", serverConfig.ValidIpAddresses.Select(x => x.ToString() + ":" + serverConfig.port.ToString()).ToArray())
                                       + "). Try putting them into your web browser, some of them might not work.");
                }
                catch (Exception e)
                {
                    PluginLogger.print(e.Message);
                    PluginLogger.print(e.StackTrace);
                }
            }
        }
Beispiel #11
0
        public void Update()
        {
            delayedAPIRunner.execute();

            if (FlightGlobals.fetch != null)
            {
                vesselChangeDetector.update(FlightGlobals.ActiveVessel);
                kspWebSocketDataStreamer.update(new UpdateTimerEventArgs(Time.time * MICRO_SECONDS));
            }
            else
            {
                PluginLogger.debug("Flight globals was null during start up; skipping update of vessel change.");
            }
        }
Beispiel #12
0
        public bool process(Servers.AsynchronousServer.ClientConnection cc, HTTPRequest request)
        {
            DataSources dataSources = new DataSources();

            if (request.path.StartsWith(PAGE_PREFIX))
            {
                if (request.requestType == HTTPRequest.GET)
                {
                    dataRates.addUpLinkPoint(System.DateTime.Now, request.path.Length * UpLinkDownLinkRate.BITS_PER_BYTE);
                }
                else if (request.requestType == HTTPRequest.POST)
                {
                    dataRates.addUpLinkPoint(System.DateTime.Now, request.content.Length * UpLinkDownLinkRate.BITS_PER_BYTE);
                }

                try
                {
                    dataSources.vessel = kspAPI.getVessel();
                }
                catch (Exception e)
                {
                    PluginLogger.debug(e.Message + " " + e.StackTrace);
                }

                if (request.requestType == HTTPRequest.GET)
                {
                    dataRates.addDownLinkPoint(
                        System.DateTime.Now,
                        ((Servers.MinimalHTTPServer.ClientConnection)cc).Send(new OKResponsePage(
                                                                                  argumentsParse(request.path.Remove(0,
                                                                                                                     request.path.IndexOf(ARGUMENTS_START) + 1),
                                                                                                 dataSources)
                                                                                  )) * UpLinkDownLinkRate.BITS_PER_BYTE);
                }
                else if (request.requestType == HTTPRequest.POST)
                {
                    dataRates.addDownLinkPoint(
                        System.DateTime.Now,
                        ((Servers.MinimalHTTPServer.ClientConnection)cc).Send(new OKResponsePage(
                                                                                  argumentsParse(request.content,
                                                                                                 dataSources)
                                                                                  )) * UpLinkDownLinkRate.BITS_PER_BYTE);
                }

                return(true);
            }

            return(false);
        }
 /// Iterate over all responders to find one that works
 public void DispatchRequest(object sender, HttpRequestEventArgs request)
 {
     foreach (var responder in responderChain.Reverse <IHTTPRequestResponder>())
     {
         try {
             if (responder.process(request.Request, request.Response))
             {
                 return;
             }
         } catch (Exception ex) {
             PluginLogger.print("Caught exception in web handlers: " + ex.ToString());
         }
     }
     // If here, we had no responder.
     request.Response.StatusCode = (int)HttpStatusCode.NotFound;
 }
        /// <summary>
        /// Registers a plugin API with Telemachus
        /// </summary>
        /// <param name="toRegister">An instance of a Plugin object, that conforms to the TelemachusPlugin interface.
        /// NOTE: Does NOT have to be a physical instance of the interface.</param>
        /// <returns>An Action, calling of which Deregisters the plugin. This is disposeable.</returns>
        public void Register(object toRegister)
        {
            var pluginType = toRegister.GetType();

            // Must conform at least to the minimal interface
            if (!typeof(IMinimalTelemachusPlugin).IsAssignableFrom(pluginType) && !pluginType.DoesMatchInterfaceOf(typeof(IMinimalTelemachusPlugin)))
            {
                throw new ArgumentException("Object " + toRegister.GetType().ToString() + " does not conform to the minimal interface");
            }

            var handler = new PluginHandler()
            {
                instance = toRegister
            };
            // Get a list of commands that this instance handles
            var commands = ReadCommandList(toRegister);
            // Get the plugin handler function
            var apiMethod = toRegister.GetType().GetMethod("GetAPIHandler", new Type[] { typeof(string) });

            handler.apiHandler = (APIHandler)Delegate.CreateDelegate(typeof(APIHandler), toRegister, apiMethod);

            // Does it match the Deregistration? If so, pass it the deregistration method
            if (toRegister is IDeregisterableTelemachusPlugin || pluginType.DoesMatchInterfaceOf(typeof(IDeregisterableTelemachusPlugin)))
            {
                Action deregistration = () => Deregister(handler);
                pluginType.GetProperty("Deregister").SetValue(toRegister, deregistration, null);
                handler.is_deregisterable = true;
            }

            var optional_interfaces = new List <string>();

            if (handler.is_deregisterable)
            {
                optional_interfaces.Add("Deregister");
            }
            PluginLogger.print("Got plugin registration call for " + toRegister.GetType() + ".\n  Optional interfaces enabled: " + (optional_interfaces.Count == 0 ? "None" : string.Join(", ", optional_interfaces.ToArray())));

            // Make a simple hashset of basic commands
            handler.commands = new HashSet <string>(commands.Where(x => !x.Contains("*")));
            // Now, deal with any wildcard plugin strings by building a regex
            handler.regexCommands = commands
                                    .Where(x => x.Contains("*"))
                                    .Select(x => new Regex("^" + x.Replace(".", "\\.").Replace("*", ".*") + "$")).ToList();

            lock (_dataLock)
                registeredPlugins.Add(handler);
        }
Beispiel #15
0
        public bool process(HttpListenerRequest request, HttpListenerResponse response)
        {
            PluginLogger.print("Falling back on default handler");

            // For now, copy the behaviour until we understand it more
            if (!KSP.IO.FileInfo.CreateForType <TelemachusDataLink>(INDEX_PAGE).Exists)
            {
                throw new FileNotFoundException("Unable to find the Telemachus index page. Is it installed in the PluginData folder?");
            }
            else if (request.RawUrl == "/" || request.RawUrl.ToLowerInvariant().StartsWith("/index"))
            {
                // Just redirect them
                var index = new Uri(request.Url, "/" + INDEX_PAGE);
                response.Redirect(index.ToString());
                return(true);
            }
            return(false);
        }
        private void rate(string p)
        {
            int proposedRate = 0;

            try
            {
                proposedRate = int.Parse(p);

                if (proposedRate >= MAX_STREAM_RATE)
                {
                    streamRate = proposedRate;
                }
            }
            catch (Exception)
            {
                PluginLogger.debug("Swallowing integer parse failure when setting stream rate.");
            }
        }
Beispiel #17
0
        static private void startDataLink()
        {
            if (server == null)
            {
                try
                {
                    PluginLogger.print("Telemachus data link starting");

                    readConfiguration();

                    server = new Server(serverConfig);
                    server.ServerNotify += HTTPServerNotify;
                    server.addHTTPResponsibility(new ElseResponsibility());
                    ioPageResponsibility = new IOPageResponsibility();
                    server.addHTTPResponsibility(ioPageResponsibility);

                    vesselChangeDetector = new VesselChangeDetector(isPartless);

                    dataLinkResponsibility = new DataLinkResponsibility(serverConfig, new KSPAPI(JSONFormatterProvider.Instance, vesselChangeDetector, serverConfig));
                    server.addHTTPResponsibility(dataLinkResponsibility);

                    Servers.MinimalWebSocketServer.ServerConfiguration webSocketconfig = new Servers.MinimalWebSocketServer.ServerConfiguration();
                    webSocketconfig.bufferSize    = 300;
                    webSocketServer               = new Servers.MinimalWebSocketServer.Server(webSocketconfig);
                    webSocketServer.ServerNotify += WebSocketServerNotify;
                    kspWebSocketService           = new KSPWebSocketService(new KSPAPI(JSONFormatterProvider.Instance, vesselChangeDetector, serverConfig),
                                                                            kspWebSocketDataStreamer);
                    webSocketServer.addWebSocketService("/datalink", kspWebSocketService);
                    webSocketServer.subscribeToHTTPForStealing(server);

                    server.startServing();

                    PluginLogger.print("Telemachus data link listening for requests on the following addresses: ("
                                       + server.getIPsAsString() +
                                       "). Try putting them into your web browser, some of them might not work.");
                }
                catch (Exception e)
                {
                    PluginLogger.print(e.Message);
                    PluginLogger.print(e.StackTrace);
                }
            }
        }
        public void Update()
        {
            delayedAPIRunner.execute();

            if (FlightGlobals.fetch != null)
            {
                vesselChangeDetector.update(FlightGlobals.ActiveVessel);

                foreach (var client in webServer.WebSocketServices["/datalink"].Sessions.Sessions.OfType <KSPWebSocketService>())
                {
                    if (client.UpdateRequired(Time.time))
                    {
                        client.SendDataUpdate();
                    }
                }
            }
            else
            {
                PluginLogger.debug("Flight globals was null during start up; skipping update of vessel change.");
            }
        }
        static private void readConfiguration()
        {
            config.load();

            int port = config.GetValue <int>("PORT");

            if (port != 0)
            {
                serverConfig.port = port;
            }
            else
            {
                PluginLogger.print("No port in configuration file.");
            }

            String ip = config.GetValue <String>("IPADDRESS");

            if (ip != null)
            {
                try
                {
                    serverConfig.addIPAddressAsString(ip);
                }
                catch
                {
                    PluginLogger.print("Invalid IP address in configuration file, falling back to find.");
                }
            }
            else
            {
                PluginLogger.print("No IP address in configuration file.");
            }

            serverConfig.maxRequestLength = 8000;

            serverConfig.version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            serverConfig.name    = "Telemachus";
            serverConfig.backLog = 1000;
        }
        public void parseParams(ref String arg, ref DataSources dataSources)
        {
            dataSources.args.Clear();

            try
            {
                if (arg.Contains("["))
                {
                    String[] argsSplit = arg.Split('[');
                    argsSplit[1] = argsSplit[1].Substring(0, argsSplit[1].Length - 1);
                    arg          = argsSplit[0];
                    String[] paramSplit = argsSplit[1].Split(',');

                    for (int i = 0; i < paramSplit.Length; i++)
                    {
                        dataSources.args.Add(paramSplit[i]);
                    }
                }
            }
            catch (Exception e)
            {
                PluginLogger.debug(e.Message + " " + e.StackTrace);
            }
        }
Beispiel #21
0
        private String argumentsParse(String args, DataSources dataSources)
        {
            APIEntry currentEntry = null;
            var      APIResults   = new Dictionary <string, object>();

            String[] argsSplit = args.Split(ARGUMENTS_DELIMETER);

            foreach (String arg in argsSplit)
            {
                string refArg = arg;
                PluginLogger.fine(refArg);
                kspAPI.parseParams(ref refArg, ref dataSources);
                currentEntry = argumentParse(refArg, dataSources);
                APIResults[dataSources.getVarName()] = currentEntry.formatter.prepareForSerialization(currentEntry.function(dataSources));

                //Only parse the paused argument if the active vessel is null
                if (dataSources.vessel == null)
                {
                    break;
                }
            }

            return(SimpleJson.SimpleJson.SerializeObject(APIResults));
        }
        private String argumentsParse(String args, DataSources dataSources)
        {
            APIEntry      currentEntry = null;
            List <string> APIResults   = new List <string>();

            String[] argsSplit = args.Split(ARGUMENTS_DELIMETER);

            foreach (String arg in argsSplit)
            {
                string refArg = arg;
                PluginLogger.fine(refArg);
                kspAPI.parseParams(ref refArg, ref dataSources);
                currentEntry = argumentParse(refArg, dataSources);
                APIResults.Add(currentEntry.formatter.format(currentEntry.function(dataSources)));

                //Only parse the paused argument if the active vessel is null
                if (dataSources.vessel == null)
                {
                    break;
                }
            }

            return(currentEntry.formatter.pack(APIResults));
        }
        private void streamData(object sender, ElapsedEventArgs e)
        {
            streamTimer.Interval = streamRate;

            DataSources dataSources = new DataSources();

            if (toRun.Count + subscriptions.Count > 0)
            {
                try
                {
                    List <string> entries = new List <string>();

                    APIEntry entry = null;

                    lock (subscriptionLock)
                    {
                        dataSources.vessel = kspAPI.getVessel();

                        //Only parse the paused argument if the active vessel is null
                        if (dataSources.vessel != null)
                        {
                            toRun.UnionWith(subscriptions);

                            foreach (string s in toRun)
                            {
                                DataSources dataSourcesClone = dataSources.Clone();
                                string      trimedQuotes     = s.Trim();
                                string      refArg           = trimedQuotes;
                                kspAPI.parseParams(ref refArg, ref dataSourcesClone);

                                kspAPI.process(refArg, out entry);

                                if (entry != null)
                                {
                                    dataSourcesClone.setVarName(trimedQuotes);
                                    entries.Add(entry.formatter.format(entry.function(dataSourcesClone), dataSourcesClone.getVarName()));
                                }
                            }

                            toRun.Clear();

                            if (entry != null)
                            {
                                WebSocketFrame frame  = new WebSocketFrame(ASCIIEncoding.UTF8.GetBytes(entry.formatter.pack(entries)));
                                byte[]         bFrame = frame.AsBytes();
                                dataRates.addDownLinkPoint(System.DateTime.Now, bFrame.Length * UpLinkDownLinkRate.BITS_PER_BYTE);
                                clientConnection.Send(bFrame);
                            }
                        }
                        else
                        {
                            sendNullMessage();
                        }
                    }
                }
                catch (NullReferenceException)
                {
                    PluginLogger.debug("Swallowing null reference exception, potentially due to async game state change.");
                    sendNullMessage();
                }
                catch (Exception ex)
                {
                    PluginLogger.debug("Closing socket due to potential client disconnect:" + ex.GetType().ToString());
                    close();
                }
            }
            else
            {
                sendNullMessage();
            }
        }
        }     // OnMessage

        /// Read all variables and send back the responses for just this client
        public void SendDataUpdate()
        {
            // Don't do anything if we are e.g. still awaiting data to be fully set
            if (!readyToSend)
            {
                return;
            }
            lastUpdate = UnityEngine.Time.time;

            // Grab all of the variables at once
            string[] allVariables;
            lock (dataLock)
            {
                allVariables = subscriptions.Union(oneShotRuns).Union(binarySubscriptions).ToArray();
                oneShotRuns.Clear();
            }

            var vessel = api.getVessel();

            // Now, process them all into a data dictionary
            var apiResults = new Dictionary <string, object>();
            var unknowns   = new List <string>();
            var errors     = new Dictionary <string, string>();

            foreach (var apiString in allVariables)
            {
                try
                {
                    apiResults[apiString] = api.ProcessAPIString(apiString);
                }
                catch (IKSPAPI.UnknownAPIException)
                {
                    // IF we get this message, we know it was because no variable was found
                    unknowns.Add(apiString);
                } catch (IKSPAPI.VariableNotEvaluable)
                {
                    // We can't evaluate this at the moment. Just ignore until we can.
                } catch (Exception ex)
                {
                    errors[apiString] = ex.ToString();
                }
            }
            if (unknowns.Count > 0)
            {
                apiResults["unknown"] = unknowns;
            }
            if (errors.Count > 0)
            {
                apiResults["errors"] = errors;
            }

            // Handle sending a binary packet if requested
            if (binarySubscriptions.Length > 0)
            {
                var variableValues = new List <float>();
                // Read every binary value
                foreach (var name in binarySubscriptions)
                {
                    try {
                        variableValues.Add(Convert.ToSingle(apiResults[name]));
                    } catch (Exception ex)
                    {
                        variableValues.Add(0);
                        if (apiResults.ContainsKey(name))
                        {
                            errors[name] = "Error streaming to binary " + name + "='" + apiResults[name] + "'; " + ex.ToString();
                        }
                        else
                        {
                            errors[name] = "Error streaming to binary: value for " + name + " not found; " + ex.ToString();
                        }
                    }
                }
                // Which byte translation?
                Func <float, IEnumerable <byte> > reverser = x => BitConverter.GetBytes(x).Reverse();
                var byteTranslation = BitConverter.IsLittleEndian ? reverser : BitConverter.GetBytes;

                // Now translate these to binary bytes
                var byteData = new List <byte>();
                byteData.Add(1);
                byteData.AddRange(variableValues.SelectMany(x => byteTranslation(x)));
                SendAsync(byteData.ToArray(), x => { });
            }

            //if (allVariables.Contains("binaryNavigation"))
            //{
            //    allVariables = allVariables.Where(x => x != "binaryNavigation").ToArray();
            //    // Build and dispatch the binary information, here and quickly....
            //    var pitch = Convert.ToSingle(api.ProcessAPIString("n.pitch"));
            //    var roll = Convert.ToSingle(api.ProcessAPIString("n.roll"));
            //    var heading = Convert.ToSingle(api.ProcessAPIString("n.heading"));
            //    var deltaV = Convert.ToSingle(api.ProcessAPIString("v.verticalSpeed"));
            //    var parts = new List<byte[]>();
            //    parts.Add(new byte[] { 1 });
            //    parts.Add(BitConverter.GetBytes(heading));
            //    parts.Add(BitConverter.GetBytes(pitch));
            //    parts.Add(BitConverter.GetBytes(roll));
            //    parts.Add(BitConverter.GetBytes(deltaV));
            //    if (BitConverter.IsLittleEndian) parts = parts.Select(x => x.Reverse().ToArray()).ToList();
            //    var byteData = parts.SelectMany(x => x).ToArray();
            //    SendAsync(byteData, x => { });
            //    PluginLogger.print(string.Format("Send byte data for {0}, {1}, {2}, {3}", heading, pitch, roll, deltaV));
            //}

            var data = SimpleJson.SimpleJson.SerializeObject(apiResults);

            // Now, if we have data send a message, otherwise send a null message
            readyToSend = false;
            try
            {
                SendAsync(data, (b) => readyToSend = true);
                dataRates.SendDataToClient(data.Length);
            }
            catch (Exception ex)
            {
                PluginLogger.print("Caught " + ex.ToString());
            }
            finally
            {
                readyToSend = true;
            }
        }
        /// Process a message recieved from a client
        protected override void OnMessage(MessageEventArgs e)
        {
            // We only care about text messages, for now.
            if (e.Type != Opcode.Text)
            {
                return;
            }
            dataRates.RecieveDataFromClient(e.RawData.Length);

            // deserialize the message as JSON
            var json = SimpleJson.SimpleJson.DeserializeObject(e.Data) as SimpleJson.JsonObject;

            lock (dataLock)
            {
                // Do any tasks requested here
                foreach (var entry in json)
                {
                    // Try converting the item to a list - this is the most common expected.
                    // If we got a string, then add it to the list to allow "one-shot" submission
                    string[] listContents = new string[] { };
                    if (entry.Value is SimpleJson.JsonArray)
                    {
                        listContents = (entry.Value as SimpleJson.JsonArray).OfType <string>().Select(x => x.Trim()).ToArray();
                    }
                    else if (entry.Value is string)
                    {
                        listContents = new[] { entry.Value as string };
                    }

                    // Process the possible API entries
                    if (entry.Key == "+")
                    {
                        PluginLogger.print(string.Format("Client {0} added {1}", ID, string.Join(",", listContents)));
                        subscriptions.UnionWith(listContents);
                    }
                    else if (entry.Key == "-")
                    {
                        PluginLogger.print(string.Format("Client {0} removed {1}", ID, string.Join(",", listContents)));
                        subscriptions.ExceptWith(listContents);
                    }
                    else if (entry.Key == "run")
                    {
                        PluginLogger.print(string.Format("Client {0} running {1}", ID, string.Join(",", listContents)));
                        oneShotRuns.UnionWith(listContents);
                    }
                    else if (entry.Key == "rate")
                    {
                        streamRate = Convert.ToInt32(entry.Value);
                        PluginLogger.print(string.Format("Client {0} setting rate {1}", ID, streamRate));
                    }
                    else if (entry.Key == "binary")
                    {
                        binarySubscriptions = listContents;
                        PluginLogger.print(string.Format("Client {0} requests binary packets {1}", ID, string.Join(", ", listContents)));
                    }
                    else
                    {
                        PluginLogger.print(String.Format("Client {0} send unrecognised key {1}", ID, entry.Key));
                    }
                }
            } // Lock
        }     // OnMessage
        void LookForModsToInject()
        {
            string foundMods = "Loading; Looking for compatible mods to inject registration....\nTelemachus compatible modules Found:\n";
            int    found     = 0;

            foreach (var asm in AssemblyLoader.loadedAssemblies)
            {
                foreach (var type in asm.assembly.GetTypes())
                {
                    if (type.IsSubclassOf(typeof(MonoBehaviour)))
                    {
                        // Does this have a static property named "Func<string> TelemachusPluginRegister { get; set; }?
                        var prop = type.GetProperty("TelemachusPluginRegister", BindingFlags.Static | BindingFlags.Public);
                        if (prop == null)
                        {
                            continue;
                        }
                        found     += 1;
                        foundMods += "  - " + type.ToString() + " ";
                        if (prop.PropertyType != typeof(Action <object>))
                        {
                            foundMods += "(Fail - Invalid property type)\n";
                            continue;
                        }

                        if (!prop.CanWrite)
                        {
                            foundMods += "(Fail - Property not writeable)\n";
                            continue;
                        }
                        // Can we read it - if so, only write if it is not null.
                        if (prop.CanRead)
                        {
                            if (prop.GetValue(null, null) != null)
                            {
                                foundMods += "(Fail - Property not null)\n";
                                continue;
                            }
                        }
                        // Write the value here
                        Action <object> pluginRegister = PluginRegistration.Register;
                        prop.SetValue(null, pluginRegister, null);
                        foundMods += "(Success)\n";
                    }
                }
            }
            if (found == 0)
            {
                foundMods += "  None\n";
            }

            foundMods += "Internal plugins loaded:\n";
            found      = 0;
            // Look for any mods in THIS assembly that inherit ITelemachusMinimalPlugin...
            foreach (var typ in Assembly.GetExecutingAssembly().GetTypes())
            {
                try {
                    if (!typeof(IMinimalTelemachusPlugin).IsAssignableFrom(typ))
                    {
                        continue;
                    }
                    // Make sure we have a default constructor
                    if (typ.GetConstructor(Type.EmptyTypes) == null)
                    {
                        continue;
                    }
                    // We have found a plugin internally. Instantiate it
                    PluginRegistration.Register(Activator.CreateInstance(typ));

                    foundMods += "  - " + typ.ToString() + "\n";
                    found     += 1;
                } catch (Exception ex)
                {
                    PluginLogger.print("Exception caught whilst loading internal plugin " + typ.ToString() + "; " + ex.ToString());
                }
            }
            if (found == 0)
            {
                foundMods += "  None";
            }
            PluginLogger.print(foundMods);
        }
Beispiel #27
0
 private static void WebSocketServerNotify(object sender, Servers.NotifyEventArgs e)
 {
     PluginLogger.debug(e.message);
 }