Example #1
0
        private SensorHost LoadSensor(string filePath)
        {
            Log.Verbose($"Loading sensor [{Path.GetFileName(filePath)}]");

            var s = new SensorHost(_client, this);

            s.LoadFromFile(filePath);

            if (s.IsCodeLoaded && s.IsCompiled)
            {
                if (!this.sensors.TryAdd(s.SensorIdentifier, s))
                {
                    Log.Debug($"Unable to load sensor [{s.SensorIdentifier}] - same sensor name exists?");
                }
                else
                {
                    Log.Debug($"Found and loaded sensor [{s.SensorIdentifier}]");
                }
            }
            else
            {
                Log.Warn($"Unable to load/compile {filePath}: [{s.GetLastError}]");
            }

            return(s);
        }
Example #2
0
        internal List <string> LoadBuiltInSensors()
        {
            System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly();

            List <string> availableSensors = new List <string>();

            var tasks = new List <Task <SensorHost> >();

            foreach (System.Reflection.TypeInfo ti in ass.DefinedTypes)
            {
                if (ti.ImplementedInterfaces.Contains(typeof(ISensor)) && ti.Name != "SensorBase")
                {
                    tasks.Add(Task.Run(() =>
                    {
                        var s = new SensorHost((ISensor)ass.CreateInstance(ti.FullName), _client, this);

                        if (s != null && !this.sensors.TryAdd(s.SensorIdentifier, s))
                        {
                            Log.Verbose($"Skipping built-in sensor [{s.SensorIdentifier}]");
                        }

                        return(s);
                    }));
                }
            }
            Task.WaitAll(tasks.ToArray());

            availableSensors.AddRange(tasks.Select(item => item.Result.SensorIdentifier).Where(ident => ident != null));

            return(availableSensors);
        }
Example #3
0
        public bool UnmapTopicToSensor(MqttMessage mqttMessage, SensorHost sensorHost)
        {
            Log.Debug($"Unmapping topic [{mqttMessage.GetRawTopic()}] for [{sensorHost.SensorIdentifier}]");

            SensorHost previous;
            bool       result;

            if (mqttMessage.GetRawTopic().Contains("/#")) // multi-level wildcard topic
            {
                sensorMultiLevelWildcardTopics.TryRemove(mqttMessage.GetRawTopic().Replace("/#", ""), out var sMultiWild);
                result = true;
            }
            else if (mqttMessage.GetRawTopic().Contains("/+")) // single level wildcard topic
            {
                sensorSingleLevelWildcardTopics.TryRemove(mqttMessage.GetRawTopic().Replace("/+", ""), out var sSingleWild);
                result = true;
            }
            else
            {
                result = sensorTopics.TryRemove(mqttMessage.GetRawTopic(), out previous);

                if (sensorHost != previous)
                {
                    Log.Warn($"{sensorHost.SensorIdentifier} unsubscribed for [{previous.SensorIdentifier}]");
                }
            }

            return(result);
        }
Example #4
0
        public bool MapTopicToSensor(MqttMessage mqttMessage, SensorHost sensorHost, bool prependDeviceId = true)
        {
            Log.Debug($"Mapping topic [{mqttMessage.GetRawTopic()}] for [{sensorHost.SensorIdentifier}]");

            bool result;

            try
            {
                mqttMessage.GetRawTopic().ValidateTopic();
            }
            catch (Exception ex)
            {
                Log.Debug($"Topic {mqttMessage.GetRawTopic()} validated false: {ex.Message}");
                return(false);
            }

            if (mqttMessage.GetRawTopic().Contains("#")) // multi-level wildcard topic
            {
                result = sensorMultiLevelWildcardTopics.TryAdd(mqttMessage.GetRawTopic(), sensorHost);
            }
            else if (mqttMessage.GetRawTopic().Contains("+"))// single level wildcard topic
            {
                result = sensorSingleLevelWildcardTopics.TryAdd(mqttMessage.GetRawTopic(), sensorHost);
            }
            else
            {
                result = sensorTopics.TryAdd(mqttMessage.GetRawTopic(), sensorHost);
            }

            return(result);
        }
Example #5
0
        /// <summary>
        /// This is called by PC2MQTT after compiling the sensor.
        /// </summary>
        /// <remarks>
        /// Load any databases, connect to any services, spin up any servers, etc.
        /// Control will be returned to the sensor in <see cref="SensorMain"/> after all sensors have loaded.
        /// Note that sensor scripts are non-blocking so other scripts will run as well, but if you take too long without
        /// returning here your sensor will be disposed because it did not initialize in a timely manner.
        /// </remarks>
        /// <param name="sensorHost"></param>
        /// <returns>True if initialized successfully, false if not.</returns>
        public bool Initialize(SensorHost sensorHost)
        {
            Log = LogManager.GetCurrentClassLogger(GetSensorIdentifier());

            this.sensorHost = sensorHost;

            Log.Info($"Finishing initialization in {this.GetSensorIdentifier()}");

            return(true);
        }
Example #6
0
        public void UnmapAlltopics(SensorHost sensorHost)
        {
            foreach (var item in sensorTopics)
            {
                if (item.Value == sensorHost && item.Value.IsCompiled && item.Value.sensor.IsInitialized)
                {
                    var mTopic = MqttMessageBuilder
                                 .NewMessage()
                                 .AddTopic(item.Key)
                                 .UnsubscribeMessage
                                 .Build();

                    Log.Debug($"Unsubscribing from [{item.Key}] for [{item.Value.sensor.GetSensorIdentifier()}]");
                    _client.Unsubscribe(mTopic);
                    sensorTopics.TryRemove(item.Key, out var removed);
                }
            }

            foreach (var item in sensorMultiLevelWildcardTopics)
            {
                if (item.Value == sensorHost && item.Value.IsCompiled && item.Value.sensor.IsInitialized)
                {
                    var mMulti = MqttMessageBuilder
                                 .NewMessage()
                                 .AddTopic(item.Key)
                                 .UnsubscribeMessage
                                 .Build();

                    Log.Debug($"Unsubscribing from [{item.Key}] for [{item.Value.sensor.GetSensorIdentifier()}]");
                    _client.Unsubscribe(mMulti);

                    sensorMultiLevelWildcardTopics.Remove(item.Key, out var removed);
                }
            }

            foreach (var item in sensorSingleLevelWildcardTopics)
            {
                if (item.Value == sensorHost && item.Value.IsCompiled && item.Value.sensor.IsInitialized)
                {
                    var mSingle = MqttMessageBuilder
                                  .NewMessage()
                                  .AddTopic(item.Key)
                                  .UnsubscribeMessage
                                  .Build();

                    Log.Debug($"Unsubscribing from [{item.Key}] for [{item.Value.sensor.GetSensorIdentifier()}]");
                    _client.Unsubscribe(mSingle);
                    sensorSingleLevelWildcardTopics.Remove(item.Key, out var removed);
                }
            }
        }
Example #7
0
        /// <inheritdoc cref="SensorBase.Initialize(SensorHost)"/>
        public new bool Initialize(SensorHost sensorHost)
        {
            // Initialize BadLogger so we can pass log messages
            Log = LogManager.GetCurrentClassLogger(GetSensorIdentifier());

            // You'll want to save this for later in the interface sensorHost object
            this.sensorHost = sensorHost;

            Log.Info($"(Initialize) CPU id: {System.Threading.Thread.GetCurrentProcessorId()} ThreadId: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
            Log.Info($"IsLinux: {CSScriptLib.Runtime.IsLinux} IsWin: {CSScriptLib.Runtime.IsWin} IsCore: { CSScriptLib.Runtime.IsCore} IsMono: {CSScriptLib.Runtime.IsMono} IsNet: {CSScriptLib.Runtime.IsNet}");

            // Initialize needs to return true relatively quickly but you can stall for a while or run processor-intensive things beforehand.
            // Control is returned to the sensor in SensorMain after initialization is complete.
            Log.Info($"We're not done initializing yet.. just a bit longer..");
            System.Threading.Thread.Sleep(2000);

            // You can save and load data types that NewtonsoftJson can handle using built-in Save/Load features shown below
            // Note that this data is only saved every 5 minutes or if the program gracefully shuts down!
            // Or you can of course roll your own save/load methods.
            string test = "hello world";

            // Save the string "hello world" under the key "test" using sensorHost's SaveData method
            sensorHost.SaveData("test", test);

            // Retrieve the string with the same key "test".
            // With this, you need to specify the type of the data you are retrieving
            var stringResult1 = sensorHost.LoadData("test", type: typeof(string));

            // This one will fail because it doesn't exist
            var stringResult2 = sensorHost.LoadData("test2", type: typeof(string));

            // This one will succeed because it has a default value supplied.
            var stringResult3 = sensorHost.LoadData("test3", "test3", type: typeof(string));

            Log.Info("Load Data [test] result: " + stringResult1);

            // Can also use other data types such as collections
            List <string> testList = new List <string>();

            testList.Add("hello");
            testList.Add("world");
            testList.Add("!");

            // save the collection under "testList"
            // Note that overWrite is true by default and only shown as an example
            sensorHost.SaveData("testList", testList, overWrite: true);

            // Load it again. Note that we're setting global = false but it's not necessary.
            // You can store global objects for use in other sensors with global = true
            // For this data, however, we need to pass the type otherwise it returns a JArray.
            List <string> resultList = sensorHost.LoadData("testList", global: false, type: typeof(List <string>));

            Log.Info($"Load Data [testList] result: Count:{resultList.Count}  [{String.Join(" ", resultList)}]");

            System.Threading.Thread.Sleep(5000);
            Log.Info($"Finishing initialization in {this.GetSensorIdentifier()}");

            // Let PC2MQTT know that we're done and initialized properly.
            // If for some reason your code didn't initialize properly you can return false
            // Just make sure to clean up after yourself as best you can.
            // uninitialized sensors are cleaned up automatically after all sensors are done loading.
            return(true);
        }
Example #8
0
 public void DisposeSensorHost(SensorHost sensorHost)
 {
     sensorHost.Dispose();
     sensorHost = null;
 }