[NF] Now possible to control F4G Devices

This commit is contained in:
BlubbFish 2017-09-20 21:43:43 +00:00
parent a0312c7757
commit e6429ef76c
8 changed files with 118 additions and 29 deletions

View File

@ -11,23 +11,24 @@ namespace Dashboard.Connector {
public override event MqttMessage MessageIncomming; public override event MqttMessage MessageIncomming;
public override event MqttMessage MessageSending; public override event MqttMessage MessageSending;
public Mosquitto(Dictionary<String, String> settings) { public Mosquitto(Dictionary<String, String> mqtt_settings) {
this.settings = mqtt_settings;
//mosquitto_sub --cafile ca.pem --cert cert.pem --key cert.key -h swb.broker.flex4grid.eu -p 8883 -t /# -v //mosquitto_sub --cafile ca.pem --cert cert.pem --key cert.key -h swb.broker.flex4grid.eu -p 8883 -t /# -v
this.message = ""; this.message = "";
this.p = new Process(); this.p = new Process();
this.p.StartInfo.FileName = "mosquitto_sub.exe"; this.p.StartInfo.FileName = "mosquitto_sub";
String args = "-h " + settings["server"]+" "; String args = "-h " + this.settings["server"]+" ";
if(settings.ContainsKey("port")) { if(this.settings.ContainsKey("port")) {
args += "-p "+ settings["port"]+" "; args += "-p "+ this.settings["port"]+" ";
} }
if (settings.ContainsKey("cafile")) { if (this.settings.ContainsKey("cafile")) {
args += "--cafile " + settings["cafile"] + " "; args += "--cafile " + this.settings["cafile"] + " ";
} }
if (settings.ContainsKey("cert")) { if (this.settings.ContainsKey("cert")) {
args += "--cert " + settings["cert"] + " "; args += "--cert " + this.settings["cert"] + " ";
} }
if (settings.ContainsKey("key")) { if (this.settings.ContainsKey("key")) {
args += "--key " + settings["key"] + " "; args += "--key " + this.settings["key"] + " ";
} }
this.p.StartInfo.Arguments = args+"-t /# -v -d"; this.p.StartInfo.Arguments = args+"-t /# -v -d";
this.p.StartInfo.CreateNoWindow = true; this.p.StartInfo.CreateNoWindow = true;
@ -38,9 +39,30 @@ namespace Dashboard.Connector {
this.p.ErrorDataReceived += this.P_ErrorDataReceived; this.p.ErrorDataReceived += this.P_ErrorDataReceived;
this.p.Start(); this.p.Start();
this.p.BeginOutputReadLine(); this.p.BeginOutputReadLine();
} }
public override void Send(String topic, String data) { public override void Send(String topic, String data) {
Process send = new Process();
send.StartInfo.FileName = "mosquitto_pub";
String args = "-h " + this.settings["server"] + " ";
if (this.settings.ContainsKey("port")) {
args += "-p " + this.settings["port"] + " ";
}
if (this.settings.ContainsKey("cafile")) {
args += "--cafile " + this.settings["cafile"] + " ";
}
if (this.settings.ContainsKey("cert")) {
args += "--cert " + this.settings["cert"] + " ";
}
if (this.settings.ContainsKey("key")) {
args += "--key " + this.settings["key"] + " ";
}
send.StartInfo.Arguments = args + "-m \""+data.Replace("\"","\\\"")+"\" -t \""+topic+"\" -d";
send.StartInfo.CreateNoWindow = true;
send.StartInfo.UseShellExecute = false;
send.Start();
send.WaitForExit();
MessageSending?.Invoke(this, new MqttEventArgs(data, topic)); MessageSending?.Invoke(this, new MqttEventArgs(data, topic));
} }
@ -68,6 +90,7 @@ namespace Dashboard.Connector {
#region IDisposable Support #region IDisposable Support
private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe. private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe.
private readonly Dictionary<String, String> settings;
protected virtual void Dispose(Boolean disposing) { protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) { if (!this.disposedValue) {

View File

@ -66,6 +66,7 @@
<Compile Include="Sensor\ASensor.cs" /> <Compile Include="Sensor\ASensor.cs" />
<Compile Include="Sensor\Flex4GridPower.cs" /> <Compile Include="Sensor\Flex4GridPower.cs" />
<Compile Include="Sensor\Power.cs" /> <Compile Include="Sensor\Power.cs" />
<Compile Include="Sensor\Flex4GridSwitch.cs" />
<Compile Include="Sensor\Switch.cs" /> <Compile Include="Sensor\Switch.cs" />
<Compile Include="Tracings\ATracings.cs" /> <Compile Include="Tracings\ATracings.cs" />
<Compile Include="Tracings\Graph.cs" /> <Compile Include="Tracings\Graph.cs" />

View File

@ -29,9 +29,9 @@
// //
// statusStrip1 // statusStrip1
// //
this.statusStrip1.Location = new System.Drawing.Point(0, 370); this.statusStrip1.Location = new System.Drawing.Point(0, 490);
this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(843, 22); this.statusStrip1.Size = new System.Drawing.Size(1247, 22);
this.statusStrip1.TabIndex = 0; this.statusStrip1.TabIndex = 0;
this.statusStrip1.Text = "statusStrip1"; this.statusStrip1.Text = "statusStrip1";
// //
@ -39,14 +39,14 @@
// //
this.flowLayoutPanel2.Location = new System.Drawing.Point(12, 12); this.flowLayoutPanel2.Location = new System.Drawing.Point(12, 12);
this.flowLayoutPanel2.Name = "flowLayoutPanel2"; this.flowLayoutPanel2.Name = "flowLayoutPanel2";
this.flowLayoutPanel2.Size = new System.Drawing.Size(819, 355); this.flowLayoutPanel2.Size = new System.Drawing.Size(1223, 475);
this.flowLayoutPanel2.TabIndex = 3; this.flowLayoutPanel2.TabIndex = 3;
// //
// Dashboard // Dashboard
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(843, 392); this.ClientSize = new System.Drawing.Size(1247, 512);
this.Controls.Add(this.flowLayoutPanel2); this.Controls.Add(this.flowLayoutPanel2);
this.Controls.Add(this.statusStrip1); this.Controls.Add(this.statusStrip1);
this.Name = "Dashboard"; this.Name = "Dashboard";

View File

@ -21,6 +21,7 @@ namespace Dashboard {
this.SizeChanged += this.Dashboard_SizeChanged; this.SizeChanged += this.Dashboard_SizeChanged;
AMqtt.Instance.MessageIncomming += this.Instance_MessageIncomming; AMqtt.Instance.MessageIncomming += this.Instance_MessageIncomming;
AMqtt.Instance.MessageSending += this.Instance_MessageSending;
} }
private void Dashboard_SizeChanged(Object sender, EventArgs e) { private void Dashboard_SizeChanged(Object sender, EventArgs e) {
@ -55,8 +56,13 @@ namespace Dashboard {
AMqtt.Instance.Dispose(); AMqtt.Instance.Dispose();
this.Dispose(true); this.Dispose(true);
} }
private void Instance_MessageIncomming(Object sender, MqttEventArgs e) { private void Instance_MessageIncomming(Object sender, MqttEventArgs e) {
System.Diagnostics.Debug.WriteLine("Received = " + e.Message + " on topic " + e.Topic+" at "+DateTime.Now.ToUniversalTime()); System.Diagnostics.Debug.WriteLine("Received = " + e.Message + " on topic " + e.Topic+" at "+DateTime.Now.ToUniversalTime());
} }
private void Instance_MessageSending(Object sender, MqttEventArgs e) {
System.Diagnostics.Debug.WriteLine("Sended = " + e.Message + " on topic " + e.Topic + " at " + DateTime.Now.ToUniversalTime());
}
} }
} }

View File

@ -3,36 +3,41 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Text.RegularExpressions;
namespace Dashboard.Sensor { namespace Dashboard.Sensor {
public abstract class ASensor : IDisposable { public abstract class ASensor : IDisposable {
private String topic; protected String topic;
private Int32 pollcount; protected Int32 pollcount;
private Dictionary<String, String> settings; private Dictionary<String, String> settings;
private Thread updateThread; private Thread updateThread;
private Boolean pollEnabled = false;
public ASensor(Dictionary<String, String> settings) { public ASensor(Dictionary<String, String> settings) {
this.GetBool = true; this.GetBool = true;
this.GetFloat = 0.0f; this.GetFloat = 0.0f;
this.GetInt = 0; this.GetInt = 0;
this.topic = (settings.Keys.Contains("topic")) ? settings["topic"] : ""; this.topic = (settings.Keys.Contains("topic")) ? settings["topic"] : "";
this.Polling = (settings.Keys.Contains("polling")) ? Int32.Parse(settings["polling"]) : 60;
this.pollcount = this.Polling;
this.settings = settings; this.settings = settings;
AMqtt.Instance.MessageIncomming += this.IncommingMqttMessage; AMqtt.Instance.MessageIncomming += this.IncommingMqttMessage;
if (settings.Keys.Contains("polling")) {
this.pollEnabled = true;
this.Polling = Int32.Parse(settings["polling"]);
this.pollcount = this.Polling;
this.updateThread = new Thread(this.SensorPolling); this.updateThread = new Thread(this.SensorPolling);
this.updateThread.Start(); this.updateThread.Start();
} }
}
private void SensorPolling() { private void SensorPolling() {
while(true) { while(this.pollEnabled) {
Thread.Sleep(1000); Thread.Sleep(1000);
this.Poll(); this.Poll();
} }
} }
private void IncommingMqttMessage(Object sender, MqttEventArgs e) { private void IncommingMqttMessage(Object sender, MqttEventArgs e) {
if(e.Topic == this.topic) { if(Regex.Match(e.Topic, this.topic).Success) {
if (this.UpdateValue(e)) { if (this.UpdateValue(e)) {
this.Timestamp = DateTime.Now; this.Timestamp = DateTime.Now;
this.Update?.Invoke(this, e); this.Update?.Invoke(this, e);
@ -51,7 +56,7 @@ namespace Dashboard.Sensor {
return (ASensor)t.GetConstructor(new Type[] { typeof(Dictionary<String, String>) }).Invoke(new Object[] { dictionary }); return (ASensor)t.GetConstructor(new Type[] { typeof(Dictionary<String, String>) }).Invoke(new Object[] { dictionary });
} }
private void Poll() { protected virtual void Poll() {
if(this.pollcount++ >= this.Polling) { if(this.pollcount++ >= this.Polling) {
this.pollcount = 1; this.pollcount = 1;
AMqtt.Instance.Send(this.topic + "/status",""); AMqtt.Instance.Send(this.topic + "/status","");
@ -80,11 +85,16 @@ namespace Dashboard.Sensor {
#region IDisposable Support #region IDisposable Support
private Boolean disposedValue = false; private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) { protected virtual void Dispose(Boolean disposing) {
if(!this.disposedValue) { if(!this.disposedValue) {
if(disposing) { if(disposing) {
this.pollEnabled = false;
if (this.updateThread != null && this.updateThread.ThreadState == ThreadState.Running) {
this.updateThread.Abort(); this.updateThread.Abort();
while(this.updateThread.ThreadState != ThreadState.Aborted) { } while (this.updateThread.ThreadState != ThreadState.Aborted) { }
}
AMqtt.Instance.MessageIncomming -= this.IncommingMqttMessage; AMqtt.Instance.MessageIncomming -= this.IncommingMqttMessage;
} }
this.settings = null; this.settings = null;

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using Dashboard.Connector;
using LitJson;
namespace Dashboard.Sensor {
class Flex4gridswitch : ASensor {
private String id;
public Flex4gridswitch(Dictionary<String, String> settings) : base(settings) {
this.Datatypes = Types.Bool;
this.id = settings["id"];
}
protected override Boolean UpdateValue(MqttEventArgs e) {
CultureInfo info = new CultureInfo("de-DE");
info.NumberFormat.NumberDecimalSeparator = ".";
CultureInfo.DefaultThreadCurrentCulture = info;
CultureInfo.DefaultThreadCurrentUICulture = info;
System.Threading.Thread.CurrentThread.CurrentCulture = info;
System.Threading.Thread.CurrentThread.CurrentUICulture = info;
try {
JsonData data = JsonMapper.ToObject(e.Message);
if (data.Keys.Contains("id") && data["id"].ToString() == this.id) {
this.GetBool = data["status"].ToString() == "active" ? true : false;
return true;
}
if(data.Keys.Contains(this.id)) {
this.GetBool = data[this.id].ToString() == "active" ? true : false;
return true;
}
} catch (Exception) {
}
return false;
}
protected override void Poll() {
if (this.pollcount++ >= this.Polling) {
this.pollcount = 1;
String hid = Regex.Match(this.topic, "/flex4grid/v1/households/([^/]*)/device/state").Groups[1].Value;
AMqtt.Instance.Send("/flex4grid/v1/households/" + hid + "/devices/state/request", "{\"timestamp\": \"" + DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'") + "\"}");
}
}
internal override void SetBool(Boolean v) {
String hid = Regex.Match(this.topic, "/flex4grid/v1/households/([^/]*)/device/state").Groups[1].Value;
AMqtt.Instance.Send("/flex4grid/v1/households/" + hid + "/device/actuate", "{\"command\":\""+(v ? "ON" : "OFF") + "\",\"deviceId\":\"6\",\"timestamp\":\"" + DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'") + "\"}");
}
}
}

View File

@ -9,9 +9,6 @@ namespace Dashboard.Sensor {
private String id; private String id;
public Flex4gridpower(Dictionary<String, String> settings) : base(settings) { public Flex4gridpower(Dictionary<String, String> settings) : base(settings) {
this.GetBool = true;
this.GetFloat = 0.0f;
this.GetInt = 0;
this.Datatypes = Types.Float; this.Datatypes = Types.Float;
this.id = settings["id"]; this.id = settings["id"];
} }