diff --git a/Bot-Utils/ABot.cs b/Bot-Utils/ABot.cs new file mode 100644 index 0000000..86da32b --- /dev/null +++ b/Bot-Utils/ABot.cs @@ -0,0 +1,48 @@ +using System; +using System.Threading; + +namespace BlubbFish.Utils.IoT.Bots { + public abstract class ABot { + private Thread sig_thread; + private Boolean RunningProcess = true; + + protected ProgramLogger logger = new ProgramLogger(); + + private void SetupShutdown(Object sender, ConsoleCancelEventArgs e) { + e.Cancel = true; + Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.SetupShutdown: Signalhandler Windows INT recieved."); + this.RunningProcess = false; + } + + protected void WaitForShutdown() { + if(Type.GetType("Mono.Runtime") != null) { + this.sig_thread = new Thread(delegate () { + Mono.Unix.UnixSignal[] signals = new Mono.Unix.UnixSignal[] { + new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGTERM), + new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGINT) + }; + Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Mono attached."); + while(true) { + Int32 i = Mono.Unix.UnixSignal.WaitAny(signals, -1); + Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Mono INT recieved " + i + "."); + this.RunningProcess = false; + break; + } + }); + this.sig_thread.Start(); + } else { + Console.CancelKeyPress += new ConsoleCancelEventHandler(this.SetupShutdown); + Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Windows attached."); + } + while(this.RunningProcess) { + Thread.Sleep(100); + } + } + + public virtual void Dispose() { + if(this.sig_thread != null && this.sig_thread.IsAlive) { + this.sig_thread.Abort(); + } + } + } +} diff --git a/Bot-Utils/Bot-Utils.csproj b/Bot-Utils/Bot-Utils.csproj index d00ac9c..d603c05 100644 --- a/Bot-Utils/Bot-Utils.csproj +++ b/Bot-Utils/Bot-Utils.csproj @@ -46,6 +46,7 @@ + @@ -59,6 +60,7 @@ + diff --git a/Bot-Utils/Bot.cs b/Bot-Utils/Bot.cs index 440d812..9ce050f 100644 --- a/Bot-Utils/Bot.cs +++ b/Bot-Utils/Bot.cs @@ -1,57 +1,20 @@ using System; using System.Collections.Generic; using System.Reflection; -using System.Threading; -using BlubbFish.Utils.IoT.Bots.Moduls; using BlubbFish.Utils.IoT.Bots.Events; using BlubbFish.Utils.IoT.Bots.Interfaces; +using BlubbFish.Utils.IoT.Bots.Moduls; namespace BlubbFish.Utils.IoT.Bots { - public abstract class Bot { - private Thread sig_thread; - private Boolean RunningProcess = true; - protected ProgramLogger logger = new ProgramLogger(); - protected readonly Dictionary> moduls = new Dictionary>(); - - protected void WaitForShutdown() { - if (Type.GetType("Mono.Runtime") != null) { - this.sig_thread = new Thread(delegate () { - Mono.Unix.UnixSignal[] signals = new Mono.Unix.UnixSignal[] { - new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGTERM), - new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGINT) - }; - Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Mono attached."); - while (true) { - Int32 i = Mono.Unix.UnixSignal.WaitAny(signals, -1); - Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Mono INT recieved " + i + "."); - this.RunningProcess = false; - break; - } - }); - this.sig_thread.Start(); - } else { - Console.CancelKeyPress += new ConsoleCancelEventHandler(this.SetupShutdown); - Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Windows attached."); - } - while (this.RunningProcess) { - Thread.Sleep(100); - } - } - - private void SetupShutdown(Object sender, ConsoleCancelEventArgs e) { - e.Cancel = true; - Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.SetupShutdown: Signalhandler Windows INT recieved."); - this.RunningProcess = false; - } - + public abstract class Bot : ABot { + protected readonly Dictionary> moduls = new Dictionary>(); + protected void ModulDispose() { foreach (KeyValuePair> item in this.moduls) { item.Value.Dispose(); Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulDispose: Modul entladen: " + item.Key); } - if (this.sig_thread != null && this.sig_thread.IsAlive) { - this.sig_thread.Abort(); - } + this.Dispose(); } protected void ModulLoader(String @namespace, Object library) { @@ -92,8 +55,6 @@ namespace BlubbFish.Utils.IoT.Bots { } } - protected void ModulUpdate(Object sender, ModulEventArgs e) { - Console.WriteLine(e.ToString()); - } + protected void ModulUpdate(Object sender, ModulEventArgs e) => Console.WriteLine(e.ToString()); } } diff --git a/Bot-Utils/Moduls/AModul.cs b/Bot-Utils/Moduls/AModul.cs index 5d3d463..59c90cd 100644 --- a/Bot-Utils/Moduls/AModul.cs +++ b/Bot-Utils/Moduls/AModul.cs @@ -54,9 +54,7 @@ namespace BlubbFish.Utils.IoT.Bots.Moduls { protected abstract void LibUpadteThread(Object state); - protected void HandleLibUpdate(Object sender, EventArgs e) { - ThreadPool.QueueUserWorkItem(this.LibUpadteThread, e); - } + protected void HandleLibUpdate(Object sender, EventArgs e) => ThreadPool.QueueUserWorkItem(this.LibUpadteThread, e); public abstract void Dispose(); diff --git a/Bot-Utils/Moduls/Mqtt.cs b/Bot-Utils/Moduls/Mqtt.cs index 3dabcbe..144bcce 100644 --- a/Bot-Utils/Moduls/Mqtt.cs +++ b/Bot-Utils/Moduls/Mqtt.cs @@ -1,119 +1,102 @@ -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Threading; -using BlubbFish.Utils.IoT.Bots.Events; -using BlubbFish.Utils.IoT.Connector; -using BlubbFish.Utils.IoT.Events; -using LitJson; - -namespace BlubbFish.Utils.IoT.Bots.Moduls { - public abstract class Mqtt : AModul, IDisposable { - protected readonly Thread connectionWatcher; - protected ABackend mqtt; - protected Dictionary> modules; - - #region Constructor - public Mqtt(T lib, InIReader settings) : base(lib, settings) { - if (this.config.ContainsKey("settings")) { - this.connectionWatcher = new Thread(this.ConnectionWatcherRunner); - this.connectionWatcher.Start(); - } else { - throw new ArgumentException("Setting section [settings] is missing!"); - } - } - #endregion - - #region Watcher - protected void ConnectionWatcherRunner() { - while (true) { - try { - if (this.mqtt == null || !this.mqtt.IsConnected) { - this.Reconnect(); - } - Thread.Sleep(10000); - } catch (Exception) { } - } - } - - protected void Reconnect() { - Console.WriteLine("BlubbFish.Utils.IoT.Bots.Moduls.Mqtt.Reconnect()"); - this.Disconnect(); - this.Connect(); - } - - protected abstract void Connect(); - - protected abstract void Disconnect(); - #endregion - - #region AModul - public override void Interconnect(Dictionary> moduls) { - this.modules = moduls; - } - - protected override void UpdateConfig() { - this.Reconnect(); - } - #endregion - - protected Tuple ChangeConfig(BackendEvent e, String topic) { - if (e.From.ToString().StartsWith(topic) && (e.From.ToString().EndsWith("/set") || e.From.ToString().EndsWith("/get"))) { - Match m = new Regex("^"+ topic + "(\\w+)/[gs]et$|").Match(e.From.ToString()); - if (!m.Groups[1].Success) { - return new Tuple(false, null); - } - AModul modul = null; - foreach (KeyValuePair> item in this.modules) { - if (item.Key.ToLower() == m.Groups[1].Value) { - modul = item.Value; - } - } - if (modul == null) { - return new Tuple(false, null); - } - if (e.From.ToString().EndsWith("/get") && modul.HasConfig && modul.ConfigPublic) { - String t = topic + m.Groups[1].Value; - String d = JsonMapper.ToJson(modul.GetConfig()).ToString(); - ((ADataBackend)this.mqtt).Send(t, d); - return new Tuple(true, new MqttEvent(t, d)); - } else if (e.From.ToString().EndsWith("/set") && modul.HasConfig && modul.ConfigPublic) { - try { - JsonData a = JsonMapper.ToObject(e.Message); - Dictionary> newconf = new Dictionary>(); - foreach (String section in a.Keys) { - Dictionary sectiondata = new Dictionary(); - foreach (String item in a[section].Keys) { - sectiondata.Add(item, a[section][item].ToString()); - } - newconf.Add(section, sectiondata); - } - modul.SetConfig(newconf); - return new Tuple(true, new MqttEvent("New Config", "Write")); - } catch (Exception) { } - } - } - return new Tuple(false, null); - } - - #region IDisposable Support - private Boolean disposedValue = false; - - protected void Dispose(Boolean disposing) { - if (!this.disposedValue) { - if (disposing) { - this.connectionWatcher.Abort(); - while (this.connectionWatcher.ThreadState == ThreadState.Running) { Thread.Sleep(10); } - this.Disconnect(); - } - this.disposedValue = true; - } - } - - public override void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using BlubbFish.Utils.IoT.Bots.Events; +using BlubbFish.Utils.IoT.Connector; +using BlubbFish.Utils.IoT.Events; +using LitJson; + +namespace BlubbFish.Utils.IoT.Bots.Moduls { + public abstract class Mqtt : AModul, IDisposable { + protected ABackend mqtt; + protected Dictionary> modules; + + #region Constructor + public Mqtt(T lib, InIReader settings) : base(lib, settings) => this.Connect(); + #endregion + + #region Connection + protected void Reconnect() { + if(!this.config.ContainsKey("settings")) { + throw new ArgumentException("Setting section [settings] is missing!"); + } else { + this.Disconnect(); + this.Connect(); + } + } + + protected void Connect() { + if(!this.config.ContainsKey("settings")) { + throw new ArgumentException("Setting section [settings] is missing!"); + } else { + this.mqtt = ABackend.GetInstance(this.config["settings"], ABackend.BackendType.Data); + } + } + + protected void Disconnect() => this.mqtt.Dispose(); + #endregion + + #region AModul + public override void Interconnect(Dictionary> moduls) => this.modules = moduls; + + protected override void UpdateConfig() => this.Reconnect(); + #endregion + + protected Tuple ChangeConfig(BackendEvent e, String topic) { + if (e.From.ToString().StartsWith(topic) && (e.From.ToString().EndsWith("/set") || e.From.ToString().EndsWith("/get"))) { + Match m = new Regex("^"+ topic + "(\\w+)/[gs]et$|").Match(e.From.ToString()); + if (!m.Groups[1].Success) { + return new Tuple(false, null); + } + AModul modul = null; + foreach (KeyValuePair> item in this.modules) { + if (item.Key.ToLower() == m.Groups[1].Value) { + modul = item.Value; + } + } + if (modul == null) { + return new Tuple(false, null); + } + if (e.From.ToString().EndsWith("/get") && modul.HasConfig && modul.ConfigPublic) { + String t = topic + m.Groups[1].Value; + String d = JsonMapper.ToJson(modul.GetConfig()).ToString(); + ((ADataBackend)this.mqtt).Send(t, d); + return new Tuple(true, new MqttEvent(t, d)); + } else if (e.From.ToString().EndsWith("/set") && modul.HasConfig && modul.ConfigPublic) { + try { + JsonData a = JsonMapper.ToObject(e.Message); + Dictionary> newconf = new Dictionary>(); + foreach (String section in a.Keys) { + Dictionary sectiondata = new Dictionary(); + foreach (String item in a[section].Keys) { + sectiondata.Add(item, a[section][item].ToString()); + } + newconf.Add(section, sectiondata); + } + modul.SetConfig(newconf); + return new Tuple(true, new MqttEvent("New Config", "Write")); + } catch { } + } + } + return new Tuple(false, null); + } + + #region IDisposable Support + private Boolean disposedValue = false; + + protected void Dispose(Boolean disposing) { + if (!this.disposedValue) { + if (disposing) { + this.Disconnect(); + } + this.disposedValue = true; + } + } + + public override void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/Bot-Utils/MultiSourceBot.cs b/Bot-Utils/MultiSourceBot.cs new file mode 100644 index 0000000..9b2bd28 --- /dev/null +++ b/Bot-Utils/MultiSourceBot.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.Utils.IoT.Bots { + public abstract class MultiSourceBot : ABot { + protected Dictionary sources; + protected Dictionary settings; + + protected MultiSourceBot(Dictionary sources, Dictionary settings) { + this.sources = sources; + this.settings = settings; + } + } +} diff --git a/Bot-Utils/Properties/AssemblyInfo.cs b/Bot-Utils/Properties/AssemblyInfo.cs index 30e939b..bc7dd4a 100644 --- a/Bot-Utils/Properties/AssemblyInfo.cs +++ b/Bot-Utils/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Resources; using System.Runtime.InteropServices; // Allgemeine Informationen über eine Assembly werden über die folgenden @@ -9,9 +10,10 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BlubbFish")] [assembly: AssemblyProduct("Bot-Utils")] -[assembly: AssemblyCopyright("Copyright © 2018 - 21.04.2019")] +[assembly: AssemblyCopyright("Copyright © 2018 - 27.05.2019")] [assembly: AssemblyTrademark("© BlubbFish")] [assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("de-DE")] // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von @@ -31,8 +33,8 @@ using System.Runtime.InteropServices; // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, // indem Sie "*" wie unten gezeigt eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.9")] -[assembly: AssemblyFileVersion("1.1.9")] +[assembly: AssemblyVersion("1.2.0")] +[assembly: AssemblyFileVersion("1.2.0")] /* * 1.1.0 Remove Helper from Bot-Utils @@ -46,4 +48,5 @@ using System.Runtime.InteropServices; * 1.1.7 Restrucutre loading, so that all is init and after the listener is started, REQUEST_URL_HOST gives now host and port * 1.1.8 Add logger to Webserver Class * 1.1.9 Modify Output of SendFileResponse + * 1.2.0 Refactor Bot to ABot and refere MultiSourceBot, Webserver and Bot to it. Add MultiSourceBot. Rewrite Mqtt module so that it not need to watch the connection. */ diff --git a/Bot-Utils/Webserver.cs b/Bot-Utils/Webserver.cs index 8096a46..1ccc77b 100644 --- a/Bot-Utils/Webserver.cs +++ b/Bot-Utils/Webserver.cs @@ -10,13 +10,12 @@ using BlubbFish.Utils.IoT.Events; using LitJson; namespace BlubbFish.Utils.IoT.Bots { - public abstract class Webserver + public abstract class Webserver : ABot { protected Dictionary config; protected static InIReader requests; protected HttpListener httplistener; protected ABackend databackend; - protected ProgramLogger logger = new ProgramLogger(); public Webserver(ABackend backend, Dictionary settings, InIReader requestslookup) { this.config = settings; @@ -142,9 +141,10 @@ namespace BlubbFish.Utils.IoT.Bots { return new Dictionary(); } - public void Dispose() { + public override void Dispose() { this.httplistener.Stop(); this.httplistener.Close(); + base.Dispose(); } protected abstract void Backend_MessageIncomming(Object sender, BackendEvent e);