using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using BlubbFish.Utils.IoT.Connector; namespace BlubbFish.Utils.IoT.Sensor { public abstract class ASensor : IDisposable { protected String topic; protected Int32 pollcount; private Dictionary settings; protected ADataBackend backend; private Thread updateThread; private Boolean pollEnabled = false; public ASensor(Dictionary settings, String name, ADataBackend backend) { this.GetBool = true; this.GetFloat = 0.0f; this.GetInt = 0; this.topic = (settings.Keys.Contains("topic")) ? settings["topic"] : ""; this.settings = settings; this.Title = (settings.Keys.Contains("title")) ? settings["title"] : ""; this.Name = name; this.backend = backend; this.backend.MessageIncomming += this.IncommingMqttMessage; if (settings.Keys.Contains("polling")) { this.pollEnabled = true; this.Polling = Int32.Parse(settings["polling"]); this.pollcount = this.Polling; this.updateThread = new Thread(this.SensorPolling); this.updateThread.Start(); } } private void SensorPolling() { while(this.pollEnabled) { Thread.Sleep(1000); this.Poll(); } } private void IncommingMqttMessage(Object sender, MqttEventArgs e) { if(Regex.Match(e.Topic, this.topic).Success) { if (this.UpdateValue(e)) { this.Timestamp = DateTime.Now; this.Update?.Invoke(this, e); } } } public static ASensor GetInstance(ADataBackend backend, Dictionary dictionary, String name) { String object_sensor = "BlubbFish.Utils.IoT.Sensor." + Char.ToUpper(dictionary["type"][0]) + dictionary["type"].Substring(1).ToLower(); Type t = null; try { t = Type.GetType(object_sensor, true); } catch(TypeLoadException) { throw new ArgumentException("sensor.ini: " + dictionary["type"] + " is not a Sensor"); } return (ASensor)t.GetConstructor(new Type[] { typeof(Dictionary), typeof(String), typeof(ADataBackend) }).Invoke(new Object[] { dictionary, name, backend }); } protected virtual void Poll() { if(this.pollcount++ >= this.Polling) { this.pollcount = 1; this.backend.Send(this.topic + "/status",""); } } public virtual void SetBool(Boolean v) { this.backend.Send(this.topic + "/set", v ? "on" : "off"); } protected abstract Boolean UpdateValue(MqttEventArgs e); public Single GetFloat { get; protected set; } public Boolean GetBool { get; protected set; } public Int32 GetInt { get; protected set; } public Types Datatypes { get; protected set; } public DateTime Timestamp { get; protected set; } public Int32 Polling { get; private set; } public String Title { get; protected set; } public String Name { get; internal set; } public enum Types { Bool, Int, Float } public delegate void UpdatedValue(Object sender, EventArgs e); public event UpdatedValue Update; #region IDisposable Support private Boolean disposedValue = false; protected virtual void Dispose(Boolean disposing) { if(!this.disposedValue) { if(disposing) { this.pollEnabled = false; if (this.updateThread != null && this.updateThread.ThreadState == ThreadState.Running) { this.updateThread.Abort(); while (this.updateThread.ThreadState != ThreadState.Aborted) { } } this.backend.MessageIncomming -= this.IncommingMqttMessage; } this.settings = null; this.updateThread = null; this.disposedValue = true; } } ~ASensor() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } }