Compare commits

..
12 Commits
Author SHA1 Message Date
BlubbFish 75eac65510 [BF] v1.3.4.0 Fixing Json Names
[NF] v1.2.2.0 Mqtt can now get and set values
2017-12-19 20:18:30 +00:00
BlubbFish 44b8daa325 [BF] v.1.3.3 fixing polling once bug 2017-12-19 17:33:31 +00:00
BlubbFish 2cd2c7c02e [BF] v1.3.1.0 Forgot some settings, now configuration setting also works again 2017-12-18 16:02:18 +00:00
BlubbFish 33b1b6527c [NF] Tiny fix for mqtt 2017-12-17 21:53:16 +00:00
BlubbFish 9e60264d7d [NF] v1.3.0.0 Adding Status Polling and Mqtt (not compelete)
[NF] Able to force loading modules, so dependencys are ok
[NF] Cleanup because its now easyer to implement Zway
2017-12-17 20:09:28 +00:00
BlubbFish c96b2393d3 [BF] v.1.2.1.1 Next try to emulate F4G Events 2017-12-09 12:33:15 +00:00
BlubbFish 5fa97ea82b [NF] v1.1.2 Now complete Emulation of F4G Node
[NF] Possibility to attach internal cron events
2017-12-08 19:30:29 +00:00
BlubbFish 74027d705d [NF] Filter topics if usefull 2017-12-05 23:22:33 +00:00
BlubbFish 8dfc339194 [NF] Now possible to emulate F4G 2017-12-05 23:10:52 +00:00
BlubbFish f4545af4fe 2017-12-03 22:18:29 +00:00
BlubbFish 81737d5d3a [NF] Flex4Grid Plugin for Zway-Bot beginning 2017-12-03 22:07:33 +00:00
BlubbFish 8771a3ce89 [NF] Zway-Bot Module eingefügt 2017-12-02 18:04:43 +00:00
26 changed files with 935 additions and 179 deletions
+19 -1
View File
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.16
VisualStudioVersion = 15.0.27004.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Zway-Bot", "Zway-Bot\Zway-Bot.csproj", "{AEF8059F-8AEF-45C7-85C4-318C8F797900}"
EndProject
@@ -9,6 +9,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Zway", "..\Zway\Zway\Zway.c
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\Utils\Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils-IoT", "..\Utils\IoT\Utils-IoT.csproj", "{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConnectorDataMosquitto", "..\Utils\IoT\Connector\Data\Mosquitto\ConnectorDataMosquitto.csproj", "{39235FAD-BA9D-4B51-82FC-6969967BEAE9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConnectorDataMqtt", "..\Utils\IoT\Connector\Data\Mqtt\ConnectorDataMqtt.csproj", "{EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +33,18 @@ Global
{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.Build.0 = Release|Any CPU
{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Release|Any CPU.Build.0 = Release|Any CPU
{39235FAD-BA9D-4B51-82FC-6969967BEAE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39235FAD-BA9D-4B51-82FC-6969967BEAE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39235FAD-BA9D-4B51-82FC-6969967BEAE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39235FAD-BA9D-4B51-82FC-6969967BEAE9}.Release|Any CPU.Build.0 = Release|Any CPU
{EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+56 -9
View File
@@ -1,7 +1,7 @@
using System;
namespace ZwayBot {
public class CronEvent : EventArgs {
public class CronEvent : ModulEventArgs {
public CronEvent() {
}
@@ -10,13 +10,10 @@ namespace ZwayBot {
this.Address = addr;
this.Property = prop;
this.Value = value;
this.Source = "Cronjob";
}
public String Address { get; }
public String Property { get; }
public String Value { get; }
}
public class OvertakerEvent : EventArgs {
public class OvertakerEvent : ModulEventArgs {
public OvertakerEvent() {
}
@@ -25,10 +22,60 @@ namespace ZwayBot {
this.Address = addr;
this.Property = prop;
this.Value = value;
this.Source = "Overtaker";
}
}
public class Flex4gridEvent : ModulEventArgs {
public Flex4gridEvent() {
}
public Flex4gridEvent(String topic, String text) {
this.Address = topic;
this.Value = text;
this.Source = "Flex4Grid";
}
public override String ToString() {
return this.Source + ": on " + this.Address + " set " + this.Value;
}
}
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;
}
}
public class StatusPollingEvent : ModulEventArgs {
public StatusPollingEvent() {
}
public String Address { get; }
public String Property { get; }
public String Value { get; }
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;
}
}
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;
}
}
}
+32 -7
View File
@@ -2,8 +2,8 @@
using System.Reflection;
namespace ZwayBot {
class Helper {
public static void SetProperty(Object o, String name, String value) {
static class Helper {
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)) {
@@ -12,12 +12,15 @@ namespace ZwayBot {
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);
}
}
}
public static Boolean HasProperty(Object o, String type) {
internal static Boolean HasProperty(this Object o, String type) {
Type t = o.GetType();
foreach (PropertyInfo item in t.GetProperties()) {
if (item.Name == type) {
@@ -27,7 +30,7 @@ namespace ZwayBot {
return false;
}
internal static Object GetProperty(Object o, String name) {
internal static Object GetProperty(this Object o, String name) {
PropertyInfo prop = o.GetType().GetProperty(name);
if(prop.CanRead) {
return prop.GetValue(o);
@@ -35,14 +38,36 @@ namespace ZwayBot {
return null;
}
internal static Boolean HasInterface(Object o, String type) {
Type t = o.GetType();
foreach (Type item in t.GetInterfaces()) {
internal static Boolean HasAbstract(this Object o, Type type) {
if(o.GetType().BaseType == type) {
return true;
}
return false;
}
internal static Boolean HasInterface(this Type o, String type) {
foreach (Type item in o.GetInterfaces()) {
if(item.Name == type) {
return true;
}
}
return false;
}
internal static void WriteError(String text) {
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine("ERROR: " + text);
Console.ResetColor();
}
internal 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();
}
}
}
+4
View File
@@ -0,0 +1,4 @@
namespace ZwayBot.Interfaces {
interface IForceLoad {
}
}
+25
View File
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using BlubbFish.IoT.Zway;
using BlubbFish.Utils;
namespace ZwayBot {
abstract class AModul {
protected ZwayController zw;
protected InIReader ini;
public delegate void ModulEvent(Object sender, ModulEventArgs e);
public abstract event ModulEvent Update;
public AModul(ZwayController zway, InIReader settings) {
this.zw = zway;
this.ini = settings;
}
public virtual void Interconnect(Dictionary<String, AModul> moduls) { }
public virtual void SetInterconnection(String param, Action<Object> hook, Object data) { }
public abstract void Dispose();
}
}
@@ -6,16 +6,15 @@ using System.Threading;
using BlubbFish.IoT.Zway;
using BlubbFish.IoT.Zway.Interfaces;
using BlubbFish.Utils;
using ZwayBot.Interfaces;
namespace ZwayBot {
internal class CronJob : IDisposable {
private ZwayController zw;
private InIReader ini;
namespace ZwayBot.Moduls {
internal class CronJob : AModul, IDisposable, IForceLoad {
private DateTime crontime;
private Thread thread;
private List<Tuple<String, Action<Object>, Object>> internalCron = new List<Tuple<String, Action<Object>, Object>>();
public delegate void CronRunned(Object sender, CronEvent e);
public event CronRunned Update;
public override event ModulEvent Update;
private Dictionary<String, String> cron_named = new Dictionary<String, String> {
{ "@yearly", "0 0 1 1 *" },
@@ -26,9 +25,7 @@ namespace ZwayBot {
{ "@hourly", "0 * * * *" }
};
public CronJob(ZwayController zw) {
this.zw = zw;
this.ini = InIReader.GetInstance("cron.ini");
public CronJob(ZwayController zway, InIReader settings) : base(zway, settings) {
this.crontime = DateTime.Now;
this.thread = new Thread(this.Runner);
this.thread.Start();
@@ -39,9 +36,16 @@ namespace ZwayBot {
while (true) {
if(this.crontime.Minute != DateTime.Now.Minute) {
this.crontime = DateTime.Now;
foreach (String item in this.ini.GetSections()) {
if(ParseCronString(this.ini.GetValue(item, "cron"))) {
this.SetValues(this.ini.GetValue(item, "set"));
if (this.ini != null) {
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<Object>, Object> item in this.internalCron) {
if(this.ParseCronString(item.Item1)) {
item.Item2?.Invoke(item.Item3);
}
}
}
@@ -53,24 +57,12 @@ namespace ZwayBot {
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]));
}
ACommandClass c = this.zw.GetCommandClass(items[0]);
if (c != null && values.Length == 2) {
if (c.HasProperty(values[0])) {
c.SetProperty(values[0], values[1]);
this.Update?.Invoke(this, new CronEvent(items[0], values[0], values[1]));
}
}
}
@@ -117,7 +109,7 @@ namespace ZwayBot {
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("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("*")) {
@@ -161,8 +153,12 @@ namespace ZwayBot {
return ret.ContainsKey(Int32.Parse(date));
}
public override void SetInterconnection(String cron, Action<Object> hook, Object data) {
this.internalCron.Add(new Tuple<String, Action<Object>, Object>(cron, hook, data));
}
#region IDisposable Support
private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe.
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
@@ -181,7 +177,7 @@ namespace ZwayBot {
Dispose(false);
}
public void Dispose() {
public override void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
+187
View File
@@ -0,0 +1,187 @@
using System;
using System.Collections.Generic;
using System.Net;
using BlubbFish.IoT.Zway;
using BlubbFish.IoT.Zway.Devices;
using BlubbFish.IoT.Zway.Devices.CommandClasses;
using BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs;
using BlubbFish.IoT.Zway.Events;
using BlubbFish.IoT.Zway.Interfaces;
using BlubbFish.Utils;
using BlubbFish.Utils.IoT.Connector;
using LitJson;
namespace ZwayBot.Moduls {
class Flex4Grid : AModul, IDisposable {
private ADataBackend mqtt;
private String household = "";
private Object requestalivelock = new Object();
public override event ModulEvent Update;
public Flex4Grid(ZwayController zway, InIReader settings) : base(zway, settings) {
this.mqtt = ADataBackend.GetInstance(this.ini.GetSection("settings"));
this.ParseIni();
this.mqtt.MessageIncomming += this.Mqtt_MessageIncomming;
}
private void ParseIni() {
if (this.ini.GetValue("zway", "devices") != null) {
foreach (String device in this.ini.GetValue("zway", "devices").Split(',')) {
Int32 deviceid = Int32.Parse(device);
if (this.zw.Devices.ContainsKey(deviceid) && this.zw.Devices[deviceid].Instances.ContainsKey(0)) {
this.zw.Devices[deviceid].Instances[0].Update += this.DeviceUpdate;
}
}
}
if(this.ini.GetValue("f4g", "household") != null) {
this.household = this.ini.GetValue("f4g", "household");
}
}
private void DeviceUpdate(Object sender, DeviceUpdateEvent e) {
Instance instance = (Instance)sender;
if(e.Parent.GetType() == typeof(Switchbinary)) {
if (instance.CommandClasses.ContainsKey(ACommandClass.Classes.SwitchBinary)) {
String topic = "/flex4grid/v1/households/" + this.household + "/device/state";
String text = JsonMapper.ToJson(new Dictionary<String, String>() {
{ "status", ((Switchbinary)instance.CommandClasses[ACommandClass.Classes.SwitchBinary]).Level?"active":"idle" },
{ "timestamp", DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'") },
{ "type", ((Switchbinary)instance.CommandClasses[ACommandClass.Classes.SwitchBinary]).Name },
{ "id", instance.DeviceId.ToString() }
}).ToString();
this.mqtt.Send(topic, text);
this.Update?.Invoke(this, new Flex4gridEvent(topic, text));
}
} else if(e.Parent.GetType() == typeof(Sensormultilevelsub) || e.Parent.GetType() == typeof(Metersub)) {
if (instance.CommandClasses.ContainsKey(ACommandClass.Classes.SensorMultilevel) &&
((Sensormultilevel)instance.CommandClasses[ACommandClass.Classes.SensorMultilevel]).Sub.ContainsKey(4) &&
instance.CommandClasses.ContainsKey(ACommandClass.Classes.Meter) && ((Meter)instance.CommandClasses[ACommandClass.Classes.Meter]).Sub.ContainsKey(0)) {
String topic = "/flex4grid/v1/households/" + this.household + "/device/consumption";
String text = JsonMapper.ToJson(new Dictionary<String, String>() {
{ "timestamp", DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'") },
{ "id", instance.DeviceId.ToString() },
{ "power", Math.Round(((Sensormultilevelsub)((Sensormultilevel)instance.CommandClasses[ACommandClass.Classes.SensorMultilevel]).Sub[4]).Level).ToString("F0") },
{ "energyCumul", ((Metersub)((Meter)instance.CommandClasses[ACommandClass.Classes.Meter]).Sub[0]).Level.ToString() }
}).ToString();
this.mqtt.Send(topic, text);
this.Update?.Invoke(this, new Flex4gridEvent(topic, text));
}
}
}
private void Mqtt_MessageIncomming(Object sender, MqttEventArgs e) {
JsonData message;
String topic = e.Topic;
try {
if (e.Message.StartsWith("{")) {
message = JsonMapper.ToObject(e.Message);
} else {
return;
}
} catch (Exception) {
return;
}
if(topic == "/flex4grid/v1/households/" + this.household + "/device/actuate") {
if(message.Keys.Contains("deviceId") && message.Keys.Contains("command")) {
String device = message["deviceId"].ToString();
if(this.ini.GetValue("zway", "devices") != null) {
foreach (String item in this.ini.GetValue("zway", "devices").Split(',')) {
if (item == device) {
Int32 deviceid = Int32.Parse(device);
if (this.zw.Devices.ContainsKey(deviceid) && this.zw.Devices[deviceid].Instances.ContainsKey(0) &&
this.zw.Devices[deviceid].Instances[0].CommandClasses.ContainsKey(ACommandClass.Classes.SwitchBinary)) {
((Switchbinary)this.zw.Devices[deviceid].Instances[0].CommandClasses[ACommandClass.Classes.SwitchBinary]).Level = message["command"].ToString() == "ON";
}
}
}
}
}
}
if (topic == "/flex4grid/v1/households/" + this.household + "/devices/state/request") {
if (this.ini.GetValue("zway", "devices") != null) {
Dictionary<String, String> response = new Dictionary<String, String>();
foreach (String device in this.ini.GetValue("zway", "devices").Split(',')) {
Int32 deviceid = Int32.Parse(device);
if (this.zw.Devices.ContainsKey(deviceid) && this.zw.Devices[deviceid].Instances.ContainsKey(0)) {
if (this.zw.Devices[deviceid].Instances[0].CommandClasses.ContainsKey(ACommandClass.Classes.SwitchBinary)) {
Switchbinary sw = ((Switchbinary)this.zw.Devices[deviceid].Instances[0].CommandClasses[ACommandClass.Classes.SwitchBinary]);
response.Add(sw.DeviceId.ToString(), sw.Level ? "active" : "idle");
}
}
}
if(response.Count != 0) {
response.Add("timestamp", DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'"));
String rtopic = "/flex4grid/v1/households/" + this.household + "/devices/state/response";
String rtext = JsonMapper.ToJson(response).ToString();
}
}
}
}
private void RequestAlive(Object o) {
String raspi = this.ini.GetValue("f4g", "raspi");
lock (this.requestalivelock) {
String req = "https://wiki.flex4grid.eu/rupdate/rupdate_general.yml.gpg.asc?gw=" + raspi;
HttpWebRequest request = WebRequest.CreateHttp(req);
try {
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
this.Update?.Invoke(this, new Flex4gridEvent(req, response.StatusCode.ToString()));
}
} catch (Exception) { }
}
lock (this.requestalivelock) {
String req = "https://wiki.flex4grid.eu/rupdate/rupdate_general.yml?gw=" + raspi;
HttpWebRequest request = WebRequest.CreateHttp(req);
try {
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
this.Update?.Invoke(this, new Flex4gridEvent(req, response.StatusCode.ToString()));
}
} catch (Exception) { }
}
lock (this.requestalivelock) {
String req = "http://swb.pcs.flex4grid.eu/gateway/" + raspi;
HttpWebRequest request = WebRequest.CreateHttp(req);
try {
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
this.Update?.Invoke(this, new Flex4gridEvent(req, response.StatusCode.ToString()));
}
} catch (Exception) { }
}
}
public override void Interconnect(Dictionary<String, AModul> moduls) {
if (this.ini.GetValue("f4g", "raspi") != null) {
foreach (KeyValuePair<String, AModul> item in moduls) {
if (item.Value is CronJob) {
item.Value.SetInterconnection("10,40 * * * *", new Action<Object>(this.RequestAlive), null);
}
}
}
}
#region IDisposable Support
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
if (disposing) {
this.mqtt.Dispose();
}
this.disposedValue = true;
}
}
~Flex4Grid() {
Dispose(false);
}
public override void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}
+102
View File
@@ -0,0 +1,102 @@
using System;
using System.Text.RegularExpressions;
using BlubbFish.IoT.Zway;
using BlubbFish.IoT.Zway.Events;
using BlubbFish.IoT.Zway.Interfaces;
using BlubbFish.Utils;
using BlubbFish.Utils.IoT.Connector;
using LitJson;
namespace ZwayBot.Moduls {
class Mqtt : AModul, IDisposable {
private ADataBackend mqtt;
public override event ModulEvent Update;
public Mqtt(ZwayController zway, InIReader settings) : base(zway, settings) {
this.mqtt = ADataBackend.GetInstance(this.ini.GetSection("settings"));
this.mqtt.MessageIncomming += this.Mqtt_MessageIncomming;
this.zw.Update += this.ZwayEvent;
}
private void ZwayEvent(Object sender, DeviceUpdateEvent e) {
String topic = "";
String data = "";
if(e.Parent.HasAbstract(typeof(ACommandClass))) {
ACommandClass sensor = (ACommandClass)e.Parent;
topic = "/zwavebot/devices/" + sensor.MqttTopic();
data = sensor.ToJson();
}
if(topic != "" && data != "") {
this.mqtt.Send(topic, data);
this.Update?.Invoke(this, new MqttEvent(topic, data));
}
}
private void Mqtt_MessageIncomming(Object sender, MqttEventArgs e) {
if (e.Topic.StartsWith("/zwavebot/devices/") && e.Topic.EndsWith("set")) {
Match m = new Regex("^/zwavebot/devices/(\\d+)/(\\d+)/(\\d+)/set$|^/zwavebot/devices/(\\d+)/(\\d+)/(\\d+)/(\\d+)/set$").Match(e.Topic);
String id = "";
if(m.Groups[1].Success) {
id = m.Groups[1].Value + "-" + m.Groups[2].Value + "-" + m.Groups[3].Value;
}
if(m.Groups[4].Success) {
id = m.Groups[4].Value + "-" + m.Groups[5].Value + "-" + m.Groups[6].Value + "-" + m.Groups[7].Value;
}
ACommandClass c = this.zw.GetCommandClass(id);
if(c == null) {
return;
}
try {
JsonData a = JsonMapper.ToObject(e.Message);
foreach (String item in a.Keys) {
String key = item.ToUpperLower();
if(c.HasProperty(key)) {
c.SetProperty(key, a[item].ToString());
this.Update?.Invoke(this, new MqttEvent(c.Id, a[item].ToString()));
}
}
} catch (Exception) { }
}
if(e.Topic.StartsWith("/zwavebot/devices/") && e.Topic.EndsWith("get")) {
Match m = new Regex("^/zwavebot/devices/(\\d+)/(\\d+)/(\\d+)/get$|^/zwavebot/devices/(\\d+)/(\\d+)/(\\d+)/(\\d+)/get$").Match(e.Topic);
String id = "";
if (m.Groups[1].Success) {
id = m.Groups[1].Value + "-" + m.Groups[2].Value + "-" + m.Groups[3].Value;
}
if (m.Groups[4].Success) {
id = m.Groups[4].Value + "-" + m.Groups[5].Value + "-" + m.Groups[6].Value + "-" + m.Groups[7].Value;
}
ACommandClass c = this.zw.GetCommandClass(id);
if (c == null) {
return;
}
c.PollOnce = true;
this.mqtt.Send("/zwavebot/devices/" + c.MqttTopic(), c.ToJson());
this.Update?.Invoke(this, new MqttEvent(e.Topic, "Dataget"));
}
}
#region IDisposable Support
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
if (disposing) {
this.mqtt.Dispose();
}
this.disposedValue = true;
}
}
~Mqtt() {
Dispose(false);
}
public override void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}
+96
View File
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using BlubbFish.IoT.Zway;
using BlubbFish.IoT.Zway.Events;
using BlubbFish.IoT.Zway.Interfaces;
using BlubbFish.Utils;
namespace ZwayBot.Moduls {
internal class Overtaker : AModul, IDisposable {
private Dictionary<String, Dictionary<String, String>> events = new Dictionary<String, Dictionary<String, String>>();
public override event ModulEvent Update;
public Overtaker(ZwayController zway, InIReader settings) : base(zway, settings) {
this.ParseIni();
}
private void ParseIni() {
foreach (String item in this.ini.GetSections()) {
String from = this.ini.GetValue(item, "from");
String[] source = from.Split(':');
this.events.Add(source[0], this.ini.GetSection(item));
ACommandClass c = this.zw.GetCommandClass(source[0]);
if (c != null) {
c.Polling = true;
c.Update += this.ChangedEvent;
}
}
}
private void ChangedEvent(Object sender, DeviceUpdateEvent e) {
if(sender.HasAbstract(typeof(ACommandClass))) {
if (this.events.ContainsKey(((ACommandClass)sender).Id)) {
this.SetValues(sender, ((ACommandClass)sender).Id, this.events[((ACommandClass)sender).Id]);
}
}
}
private void SetValues(Object sender, String name, Dictionary<String, String> 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];
}
}
}
foreach (String to in dictionary["to"].Split(';')) {
String[] target = to.Split(':');
if(target.Length == 2) {
ACommandClass c = this.zw.GetCommandClass(target[0]);
if (c != null) {
if (c.HasProperty(target[1])) {
if (c.GetProperty(target[1]).ToString() != source_value) {
c.SetProperty(target[1], source_value);
this.Update?.Invoke(this, new OvertakerEvent(target[0], target[1], source_value));
}
}
}
}
}
}
#region IDisposable Support
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
if (disposing) {
}
this.disposedValue = true;
}
}
~Overtaker() {
Dispose(false);
}
public override void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}
+58
View File
@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using BlubbFish.IoT.Zway;
using BlubbFish.IoT.Zway.Devices;
using BlubbFish.IoT.Zway.Interfaces;
using BlubbFish.Utils;
using ZwayBot.Interfaces;
namespace ZwayBot.Moduls {
class Statuspolling : AModul, IDisposable, IForceLoad {
public override event ModulEvent Update;
public Statuspolling(ZwayController zway, InIReader settings) : base(zway, settings) { }
public override void Interconnect(Dictionary<String, AModul> moduls) {
foreach (KeyValuePair<String, AModul> item in moduls) {
if (item.Value is CronJob) {
item.Value.SetInterconnection("0 0 * * *", new Action<Object>(this.PollAll), null);
if (this.ini != null) {
foreach (String section in this.ini.GetSections()) {
if (this.ini.GetValue(section, "cron") != null && this.ini.GetValue(section, "devices") != null) {
item.Value.SetInterconnection(this.ini.GetValue(section, "cron"), new Action<Object>(this.PollSpecific), this.ini.GetValue(section, "devices"));
}
}
}
}
}
}
private void PollSpecific(Object obj) {
String devices = (String)obj;
foreach (String item in devices.Split(',')) {
ACommandClass c = this.zw.GetCommandClass(item);
c.PollOnce = true;
this.Update?.Invoke(this, new StatusPollingEvent("Polling", item));
}
}
private void PollAll(Object o) {
foreach (KeyValuePair<Int32, Device> device in this.zw.Devices) {
foreach (KeyValuePair<Int32, Instance> instance in device.Value.Instances) {
foreach (KeyValuePair<ACommandClass.Classes, ACommandClass> commandclass in instance.Value.CommandClasses) {
commandclass.Value.PollOnce = true;
if(commandclass.Value.HasSub) {
foreach (KeyValuePair<Int32, ACommandClass> subclass in commandclass.Value.Sub) {
subclass.Value.PollOnce = true;
}
}
}
}
}
this.Update?.Invoke(this, new StatusPollingEvent("Polling", "all nodes"));
}
public override void Dispose() {}
}
}
-106
View File
@@ -1,106 +0,0 @@
using System;
using System.Collections.Generic;
using BlubbFish.IoT.Zway;
using BlubbFish.IoT.Zway.Events;
using BlubbFish.IoT.Zway.Interfaces;
using BlubbFish.Utils;
namespace ZwayBot {
internal class Overtaker {
private ZwayController zw;
private InIReader ini;
private Dictionary<String, Dictionary<String, String>> events = new Dictionary<String, Dictionary<String, String>>();
public delegate void OvertakeValue(Object sender, OvertakerEvent e);
public event OvertakeValue Update;
public Overtaker(ZwayController zw) {
this.zw = zw;
this.ini = InIReader.GetInstance("overtaker.ini");
this.ParseIni();
}
private void ParseIni() {
foreach (String item in this.ini.GetSections()) {
String from = this.ini.GetValue(item, "from");
String[] source = from.Split(':');
this.events.Add(source[0], this.ini.GetSection(item));
String[] addr = source[0].Split('-');
ICommandClass c;
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]);
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) {
c.Polling = true;
c.Update += this.ChangedEvent;
}
}
}
}
private void ChangedEvent(Object sender, DeviceUpdateEvent e) {
if(Helper.HasInterface(sender, "ICommandClass")) {
if (this.events.ContainsKey(((ICommandClass)sender).Id)) {
this.SetValues(sender, ((ICommandClass)sender).Id, this.events[((ICommandClass)sender).Id]);
}
}
}
private void SetValues(Object sender, String name, Dictionary<String, String> dictionary) {
String from = dictionary["from"];
String[] source = from.Split(':');
if (source.Length != 2) {
return;
}
String source_value;
if (Helper.HasProperty(sender, source[1])) {
source_value = Helper.GetProperty(sender, 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];
}
}
}
foreach (String to in dictionary["to"].Split(';')) {
String[] target = to.Split(':');
if(target.Length == 2) {
String[] addr = target[0].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) {
String target_value;
if (Helper.HasProperty(c, target[1])) {
target_value = Helper.GetProperty(c, target[1]).ToString();
if (target_value != source_value) {
Helper.SetProperty(c, target[1], source_value);
this.Update?.Invoke(this, new OvertakerEvent(target[0], target[1], source_value));
}
}
}
}
}
}
}
}
}
+68 -15
View File
@@ -1,16 +1,44 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using BlubbFish.IoT.Zway;
using BlubbFish.Utils;
namespace ZwayBot {
class Program {
static void Main(String[] args) {
ZwayController zw = new ZwayController(InIReader.GetInstance("settings.ini").GetSection("zway"), InIReader.GetInstance("names.ini").GetSection("names"), false);
zw.Update += ZwayDataUpate;
CronJob cron = new CronJob(zw);
cron.Update += Cron_Update;
Overtaker over = new Overtaker(zw);
over.Update += Over_Update;
static void Main(String[] args) => new Program(args);
private ZwayController zw;
private Dictionary<String, AModul> moduls = new Dictionary<String, AModul>();
public Program(String[] args) {
Dictionary<String, String> names;
if(File.Exists("names.ini")) {
names = InIReader.GetInstance("names.ini").GetSection("names");
} else {
names = new Dictionary<String, String>();
}
if(!File.Exists("settings.ini")) {
Helper.WriteError("No settings.ini found. Abord!");
return;
}
this.zw = new ZwayController(InIReader.GetInstance("settings.ini").GetSection("zway"), names, false);
this.zw.Update += this.ZwayDataUpate;
this.ModulLoader();
this.ModulInterconnect();
this.ModulEvents();
this.WaitForShutdown();
this.ModulDispose();
}
private void ModulInterconnect() {
foreach (KeyValuePair<String, AModul> item in this.moduls) {
item.Value.Interconnect(this.moduls);
}
}
private void WaitForShutdown() {
while (true) {
System.Threading.Thread.Sleep(100);
if (Console.KeyAvailable) {
@@ -20,20 +48,45 @@ namespace ZwayBot {
}
}
}
cron.Dispose();
zw.Dispose();
}
private static void Over_Update(Object sender, OvertakerEvent e) {
Console.WriteLine("OVERTAKE: " + e.Address + " set " + e.Property + " to " + e.Value);
private void ModulDispose() {
foreach (KeyValuePair<String, AModul> item in this.moduls) {
item.Value.Dispose();
Console.WriteLine("Modul entladen: " + item.Key);
}
this.zw.Dispose();
}
private static void Cron_Update(Object sender, CronEvent e) {
Console.WriteLine("CRON: " + e.Address + " set " + e.Property + " to " + e.Value);
private void ModulEvents() {
foreach (KeyValuePair<String, AModul> item in this.moduls) {
item.Value.Update += this.ModulUpdate;
}
}
private static void ZwayDataUpate(Object sender, BlubbFish.IoT.Zway.Events.DeviceUpdateEvent e) {
Console.WriteLine("-> ZW [" + e.UpdateTime + "]: " + sender.ToString());
private void ModulUpdate(Object sender, ModulEventArgs e) {
Console.WriteLine(e.ToString());
}
private void ModulLoader() {
Assembly asm = Assembly.GetExecutingAssembly();
foreach (Type item in asm.GetTypes()) {
if(item.Namespace == "ZwayBot.Moduls") {
Type t = item;
String name = t.Name;
if (File.Exists(name.ToLower() + ".ini")) {
this.moduls.Add(name, (AModul)t.GetConstructor(new Type[] { typeof(ZwayController), typeof(InIReader) }).Invoke(new Object[] { this.zw, InIReader.GetInstance(name.ToLower() + ".ini") }));
Console.WriteLine("Load Modul " + name);
} else if(t.HasInterface("IForceLoad")) {
this.moduls.Add(name, (AModul)t.GetConstructor(new Type[] { typeof(ZwayController), typeof(InIReader) }).Invoke(new Object[] { this.zw, null }));
Console.WriteLine("Load Modul Forced " + name);
}
}
}
}
private void ZwayDataUpate(Object sender, BlubbFish.IoT.Zway.Events.DeviceUpdateEvent e) {
Console.WriteLine("-> ZW [" + e.UpdateTime + "]: " + e.Parent.ToString());
}
}
}
+9 -6
View File
@@ -1,17 +1,17 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Resources;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("Zway-Bot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyDescription("Is a Bot for Zwave Devices")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCompany("BlubbFish")]
[assembly: AssemblyProduct("Zway-Bot")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyTrademark("BlubbFish")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
@@ -32,5 +32,8 @@ using System.Runtime.InteropServices;
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.2.2.0")]
[assembly: AssemblyFileVersion("1.2.2.0")]
[assembly: NeutralResourcesLanguage("de-DE")]
// “Internet Of Things” icon by By Michael Wohlwend, US, from thenounproject.com.
+73
View File
@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ZwayBot.Properties {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ZwayBot.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol).
/// </summary>
public static System.Drawing.Icon Icon {
get {
object obj = ResourceManager.GetObject("Icon", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
}
}
+124
View File
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

+1
View File
@@ -0,0 +1 @@
<svg width='200' height='200' fill="#000000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path d="M21,57.9v-6.5c0-2.9,2.4-5.3,5.3-5.3H41v-6.1c0-1.1,0.9-2,2-2s2,0.9,2,2v14.7c0,0.7,0.6,1.3,1.3,1.3h15.8c1.1,0,2,0.9,2,2 s-0.9,2-2,2H46.3c-2.9,0-5.3-2.4-5.3-5.3V50H26.3c-0.7,0-1.3,0.6-1.3,1.3v6.5c0,1.1-0.9,2-2,2S21,59,21,57.9z M79.8,72.9 c-1.1,0-2,0.9-2,2v1.7c0,0.7-0.6,1.3-1.3,1.3H62.2c-0.7,0-1.3-0.6-1.3-1.3c0-3.1-3.3-5.7-6.1-5.7H42.3c-1.1,0-2,0.9-2,2s0.9,2,2,2 h12.5c0.9,0,2.1,1.1,2.1,1.7c0,2.9,2.4,5.3,5.3,5.3h14.3c2.9,0,5.3-2.4,5.3-5.3v-1.7C81.8,73.8,80.9,72.9,79.8,72.9z M36,70.1 C36,70.1,36,70.1,36,70.1l0,14.4c0,0.8-0.4,1.4-1.1,1.8l-11,5.5c-0.1,0-0.2,0.1-0.2,0.1c-0.1,0-0.1,0-0.2,0.1C23.3,92,23.2,92,23,92 c0,0,0,0,0,0c-0.2,0-0.3,0-0.5-0.1c-0.1,0-0.1,0-0.2-0.1c-0.1,0-0.2,0-0.2-0.1l-11-5.5c-0.7-0.3-1.1-1-1.1-1.8V70.2c0,0,0-0.1,0-0.1 c0-0.1,0-0.2,0-0.3c0,0,0-0.1,0-0.1c0.1-0.3,0.2-0.6,0.4-0.8c0,0,0.1-0.1,0.1-0.1c0.1-0.1,0.2-0.2,0.3-0.2c0,0,0,0,0.1-0.1 c0,0,0,0,0.1,0c0,0,0.1,0,0.1-0.1l11-5.5c0.6-0.3,1.2-0.3,1.8,0l11,5.5c0,0,0.1,0,0.1,0.1c0,0,0,0,0.1,0c0,0,0,0,0.1,0.1 c0.1,0.1,0.2,0.1,0.3,0.2c0,0,0.1,0.1,0.1,0.1c0.2,0.2,0.4,0.5,0.4,0.8c0,0,0,0.1,0,0.1C36,69.9,36,70,36,70.1z M16.4,70.2l6.6,3.3 l6.6-3.3L23,66.9L16.4,70.2z M21,76.9l-7-3.5v9.8l7,3.5V76.9z M32,73.4l-7,3.5v9.8l7-3.5V73.4z M90.3,57.5c0,6.2-5.1,11.3-11.3,11.3 s-11.3-5.1-11.3-11.3S72.8,46.2,79,46.2S90.3,51.3,90.3,57.5z M86.3,57.5c0-4-3.3-7.3-7.3-7.3s-7.3,3.3-7.3,7.3s3.3,7.3,7.3,7.3 S86.3,61.5,86.3,57.5z M29.1,26.5c-0.1-0.6,0-1.2,0.3-1.6l12-17.1c0-0.1,0.1-0.1,0.2-0.2c0.1-0.1,0.1-0.1,0.2-0.2 C42,7.1,42.5,6.9,43,6.9c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0.5,0,1,0.2,1.3,0.5c0.1,0.1,0.1,0.1,0.2,0.2 c0.1,0.1,0.1,0.1,0.2,0.2l12,17.1c0.3,0.5,0.4,1.1,0.3,1.6c-0.1,0.6-0.5,1-1,1.3l-12,6c-0.1,0-0.1,0.1-0.2,0.1 c-0.1,0-0.2,0.1-0.3,0.1C43.3,34,43.2,34,43,34c-0.3,0-0.6-0.1-0.8-0.2c0,0,0,0,0,0c0,0-0.1,0-0.1,0l-12-6 C29.6,27.5,29.2,27.1,29.1,26.5z M45,28.8l7-3.5l-7-10V28.8z M34,25.2l7,3.5V15.2L34,25.2z M78.2,51.6c-2.5,0.3-4.5,2.1-4.9,4.6 c-0.2,1.1,0.5,2.1,1.6,2.3c0.1,0,0.2,0,0.4,0c0.9,0,1.8-0.7,2-1.6c0.1-0.7,0.7-1.3,1.4-1.3c1.1-0.1,1.9-1.1,1.8-2.2 C80.3,52.3,79.2,51.5,78.2,51.6z M92.9,34.5c-3.8-3.8-8.8-5.8-14.1-5.8s-10.3,2.1-14.1,5.8c-0.8,0.8-0.8,2,0,2.8 c0.8,0.8,2,0.8,2.8,0c3-3,7-4.7,11.3-4.7s8.3,1.7,11.3,4.7c0.4,0.4,0.9,0.6,1.4,0.6s1-0.2,1.4-0.6C93.7,36.5,93.7,35.3,92.9,34.5z M73.1,42.8c1.5-1.5,3.6-2.4,5.8-2.4c2.2,0,4.2,0.8,5.8,2.4c0.4,0.4,0.9,0.6,1.4,0.6s1-0.2,1.4-0.6c0.8-0.8,0.8-2,0-2.8 c-2.3-2.3-5.3-3.6-8.6-3.6c-3.2,0-6.3,1.3-8.6,3.6c-0.8,0.8-0.8,2,0,2.8C71,43.6,72.3,43.6,73.1,42.8z"/></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

+49 -3
View File
@@ -8,9 +8,10 @@
<OutputType>Exe</OutputType>
<RootNamespace>ZwayBot</RootNamespace>
<AssemblyName>Zway-Bot</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -31,9 +32,19 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>ZwayBot.Program</StartupObject>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\Icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="LitJson, Version=0.9.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\LitJson.0.9.0\lib\LitJson.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@@ -43,13 +54,35 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Events.cs" />
<Compile Include="CronJob.cs" />
<Compile Include="Interfaces\IForceLoad.cs" />
<Compile Include="Moduls\AModul.cs" />
<Compile Include="Moduls\CronJob.cs" />
<Compile Include="Helper.cs" />
<Compile Include="Overtaker.cs" />
<Compile Include="Moduls\Flex4Grid.cs" />
<Compile Include="Moduls\Mqtt.cs" />
<Compile Include="Moduls\Overtaker.cs" />
<Compile Include="Moduls\StatusPolling.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Utils\IoT\Connector\Data\Mosquitto\ConnectorDataMosquitto.csproj">
<Project>{39235fad-ba9d-4b51-82fc-6969967beae9}</Project>
<Name>ConnectorDataMosquitto</Name>
</ProjectReference>
<ProjectReference Include="..\..\Utils\IoT\Connector\Data\Mqtt\ConnectorDataMqtt.csproj">
<Project>{ee6c8f68-ed46-4c1c-abdd-cfcdf75104f2}</Project>
<Name>ConnectorDataMqtt</Name>
</ProjectReference>
<ProjectReference Include="..\..\Utils\IoT\Utils-IoT.csproj">
<Project>{b870e4d5-6806-4a0b-b233-8907eedc5afc}</Project>
<Name>Utils-IoT</Name>
</ProjectReference>
<ProjectReference Include="..\..\Utils\Utils\Utils.csproj">
<Project>{fac8ce64-bf13-4ece-8097-aeb5dd060098}</Project>
<Name>Utils</Name>
@@ -59,5 +92,18 @@
<Name>Zway</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\Icon.ico" />
<Content Include="Resources\icon.svg" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="LitJson" version="0.9.0" targetFramework="net461" />
</packages>