From 57856a4d8f01dfdfc655f11110e2f326449af4d3 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Mon, 2 Oct 2017 16:26:38 +0000 Subject: [PATCH] =?UTF-8?q?[NF]=20Aufger=C3=A4umt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IoT.sln | 31 ++++++++ IoT/Connector/ADataBackend.cs | 38 +++++++++ IoT/Connector/Mosquitto.cs | 121 +++++++++++++++++++++++++++++ IoT/Connector/Mqtt.cs | 65 ++++++++++++++++ IoT/Connector/Telegram.cs | 65 ++++++++++++++++ IoT/Properties/AssemblyInfo.cs | 36 +++++++++ IoT/Sensor/ASensor.cs | 121 +++++++++++++++++++++++++++++ IoT/Sensor/Flex4GridSwitch.cs | 52 +++++++++++++ IoT/Sensor/Flex4gridPower.cs | 34 +++++++++ IoT/Sensor/Luminanz.cs | 20 +++++ IoT/Sensor/Pir.cs | 16 ++++ IoT/Sensor/Power.cs | 20 +++++ IoT/Sensor/Switch.cs | 16 ++++ IoT/Sensor/Temperatur.cs | 20 +++++ IoT/Utils-IoT.csproj | 136 +++++++++++++++++++++++++++++++++ IoT/app.config | 15 ++++ IoT/bin/Release/Utils-IoT.dll | Bin 0 -> 21504 bytes IoT/packages.config | 53 +++++++++++++ Utils/bin/Release/Utils.dll | Bin 24576 -> 24576 bytes 19 files changed, 859 insertions(+) create mode 100644 IoT.sln create mode 100644 IoT/Connector/ADataBackend.cs create mode 100644 IoT/Connector/Mosquitto.cs create mode 100644 IoT/Connector/Mqtt.cs create mode 100644 IoT/Connector/Telegram.cs create mode 100644 IoT/Properties/AssemblyInfo.cs create mode 100644 IoT/Sensor/ASensor.cs create mode 100644 IoT/Sensor/Flex4GridSwitch.cs create mode 100644 IoT/Sensor/Flex4gridPower.cs create mode 100644 IoT/Sensor/Luminanz.cs create mode 100644 IoT/Sensor/Pir.cs create mode 100644 IoT/Sensor/Power.cs create mode 100644 IoT/Sensor/Switch.cs create mode 100644 IoT/Sensor/Temperatur.cs create mode 100644 IoT/Utils-IoT.csproj create mode 100644 IoT/app.config create mode 100644 IoT/bin/Release/Utils-IoT.dll create mode 100644 IoT/packages.config diff --git a/IoT.sln b/IoT.sln new file mode 100644 index 0000000..234c4e4 --- /dev/null +++ b/IoT.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.16 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils-IoT", "IoT\Utils-IoT.csproj", "{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {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 + {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {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 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {844D8F60-6DE1-4C48-976D-F71450E9707B} + EndGlobalSection +EndGlobal diff --git a/IoT/Connector/ADataBackend.cs b/IoT/Connector/ADataBackend.cs new file mode 100644 index 0000000..44f6996 --- /dev/null +++ b/IoT/Connector/ADataBackend.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace BlubbFish.Utils.IoT.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 dictionary) { + String object_sensor = "BlubbFish.Utils.IoT.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) }).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; } + } +} diff --git a/IoT/Connector/Mosquitto.cs b/IoT/Connector/Mosquitto.cs new file mode 100644 index 0000000..6f856c5 --- /dev/null +++ b/IoT/Connector/Mosquitto.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.RegularExpressions; + +namespace BlubbFish.Utils.IoT.Connector { + class Mosquitto : ADataBackend, IDisposable { + private Process p; + private String message; + + public override event MqttMessage MessageIncomming; + public override event MqttMessage MessageSending; + + public Mosquitto(Dictionary 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 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 + } +} diff --git a/IoT/Connector/Mqtt.cs b/IoT/Connector/Mqtt.cs new file mode 100644 index 0000000..c031382 --- /dev/null +++ b/IoT/Connector/Mqtt.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; +using uPLibrary.Networking.M2Mqtt; +using uPLibrary.Networking.M2Mqtt.Messages; + +namespace BlubbFish.Utils.IoT.Connector { + class Mqtt : ADataBackend, IDisposable { + private MqttClient client; + + public override event MqttMessage MessageIncomming; + public override event MqttMessage MessageSending; + + public Mqtt(Dictionary 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 + } +} diff --git a/IoT/Connector/Telegram.cs b/IoT/Connector/Telegram.cs new file mode 100644 index 0000000..98a0531 --- /dev/null +++ b/IoT/Connector/Telegram.cs @@ -0,0 +1,65 @@ +using System; +using Telegram.Bot; +using Telegram.Bot.Args; +using Telegram.Bot.Exceptions; +using Telegram.Bot.Types; + +namespace BlubbFish.Utils.IoT.Connector { + public class Telegram { + private static Telegram instance; + private TelegramBotClient bot; + private ChatId chat; + + public delegate void TelegramMessage(Object sender, TelegramEventArgs e); + + public event TelegramMessage MessageIncomming; + public event TelegramMessage MessageSending; + + private Telegram() { + this.bot = new TelegramBotClient(InIReader.GetInstance("settings.ini").GetValue("general", "telegram-key")); + this.bot.OnMessage += this.Bot_OnMessage; + this.Connect(); + } + + private void Bot_OnMessage(Object sender, MessageEventArgs e) { + this.MessageIncomming?.Invoke(this, new TelegramEventArgs(e.Message.Text, e.Message.Chat.Id, e.Message.Date)); + } + + public static Telegram Instance { + get { + if(instance == null) { + instance = new Telegram(); + } + return instance; + } + } + + private void Connect() { + this.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, new TelegramEventArgs(x.Text, x.Chat.Id, x.Date)); + } catch(ApiRequestException e) { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(e.Message+" "+e.ErrorCode+" "+e.Parameters); + Console.ForegroundColor = ConsoleColor.White; + } + } + } + public class TelegramEventArgs : EventArgs { + public TelegramEventArgs() : base() { } + public TelegramEventArgs(String message, Int64 UserId, DateTime date) { + this.UserId = UserId; + this.Message = message; + this.Date = date; + } + + public Int64 UserId { get; private set; } + public String Message { get; private set; } + public DateTime Date { get; private set; } + } +} diff --git a/IoT/Properties/AssemblyInfo.cs b/IoT/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5a657bb --- /dev/null +++ b/IoT/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +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("IoT")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("IoT")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("b870e4d5-6806-4a0b-b233-8907eedc5afc")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// indem Sie "*" wie unten gezeigt eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/IoT/Sensor/ASensor.cs b/IoT/Sensor/ASensor.cs new file mode 100644 index 0000000..9a835d5 --- /dev/null +++ b/IoT/Sensor/ASensor.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.Utils.IoT.Sensor { + public abstract class ASensor : IDisposable { + protected String topic; + protected Int32 pollcount; + private Dictionary settings; + protected ADataBackend backend; + private Thread updateThread; + private Boolean pollEnabled = false; + + public ASensor(Dictionary 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); + } + } + } + + public static ASensor GetInstance(ADataBackend backend, Dictionary dictionary, String name) { + String object_sensor = "BlubbFish.Utils.IoT.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), 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",""); + } + } + + public 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(Object 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 + } +} \ No newline at end of file diff --git a/IoT/Sensor/Flex4GridSwitch.cs b/IoT/Sensor/Flex4GridSwitch.cs new file mode 100644 index 0000000..112ab5b --- /dev/null +++ b/IoT/Sensor/Flex4GridSwitch.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.RegularExpressions; +using BlubbFish.Utils.IoT.Connector; +using LitJson; + +namespace BlubbFish.Utils.IoT.Sensor { + class Flex4gridswitch : ASensor { + private String id; + + public Flex4gridswitch(Dictionary 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'") + "\"}"); + } + } + + public 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'") + "\"}"); + } + } +} \ No newline at end of file diff --git a/IoT/Sensor/Flex4gridPower.cs b/IoT/Sensor/Flex4gridPower.cs new file mode 100644 index 0000000..5ef645f --- /dev/null +++ b/IoT/Sensor/Flex4gridPower.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using BlubbFish.Utils.IoT.Connector; +using LitJson; + +namespace BlubbFish.Utils.IoT.Sensor { + class Flex4gridpower : ASensor { + private String id; + + public Flex4gridpower(Dictionary 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; + } + } +} diff --git a/IoT/Sensor/Luminanz.cs b/IoT/Sensor/Luminanz.cs new file mode 100644 index 0000000..5929a99 --- /dev/null +++ b/IoT/Sensor/Luminanz.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.Utils.IoT.Sensor { + class Luminanz : ASensor { + public Luminanz(Dictionary settings, String name, ADataBackend backend) : base(settings, name, backend) { + this.GetBool = true; + this.GetFloat = 0.0f; + this.GetInt = 0; + this.Datatypes = Types.Int; + } + + protected override Boolean UpdateValue(MqttEventArgs e) { + this.GetInt = Int32.Parse(e.Message, new CultureInfo("en-US")); + return true; + } + } +} diff --git a/IoT/Sensor/Pir.cs b/IoT/Sensor/Pir.cs new file mode 100644 index 0000000..92e070c --- /dev/null +++ b/IoT/Sensor/Pir.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.Utils.IoT.Sensor { + class Pir : ASensor { + public Pir(Dictionary 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; + } + } +} \ No newline at end of file diff --git a/IoT/Sensor/Power.cs b/IoT/Sensor/Power.cs new file mode 100644 index 0000000..da5c7fc --- /dev/null +++ b/IoT/Sensor/Power.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.Utils.IoT.Sensor { + class Power : ASensor { + public Power(Dictionary 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; + } + } +} diff --git a/IoT/Sensor/Switch.cs b/IoT/Sensor/Switch.cs new file mode 100644 index 0000000..d802412 --- /dev/null +++ b/IoT/Sensor/Switch.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.Utils.IoT.Sensor { + class Switch : ASensor { + public Switch(Dictionary 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; + } + } +} \ No newline at end of file diff --git a/IoT/Sensor/Temperatur.cs b/IoT/Sensor/Temperatur.cs new file mode 100644 index 0000000..4365013 --- /dev/null +++ b/IoT/Sensor/Temperatur.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.Utils.IoT.Sensor { + class Temperatur : ASensor { + public Temperatur(Dictionary 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; + } + } +} \ No newline at end of file diff --git a/IoT/Utils-IoT.csproj b/IoT/Utils-IoT.csproj new file mode 100644 index 0000000..2e1426c --- /dev/null +++ b/IoT/Utils-IoT.csproj @@ -0,0 +1,136 @@ + + + + + Debug + AnyCPU + {B870E4D5-6806-4A0B-B233-8907EEDC5AFC} + Library + Properties + BlubbFish.Utils.IoT + Utils-IoT + v4.6.2 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\LitJson.0.9.0\lib\LitJson.dll + + + ..\..\IoT-Bot\packages\M2Mqtt.4.3.0.0\lib\net45\M2Mqtt.Net.dll + + + ..\..\IoT-Bot\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll + + + ..\..\IoT-Bot\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + + ..\..\IoT-Bot\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll + + + + ..\..\IoT-Bot\packages\System.Console.4.3.0\lib\net46\System.Console.dll + + + + ..\..\IoT-Bot\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + + ..\..\IoT-Bot\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll + + + ..\..\IoT-Bot\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + True + + + + ..\..\IoT-Bot\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll + + + ..\..\IoT-Bot\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + + + ..\..\IoT-Bot\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll + + + ..\..\IoT-Bot\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll + + + ..\..\IoT-Bot\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll + + + + ..\..\IoT-Bot\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + + + ..\..\IoT-Bot\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + + + ..\..\IoT-Bot\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + + + ..\..\IoT-Bot\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + + + ..\..\IoT-Bot\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + + + + + + + + ..\..\IoT-Bot\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll + + + ..\..\IoT-Bot\packages\Telegram.Bot.13.2.1\lib\netstandard1.1\Telegram.Bot.dll + + + + + + + + + + + + + + + + + + + + + + + + {fac8ce64-bf13-4ece-8097-aeb5dd060098} + Utils + + + + \ No newline at end of file diff --git a/IoT/app.config b/IoT/app.config new file mode 100644 index 0000000..09059bf --- /dev/null +++ b/IoT/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/IoT/bin/Release/Utils-IoT.dll b/IoT/bin/Release/Utils-IoT.dll new file mode 100644 index 0000000000000000000000000000000000000000..e0255a5a5d272b520b9c72b5ea4895bf8a795f97 GIT binary patch literal 21504 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 S2A;j@-?f(iU%7uH3;b_Ay?JK< literal 0 HcmV?d00001 diff --git a/IoT/packages.config b/IoT/packages.config new file mode 100644 index 0000000..fbbfca6 --- /dev/null +++ b/IoT/packages.config @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Utils/bin/Release/Utils.dll b/Utils/bin/Release/Utils.dll index dfb96ce21f6df6b43949d0585426421867ccc093..742ea40145102f96d67e8e749fe97319db1220f9 100644 GIT binary patch delta 88 zcmZoTz}RqraY6@kc+#bf-KG8lIaZ!LvAlb|+Z=AKU&O3;WV1lP0(KpsY$O8^Fafa) oBLl;UQXmdzUzND1WZ6I o!^psJq7;b385n|sU4l1m;CDQm%jdVQ)~4R$smqbgcfwUT0FkOAApigX