[NF] Aufgeräumt

This commit is contained in:
BlubbFish 2017-09-26 21:44:41 +02:00
parent 319ca0cbbb
commit 477e20c474
35 changed files with 1070 additions and 208 deletions

3
.gitignore vendored
View File

@ -79,3 +79,6 @@
/TimeKeeper/Arduino/Zeit/Zeit-V2/Debug /TimeKeeper/Arduino/Zeit/Zeit-V2/Debug
/TimeKeeper/Arduino/Zeit/Zeit-V2/__vm /TimeKeeper/Arduino/Zeit/Zeit-V2/__vm
/TimeKeeper/lib/System.Data.SQLite.xml /TimeKeeper/lib/System.Data.SQLite.xml
/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Connector/.svn
/MqttToTelegram/MqttToTelegram/Connector/.svn
/MqttToTelegram/MqttToTelegram/Sensor/.svn

View File

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
namespace Dashboard.Connector {
public abstract class ADataBackend {
public abstract event MqttMessage MessageIncomming;
public abstract event MqttMessage MessageSending;
public delegate void MqttMessage(Object sender, MqttEventArgs e);
public static ADataBackend GetInstance(Dictionary<String, String> dictionary) {
String object_sensor = "Dashboard.Connector." + Char.ToUpper(dictionary["type"][0]) + dictionary["type"].Substring(1).ToLower();
Type t = null;
try {
t = Type.GetType(object_sensor, true);
} catch (TypeLoadException) {
throw new ArgumentException("settings.ini: " + dictionary["type"] + " is not a Connector");
}
return (ADataBackend)t.GetConstructor(new Type[] { typeof(Dictionary<String, String>) }).Invoke(new Object[] { dictionary });
}
public abstract void Send(String topic, String data);
public abstract void Dispose();
}
public class MqttEventArgs : EventArgs {
public MqttEventArgs() : base() { }
public MqttEventArgs(String message, String topic) {
this.Topic = topic;
this.Message = message;
this.Date = DateTime.Now;
}
public String Topic { get; private set; }
public String Message { get; private set; }
public DateTime Date { get; private set; }
}
}

View File

@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace Dashboard.Connector {
class Mosquitto : ADataBackend, IDisposable {
private Process p;
private String message;
public override event MqttMessage MessageIncomming;
public override event MqttMessage MessageSending;
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 -d
this.message = "";
this.p = new Process();
this.p.StartInfo.FileName = "mosquitto_sub";
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"] + " ";
}
this.p.StartInfo.Arguments = args+"-t \"#\" -v -d";
this.p.StartInfo.CreateNoWindow = true;
this.p.StartInfo.UseShellExecute = false;
this.p.StartInfo.RedirectStandardOutput = true;
this.p.StartInfo.RedirectStandardError = true;
this.p.OutputDataReceived += this.P_OutputDataReceived;
this.p.ErrorDataReceived += this.P_ErrorDataReceived;
this.p.Start();
this.p.BeginOutputReadLine();
}
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.StartInfo.RedirectStandardOutput = true;
send.StartInfo.RedirectStandardError = true;
send.Start();
send.WaitForExit();
MessageSending?.Invoke(this, new MqttEventArgs(data, topic));
}
private void P_ErrorDataReceived(Object sender, DataReceivedEventArgs e) {
if (e.Data != null) {
throw new NotImplementedException(e.Data);
}
}
private void P_OutputDataReceived(Object sender, DataReceivedEventArgs e) {
if (e.Data != null) {
if (e.Data.StartsWith("Client mosqsub")) {
if (this.message != "" && this.message.IndexOf(" received PUBLISH ") > 0) {
MatchCollection matches = (new Regex("^Client mosqsub[\\|/].*received PUBLISH \\(.*,.*,.*,.*, '(.*)'.*\\)\\)\n[^ ]* (.*)$", RegexOptions.IgnoreCase | RegexOptions.Singleline)).Matches(this.message);
String topic = matches[0].Groups[1].Value;
String message = matches[0].Groups[2].Value.Trim();
this.MessageIncomming?.Invoke(this, new MqttEventArgs(message, topic));
}
this.message = e.Data + "\n";
} else {
this.message += e.Data + "\n";
}
}
}
#region IDisposable Support
private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe.
private readonly Dictionary<String, String> settings;
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
if (disposing) {
this.p.CancelOutputRead();
if (!this.p.HasExited) {
this.p.Kill();
}
this.p.Close();
}
this.p = null;
this.disposedValue = true;
}
}
~Mosquitto() {
Dispose(false);
}
public override void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Text;
using BlubbFish.Utils;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace Dashboard.Connector {
class Mqtt : ADataBackend, IDisposable {
private MqttClient client;
public override event MqttMessage MessageIncomming;
public override event MqttMessage MessageSending;
public Mqtt(Dictionary<String, String> settings) {
if(settings.ContainsKey("port")) {
this.client = new MqttClient(settings["server"], Int32.Parse(settings["port"]), false, null, null, MqttSslProtocols.None);
} else {
this.client = new MqttClient(settings["server"]);
}
Connect();
}
private void Connect() {
this.client.MqttMsgPublishReceived += this.Client_MqttMsgPublishReceived;
this.client.Connect(Guid.NewGuid().ToString());
this.client.Subscribe(new String[] { "#" }, new Byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });
}
private void Client_MqttMsgPublishReceived(Object sender, MqttMsgPublishEventArgs e) {
this.MessageIncomming?.Invoke(this, new MqttEventArgs(Encoding.UTF8.GetString(e.Message), e.Topic));
}
public override void Send(String topic, String data) {
this.client.Publish(topic, Encoding.UTF8.GetBytes(data));
this.MessageSending?.Invoke(this, new MqttEventArgs(data, topic));
}
#region IDisposable Support
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if(!this.disposedValue) {
if(disposing) {
this.client.MqttMsgPublishReceived -= this.Client_MqttMsgPublishReceived;
this.client.Unsubscribe(new String[] { "#" });
this.client.Disconnect();
}
this.client = null;
this.disposedValue = true;
}
}
~Mqtt() {
Dispose(false);
}
public override void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}

View File

@ -0,0 +1,54 @@
using BlubbFish.Utils;
using System;
using Telegram.Bot;
using Telegram.Bot.Args;
using Telegram.Bot.Exceptions;
using Telegram.Bot.Types;
namespace MqttToTelegram {
class Telegram {
private static Telegram instance;
private TelegramBotClient bot;
private ChatId chat;
public delegate void TelegramMessage(Object sender, Message e);
public event TelegramMessage MessageIncomming;
public event TelegramMessage MessageSending;
private Telegram() {
bot = new TelegramBotClient(InIReader.GetInstance("settings.ini").GetValue("general", "telegram-key"));
bot.OnMessage += Bot_OnMessage;
this.Connect();
}
private void Bot_OnMessage(Object sender, MessageEventArgs e) {
this.MessageIncomming?.Invoke(this, e.Message);
}
public static Telegram Instance {
get {
if(instance == null) {
instance = new Telegram();
}
return instance;
}
}
private void Connect() {
bot.StartReceiving();
this.chat = new ChatId(InIReader.GetInstance("settings.ini").GetValue("general", "chatid"));
}
public async void Send(String text) {
try {
Message x = await this.bot.SendTextMessageAsync(this.chat, text);
this.MessageSending?.Invoke(this, x);
} catch(ApiRequestException e) {
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.Message+" "+e.ErrorCode+" "+e.Parameters);
Console.ForegroundColor = ConsoleColor.White;
}
}
}
}

View File

@ -48,7 +48,7 @@ namespace Mqtt_SWB_Dashboard.Helper {
internal Int32 GetActive() { internal Int32 GetActive() {
Int32 ret = 0; Int32 ret = 0;
foreach (KeyValuePair<String, Device> item in this.Devices) { foreach (KeyValuePair<String, Device> item in this.Devices) {
if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-10)) { if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-15)) {
ret++; ret++;
} }
} }
@ -58,7 +58,7 @@ namespace Mqtt_SWB_Dashboard.Helper {
internal Double GetPower() { internal Double GetPower() {
Double ret = 0; Double ret = 0;
foreach (KeyValuePair<String, Device> item in this.Devices) { foreach (KeyValuePair<String, Device> item in this.Devices) {
if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-10) && item.Value.Type != Device.DevType.Production) { if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-15) && item.Value.Type != Device.DevType.Production) {
ret += item.Value.Power; ret += item.Value.Power;
} }
} }
@ -78,7 +78,7 @@ namespace Mqtt_SWB_Dashboard.Helper {
internal Double GetColum() { internal Double GetColum() {
Double ret = 0; Double ret = 0;
foreach (KeyValuePair<String, Device> item in this.Devices) { foreach (KeyValuePair<String, Device> item in this.Devices) {
if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-10) && item.Value.Type != Device.DevType.Production) { if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-15) && item.Value.Type != Device.DevType.Production) {
ret += item.Value.Comul; ret += item.Value.Comul;
} }
} }

View File

@ -2,6 +2,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Windows; using System.Windows;
using Dashboard.Connector;
namespace Mqtt_SWB_Dashboard { namespace Mqtt_SWB_Dashboard {
/// <summary> /// <summary>
@ -21,11 +22,11 @@ namespace Mqtt_SWB_Dashboard {
LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))); LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
try { try {
String broker = InIReader.GetInstance("settings.ini").GetValue("general", "broker"); String broker = InIReader.GetInstance("settings.ini").GetValue("mqtt", "server");
this.Dispatcher.BeginInvoke((Action)(() => { this.Dispatcher.BeginInvoke((Action)(() => {
this.connectedTo.Text = "Connected to: " + broker; this.connectedTo.Text = "Connected to: " + broker;
})); }));
this.s = new Stats(new Mosquitto(broker)); this.s = new Stats(ADataBackend.GetInstance(InIReader.GetInstance("settings.ini").GetSection("mqtt")));
this.s.UpdatedConsumption += this.S_UpdatedConsumption; this.s.UpdatedConsumption += this.S_UpdatedConsumption;
this.S_UpdatedConsumption(this.s, null); this.S_UpdatedConsumption(this.s, null);
} catch(Exception e) { } catch(Exception e) {
@ -36,16 +37,17 @@ namespace Mqtt_SWB_Dashboard {
private void S_UpdatedConsumption(Stats sender, EventArgs e) { private void S_UpdatedConsumption(Stats sender, EventArgs e) {
this.Dispatcher.BeginInvoke((Action)(() => { this.Dispatcher.BeginInvoke((Action)(() => {
this.countHouses.Text = sender.GetNumberHouseholds();
this.countDevices.Text = sender.GetNumberDevices();
this.countRaspis.Text = sender.GetNumberRaspis(); this.countRaspis.Text = sender.GetNumberRaspis();
this.maxRaspi.Text = sender.GetMostRaspiUptime(); this.maxRaspi.Text = sender.GetMostRaspiUptime();
this.avgUptime.Text = sender.GetAvgRaspiUptime(); this.avgUptime.Text = sender.GetAvgRaspiUptime();
this.countColum.Text = sender.GetCurrentColum();
Tuple<Int32, Int32> devices = sender.GetNumberDevices();
this.countDevices.Text = devices.Item1 + " / " + devices.Item2;
Tuple<Int32, Int32, Int32> houses = sender.GetNumberHouseholds();
this.countHouses.Text = houses.Item1 + " / " + houses.Item2 + " / " + houses.Item3;
Tuple<Double, Double> power = sender.GetCurrentPower(); Tuple<Double, Double> power = sender.GetCurrentPower();
this.countPower.Text = power.Item1 + "W / " + power.Item2 + "W"; this.countPower.Text = power.Item1 + "W / " + power.Item2 + "W";
Tuple<Double, Double> colum = sender.GetCurrentColum(); ((Models.PowerChartModel)this.DataContext).AddPower(power, houses, devices);
this.countColum.Text = colum.Item1.ToString("F1") + "kW / " + colum.Item2.ToString("F1") + "kW";
((Models.PowerChartModel)this.DataContext).AddPower(power, colum);
})); }));
} }

View File

@ -12,7 +12,7 @@ using OxyPlot.Series;
namespace Mqtt_SWB_Dashboard.Models { namespace Mqtt_SWB_Dashboard.Models {
public class PowerChartModel : INotifyPropertyChanged { public class PowerChartModel : INotifyPropertyChanged {
private Double MaximumDrawnL = 5; private Double MaximumDrawnL = 5;
private Double MaximumDrawnR = 5; private Int32 MaximumDrawnR = 5;
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
@ -23,33 +23,28 @@ namespace Mqtt_SWB_Dashboard.Models {
this.Model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, AbsoluteMinimum = 0, Minimum = 0, AbsoluteMaximum = 1, IsZoomEnabled = false }); this.Model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, AbsoluteMinimum = 0, Minimum = 0, AbsoluteMaximum = 1, IsZoomEnabled = false });
this.Model.Axes.Add(new LinearAxis { Position = AxisPosition.Right, AbsoluteMinimum = 0, Minimum = 0, AbsoluteMaximum = 1, IsZoomEnabled = false, Key = "Right" }); this.Model.Axes.Add(new LinearAxis { Position = AxisPosition.Right, AbsoluteMinimum = 0, Minimum = 0, AbsoluteMaximum = 1, IsZoomEnabled = false, Key = "Right" });
this.Model.Series.Add(new LineSeries { Title = "Active [W]", Color = OxyColor.FromRgb(0, 150, 0) }); this.Model.Series.Add(new LineSeries { Title = "Power [W]", Color = OxyColor.FromRgb(0, 150, 0) });
this.Model.Series.Add(new LineSeries { Title = "Seen [W]", Color = OxyColor.FromRgb(0, 255, 0) }); this.Model.Series.Add(new LineSeries { Title = "Houses", Color = OxyColor.FromRgb(0, 0, 255), YAxisKey= "Right" });
this.Model.Series.Add(new LineSeries { Title = "Active [kW]", Color = OxyColor.FromRgb(0, 0, 150), YAxisKey= "Right" }); this.Model.Series.Add(new LineSeries { Title = "Devices", Color = OxyColor.FromRgb(255, 0, 0), YAxisKey = "Right" });
this.Model.Series.Add(new LineSeries { Title = "Seen [kW]", Color = OxyColor.FromRgb(0, 0, 255), YAxisKey = "Right" });
this.RaisePropertyChanged("Model"); this.RaisePropertyChanged("Model");
} }
internal void AddPower(Tuple<Double, Double> power, Tuple<Double, Double> colum) { internal void AddPower(Tuple<Double, Double> power, Tuple<Int32, Int32, Int32> houses, Tuple<Int32, Int32> devices) {
if((power.Item1 == 0 && power.Item2 == 0) || (colum.Item1 == 0 && colum.Item2 == 0)) { if((power.Item1 == 0 && power.Item2 == 0) || (houses.Item1 == 0 && houses.Item2 == 0 && houses.Item3 == 0) || (devices.Item1 == 0 && devices.Item2 == 0)) {
return; return;
} }
((LineSeries)this.Model.Series[0]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), power.Item1)); ((LineSeries)this.Model.Series[0]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), power.Item1));
((LineSeries)this.Model.Series[1]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), power.Item2)); ((LineSeries)this.Model.Series[1]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), houses.Item1));
((LineSeries)this.Model.Series[2]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), colum.Item1)); ((LineSeries)this.Model.Series[2]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), devices.Item1));
((LineSeries)this.Model.Series[3]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), colum.Item2));
if (this.MaximumDrawnL < power.Item1) { if (this.MaximumDrawnL < power.Item1) {
this.MaximumDrawnL = power.Item1; this.MaximumDrawnL = power.Item1;
} }
if (this.MaximumDrawnL < power.Item2) { if (this.MaximumDrawnR < houses.Item1) {
this.MaximumDrawnL = power.Item2; this.MaximumDrawnR = houses.Item1;
} }
if (this.MaximumDrawnR < colum.Item1) { if (this.MaximumDrawnR < devices.Item1) {
this.MaximumDrawnR = colum.Item1; this.MaximumDrawnR = devices.Item1;
}
if (this.MaximumDrawnR < colum.Item2) {
this.MaximumDrawnR = colum.Item2;
} }
//this.Model.Axes[1].Minimum = 0; //this.Model.Axes[1].Minimum = 0;
//this.Model.Axes[2].Minimum = 0; //this.Model.Axes[2].Minimum = 0;

View File

@ -1,88 +0,0 @@
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace Mqtt_SWB_Dashboard {
class Mosquitto : IDisposable {
private Process p;
private String message;
public delegate void MqttMessage(Object sender, MqttEventArgs e);
public event MqttMessage MessageIncomming;
public Mosquitto(String broker) {
//mosquitto_sub --cafile ca.pem --cert cert.pem --key cert.key -h swb.broker.flex4grid.eu -p 8883 -t /# -v
this.message = "";
this.p = new Process();
this.p.StartInfo.FileName = "mosquitto_sub.exe";
this.p.StartInfo.Arguments = "--cafile ca.pem --cert cert.pem --key cert.key -h "+broker+" -p 8883 -t /# -v -d";
this.p.StartInfo.CreateNoWindow = true;
this.p.StartInfo.UseShellExecute = false;
this.p.StartInfo.RedirectStandardOutput = true;
this.p.StartInfo.RedirectStandardError = true;
this.p.OutputDataReceived += this.P_OutputDataReceived;
this.p.ErrorDataReceived += this.P_ErrorDataReceived;
this.p.Start();
this.p.BeginOutputReadLine();
}
private void P_ErrorDataReceived(Object sender, DataReceivedEventArgs e) {
if (e.Data != null) {
throw new NotImplementedException(e.Data);
}
}
private void P_OutputDataReceived(Object sender, DataReceivedEventArgs e) {
if (e.Data != null) {
if (e.Data.StartsWith("Client mosqsub")) {
if (this.message != "" && this.message.IndexOf(" received PUBLISH ") > 0) {
MatchCollection matches = (new Regex("^Client mosqsub\\|.*received PUBLISH \\(.*,.*,.*,.*, '(.*)'.*\\)\\)\n[^ ]* (.*)$", RegexOptions.IgnoreCase | RegexOptions.Singleline)).Matches(this.message);
String topic = matches[0].Groups[1].Value;
String message = matches[0].Groups[2].Value.Trim();
this.MessageIncomming?.Invoke(this, new MqttEventArgs(message, topic));
}
this.message = e.Data + "\n";
} else {
this.message += e.Data + "\n";
}
}
}
#region IDisposable Support
private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe.
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
if (disposing) {
this.p.CancelOutputRead();
this.p.Kill();
this.p.Close();
}
this.p = null;
this.disposedValue = true;
}
}
~Mosquitto() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
class MqttEventArgs : EventArgs {
public MqttEventArgs() : base() { }
public MqttEventArgs(String message, String topic) {
this.Topic = topic;
this.Message = message;
this.Date = DateTime.Now;
}
public String Topic { get; private set; }
public String Message { get; private set; }
public DateTime Date { get; private set; }
}
}

View File

@ -63,6 +63,8 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="Connector\ADataBackend.cs" />
<Compile Include="Connector\Mosquitto.cs" />
<Compile Include="Helper\Device.cs" /> <Compile Include="Helper\Device.cs" />
<Compile Include="Helper\Household.cs" /> <Compile Include="Helper\Household.cs" />
<Compile Include="Helper\Raspi.cs" /> <Compile Include="Helper\Raspi.cs" />
@ -82,7 +84,6 @@
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Mosquitto.cs" />
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
@ -105,6 +106,7 @@
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None> </None>
<None Include="settings.ini.example" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Dashboard.Connector;
using LitJson; using LitJson;
using Mqtt_SWB_Dashboard.Helper; using Mqtt_SWB_Dashboard.Helper;
@ -10,12 +11,12 @@ namespace Mqtt_SWB_Dashboard {
internal class Stats : IDisposable { internal class Stats : IDisposable {
private SortedDictionary<String, Household> households = new SortedDictionary<String, Household>(); private SortedDictionary<String, Household> households = new SortedDictionary<String, Household>();
private SortedDictionary<String, Raspi> raspis = new SortedDictionary<String, Raspi>(); private SortedDictionary<String, Raspi> raspis = new SortedDictionary<String, Raspi>();
private Mosquitto mosquitto; private ADataBackend mosquitto;
public delegate void UpdateMessage(Stats sender, EventArgs e); public delegate void UpdateMessage(Stats sender, EventArgs e);
public event UpdateMessage UpdatedConsumption; public event UpdateMessage UpdatedConsumption;
public Stats(Mosquitto mosquitto) { public Stats(ADataBackend mosquitto) {
LoadSavedData(); LoadSavedData();
this.mosquitto = mosquitto; this.mosquitto = mosquitto;
this.mosquitto.MessageIncomming += this.Mosquitto_MessageIncomming; this.mosquitto.MessageIncomming += this.Mosquitto_MessageIncomming;
@ -44,6 +45,10 @@ namespace Mqtt_SWB_Dashboard {
private void Mosquitto_MessageIncomming(Object sender, MqttEventArgs e) { private void Mosquitto_MessageIncomming(Object sender, MqttEventArgs e) {
if (Regex.Match(e.Topic, "/flex4grid/VersionControl/LocalGateway/groups/.*").Success) { if (Regex.Match(e.Topic, "/flex4grid/VersionControl/LocalGateway/groups/.*").Success) {
this.LvcMessages(e); this.LvcMessages(e);
} else if(Regex.Match(e.Topic, "/flex4grid/v1/load_balancing/events/.*").Success) {
this.PowerEvents(e);
} else if (Regex.Match(e.Topic, "/flex4grid/v1/households/[^/]*/device/error").Success) {
this.ErrorDeviceMessage(e);
} else if (Regex.Match(e.Topic, "/flex4grid/VersionControl/LocalGateway/hosts/.*/status").Success || } else if (Regex.Match(e.Topic, "/flex4grid/VersionControl/LocalGateway/hosts/.*/status").Success ||
e.Topic == "/flex4grid/VersionControl/LocalGateway/status") { e.Topic == "/flex4grid/VersionControl/LocalGateway/status") {
this.RaspiStatus(e); this.RaspiStatus(e);
@ -67,6 +72,22 @@ namespace Mqtt_SWB_Dashboard {
#region Mqtt-Message Parser #region Mqtt-Message Parser
/// <summary>
/// Fehlermeldung eines Plugs
/// </summary>
/// <param name="e"></param>
private void ErrorDeviceMessage(MqttEventArgs e) {
// /flex4grid/v1/households/[^/]*/device/error {"errorCode": "200", "timestamp": "2017-09-26T19:21:58.561839Z", "errorMessage": "Unable_to_start_ZWave_network", "id": "1"}
}
/// <summary>
/// Raspberry Powerevents
/// </summary>
/// <param name="e"></param>
private void PowerEvents(MqttEventArgs e) {
// /flex4grid/v1/load_balancing/events/10000000 {"status": 1, "areaId": "1000000", "end": "2017-09-20T18:00:00.0000000000Z", "timestamp": "2017-09-19T08:55:52.237Z", "group_name": "ALL_2017_09_20", "start" :"2017-09-20T17:00:00.0000000000Z", "magnitude": "49", "id":"84"}
}
/// <summary> /// <summary>
/// LogMessages eines Raspis /// LogMessages eines Raspis
/// </summary> /// </summary>
@ -173,7 +194,7 @@ namespace Mqtt_SWB_Dashboard {
#region Statistics Output #region Statistics Output
internal String GetNumberDevices() { internal Tuple<Int32, Int32> GetNumberDevices() {
Int32 active = 0; Int32 active = 0;
Int32 all = 0; Int32 all = 0;
try { try {
@ -182,18 +203,18 @@ namespace Mqtt_SWB_Dashboard {
all += item.Value.Devices.Count; all += item.Value.Devices.Count;
} }
} catch(Exception) { } catch(Exception) {
return "0 / 0"; return new Tuple<Int32, Int32>(0, 0);
} }
return active.ToString() + " / " + all.ToString(); return new Tuple<Int32, Int32>(active, all);
} }
internal String GetNumberHouseholds() { internal Tuple<Int32, Int32, Int32> GetNumberHouseholds() {
Int32 active = 0; Int32 active = 0;
Int32 ping = 0; Int32 ping = 0;
Int32 all = this.households.Count; Int32 all = this.households.Count;
try { try {
foreach (KeyValuePair<String, Household> item in this.households) { foreach (KeyValuePair<String, Household> item in this.households) {
if (item.Value.Active > DateTime.Now.AddMinutes(-10)) { if (item.Value.Active > DateTime.Now.AddMinutes(-15)) {
ping++; ping++;
} }
if (item.Value.Connected) { if (item.Value.Connected) {
@ -201,9 +222,9 @@ namespace Mqtt_SWB_Dashboard {
} }
} }
} catch (Exception) { } catch (Exception) {
return "0 / 0 / 0"; return new Tuple<Int32, Int32, Int32>(0, 0, 0);
} }
return ping + " / " + active + " / " + all; return new Tuple<Int32, Int32, Int32>(ping, active, all);
} }
internal Tuple<Double, Double> GetCurrentPower() { internal Tuple<Double, Double> GetCurrentPower() {
@ -220,7 +241,7 @@ namespace Mqtt_SWB_Dashboard {
return new Tuple<Double, Double>(active, all); return new Tuple<Double, Double>(active, all);
} }
internal Tuple<Double, Double> GetCurrentColum() { internal String GetCurrentColum() {
Double active = 0; Double active = 0;
Double all = 0; Double all = 0;
try { try {
@ -229,9 +250,9 @@ namespace Mqtt_SWB_Dashboard {
all += item.Value.GetAllColum(); all += item.Value.GetAllColum();
} }
} catch(Exception) { } catch(Exception) {
return new Tuple<Double, Double>(0d, 0d); return "0kWh / 0kWh";
} }
return new Tuple<Double, Double>(active, all); return active.ToString("F1") + "kWh / " + all.ToString("F1") + "kWh";
} }
internal String GetNumberRaspis() { internal String GetNumberRaspis() {

View File

@ -0,0 +1,8 @@
[mqtt]
type=mosquitto
; server=localhost
server=swb.broker.flex4grid.eu
port=8883
cafile=ca.pem
cert=cert.pem
key=cert.key

View File

@ -0,0 +1,32 @@
using Dashboard.Sensor;
using System;
using System.Collections.Generic;
namespace MqttToTelegram.Condition {
abstract class ACondition {
protected ASensor sensor;
protected Dictionary<String, String> settings;
public ACondition(Dictionary<String, String> settings) {
this.settings = settings;
Dictionary<String, String> l = new Dictionary<string, string>();
l.Add("topic", this.settings["sensor_topic"]);
l.Add("polling", this.settings["sensor_polling"]);
this.sensor = ASensor.GetInstance(this.settings["sensor"],l);
this.sensor.Update += Sensor_Update;
}
protected abstract void Sensor_Update(Object sender, EventArgs e);
public static ACondition GetInstance(String v, Dictionary<String, String> dictionary) {
string object_condition = "MqttToTelegram.Condition." + char.ToUpper(v[0]) + v.Substring(1).ToLower();
Type t = null;
try {
t = Type.GetType(object_condition, true);
} catch(TypeLoadException) {
throw new ArgumentException("condition.ini: " + v + " is not a Sensor");
}
return (ACondition)t.GetConstructor(new Type[] { typeof(Dictionary<String, String>) }).Invoke(new object[] { dictionary });
}
}
}

View File

@ -0,0 +1,35 @@
using BlubbFish.Utils;
using System;
using System.Collections.Generic;
using Dashboard.Connector;
namespace MqttToTelegram.Condition {
class ConditionWorker {
private InIReader ini;
private static ConditionWorker instance;
private List<ACondition> conditions;
private Telegram telegram;
public static ConditionWorker Instance {
get {
if(instance == null) {
instance = new ConditionWorker();
}
return instance;
}
}
internal void Run(Telegram telegram) {
this.telegram = telegram;
}
private ConditionWorker() {
this.ini = InIReader.GetInstance("condition.ini");
this.conditions = new List<ACondition>();
List<String> sections = this.ini.GetSections();
foreach(String section in sections) {
this.conditions.Add(ACondition.GetInstance(this.ini.GetValue(section,"type"), this.ini.GetSection(section)));
}
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MqttToTelegram.Condition {
class Edge : ACondition {
private Boolean histBool;
public Edge(Dictionary<String, String> settings) : base(settings) {
}
protected override void Sensor_Update(Object sender, EventArgs e) {
if(this.sensor.Datatypes == Dashboard.Sensor.ASensor.Types.Bool) {
if(this.sensor.GetBool == Boolean.Parse(this.settings["sensor_value"]) && this.histBool != this.sensor.GetBool) {
this.histBool = this.sensor.GetBool;
Telegram.Instance.Send("Jemand ist DA!");
} else {
this.histBool = this.sensor.GetBool;
}
}
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
namespace Dashboard.Connector {
public abstract class ADataBackend {
public abstract event MqttMessage MessageIncomming;
public abstract event MqttMessage MessageSending;
public delegate void MqttMessage(Object sender, MqttEventArgs e);
public static ADataBackend GetInstance(Dictionary<String, String> dictionary) {
String object_sensor = "Dashboard.Connector." + Char.ToUpper(dictionary["type"][0]) + dictionary["type"].Substring(1).ToLower();
Type t = null;
try {
t = Type.GetType(object_sensor, true);
} catch (TypeLoadException) {
throw new ArgumentException("settings.ini: " + dictionary["type"] + " is not a Connector");
}
return (ADataBackend)t.GetConstructor(new Type[] { typeof(Dictionary<String, String>) }).Invoke(new Object[] { dictionary });
}
public abstract void Send(String topic, String data);
public abstract void Dispose();
}
public class MqttEventArgs : EventArgs {
public MqttEventArgs() : base() { }
public MqttEventArgs(String message, String topic) {
this.Topic = topic;
this.Message = message;
this.Date = DateTime.Now;
}
public String Topic { get; private set; }
public String Message { get; private set; }
public DateTime Date { get; private set; }
}
}

View File

@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace Dashboard.Connector {
class Mosquitto : ADataBackend, IDisposable {
private Process p;
private String message;
public override event MqttMessage MessageIncomming;
public override event MqttMessage MessageSending;
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 -d
this.message = "";
this.p = new Process();
this.p.StartInfo.FileName = "mosquitto_sub";
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"] + " ";
}
this.p.StartInfo.Arguments = args+"-t \"#\" -v -d";
this.p.StartInfo.CreateNoWindow = true;
this.p.StartInfo.UseShellExecute = false;
this.p.StartInfo.RedirectStandardOutput = true;
this.p.StartInfo.RedirectStandardError = true;
this.p.OutputDataReceived += this.P_OutputDataReceived;
this.p.ErrorDataReceived += this.P_ErrorDataReceived;
this.p.Start();
this.p.BeginOutputReadLine();
}
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.StartInfo.RedirectStandardOutput = true;
send.StartInfo.RedirectStandardError = true;
send.Start();
send.WaitForExit();
MessageSending?.Invoke(this, new MqttEventArgs(data, topic));
}
private void P_ErrorDataReceived(Object sender, DataReceivedEventArgs e) {
if (e.Data != null) {
throw new NotImplementedException(e.Data);
}
}
private void P_OutputDataReceived(Object sender, DataReceivedEventArgs e) {
if (e.Data != null) {
if (e.Data.StartsWith("Client mosqsub")) {
if (this.message != "" && this.message.IndexOf(" received PUBLISH ") > 0) {
MatchCollection matches = (new Regex("^Client mosqsub[\\|/].*received PUBLISH \\(.*,.*,.*,.*, '(.*)'.*\\)\\)\n[^ ]* (.*)$", RegexOptions.IgnoreCase | RegexOptions.Singleline)).Matches(this.message);
String topic = matches[0].Groups[1].Value;
String message = matches[0].Groups[2].Value.Trim();
this.MessageIncomming?.Invoke(this, new MqttEventArgs(message, topic));
}
this.message = e.Data + "\n";
} else {
this.message += e.Data + "\n";
}
}
}
#region IDisposable Support
private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe.
private readonly Dictionary<String, String> settings;
protected virtual void Dispose(Boolean disposing) {
if (!this.disposedValue) {
if (disposing) {
this.p.CancelOutputRead();
if (!this.p.HasExited) {
this.p.Kill();
}
this.p.Close();
}
this.p = null;
this.disposedValue = true;
}
}
~Mosquitto() {
Dispose(false);
}
public override void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Text;
using BlubbFish.Utils;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace Dashboard.Connector {
class Mqtt : ADataBackend, IDisposable {
private MqttClient client;
public override event MqttMessage MessageIncomming;
public override event MqttMessage MessageSending;
public Mqtt(Dictionary<String, String> settings) {
if(settings.ContainsKey("port")) {
this.client = new MqttClient(settings["server"], Int32.Parse(settings["port"]), false, null, null, MqttSslProtocols.None);
} else {
this.client = new MqttClient(settings["server"]);
}
Connect();
}
private void Connect() {
this.client.MqttMsgPublishReceived += this.Client_MqttMsgPublishReceived;
this.client.Connect(Guid.NewGuid().ToString());
this.client.Subscribe(new String[] { "#" }, new Byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });
}
private void Client_MqttMsgPublishReceived(Object sender, MqttMsgPublishEventArgs e) {
this.MessageIncomming?.Invoke(this, new MqttEventArgs(Encoding.UTF8.GetString(e.Message), e.Topic));
}
public override void Send(String topic, String data) {
this.client.Publish(topic, Encoding.UTF8.GetBytes(data));
this.MessageSending?.Invoke(this, new MqttEventArgs(data, topic));
}
#region IDisposable Support
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if(!this.disposedValue) {
if(disposing) {
this.client.MqttMsgPublishReceived -= this.Client_MqttMsgPublishReceived;
this.client.Unsubscribe(new String[] { "#" });
this.client.Disconnect();
}
this.client = null;
this.disposedValue = true;
}
}
~Mqtt() {
Dispose(false);
}
public override void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}

View File

@ -0,0 +1,54 @@
using BlubbFish.Utils;
using System;
using Telegram.Bot;
using Telegram.Bot.Args;
using Telegram.Bot.Exceptions;
using Telegram.Bot.Types;
namespace MqttToTelegram {
class Telegram {
private static Telegram instance;
private TelegramBotClient bot;
private ChatId chat;
public delegate void TelegramMessage(Object sender, Message e);
public event TelegramMessage MessageIncomming;
public event TelegramMessage MessageSending;
private Telegram() {
bot = new TelegramBotClient(InIReader.GetInstance("settings.ini").GetValue("general", "telegram-key"));
bot.OnMessage += Bot_OnMessage;
this.Connect();
}
private void Bot_OnMessage(Object sender, MessageEventArgs e) {
this.MessageIncomming?.Invoke(this, e.Message);
}
public static Telegram Instance {
get {
if(instance == null) {
instance = new Telegram();
}
return instance;
}
}
private void Connect() {
bot.StartReceiving();
this.chat = new ChatId(InIReader.GetInstance("settings.ini").GetValue("general", "chatid"));
}
public async void Send(String text) {
try {
Message x = await this.bot.SendTextMessageAsync(this.chat, text);
this.MessageSending?.Invoke(this, x);
} catch(ApiRequestException e) {
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.Message+" "+e.ErrorCode+" "+e.Parameters);
Console.ForegroundColor = ConsoleColor.White;
}
}
}
}

View File

@ -1,37 +0,0 @@
using System;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace MqttToTelegram {
class Mqtt {
private static Mqtt instance;
private MqttClient client;
private Mqtt() {
client = new MqttClient("129.26.160.65");
byte code = client.Connect(System.Guid.NewGuid().ToString());
client.MqttMsgPublishReceived += MessageResieved;
}
private void MessageResieved(System.Object sender, MqttMsgPublishEventArgs e) {
Console.WriteLine("Received = " + Encoding.UTF8.GetString(e.Message) + " on Topic " + e.Topic);
}
public static Mqtt Instance {
get {
if(instance == null) {
instance = new Mqtt();
}
return instance;
}
}
public void Subscripe(string[] topics) {
byte[] qos = new byte[topics.Length];
for(int i=0;i<qos.Length;i++) {
qos[i] = MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE;
}
client.Subscribe(topics, qos);
}
}
}

View File

@ -62,15 +62,32 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Mqtt.cs" /> <Compile Include="Condition\ConditionWorker.cs" />
<Compile Include="Condition\ACondition.cs" />
<Compile Include="Condition\Edge.cs" />
<Compile Include="Connector\Mqtt.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Telegram.cs" /> <Compile Include="Sensor\ASensor.cs" />
<Compile Include="Sensor\Luminanz.cs" />
<Compile Include="Sensor\Pir.cs" />
<Compile Include="Sensor\Power.cs" />
<Compile Include="Sensor\Switch.cs" />
<Compile Include="Sensor\Temperatur.cs" />
<Compile Include="Connector\Telegram.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="settings.ini.example" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Utils\Utils\Utils.csproj">
<Project>{fac8ce64-bf13-4ece-8097-aeb5dd060098}</Project>
<Name>Utils</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -1,17 +1,37 @@
using System; using Dashboard.Connector;
using System.Collections.Generic; using MqttToTelegram.Condition;
using System.Linq; using System;
using System.Text; using System.Text;
using System.Threading.Tasks; using uPLibrary.Networking.M2Mqtt.Messages;
namespace MqttToTelegram { namespace MqttToTelegram {
class Program { class Program {
static void Main(string[] args) { static void Main(string[] args) {
Mqtt.Instance.Subscripe(new string[]{ "#"}); ConditionWorker.Instance.Run(Telegram.Instance);
Messenger.Instance.bla(); Mqtt.Instance.MessageIncomming += Mqtt_MessageIncomming;
Mqtt.Instance.MessageSending += Mqtt_MessageSending;
Telegram.Instance.MessageIncomming += Telegram_MessageIncomming;
Telegram.Instance.MessageSending += Telegram_MessageSending;
while(true) { while(true) {
System.Threading.Thread.Sleep(100); System.Threading.Thread.Sleep(100);
} }
} }
private static void Mqtt_MessageSending(Object sender, MqttMsgPublishEventArgs e) {
Console.WriteLine("-> [" + DateTime.Now.ToUniversalTime() + "] MQTT: " + Encoding.UTF8.GetString(e.Message) + " on " + e.Topic);
}
private static void Telegram_MessageSending(Object sender, global::Telegram.Bot.Types.Message e) {
Console.WriteLine("-> [" + e.Date.ToUniversalTime() + "] Telegram: " + e.Text + " on " + e.Chat.Id);
}
private static void Telegram_MessageIncomming(Object sender, global::Telegram.Bot.Types.Message e) {
Console.WriteLine("<- [" + e.Date.ToUniversalTime() + "] Telegram: " + e.Text + " on " + e.Chat.Id);
}
private static void Mqtt_MessageIncomming(Object sender, MqttMsgPublishEventArgs e) {
Console.WriteLine("<- [" + DateTime.Now.ToUniversalTime() + "] MQTT: " + Encoding.UTF8.GetString(e.Message) + " on " + e.Topic);
}
} }
} }

View File

@ -0,0 +1,121 @@
using Dashboard.Connector;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Text.RegularExpressions;
namespace Dashboard.Sensor {
public abstract class ASensor : IDisposable {
protected String topic;
protected Int32 pollcount;
private Dictionary<String, String> settings;
protected ADataBackend backend;
private Thread updateThread;
private Boolean pollEnabled = false;
public ASensor(Dictionary<String, String> settings, String name, ADataBackend backend) {
this.GetBool = true;
this.GetFloat = 0.0f;
this.GetInt = 0;
this.topic = (settings.Keys.Contains("topic")) ? settings["topic"] : "";
this.settings = settings;
this.Title = (settings.Keys.Contains("title")) ? settings["title"] : "";
this.Name = name;
this.backend = backend;
this.backend.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.Start();
}
}
private void SensorPolling() {
while(this.pollEnabled) {
Thread.Sleep(1000);
this.Poll();
}
}
private void IncommingMqttMessage(Object sender, MqttEventArgs e) {
if(Regex.Match(e.Topic, this.topic).Success) {
if (this.UpdateValue(e)) {
this.Timestamp = DateTime.Now;
this.Update?.Invoke(this, e);
}
}
}
internal static ASensor GetInstance(ADataBackend backend, Dictionary<String, String> dictionary, String name) {
String object_sensor = "Dashboard.Sensor." + Char.ToUpper(dictionary["type"][0]) + dictionary["type"].Substring(1).ToLower();
Type t = null;
try {
t = Type.GetType(object_sensor, true);
} catch(TypeLoadException) {
throw new ArgumentException("sensor.ini: " + dictionary["type"] + " is not a Sensor");
}
return (ASensor)t.GetConstructor(new Type[] { typeof(Dictionary<String, String>), typeof(String), typeof(ADataBackend) }).Invoke(new Object[] { dictionary, name, backend });
}
protected virtual void Poll() {
if(this.pollcount++ >= this.Polling) {
this.pollcount = 1;
this.backend.Send(this.topic + "/status","");
}
}
internal virtual void SetBool(Boolean v) {
this.backend.Send(this.topic + "/set", v ? "on" : "off");
}
protected abstract Boolean UpdateValue(MqttEventArgs e);
public Single GetFloat { get; protected set; }
public Boolean GetBool { get; protected set; }
public Int32 GetInt { get; protected set; }
public Types Datatypes { get; protected set; }
public DateTime Timestamp { get; protected set; }
public Int32 Polling { get; private set; }
public String Title { get; protected set; }
public String Name { get; internal set; }
public enum Types {
Bool,
Int,
Float
}
public delegate void UpdatedValue(ASensor sender, EventArgs e);
public event UpdatedValue Update;
#region IDisposable Support
private Boolean disposedValue = false;
protected virtual void Dispose(Boolean disposing) {
if(!this.disposedValue) {
if(disposing) {
this.pollEnabled = false;
if (this.updateThread != null && this.updateThread.ThreadState == ThreadState.Running) {
this.updateThread.Abort();
while (this.updateThread.ThreadState != ThreadState.Aborted) { }
}
this.backend.MessageIncomming -= this.IncommingMqttMessage;
}
this.settings = null;
this.updateThread = null;
this.disposedValue = true;
}
}
~ASensor() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}

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, String name, ADataBackend backend) : base(settings, name, backend) {
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;
this.backend.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;
this.backend.Send("/flex4grid/v1/households/" + hid + "/device/actuate", "{\"command\":\""+(v ? "ON" : "OFF") + "\",\"deviceId\":\""+ this.id + "\",\"timestamp\":\"" + DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'") + "\"}");
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Dashboard.Connector;
using LitJson;
namespace Dashboard.Sensor {
class Flex4gridpower : ASensor {
private String id;
public Flex4gridpower(Dictionary<String, String> settings, String name, ADataBackend backend) : base(settings, name, backend) {
this.Datatypes = Types.Float;
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["id"].ToString() == this.id) {
this.GetFloat = Single.Parse(data["power"].ToString());
return true;
}
} catch (Exception) {
}
return false;
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace Dashboard.Sensor {
class Luminanz : ASensor {
public Luminanz(Dictionary<String, String> settings) : base(settings) {
this.GetBool = true;
this.GetFloat = 0.0f;
this.GetInt = 0;
this.Datatypes = Types.Int;
}
protected override void UpdateValue(MqttMsgPublishEventArgs e) {
this.GetInt = Int32.Parse(Encoding.UTF8.GetString(e.Message), new CultureInfo("en-US"));
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace Dashboard.Sensor {
class Pir : ASensor {
public Pir(Dictionary<String, String> settings) : base(settings) {
this.Datatypes = Types.Bool;
}
protected override void UpdateValue(MqttMsgPublishEventArgs e) {
this.GetBool = (Encoding.UTF8.GetString(e.Message).ToLower() == "on") ? true : false;
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Dashboard.Connector;
namespace Dashboard.Sensor {
class Power : ASensor {
public Power(Dictionary<String, String> settings, String name, ADataBackend backend) : base(settings, name, backend) {
this.GetBool = true;
this.GetFloat = 0.0f;
this.GetInt = 0;
this.Datatypes = Types.Float;
}
protected override Boolean UpdateValue(MqttEventArgs e) {
this.GetFloat = Single.Parse(e.Message, new CultureInfo("en-US"));
return true;
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using Dashboard.Connector;
namespace Dashboard.Sensor {
class Switch : ASensor {
public Switch(Dictionary<System.String, System.String> settings, String name, ADataBackend backend) : base(settings, name, backend) {
this.Datatypes = Types.Bool;
}
protected override Boolean UpdateValue(MqttEventArgs e) {
this.GetBool = (e.Message.ToLower() == "on") ? true : false;
return true;
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace Dashboard.Sensor {
class Temperatur : ASensor {
public Temperatur(Dictionary<String, String> settings) : base(settings) {
this.GetBool = true;
this.GetFloat = 0.0f;
this.GetInt = 0;
this.Datatypes = Types.Float;
}
protected override void UpdateValue(MqttMsgPublishEventArgs e) {
this.GetFloat = Single.Parse(Encoding.UTF8.GetString(e.Message), new CultureInfo("en-US"));
}
}
}

View File

@ -1,35 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot;
namespace MqttToTelegram {
class Messenger {
private static Messenger instance;
private TelegramBotClient bot;
private Messenger() {
bot = new TelegramBotClient("");
bot.OnMessage += Bot_OnMessage;
}
private void Bot_OnMessage(Object sender, Telegram.Bot.Args.MessageEventArgs e) {
Console.WriteLine("Telegram: " + e.Message.Text);
}
public static Messenger Instance {
get {
if(instance == null) {
instance = new Messenger();
}
return instance;
}
}
public void bla() {
bot.StartReceiving();
}
}
}

View File

@ -0,0 +1,4 @@
[general]
mqtt-server=localhost
telegram-key=ABCDEFGH
chatid=1234

Binary file not shown.