diff --git a/Bot-Utils.csproj b/Bot-Utils.csproj index 7c26c2d..7592403 100644 --- a/Bot-Utils.csproj +++ b/Bot-Utils.csproj @@ -55,7 +55,10 @@ + + + diff --git a/Moduls/CronJob.cs b/Moduls/CronJob.cs new file mode 100644 index 0000000..0959169 --- /dev/null +++ b/Moduls/CronJob.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.RegularExpressions; +using System.Threading; +using BlubbFish.Utils.IoT.Bots.Interfaces; + +namespace BlubbFish.Utils.IoT.Bots.Moduls { + public abstract class CronJob : AModul, IDisposable, IForceLoad { + protected readonly List, Object>> internalCron = new List, Object>>(); + protected Thread thread; + protected DateTime crontime; + + protected readonly Dictionary cron_named = new Dictionary { + { "@yearly", "0 0 1 1 *" }, + { "@annually", "0 0 1 1 *" }, + { "@monthly", "0 0 1 * *" }, + { "@weekly", "0 0 * * 0" }, + { "@daily", "0 0 * * *" }, + { "@hourly", "0 * * * *" } + }; + + #region Constructor + public CronJob(T lib, InIReader settings) : base(lib, settings) { + this.crontime = DateTime.Now; + this.thread = new Thread(this.Runner); + this.thread.Start(); + } + #endregion + + #region Cronjobrunner + protected void Runner() { + Thread.Sleep(DateTime.Now.AddMinutes(1).AddSeconds(DateTime.Now.Second * (-1)).AddMilliseconds(DateTime.Now.Millisecond * (-1)) - DateTime.Now); + while (true) { + if (this.crontime.Minute != DateTime.Now.Minute) { + this.crontime = DateTime.Now; + if (this.config.Count != 0) { + foreach (KeyValuePair> item in this.config) { + if (item.Value.ContainsKey("cron") && item.Value.ContainsKey("set") && this.ParseCronString(item.Value["cron"])) { + this.SetValues(item.Value["set"]); + } + } + } + foreach (Tuple, Object> item in this.internalCron) { + if (this.ParseCronString(item.Item1)) { + item.Item2?.Invoke(item.Item3); + } + } + } + Thread.Sleep(100); + } + } + + protected abstract void SetValues(String value); + #endregion + + #region CronFunctions + protected Boolean ParseCronString(String cronstring) { + cronstring = cronstring.Trim(); + if (this.cron_named.ContainsKey(cronstring)) { + cronstring = this.cron_named[cronstring]; + } + String[] value = cronstring.Split(' '); + if (value.Length != 5) { + return false; + } + if (!this.CheckDateStr(this.crontime.ToString("mm"), value[0], "0-59")) { + return false; + } + if (!this.CheckDateStr(this.crontime.ToString("HH"), value[1], "0-23")) { + return false; + } + if (!this.CheckDateStr(this.crontime.ToString("MM"), value[3], "1-12")) { + return false; + } + if (value[2] != "*" && value[4] != "*") { + if (!this.CheckDateStr(this.crontime.ToString("dd"), value[2], "1-31") && !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; + } + if (!this.CheckDateStr(((Int32)this.crontime.DayOfWeek).ToString(), value[4], "0-7")) { + return false; + } + } + return true; + } + protected Boolean CheckDateStr(String date, String cron, String limit) { + 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()); + cron = cron.Replace(DateTime.Parse("2015-01-" + (4 + i) + "T00:00:00").ToString("dddd", CultureInfo.CreateSpecificCulture("en-US")), i.ToString()); + } + 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()); + cron = cron.Replace(DateTime.Parse("2015-" + i + "-01T00:00:00").ToString("MMMM", CultureInfo.CreateSpecificCulture("en-US")), i.ToString()); + } + if (cron.Contains("*")) { + cron = cron.Replace("*", limit); + } + if (cron.Contains("-")) { + MatchCollection m = new Regex("(\\d+)-(\\d+)").Matches(cron); + foreach (Match p in m) { + List s = new List(); + 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()); + } + cron = cron.Replace(p.Groups[0].Value, String.Join(",", s)); + } + } + Int32 match = 0; + if (cron.Contains("/")) { + Match m = new Regex("/(\\d+)").Match(cron); + cron = cron.Replace(m.Groups[0].Value, ""); + match = Int32.Parse(m.Groups[1].Value); + } + Dictionary ret = new Dictionary(); + if (!cron.Contains(",")) { + ret.Add(Int32.Parse(cron), ""); + } else { + foreach (String item in cron.Split(',')) { + if (!ret.ContainsKey(Int32.Parse(item))) { + ret.Add(Int32.Parse(item), ""); + } + } + } + if (match != 0) { + Dictionary r = new Dictionary(); + foreach (KeyValuePair item in ret) { + if (item.Key % match == 0) { + r.Add(item.Key, ""); + } + } + ret = r; + } + return ret.ContainsKey(Int32.Parse(date)); + } + #endregion + + #region AModul + public override void SetInterconnection(String cron, Action hook, Object data) { + this.internalCron.Add(new Tuple, Object>(cron, hook, data)); + } + + protected override void UpdateConfig() { } + #endregion + + #region IDisposable Support + private Boolean disposedValue = false; + + protected virtual void Dispose(Boolean disposing) { + if (!this.disposedValue) { + if (disposing) { + if (this.thread != null) { + this.thread.Abort(); + while (this.thread.ThreadState == ThreadState.Running) { Thread.Sleep(100); } + } + } + this.thread = null; + this.disposedValue = true; + } + } + + public override void Dispose() { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/Moduls/Overtaker.cs b/Moduls/Overtaker.cs new file mode 100644 index 0000000..1a31a04 --- /dev/null +++ b/Moduls/Overtaker.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; + +namespace BlubbFish.Utils.IoT.Bots.Moduls { + public abstract class Overtaker : AModul, IDisposable { + protected readonly Dictionary> events = new Dictionary>(); + + #region Constructor + public Overtaker(T lib, InIReader settings) : base(lib, settings) { + this.ParseIni(); + } + #endregion + + #region Overtakerfunctions + protected void ParseIni() { + foreach (KeyValuePair> item in this.config) { + if (item.Value.ContainsKey("from")) { + String from = item.Value["from"]; + String[] source = from.Split(':'); + this.events.Add(source[0], item.Value); + this.LibraryUpdateHook(source[0]); + } + } + } + + protected void SetValues(Object sender, String name, Dictionary dictionary) { + String from = dictionary["from"]; + String[] source = from.Split(':'); + if (source.Length != 2) { + return; + } + String source_value; + if (sender.HasProperty(source[1])) { + source_value = sender.GetProperty(source[1]).ToString(); + } else { + return; + } + if (dictionary.ContainsKey("convert")) { + foreach (String tuple in dictionary["convert"].Split(';')) { + String[] item = tuple.Split('-'); + if (source_value == item[0]) { + source_value = item[1]; + } + } + } + if (dictionary.ContainsKey("to")) { + foreach (String to in dictionary["to"].Split(';')) { + String[] target = to.Split(':'); + if (target.Length == 2) { + this.SetValueHook(target[0], target[1], source_value); + } + } + } + } + + protected abstract void LibraryUpdateHook(String id); + + protected abstract void SetValueHook(String id, String prop, String value); + #endregion + + #region AModul + public override void Interconnect(Dictionary moduls) { } + protected override void UpdateConfig() { + this.ParseIni(); + } + #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() { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/Moduls/Statuspolling.cs b/Moduls/Statuspolling.cs new file mode 100644 index 0000000..974cb54 --- /dev/null +++ b/Moduls/Statuspolling.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using BlubbFish.Utils.IoT.Bots.Interfaces; + +namespace BlubbFish.Utils.IoT.Bots.Moduls { + public abstract class Statuspolling : AModul, IDisposable, IForceLoad { + + #region Constructor + public Statuspolling(T lib, InIReader settings) : base(lib, settings) { } + #endregion + + #region Statuspollingfunctions + protected abstract void PollSpecific(Object obj); + + protected abstract void PollAll(Object obj); + #endregion + + #region AModul + public override void Interconnect(Dictionary moduls) { + foreach (KeyValuePair item in moduls) { + if (item.Value is CronJob) { + ((AModul)item.Value).SetInterconnection("0 0 * * *", new Action(this.PollAll), null); + if (this.config.Count != 0) { + foreach (KeyValuePair> section in this.config) { + if (section.Value.ContainsKey("cron") && section.Value.ContainsKey("devices")) { + ((AModul)item.Value).SetInterconnection(section.Value["cron"], new Action(this.PollSpecific), section.Value["devices"]); + } + } + } + } + } + } + protected override void UpdateConfig() { } + #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() { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/bin/Release/Bot-Utils.dll b/bin/Release/Bot-Utils.dll index 42947bf..0498511 100644 Binary files a/bin/Release/Bot-Utils.dll and b/bin/Release/Bot-Utils.dll differ