diff --git a/Bot-Utils.csproj b/Bot-Utils.csproj
index ec2d46c..7c26c2d 100644
--- a/Bot-Utils.csproj
+++ b/Bot-Utils.csproj
@@ -7,10 +7,12 @@
{BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}
Library
Properties
- Bot_Utils
+ BlubbFish.Utils.IoT.Bots
Bot-Utils
v4.7.1
512
+
+
true
@@ -29,6 +31,9 @@
prompt
4
+
+
+
@@ -40,8 +45,37 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5.4.0.201
+
+
+
+
+ {91a14cd2-2940-4500-8193-56d37edddbaa}
+ litjson_4.7.1
+
+
+ {b870e4d5-6806-4a0b-b233-8907eedc5afc}
+ Utils-IoT
+
+
+ {fac8ce64-bf13-4ece-8097-aeb5dd060098}
+ Utils
+
+
\ No newline at end of file
diff --git a/Bot.cs b/Bot.cs
new file mode 100644
index 0000000..ddde4fe
--- /dev/null
+++ b/Bot.cs
@@ -0,0 +1,90 @@
+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;
+
+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("Signalhandler Mono attached.");
+ while (true) {
+ Int32 i = Mono.Unix.UnixSignal.WaitAny(signals, -1);
+ Console.WriteLine("Signalhandler Mono INT recieved " + i + ".");
+ this.RunningProcess = false;
+ break;
+ }
+ });
+ this.sig_thread.Start();
+ } else {
+ Console.CancelKeyPress += new ConsoleCancelEventHandler(this.SetupShutdown);
+ Console.WriteLine("Signalhandler Windows attached.");
+ }
+ while (this.RunningProcess) {
+ Thread.Sleep(100);
+ }
+ }
+
+ private void SetupShutdown(Object sender, ConsoleCancelEventArgs e) {
+ e.Cancel = true;
+ Console.WriteLine("Signalhandler Windows INT recieved.");
+ this.RunningProcess = false;
+ }
+
+ protected void ModulDispose() {
+ foreach (KeyValuePair item in this.moduls) {
+ ((AModul)item.Value).Dispose();
+ Console.WriteLine("Modul entladen: " + item.Key);
+ }
+ if (this.sig_thread != null && this.sig_thread.IsAlive) {
+ this.sig_thread.Abort();
+ }
+ }
+
+ protected void ModulLoader(String @namespace, Object library) {
+ Assembly asm = Assembly.GetEntryAssembly();
+ foreach (Type item in asm.GetTypes()) {
+ if (item.Namespace == @namespace) {
+ Type t = item;
+ String name = t.Name;
+ if (InIReader.ConfigExist(name.ToLower())) {
+ this.moduls.Add(name, (AModul)t.GetConstructor(new Type[] { typeof(T), typeof(InIReader) }).Invoke(new Object[] { library, InIReader.GetInstance(name.ToLower()) }));
+ Console.WriteLine("Load Modul " + name);
+ } else if (t.HasInterface(typeof(IForceLoad))) {
+ this.moduls.Add(name, (AModul)t.GetConstructor(new Type[] { typeof(T), typeof(InIReader) }).Invoke(new Object[] { library, null }));
+ Console.WriteLine("Load Modul Forced " + name);
+ }
+ }
+ }
+ }
+
+ protected void ModulInterconnect() {
+ foreach (KeyValuePair item in this.moduls) {
+ ((AModul)item.Value).Interconnect(this.moduls);
+ }
+ }
+
+ protected void ModulEvents() {
+ foreach (KeyValuePair item in this.moduls) {
+ ((AModul)item.Value).Update += this.ModulUpdate;
+ }
+ }
+
+ protected void ModulUpdate(Object sender, ModulEventArgs e) {
+ Console.WriteLine(e.ToString());
+ }
+ }
+}
diff --git a/Events/CronEvent.cs b/Events/CronEvent.cs
new file mode 100644
index 0000000..cb7237e
--- /dev/null
+++ b/Events/CronEvent.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace BlubbFish.Utils.IoT.Bots.Events {
+ public class CronEvent : ModulEventArgs {
+
+ public CronEvent() {
+ }
+
+ public CronEvent(String addr, String prop, String value) {
+ this.Address = addr;
+ this.Property = prop;
+ this.Value = value;
+ this.Source = "Cronjob";
+ }
+ }
+}
diff --git a/Events/ModulEventArgs.cs b/Events/ModulEventArgs.cs
new file mode 100644
index 0000000..ee44173
--- /dev/null
+++ b/Events/ModulEventArgs.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace BlubbFish.Utils.IoT.Bots.Events {
+ public class ModulEventArgs : EventArgs {
+ public ModulEventArgs() {
+ }
+ public String Address { get; protected set; }
+ public String Property { get; protected set; }
+ public String Value { get; protected set; }
+ public String Source { get; protected set; }
+ public override String ToString() {
+ return this.Source + ": " + this.Address + " set " + this.Property + " to " + this.Value;
+ }
+ }
+}
diff --git a/Events/MqttEvent.cs b/Events/MqttEvent.cs
new file mode 100644
index 0000000..fa30fa7
--- /dev/null
+++ b/Events/MqttEvent.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace BlubbFish.Utils.IoT.Bots.Events {
+ public class MqttEvent : ModulEventArgs {
+ public MqttEvent() {
+ }
+ public MqttEvent(String topic, String text) {
+ this.Address = topic;
+ this.Value = text;
+ this.Source = "MQTT";
+ }
+ public override String ToString() {
+ return this.Source + ": on " + this.Address + " set " + this.Value;
+ }
+ }
+}
diff --git a/Events/OvertakerEvent.cs b/Events/OvertakerEvent.cs
new file mode 100644
index 0000000..0af0525
--- /dev/null
+++ b/Events/OvertakerEvent.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace BlubbFish.Utils.IoT.Bots.Events {
+ public class OvertakerEvent : ModulEventArgs {
+
+ public OvertakerEvent() {
+ }
+
+ public OvertakerEvent(String addr, String prop, String value) {
+ this.Address = addr;
+ this.Property = prop;
+ this.Value = value;
+ this.Source = "Overtaker";
+ }
+ }
+}
diff --git a/Events/SenmlEvent.cs b/Events/SenmlEvent.cs
new file mode 100644
index 0000000..fcdfce2
--- /dev/null
+++ b/Events/SenmlEvent.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace BlubbFish.Utils.IoT.Bots.Events {
+ public class SenmlEvent : ModulEventArgs {
+ public SenmlEvent() {
+ }
+ public SenmlEvent(String topic, String text) {
+ this.Address = topic;
+ this.Value = text;
+ this.Source = "Senml";
+ }
+ public override String ToString() {
+ return this.Source + ": on " + this.Address + " set " + this.Value;
+ }
+ }
+}
diff --git a/Events/StatusPollingEvent.cs b/Events/StatusPollingEvent.cs
new file mode 100644
index 0000000..70238ed
--- /dev/null
+++ b/Events/StatusPollingEvent.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace BlubbFish.Utils.IoT.Bots.Events {
+ public class StatusPollingEvent : ModulEventArgs {
+ public StatusPollingEvent() {
+ }
+
+ public StatusPollingEvent(String text, String node) {
+ this.Value = text;
+ this.Address = node;
+ this.Source = "POLLING";
+ }
+
+ public override String ToString() {
+ return this.Source + ": " + this.Value + " on " + this.Address;
+ }
+ }
+}
diff --git a/Helper.cs b/Helper.cs
new file mode 100644
index 0000000..34fd3e7
--- /dev/null
+++ b/Helper.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Reflection;
+
+namespace BlubbFish.Utils.IoT.Bots {
+ public static class Helper {
+ #region PropertyHelper
+ public static Boolean HasProperty(this Object o, String type) {
+ Type t = o.GetType();
+ foreach (PropertyInfo item in t.GetProperties()) {
+ if (item.Name == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Object GetProperty(this Object o, String name) {
+ PropertyInfo prop = o.GetType().GetProperty(name);
+ if (prop.CanRead) {
+ return prop.GetValue(o);
+ }
+ return null;
+ }
+
+ public static void SetProperty(this Object o, String name, String value) {
+ PropertyInfo prop = o.GetType().GetProperty(name);
+ if (prop.CanWrite) {
+ if (prop.PropertyType == typeof(Boolean) && Boolean.TryParse(value, out Boolean vb)) {
+ prop.SetValue(o, vb);
+ } else if (prop.PropertyType == typeof(Int32) && Int32.TryParse(value, out Int32 v32)) {
+ prop.SetValue(o, v32);
+ } else if (prop.PropertyType == typeof(Single) && Single.TryParse(value, out Single vs)) {
+ prop.SetValue(o, vs);
+ } else if (prop.PropertyType == typeof(Double) && Double.TryParse(value, out Double vd)) {
+ prop.SetValue(o, vd);
+ } else if (prop.PropertyType == typeof(Int64) && Int64.TryParse(value, out Int64 v64)) {
+ prop.SetValue(o, v64);
+ }
+ }
+ }
+ #endregion
+
+ #region InterfaceHelper
+ public static Boolean HasInterface(this Type o, Type interf) {
+ foreach (Type item in o.GetInterfaces()) {
+ if (item == interf) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Boolean HasAbstract(this Type o, Type type) {
+ if (o.BaseType == type) {
+ return true;
+ }
+ return false;
+ }
+ #endregion
+
+ #region StringHelper
+ public static String ToUpperLower(this String s) {
+ if (s.Length == 0) {
+ return "";
+ }
+ if (s.Length == 1) {
+ return s.ToUpper();
+ }
+ return s[0].ToString().ToUpper() + s.Substring(1).ToLower();
+ }
+
+ public static void WriteError(String text) {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.Error.WriteLine("ERROR: " + text);
+ Console.ResetColor();
+ }
+ #endregion
+ }
+}
diff --git a/Interfaces/IForceLoad.cs b/Interfaces/IForceLoad.cs
new file mode 100644
index 0000000..eb89e6a
--- /dev/null
+++ b/Interfaces/IForceLoad.cs
@@ -0,0 +1,4 @@
+namespace BlubbFish.Utils.IoT.Bots.Interfaces {
+ public interface IForceLoad {
+ }
+}
diff --git a/Moduls/AModul.cs b/Moduls/AModul.cs
new file mode 100644
index 0000000..2745e60
--- /dev/null
+++ b/Moduls/AModul.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using BlubbFish.Utils.IoT.Bots.Events;
+
+namespace BlubbFish.Utils.IoT.Bots.Moduls {
+ public abstract class AModul {
+ protected T library;
+ private readonly InIReader settings;
+ protected Dictionary> config = new Dictionary>();
+
+ public Boolean HasConfig { get; private set; }
+ public Boolean ConfigPublic { get; private set; }
+
+ public delegate void ModulEvent(Object sender, ModulEventArgs e);
+ public abstract event ModulEvent Update;
+
+ public AModul(T lib, InIReader settings) {
+ this.HasConfig = false;
+ this.ConfigPublic = false;
+ this.library = lib;
+ this.settings = settings;
+ this.ParseConfig();
+ }
+
+ private void ParseConfig() {
+ if (this.settings != null) {
+ this.HasConfig = true;
+ foreach (String item in this.settings.GetSections(false)) {
+ this.config.Add(item, this.settings.GetSection(item));
+ }
+ if (this.config.ContainsKey("modul")) {
+ this.ConfigPublic = this.config["modul"].ContainsKey("config") && this.config["modul"]["config"].ToLower() == "public";
+ }
+ }
+ }
+
+ public Dictionary> GetConfig() {
+ if (this.HasConfig && this.ConfigPublic) {
+ Dictionary> ret = new Dictionary>(this.config);
+ if (ret.ContainsKey("modul")) {
+ ret.Remove("modul");
+ }
+ return ret;
+ }
+ return new Dictionary>();
+ }
+
+ public virtual void Interconnect(Dictionary moduls) { }
+
+ public virtual void SetInterconnection(String param, Action