195 lines
7.0 KiB
C#
195 lines
7.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using BlubbFish.IoT.Zway;
|
|
using BlubbFish.IoT.Zway.Interfaces;
|
|
using BlubbFish.Utils;
|
|
|
|
namespace ZwayBot.Moduls {
|
|
internal class CronJob : AModul, IDisposable {
|
|
private DateTime crontime;
|
|
private Thread thread;
|
|
private List<Tuple<String, Action>> internalCron = new List<Tuple<String, Action>>();
|
|
|
|
public override event ModulEvent Update;
|
|
|
|
private Dictionary<String, String> cron_named = new Dictionary<String, String> {
|
|
{ "@yearly", "0 0 1 1 *" },
|
|
{ "@annually", "0 0 1 1 *" },
|
|
{ "@monthly", "0 0 1 * *" },
|
|
{ "@weekly", "0 0 * * 0" },
|
|
{ "@daily", "0 0 * * *" },
|
|
{ "@hourly", "0 * * * *" }
|
|
};
|
|
|
|
public CronJob(ZwayController zway, InIReader settings) : base(zway, settings) {
|
|
this.crontime = DateTime.Now;
|
|
this.thread = new Thread(this.Runner);
|
|
this.thread.Start();
|
|
}
|
|
|
|
private 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;
|
|
foreach (String item in this.ini.GetSections()) {
|
|
if(this.ParseCronString(this.ini.GetValue(item, "cron"))) {
|
|
this.SetValues(this.ini.GetValue(item, "set"));
|
|
}
|
|
}
|
|
foreach (Tuple<String, Action> item in this.internalCron) {
|
|
if(this.ParseCronString(item.Item1)) {
|
|
item.Item2?.Invoke();
|
|
}
|
|
}
|
|
}
|
|
Thread.Sleep(100);
|
|
}
|
|
}
|
|
|
|
private void SetValues(String value) {
|
|
foreach (String item in value.Split(';')) {
|
|
String[] items = item.Split(':');
|
|
if(items.Length == 2) {
|
|
String[] addr = items[0].Split('-');
|
|
String[] values = items[1].Split('-');
|
|
if(addr.Length == 3 || addr.Length == 4) {
|
|
Int32 deviceid = Int32.Parse(addr[0]);
|
|
Int32 instanceid = Int32.Parse(addr[1]);
|
|
Int32 classid = Int32.Parse(addr[2]);
|
|
ICommandClass c;
|
|
if(addr.Length == 4) {
|
|
Int32 subcid = Int32.Parse(addr[3]);
|
|
c = this.zw.GetCommandClassSub(deviceid, instanceid, classid, subcid);
|
|
} else {
|
|
c = this.zw.GetCommandClass(deviceid, instanceid, classid);
|
|
}
|
|
if (c != null && values.Length == 2) {
|
|
if (Helper.HasProperty(c, values[0])) {
|
|
Helper.SetProperty(c, values[0], values[1]);
|
|
this.Update?.Invoke(this, new CronEvent(items[0], values[0], values[1]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private Boolean ParseCronString(String str) {
|
|
str = str.Trim();
|
|
if(this.cron_named.ContainsKey(str)) {
|
|
str = this.cron_named[str];
|
|
}
|
|
String[] value = str.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;
|
|
}
|
|
|
|
private 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<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++) {
|
|
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<Int32, String> ret = new Dictionary<Int32, String>();
|
|
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<Int32, String> r = new Dictionary<Int32, String>();
|
|
foreach (KeyValuePair<Int32, String> item in ret) {
|
|
if(item.Key%match == 0) {
|
|
r.Add(item.Key, "");
|
|
}
|
|
}
|
|
ret = r;
|
|
}
|
|
return ret.ContainsKey(Int32.Parse(date));
|
|
}
|
|
|
|
public override void SetInterconnection(String cron, Action hook) {
|
|
this.internalCron.Add(new Tuple<String, Action>(cron, hook));
|
|
}
|
|
|
|
#region IDisposable Support
|
|
private Boolean disposedValue = false;
|
|
|
|
protected virtual void Dispose(Boolean disposing) {
|
|
if (!this.disposedValue) {
|
|
if (disposing) {
|
|
this.thread.Abort();
|
|
while(this.thread.ThreadState != ThreadState.Aborted) { Thread.Sleep(100); }
|
|
}
|
|
|
|
this.thread = null;
|
|
|
|
this.disposedValue = true;
|
|
}
|
|
}
|
|
|
|
~CronJob() {
|
|
Dispose(false);
|
|
}
|
|
|
|
public override void Dispose() {
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
#endregion
|
|
}
|
|
} |