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); }
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); }
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); }
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); }
/// <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); }
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); } } }
/// <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); }
public void DisposeSensorHost(SensorHost sensorHost) { sensorHost.Dispose(); sensorHost = null; }