Compare commits

..

No commits in common. "master" and "v1.2.3" have entirely different histories.

11 changed files with 306 additions and 280 deletions

View File

@ -1,58 +1,71 @@
using System; using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Loader; using System.Runtime.Loader;
using System.Threading; using System.Threading;
namespace BlubbFish.Utils.IoT.Bots { namespace BlubbFish.Utils.IoT.Bots {
public abstract class ABot { public abstract class ABot {
#if !NETCOREAPP
private Thread sig_thread;
#endif
private Boolean RunningProcess = true; private Boolean RunningProcess = true;
private readonly ProgramLogger logger = null;
public Boolean DebugLogging { protected ProgramLogger logger = new ProgramLogger();
get;
}
public ABot(String[] _, Boolean fileLogging, String configSearchPath) { private void SetupShutdown(Object sender, ConsoleCancelEventArgs e) {
InIReader.SetSearchPath(new List<String>() { "/etc/"+ configSearchPath, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\"+ configSearchPath }); e.Cancel = true;
if(fileLogging) { Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.SetupShutdown: Signalhandler Windows INT recieved.");
this.logger = new ProgramLogger(InIReader.GetInstance("settings").GetValue("logging", "path", Assembly.GetEntryAssembly().GetName().Name + ".log")); this.RunningProcess = false;
}
if(Boolean.TryParse(InIReader.GetInstance("settings").GetValue("logging", "debug", "true"), out Boolean debuglog)) {
this.DebugLogging = debuglog;
}
}
private void ConsoleCancelEvent(Object sender, ConsoleCancelEventArgs e) {
e.Cancel = true;
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ConsoleCancelEvent()");
this.RunningProcess = false;
} }
#if NETCOREAPP #if NETCOREAPP
private void Unloading(AssemblyLoadContext obj) => this.RunningProcess = false; private void Default_Unloading(AssemblyLoadContext obj) {
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.SetupShutdown: Signalhandler Windows NETCORE recieved.");
private void ProcessExit(Object sender, EventArgs e) => this.RunningProcess = false; this.RunningProcess = false;
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Shutdown.");
this.Dispose();
}
#endif #endif
protected void WaitForShutdown() { protected void WaitForShutdown() {
#if NETCOREAPP if(Type.GetType("Mono.Runtime") != null) {
AssemblyLoadContext.Default.Unloading += this.Unloading; #if !NETCOREAPP
AppDomain.CurrentDomain.ProcessExit += this.ProcessExit; this.sig_thread = new Thread(delegate () {
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Attach Unloading and ProcessExit."); Mono.Unix.UnixSignal[] signals = new Mono.Unix.UnixSignal[] {
#endif new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGTERM),
Console.CancelKeyPress += new ConsoleCancelEventHandler(this.ConsoleCancelEvent); new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGINT)
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Attach ConsoleCancelEvent."); };
while(this.RunningProcess) { Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Mono attached.");
Thread.Sleep(100); while(true) {
} Int32 i = Mono.Unix.UnixSignal.WaitAny(signals, -1);
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Shutdown."); Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Mono INT recieved " + i + ".");
this.RunningProcess = false;
break;
}
});
this.sig_thread.Start();
#endif
} else {
#if NETCOREAPP
AssemblyLoadContext.Default.Unloading += this.Default_Unloading;
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Netcore attached.");
#endif
Console.CancelKeyPress += new ConsoleCancelEventHandler(this.SetupShutdown);
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Signalhandler Windows attached.");
}
while(this.RunningProcess) {
Thread.Sleep(100);
}
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.WaitForShutdown: Shutdown.");
} }
public virtual void Dispose() { public virtual void Dispose() {
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.Dispose: Shutdown."); #if !NETCOREAPP
this.RunningProcess = false; if(this.sig_thread != null && this.sig_thread.IsAlive) {
this.logger?.Dispose(); this.sig_thread.Abort();
}
#endif
} }
} }
} }

View File

@ -12,7 +12,7 @@ namespace BlubbFish.Utils.IoT.Bots {
protected HttpListener httplistener; protected HttpListener httplistener;
public AWebserver(String[] args, Boolean fileLogging, String configSearchPath, Dictionary<String, String> settings) : base(args, fileLogging, configSearchPath) => this.config = settings; public AWebserver(Dictionary<String, String> settings) => this.config = settings;
protected void StartListen() { protected void StartListen() {
this.httplistener = new HttpListener(); this.httplistener = new HttpListener();

View File

@ -7,7 +7,7 @@ using BlubbFish.Utils.IoT.Events;
namespace BlubbFish.Utils.IoT.Bots { namespace BlubbFish.Utils.IoT.Bots {
public abstract class AWebserverDataBackend : AWebserver { public abstract class AWebserverDataBackend : AWebserver {
protected ABackend databackend; protected ABackend databackend;
protected AWebserverDataBackend(String[] args, Boolean fileLogging, String configSearchPath, ABackend backend, Dictionary<String, String> settings) : base(args, fileLogging, configSearchPath, settings) => this.databackend = backend; protected AWebserverDataBackend(ABackend backend, Dictionary<String, String> settings) : base(settings) => this.databackend = backend;
protected void StartDataBackend() => this.databackend.MessageIncomming += this.Backend_MessageIncomming; protected void StartDataBackend() => this.databackend.MessageIncomming += this.Backend_MessageIncomming;

View File

@ -5,35 +5,32 @@
<RootNamespace>BlubbFish.Utils.IoT.Bots</RootNamespace> <RootNamespace>BlubbFish.Utils.IoT.Bots</RootNamespace>
<AssemblyName>Bot-Utils</AssemblyName> <AssemblyName>Bot-Utils</AssemblyName>
<PackageId>Bots.IoT.Utils.BlubbFish</PackageId> <PackageId>Bots.IoT.Utils.BlubbFish</PackageId>
<Version>1.2.6</Version> <Version>1.2.3</Version>
<AssemblyVersion>1.2.3</AssemblyVersion>
<FileVersion>1.2.3</FileVersion>
<NeutralLanguage>de-DE</NeutralLanguage> <NeutralLanguage>de-DE</NeutralLanguage>
<Description>Bot-Utils are helpers for programming a bot</Description> <Description>Bot-Utils are helpers for programming a bot</Description>
<Authors>BlubbFish</Authors> <Authors>BlubbFish</Authors>
<Company>BlubbFish</Company> <Company>BlubbFish</Company>
<Copyright>Copyright © BlubbFish 2018 - 25.01.2022</Copyright> <Copyright>Copyright © BlubbFish 2018 - 09.01.2022</Copyright>
<PackageLicenseFile>LICENSE</PackageLicenseFile> <PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageProjectUrl>http://git.blubbfish.net/vs_utils/Bot-Utils</PackageProjectUrl> <PackageProjectUrl>http://git.blubbfish.net/vs_utils/Bot-Utils</PackageProjectUrl>
<RepositoryUrl>http://git.blubbfish.net/vs_utils/Bot-Utils.git</RepositoryUrl> <RepositoryUrl>http://git.blubbfish.net/vs_utils/Bot-Utils.git</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PackageReleaseNotes> <PackageReleaseNotes>1.2.3 Tiny Refactoring
1.2.6 - 2022-01-25 - Makeing Logging easyier 1.2.2 Going to netcore
1.2.5 - 2022-01-20 - Better linux handling 1.2.1 When using Dispose, kill also mqtt connection and other tiny fixes
1.2.4 - 2022-01-18 - Config enabled module loading 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.
1.2.3 - 2022-01-09 - Tiny Refactoring 1.1.9 Modify Output of SendFileResponse
1.2.2 - 2021-08-22 - Going to netcore 1.1.8 Add logger to Webserver Class
1.2.1 - 2019-08-30 - When using Dispose, kill also mqtt connection and other tiny fixes 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.2.0 - 2019-05-27 - Refactor Bot to ABot and refere MultiSourceBot 1.1.6 rename functions and make SendFileResponse with a parameter for the folder (default resources), also put returntype boolean, add function that parse post params, if path is a dictionary try to load index.html
1.1.9 - 2019-04-21 - Modify Output of SendFileResponse 1.1.5 add a function to send an object as json directly
1.1.8 - 2019-04-15 - Add logger to Webserver Class 1.1.4 add Woff as Binary type
1.1.7 - 2019-04-14 - REQUEST_URL_HOST 1.1.3 Variables parsing now as a String
1.1.6 - 2019-04-03 - Refactoring and bugfixing 1.1.2 Fixing bug for Contenttype
1.1.5 - 2019-03-27 - add a function to send an object as json directly 1.1.1 Update to local librarys
1.1.4 - 2019-03-13 - add Woff as Binary type 1.1.0 Remove Helper from Bot-Utils</PackageReleaseNotes>
1.1.3 - 2019-03-10 - Variables parsing now as a String
1.1.2 - 2019-03-08 - Fixing bug for Contenttype
1.1.1 - 2019-02-17 - Update to local librarys
1.1.0 - 2019-02-14 - Remove Helper from Bot-Utils
</PackageReleaseNotes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -9,11 +9,8 @@ namespace BlubbFish.Utils.IoT.Bots {
public abstract class Bot<T> : ABot { public abstract class Bot<T> : ABot {
protected readonly Dictionary<String, AModul<T>> moduls = new Dictionary<String, AModul<T>>(); protected readonly Dictionary<String, AModul<T>> moduls = new Dictionary<String, AModul<T>>();
public Bot(String[] args, Boolean fileLogging, String configSearchPath) : base(args, fileLogging, configSearchPath) { }
protected void ModulDispose() { protected void ModulDispose() {
foreach (KeyValuePair<String, AModul<T>> item in this.moduls) { foreach (KeyValuePair<String, AModul<T>> item in this.moduls) {
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulDispose: Entlade Modul: " + item.Key);
item.Value.Dispose(); item.Value.Dispose();
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulDispose: Modul entladen: " + item.Key); Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulDispose: Modul entladen: " + item.Key);
} }
@ -28,18 +25,13 @@ namespace BlubbFish.Utils.IoT.Bots {
String name = t.Name; String name = t.Name;
try { try {
if (InIReader.ConfigExist(name.ToLower())) { if (InIReader.ConfigExist(name.ToLower())) {
Dictionary<String, String> modulconfig = InIReader.GetInstance(name.ToLower()).GetSection("modul"); Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulLoader: Load Modul " + name);
if(!(modulconfig.ContainsKey("enabled") && modulconfig["enabled"].ToLower() == "false")) { this.moduls.Add(name, (AModul<T>)t.GetConstructor(new Type[] { typeof(T), typeof(InIReader) }).Invoke(new Object[] { library, InIReader.GetInstance(name.ToLower()) }));
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulLoader: Load Modul " + name); Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulLoader: Loaded Modul " + name);
this.moduls.Add(name, (AModul<T>)t.GetConstructor(new Type[] { typeof(T), typeof(InIReader) }).Invoke(new Object[] { library, InIReader.GetInstance(name.ToLower()) })); } else if (t.HasInterface(typeof(IForceLoad))) {
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulLoader: Loaded Modul " + name); Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulLoader: Load Modul Forced " + name);
continue;
}
}
if (t.HasInterface(typeof(IForceLoad))) {
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulLoader: Forced Load Modul " + name);
this.moduls.Add(name, (AModul<T>)t.GetConstructor(new Type[] { typeof(T), typeof(InIReader) }).Invoke(new Object[] { library, null })); this.moduls.Add(name, (AModul<T>)t.GetConstructor(new Type[] { typeof(T), typeof(InIReader) }).Invoke(new Object[] { library, null }));
Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulLoader: Forced Loaded Modul " + name); Console.WriteLine("BlubbFish.Utils.IoT.Bots.Bot.ModulLoader: Loaded Modul Forced " + name);
} }
} catch(Exception e) { } catch(Exception e) {
Helper.WriteError(e.InnerException.Message); Helper.WriteError(e.InnerException.Message);
@ -63,10 +55,6 @@ namespace BlubbFish.Utils.IoT.Bots {
} }
} }
protected void ModulUpdate(Object sender, ModulEventArgs e) { protected void ModulUpdate(Object sender, ModulEventArgs e) => Console.WriteLine(e.ToString());
if(this.DebugLogging) {
Console.WriteLine(e.ToString());
}
}
} }
} }

View File

@ -1,162 +1,170 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using BlubbFish.Utils.IoT.Bots.Interfaces;
using BlubbFish.Utils.IoT.Bots.Interfaces;
namespace BlubbFish.Utils.IoT.Bots.Moduls {
namespace BlubbFish.Utils.IoT.Bots.Moduls { public abstract class CronJob<T> : AModul<T>, IDisposable, IForceLoad {
public abstract class CronJob<T> : AModul<T>, IForceLoad { protected readonly List<Tuple<String, Action<Object>, Object>> internalCron = new List<Tuple<String, Action<Object>, Object>>();
protected readonly List<Tuple<String, Action<Object>, Object>> internalCron = new List<Tuple<String, Action<Object>, Object>>(); protected Thread thread;
protected Thread thread; protected DateTime crontime;
protected Boolean threadRunning = false;
protected DateTime crontime; protected readonly Dictionary<String, String> cron_named = new Dictionary<String, String> {
{ "@yearly", "0 0 1 1 *" },
protected readonly Dictionary<String, String> cron_named = new Dictionary<String, String> { { "@annually", "0 0 1 1 *" },
{ "@yearly", "0 0 1 1 *" }, { "@monthly", "0 0 1 * *" },
{ "@annually", "0 0 1 1 *" }, { "@weekly", "0 0 * * 0" },
{ "@monthly", "0 0 1 * *" }, { "@daily", "0 0 * * *" },
{ "@weekly", "0 0 * * 0" }, { "@hourly", "0 * * * *" }
{ "@daily", "0 0 * * *" }, };
{ "@hourly", "0 * * * *" }
}; #region Constructor
public CronJob(T lib, InIReader settings) : base(lib, settings) {
#region Constructor this.crontime = DateTime.Now;
public CronJob(T lib, InIReader settings) : base(lib, settings) { this.thread = new Thread(this.Runner);
this.crontime = DateTime.Now; this.thread.Start();
this.thread = new Thread(this.Runner); }
this.threadRunning = true; #endregion
this.thread.Start();
} #region Cronjobrunner
#endregion protected void Runner() {
Thread.Sleep(DateTime.Now.AddMinutes(1).AddSeconds(DateTime.Now.Second * -1).AddMilliseconds(DateTime.Now.Millisecond * -1) - DateTime.Now);
#region Cronjobrunner while (true) {
protected void Runner() { if (this.crontime.Minute != DateTime.Now.Minute) {
DateTime nextminute = DateTime.Now.AddMinutes(1).AddSeconds(DateTime.Now.Second * -1).AddMilliseconds(DateTime.Now.Millisecond * -1); this.crontime = DateTime.Now;
while(nextminute > DateTime.Now && this.threadRunning) { if (this.config.Count != 0) {
Thread.Sleep(100); foreach (KeyValuePair<String, Dictionary<String, String>> item in this.config) {
} if (item.Value.ContainsKey("cron") && item.Value.ContainsKey("set") && this.ParseCronString(item.Value["cron"])) {
while (this.threadRunning) { this.SetValues(item.Value["set"]);
if (this.crontime.Minute != DateTime.Now.Minute) { }
this.crontime = DateTime.Now; }
if (this.config.Count != 0) { }
foreach (KeyValuePair<String, Dictionary<String, String>> item in this.config) { foreach (Tuple<String, Action<Object>, Object> item in this.internalCron) {
if (item.Value.ContainsKey("cron") && item.Value.ContainsKey("set") && this.ParseCronString(item.Value["cron"])) { if (this.ParseCronString(item.Item1)) {
this.SetValues(item.Value["set"]); item.Item2?.Invoke(item.Item3);
} }
} }
} }
foreach (Tuple<String, Action<Object>, Object> item in this.internalCron) { Thread.Sleep(100);
if (this.ParseCronString(item.Item1)) { }
item.Item2?.Invoke(item.Item3); }
}
} protected abstract void SetValues(String value);
} #endregion
Thread.Sleep(100);
} #region CronFunctions
} protected Boolean ParseCronString(String cronstring) {
cronstring = cronstring.Trim();
protected abstract void SetValues(String value); if (this.cron_named.ContainsKey(cronstring)) {
#endregion cronstring = this.cron_named[cronstring];
}
#region CronFunctions String[] value = cronstring.Split(' ');
protected Boolean ParseCronString(String cronstring) { if (value.Length != 5) {
cronstring = cronstring.Trim(); return false;
if (this.cron_named.ContainsKey(cronstring)) { }
cronstring = this.cron_named[cronstring]; if (!this.CheckDateStr(this.crontime.ToString("mm"), value[0], "0-59")) {
} return false;
String[] value = cronstring.Split(' '); }
if (value.Length != 5) { if (!this.CheckDateStr(this.crontime.ToString("HH"), value[1], "0-23")) {
return false; return false;
} }
if (!this.CheckDateStr(this.crontime.ToString("mm"), value[0], "0-59")) { if (!this.CheckDateStr(this.crontime.ToString("MM"), value[3], "1-12")) {
return false; return false;
} }
if (!this.CheckDateStr(this.crontime.ToString("HH"), value[1], "0-23")) { if (value[2] != "*" && value[4] != "*") {
return false; if (!this.CheckDateStr(this.crontime.ToString("dd"), value[2], "1-31") && !this.CheckDateStr(((Int32)this.crontime.DayOfWeek).ToString(), value[4], "0-7")) {
} return false;
if (!this.CheckDateStr(this.crontime.ToString("MM"), value[3], "1-12")) { }
return false; } else {
} if (!this.CheckDateStr(this.crontime.ToString("dd"), value[2], "1-31")) {
if (value[2] != "*" && value[4] != "*") { return false;
if (!this.CheckDateStr(this.crontime.ToString("dd"), value[2], "1-31") && !this.CheckDateStr(((Int32)this.crontime.DayOfWeek).ToString(), value[4], "0-7")) { }
return false; if (!this.CheckDateStr(((Int32)this.crontime.DayOfWeek).ToString(), value[4], "0-7")) {
} return false;
} else { }
if (!this.CheckDateStr(this.crontime.ToString("dd"), value[2], "1-31")) { }
return false; return true;
} }
if (!this.CheckDateStr(((Int32)this.crontime.DayOfWeek).ToString(), value[4], "0-7")) { protected Boolean CheckDateStr(String date, String cron, String limit) {
return false; cron = cron.ToLower();
} for (Int32 i = 0; i <= 6; i++) {
} cron = cron.Replace(DateTime.Parse("2015-01-" + (4 + i) + "T00:00:00").ToString("ddd", CultureInfo.CreateSpecificCulture("en-US")), i.ToString());
return true; cron = cron.Replace(DateTime.Parse("2015-01-" + (4 + i) + "T00:00:00").ToString("dddd", CultureInfo.CreateSpecificCulture("en-US")), i.ToString());
} }
protected Boolean CheckDateStr(String date, String cron, String limit) { for (Int32 i = 1; i <= 12; i++) {
cron = cron.ToLower(); cron = cron.Replace(DateTime.Parse("2015-" + i + "-01T00:00:00").ToString("MMM", CultureInfo.CreateSpecificCulture("en-US")), i.ToString());
for (Int32 i = 0; i <= 6; i++) { cron = cron.Replace(DateTime.Parse("2015-" + i + "-01T00:00:00").ToString("MMMM", CultureInfo.CreateSpecificCulture("en-US")), i.ToString());
cron = cron.Replace(DateTime.Parse("2015-01-" + (4 + i) + "T00:00:00").ToString("ddd", CultureInfo.CreateSpecificCulture("en-US")), i.ToString()); }
cron = cron.Replace(DateTime.Parse("2015-01-" + (4 + i) + "T00:00:00").ToString("dddd", CultureInfo.CreateSpecificCulture("en-US")), i.ToString()); if (cron.Contains("*")) {
} cron = cron.Replace("*", limit);
for (Int32 i = 1; i <= 12; i++) { }
cron = cron.Replace(DateTime.Parse("2015-" + i + "-01T00:00:00").ToString("MMM", CultureInfo.CreateSpecificCulture("en-US")), i.ToString()); if (cron.Contains("-")) {
cron = cron.Replace(DateTime.Parse("2015-" + i + "-01T00:00:00").ToString("MMMM", CultureInfo.CreateSpecificCulture("en-US")), i.ToString()); MatchCollection m = new Regex("(\\d+)-(\\d+)").Matches(cron);
} foreach (Match p in m) {
if (cron.Contains("*")) { List<String> s = new List<String>();
cron = cron.Replace("*", limit); for (Int32 i = Math.Min(Int32.Parse(p.Groups[1].Value), Int32.Parse(p.Groups[2].Value)); i <= Math.Max(Int32.Parse(p.Groups[1].Value), Int32.Parse(p.Groups[2].Value)); i++) {
} s.Add(i.ToString());
if (cron.Contains("-")) { }
MatchCollection m = new Regex("(\\d+)-(\\d+)").Matches(cron); cron = cron.Replace(p.Groups[0].Value, String.Join(",", s));
foreach (Match p in m) { }
List<String> s = new List<String>(); }
for (Int32 i = Math.Min(Int32.Parse(p.Groups[1].Value), Int32.Parse(p.Groups[2].Value)); i <= Math.Max(Int32.Parse(p.Groups[1].Value), Int32.Parse(p.Groups[2].Value)); i++) { Int32 match = 0;
s.Add(i.ToString()); if (cron.Contains("/")) {
} Match m = new Regex("/(\\d+)").Match(cron);
cron = cron.Replace(p.Groups[0].Value, String.Join(",", s)); cron = cron.Replace(m.Groups[0].Value, "");
} match = Int32.Parse(m.Groups[1].Value);
} }
Int32 match = 0; Dictionary<Int32, String> ret = new Dictionary<Int32, String>();
if (cron.Contains("/")) { if (!cron.Contains(",")) {
Match m = new Regex("/(\\d+)").Match(cron); ret.Add(Int32.Parse(cron), "");
cron = cron.Replace(m.Groups[0].Value, ""); } else {
match = Int32.Parse(m.Groups[1].Value); foreach (String item in cron.Split(',')) {
} if (!ret.ContainsKey(Int32.Parse(item))) {
Dictionary<Int32, String> ret = new Dictionary<Int32, String>(); ret.Add(Int32.Parse(item), "");
if (!cron.Contains(",")) { }
ret.Add(Int32.Parse(cron), ""); }
} else { }
foreach (String item in cron.Split(',')) { if (match != 0) {
if (!ret.ContainsKey(Int32.Parse(item))) { Dictionary<Int32, String> r = new Dictionary<Int32, String>();
ret.Add(Int32.Parse(item), ""); foreach (KeyValuePair<Int32, String> item in ret) {
} if (item.Key % match == 0) {
} r.Add(item.Key, "");
} }
if (match != 0) { }
Dictionary<Int32, String> r = new Dictionary<Int32, String>(); ret = r;
foreach (KeyValuePair<Int32, String> item in ret) { }
if (item.Key % match == 0) { return ret.ContainsKey(Int32.Parse(date));
r.Add(item.Key, ""); }
} #endregion
}
ret = r; #region AModul
} public override void SetInterconnection(String cron, Action<Object> hook, Object data) => this.internalCron.Add(new Tuple<String, Action<Object>, Object>(cron, hook, data));
return ret.ContainsKey(Int32.Parse(date));
} protected override void UpdateConfig() { }
#endregion #endregion
#region AModul #region IDisposable Support
public override void SetInterconnection(String cron, Action<Object> hook, Object data) => this.internalCron.Add(new Tuple<String, Action<Object>, Object>(cron, hook, data)); private Boolean disposedValue = false;
protected override void UpdateConfig() { } protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
public override void Dispose() { if (disposing) {
this.threadRunning = false; if (this.thread != null) {
while(this.thread != null && this.thread.IsAlive) { this.thread.Abort();
Thread.Sleep(10); while (this.thread.ThreadState == ThreadState.Running) { Thread.Sleep(100); }
} }
this.thread = null; }
} this.thread = null;
#endregion this.disposedValue = true;
} }
} }
public override void Dispose() {
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}

View File

@ -7,7 +7,7 @@ using BlubbFish.Utils.IoT.Events;
using LitJson; using LitJson;
namespace BlubbFish.Utils.IoT.Bots.Moduls { namespace BlubbFish.Utils.IoT.Bots.Moduls {
public abstract class Mqtt<T> : AModul<T> { public abstract class Mqtt<T> : AModul<T>, IDisposable {
protected ABackend mqtt; protected ABackend mqtt;
protected Dictionary<String, AModul<T>> modules; protected Dictionary<String, AModul<T>> modules;
@ -34,8 +34,6 @@ namespace BlubbFish.Utils.IoT.Bots.Moduls {
public override void Interconnect(Dictionary<String, AModul<T>> moduls) => this.modules = moduls; public override void Interconnect(Dictionary<String, AModul<T>> moduls) => this.modules = moduls;
protected override void UpdateConfig() => this.Reconnect(); protected override void UpdateConfig() => this.Reconnect();
public override void Dispose() => this.Disconnect();
#endregion #endregion
protected Tuple<Boolean, MqttEvent> ChangeConfig(BackendEvent e, String topic) { protected Tuple<Boolean, MqttEvent> ChangeConfig(BackendEvent e, String topic) {
@ -76,5 +74,23 @@ namespace BlubbFish.Utils.IoT.Bots.Moduls {
} }
return new Tuple<Boolean, MqttEvent>(false, null); return new Tuple<Boolean, MqttEvent>(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
} }
} }

View File

@ -2,7 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace BlubbFish.Utils.IoT.Bots.Moduls { namespace BlubbFish.Utils.IoT.Bots.Moduls {
public abstract class Overtaker<T> : AModul<T> { public abstract class Overtaker<T> : AModul<T>, IDisposable {
protected readonly Dictionary<String, Dictionary<String, String>> events = new Dictionary<String, Dictionary<String, String>>(); protected readonly Dictionary<String, Dictionary<String, String>> events = new Dictionary<String, Dictionary<String, String>>();
#region Constructor #region Constructor
@ -62,8 +62,23 @@ namespace BlubbFish.Utils.IoT.Bots.Moduls {
#region AModul #region AModul
public override void Interconnect(Dictionary<String, AModul<T>> moduls) { } public override void Interconnect(Dictionary<String, AModul<T>> moduls) { }
protected override void UpdateConfig() => this.ParseIni(); protected override void UpdateConfig() => this.ParseIni();
public override void Dispose() { #endregion
#region IDisposable Support
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
if (disposing) {
}
this.disposedValue = true;
}
} }
#endregion
public override void Dispose() {
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
} }
} }

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using BlubbFish.Utils.IoT.Bots.Interfaces; using BlubbFish.Utils.IoT.Bots.Interfaces;
namespace BlubbFish.Utils.IoT.Bots.Moduls { namespace BlubbFish.Utils.IoT.Bots.Moduls {
public abstract class Statuspolling<T> : AModul<T>, IForceLoad { public abstract class Statuspolling<T> : AModul<T>, IDisposable, IForceLoad {
#region Constructor #region Constructor
public Statuspolling(T lib, InIReader settings) : base(lib, settings) { } public Statuspolling(T lib, InIReader settings) : base(lib, settings) { }
@ -31,7 +31,22 @@ namespace BlubbFish.Utils.IoT.Bots.Moduls {
} }
} }
protected override void UpdateConfig() { } protected override void UpdateConfig() { }
public override void Dispose() { #endregion
#region IDisposable Support
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
if (disposing) {
}
this.disposedValue = true;
}
}
public override void Dispose() {
this.Dispose(true);
GC.SuppressFinalize(this);
} }
#endregion #endregion
} }

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BlubbFish.Utils.IoT.Connector; using BlubbFish.Utils.IoT.Connector;
namespace BlubbFish.Utils.IoT.Bots { namespace BlubbFish.Utils.IoT.Bots {
@ -8,7 +10,7 @@ namespace BlubbFish.Utils.IoT.Bots {
protected Dictionary<String, ABackend> sources; protected Dictionary<String, ABackend> sources;
protected Dictionary<String, String> settings; protected Dictionary<String, String> settings;
protected MultiSourceBot(String[] args, Boolean fileLogging, String configSearchPath, Dictionary<String, ABackend> sources, Dictionary<String, String> settings) : base(args, fileLogging, configSearchPath) { protected MultiSourceBot(Dictionary<String, ABackend> sources, Dictionary<String, String> settings) {
this.sources = sources; this.sources = sources;
this.settings = settings; this.settings = settings;
} }

View File

@ -1,33 +1,5 @@
# Changelog # Changelog
## 1.2.6 - 2022-01-25 - Makeing Logging easyier
### New Features
* Construct the Programm logger only if enabled
* Set Searchpath by default for a Bot
* Add an option that allows to debug logging (by default on)
### Bugfixes
### Changes
* Deconstruct Programmlogger
* Change all classes that extend ABot
* Module messages also uses debug logging flag
* Codingstyles
## 1.2.5 - 2022-01-20 - Better linux handling
### New Features
* Add ProcessExit Handler in ABot
* Add Output in ModulDispose
### Bugfixes
* Eleminate Hangs in Cronjob, when in startup phase it not blocks shutdown
### Changes
* Reweite ABot, remove Mono Code
* Codingstyle
## 1.2.4 - 2022-01-18 - Config enabled module loading
### New Features
* Modules can have an enabled=true|false in config, so that also enables or disables moduleloading.
### Bugfixes
### Changes
## 1.2.3 - 2022-01-09 - Tiny Refactoring ## 1.2.3 - 2022-01-09 - Tiny Refactoring
### New Features ### New Features
### Bugfixes ### Bugfixes