diff --git a/.gitignore b/.gitignore index 1bbf276..a45e573 100644 --- a/.gitignore +++ b/.gitignore @@ -163,3 +163,27 @@ /Utils/IoT/Connector/Data/Mosquitto/bin/Debug /Utils/IoT/Connector/Data/Mosquitto/bin/Release/ConnectorDataMosquitto.pdb /Utils/IoT/Connector/Data/Mosquitto/bin/Release/Utils-IoT.pdb +/BosmonMqtt +/House-Dashboard/.vs/House-Dashboard/v15 +/House-Dashboard/House-Dashboard/bin/Debug +/House-Dashboard/House-Dashboard/bin/Sample +/House-Dashboard/House-Dashboard/obj/Debug +/Zway/packages/LitJson.0.9.0 +*.pdb +/Utils/IoT/Connector/Data/Mqtt/.vs/ConnectorDataMqtt/v15 +/Librarys/litjson/.vs/litjson/v15 +/Librarys/litjson/litjson/bin/Debug +/Librarys/litjson/litjson/obj +/Librarys/mqtt/.vs/M2Mqtt/v15 +/Librarys/mqtt/M2Mqtt/.vs/M2Mqtt/v15 +/Librarys/mqtt/M2Mqtt/bin/Debug +/Librarys/mqtt/M2Mqtt/obj +/Hue-Bot/.vs +/Hue-Bot/Hue-Bot/bin/Debug +/Hue-Bot/Hue-Bot/obj +/Hue/.vs/Hue/v15 +/Hue/Hue/bin/Debug +/Hue/Hue/obj +/Hue-Bot/Hue-Bot/bin/mqtt.ini +/Hue-Bot/Hue-Bot/bin/settings.ini +/House-Dashboard/packages diff --git a/House-Dashboard/House-Dashboard.sln b/House-Dashboard/House-Dashboard.sln new file mode 100644 index 0000000..b36a61b --- /dev/null +++ b/House-Dashboard/House-Dashboard.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2010 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "House-Dashboard", "House-Dashboard\House-Dashboard.csproj", "{D1D4B67E-7BEB-4EDB-9D40-E29F0BE078C4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils-IoT", "..\Utils\IoT\Utils-IoT.csproj", "{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConnectorDataMqtt", "..\Utils\IoT\Connector\Data\Mqtt\ConnectorDataMqtt.csproj", "{EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\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 + {D1D4B67E-7BEB-4EDB-9D40-E29F0BE078C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1D4B67E-7BEB-4EDB-9D40-E29F0BE078C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1D4B67E-7BEB-4EDB-9D40-E29F0BE078C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1D4B67E-7BEB-4EDB-9D40-E29F0BE078C4}.Release|Any CPU.Build.0 = Release|Any CPU + {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Release|Any CPU.Build.0 = Release|Any CPU + {EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Release|Any CPU.Build.0 = Release|Any CPU + {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 = {85D9EA74-4174-4FF9-A623-EB89DE84C01D} + EndGlobalSection +EndGlobal diff --git a/House-Dashboard/House-Dashboard/App.config b/House-Dashboard/House-Dashboard/App.config new file mode 100644 index 0000000..8fc0551 --- /dev/null +++ b/House-Dashboard/House-Dashboard/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/House-Dashboard/House-Dashboard/App.xaml b/House-Dashboard/House-Dashboard/App.xaml new file mode 100644 index 0000000..5d1ddfd --- /dev/null +++ b/House-Dashboard/House-Dashboard/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/House-Dashboard/House-Dashboard/App.xaml.cs b/House-Dashboard/House-Dashboard/App.xaml.cs new file mode 100644 index 0000000..3d94e33 --- /dev/null +++ b/House-Dashboard/House-Dashboard/App.xaml.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace House_Dashboard { + /// + /// Interaktionslogik für "App.xaml" + /// + public partial class App : Application { + } +} diff --git a/House-Dashboard/House-Dashboard/Functions/Tabs.cs b/House-Dashboard/House-Dashboard/Functions/Tabs.cs new file mode 100644 index 0000000..ee7dded --- /dev/null +++ b/House-Dashboard/House-Dashboard/Functions/Tabs.cs @@ -0,0 +1,85 @@ +using System; +using System.Net.Cache; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using BlubbFish.House.Dashboard.Graphics; +using BlubbFish.Utils; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.House.Dashboard.Functions { + class Tabs { + private InIReader ini; + private ADataBackend data; + private TabItem tab; + + public Tabs(InIReader settings, ADataBackend data) { + this.ini = settings; + this.data = data; + } + + internal TabItem GetTab() { + this.tab = new TabItem(); + this.GenerateHeader(); + this.GenerateContent(); + return this.tab; + } + + private void GenerateContent() { + Grid g = new Grid { + Background = new BrushConverter().ConvertFromString("#FFE5E5E5") as SolidColorBrush + }; + if (this.ini.GetValue("general", "background-image") != null) { + BitmapImage bitmap = new BitmapImage(); + bitmap.BeginInit(); + bitmap.CacheOption = BitmapCacheOption.None; + bitmap.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache); + bitmap.CacheOption = BitmapCacheOption.OnLoad; + bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache; + bitmap.UriSource = new Uri(this.ini.GetValue("general", "background-image"), UriKind.RelativeOrAbsolute); + bitmap.EndInit(); + Image bgimage = new Image { + Source = bitmap + }; + g.Children.Add(bgimage); + } + foreach (String item in this.ini.GetSections(false)) { + if(item != "general") { + AGraphics a = AGraphics.GetInstance(this.ini.GetSection(item), this.data); + if (a != null) { + g.Children.Add(a.Draw()); + } + } + } + this.tab.Content = g; + } + + private void GenerateHeader() { + StackPanel header = new StackPanel { + Orientation = Orientation.Horizontal + }; + if (this.ini.GetValue("general", "icon") != null) { + BitmapImage bitmap = new BitmapImage(); + bitmap.BeginInit(); + bitmap.CacheOption = BitmapCacheOption.None; + bitmap.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache); + bitmap.CacheOption = BitmapCacheOption.OnLoad; + bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache; + bitmap.UriSource = new Uri(this.ini.GetValue("general", "icon"), UriKind.RelativeOrAbsolute); + bitmap.EndInit(); + Image image = new Image { + Source = bitmap + }; + header.Children.Add(image); + } + if (this.ini.GetValue("general", "name") != null) { + TextBlock t = new TextBlock { + Text = this.ini.GetValue("general", "name"), + FontSize = 20 + }; + header.Children.Add(t); + } + this.tab.Header = header; + } + } +} diff --git a/House-Dashboard/House-Dashboard/Functions/Workload.cs b/House-Dashboard/House-Dashboard/Functions/Workload.cs new file mode 100644 index 0000000..2dd24bc --- /dev/null +++ b/House-Dashboard/House-Dashboard/Functions/Workload.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.House.Dashboard.Functions { + class Workload { + private SortedDictionary list = new SortedDictionary(); + + public delegate void WorkloadEvent(Object sender, EventArgs e); + public event WorkloadEvent Update; + + public Int32 Maximum { get; private set; } + public Int32 Now { get; private set; } + + internal void SetMessage(MqttEventArgs e) { + DateTime d = DateTime.Now; + if (this.list.ContainsKey(d)) { + return; + } + this.list.Add(d, e); + DateTime old = DateTime.Now.AddSeconds(-30); + List remove = new List(); + foreach (KeyValuePair item in this.list) { + if(item.Key < old) { + remove.Add(item.Key); + } + } + foreach (DateTime item in remove) { + this.list.Remove(item); + } + if(this.list.Count > this.Maximum) { + this.Maximum = this.list.Count; + } + this.Now = this.list.Count; + this.Update?.Invoke(this, null); + } + } +} diff --git a/House-Dashboard/House-Dashboard/Graphics/AGraphics.cs b/House-Dashboard/House-Dashboard/Graphics/AGraphics.cs new file mode 100644 index 0000000..0fc429c --- /dev/null +++ b/House-Dashboard/House-Dashboard/Graphics/AGraphics.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Controls; +using BlubbFish.Utils.IoT.Connector; + +namespace BlubbFish.House.Dashboard.Graphics { + abstract class AGraphics { + protected ADataBackend data; + protected Dictionary settings; + + protected AGraphics(Dictionary settings, ADataBackend data) { + this.data = data; + this.settings = settings; + } + + internal static AGraphics GetInstance(Dictionary settings, ADataBackend data) { + if(!settings.ContainsKey("graphic")) { + return null; + } + String object_sensor = "BlubbFish.House.Dashboard.Graphics." + settings["graphic"].ToUpperLower(); + Type t = null; + try { + t = Type.GetType(object_sensor, true); + } catch (TypeLoadException) { + throw new ArgumentException("tracings.ini: " + settings["graphic"].ToUpperLower() + " is not a Tracing"); + } + return (AGraphics)t.GetConstructor(new Type[] { typeof(Dictionary), typeof(ADataBackend) }).Invoke(new Object[] { settings, data }); + } + + public abstract Grid Draw(); + } +} diff --git a/House-Dashboard/House-Dashboard/Graphics/Heater.cs b/House-Dashboard/House-Dashboard/Graphics/Heater.cs new file mode 100644 index 0000000..40ae2fb --- /dev/null +++ b/House-Dashboard/House-Dashboard/Graphics/Heater.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using BlubbFish.Utils.IoT.Connector; +using LitJson; + +namespace BlubbFish.House.Dashboard.Graphics { + class Heater : AGraphics { + private TextBlock targetTemp; + private Dictionary targetTemps = new Dictionary(); + private TextBlock mode; + private TextBlock now; + private String topic; + private Dictionary modes = new Dictionary(); + private Int32 activemode = -1; + private Dictionary replace = new Dictionary { + { "Heat", "Heizen" }, + { "Energy Save Heat", "Nacht" } + }; + + public Heater(Dictionary settings, ADataBackend data) : base(settings, data) { + this.targetTemp = new TextBlock { + Text = "0 °C" + }; + this.mode = new TextBlock { + Text = "Mode" + }; + this.now = new TextBlock { + Text = "0 °C" + }; + if(this.settings.ContainsKey("topic")) { + this.topic = this.settings["topic"]; + this.data.MessageIncomming += this.Data_MessageIncomming; + this.data.Send(this.topic + "/0/49/1/get", ""); + this.data.Send(this.topic + "/0/64/get", ""); + this.data.Send(this.topic + "/0/67/1/get", ""); + this.data.Send(this.topic + "/0/67/11/get", ""); + } + } + + private void Data_MessageIncomming(Object sender, MqttEventArgs e) { + if (e.Topic.StartsWith(this.topic)) { + try { + JsonData j = JsonMapper.ToObject(e.Message); + if (e.Topic == this.topic + "/0/49/1") { + if (j.Keys.Contains("Level")) { + if (Double.TryParse(j["Level"].ToString(), out Double level)) { + this.now.Dispatcher.BeginInvoke((Action)(() => { + this.now.Text = level.ToString() + " °C"; + })); + } + } + } + if (e.Topic == this.topic + "/0/64") { + if (j.Keys.Contains("ValidModes") && j["ValidModes"].IsObject && this.modes.Count == 0) { + foreach (String item in j["ValidModes"].Keys) { + if (Int32.TryParse(item, out Int32 jvmode)) { + this.modes.Add(jvmode, j["ValidModes"][item].ToString()); + } + } + } + if (j.Keys.Contains("Level")) { + if (Int32.TryParse(j["Level"].ToString(), out Int32 jmode) && this.modes.ContainsKey(jmode)) { + this.activemode = jmode; + String text = this.modes[jmode]; + if (this.replace.ContainsKey(text)) { + text = this.replace[text]; + } + this.now.Dispatcher.BeginInvoke((Action)(() => { + this.mode.Text = text; + })); + this.WriteTargetTemp(); + } + } + } + if (e.Topic == this.topic + "/0/67/1" || e.Topic == this.topic + "/0/67/11") { + if (j.Keys.Contains("Level")) { + if (Double.TryParse(j["Level"].ToString(), out Double temp)) { + Int32 id = 0; + if (e.Topic.EndsWith("/1")) { + id = 1; + } else if (e.Topic.EndsWith("/11")) { + id = 11; + } + if (this.targetTemps.ContainsKey(id)) { + this.targetTemps[id] = temp; + } else { + this.targetTemps.Add(id, temp); + } + this.WriteTargetTemp(); + } + } + } + } catch (Exception) { } + } + } + + private void WriteTargetTemp() { + if (this.targetTemps.ContainsKey(this.activemode)) { + this.now.Dispatcher.BeginInvoke((Action)(() => { + this.targetTemp.Text = this.targetTemps[this.activemode] + " °C"; + })); + } + } + + public override Grid Draw() { + Grid outergrid = this.CreateOuterGrid(); + outergrid.Children.Add(this.CreateInnerGrid()); + outergrid.Children.Add(this.CreateTextBlock()); + return outergrid; + } + + private TextBlock CreateTextBlock() { + // + this.now.HorizontalAlignment = HorizontalAlignment.Left; + this.now.VerticalAlignment = VerticalAlignment.Top; + + this.now.SetValue(Grid.ColumnProperty, 1); + this.now.FontWeight = FontWeights.Bold; + this.now.FontSize = 28; + this.now.Margin = new Thickness(5,0,10,0); + return this.now; + } + + private Grid CreateInnerGrid() { + // + // + // + // + // + // + // + // + Grid grid = new Grid { + Height = 45, + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Margin = new Thickness(10, 0, 0, 0) + }; + + grid.RowDefinitions.Add(new RowDefinition { + Height = new GridLength(22) + }); + grid.RowDefinitions.Add(new RowDefinition()); + this.targetTemp.HorizontalAlignment = HorizontalAlignment.Center; + this.targetTemp.VerticalAlignment = VerticalAlignment.Top; + this.targetTemp.FontSize = 18; + grid.Children.Add(this.targetTemp); + this.mode.HorizontalAlignment = HorizontalAlignment.Center; + this.mode.VerticalAlignment = VerticalAlignment.Top; + this.mode.SetValue(Grid.RowProperty, 1); + this.mode.FontSize = 12; + grid.Children.Add(this.mode); + return grid; + } + + private Grid CreateOuterGrid() { + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + Double rotate = 0; + if (this.settings.ContainsKey("rotate") && Double.TryParse(this.settings["rotate"], out rotate)) { } + Grid grid = new Grid { + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Background = new ImageBrush(Helper.BitmapToImageSource(Properties.Resources.graphics_heater)), + RenderTransform = new RotateTransform(rotate) + }; + Thickness thickness = new Thickness(); + Boolean thicknessSet = false; + if (this.settings.ContainsKey("x") && Int32.TryParse(this.settings["x"], out Int32 x)) { + thickness.Left = x; + thicknessSet = true; + } + if (this.settings.ContainsKey("y") && Int32.TryParse(this.settings["y"], out Int32 y)) { + thickness.Top = y; + thicknessSet = true; + } + if (thicknessSet) { + grid.Margin = thickness; + } + grid.ColumnDefinitions.Add(new ColumnDefinition()); + grid.ColumnDefinitions.Add(new ColumnDefinition()); + return grid; + } + } +} diff --git a/House-Dashboard/House-Dashboard/Helper.cs b/House-Dashboard/House-Dashboard/Helper.cs new file mode 100644 index 0000000..ff22335 --- /dev/null +++ b/House-Dashboard/House-Dashboard/Helper.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; + +namespace BlubbFish.House.Dashboard { + static class Helper { + internal static String ToUpperLower(this String s) { + if (s.Length == 0) { + return ""; + } + if (s.Length == 1) { + return s.ToUpper(); + } + return s[0].ToString().ToUpper() + s.Substring(1).ToLower(); + } + internal static BitmapImage BitmapToImageSource(Bitmap bitmap) { + using (MemoryStream memory = new MemoryStream()) { + bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png); + memory.Position = 0; + BitmapImage bitmapimage = new BitmapImage(); + bitmapimage.BeginInit(); + bitmapimage.StreamSource = memory; + bitmapimage.CacheOption = BitmapCacheOption.OnLoad; + bitmapimage.EndInit(); + + return bitmapimage; + } + } + } +} diff --git a/House-Dashboard/House-Dashboard/House-Dashboard.csproj b/House-Dashboard/House-Dashboard/House-Dashboard.csproj new file mode 100644 index 0000000..ed77177 --- /dev/null +++ b/House-Dashboard/House-Dashboard/House-Dashboard.csproj @@ -0,0 +1,126 @@ + + + + + Debug + AnyCPU + {D1D4B67E-7BEB-4EDB-9D40-E29F0BE078C4} + WinExe + BlubbFish.House.Dashboard + Dashboard + v4.7.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\LitJson.0.9.0\lib\LitJson.dll + + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + + + + MainWindow.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + {ee6c8f68-ed46-4c1c-abdd-cfcdf75104f2} + ConnectorDataMqtt + + + {b870e4d5-6806-4a0b-b233-8907eedc5afc} + Utils-IoT + + + {fac8ce64-bf13-4ece-8097-aeb5dd060098} + Utils + + + + + + + \ No newline at end of file diff --git a/House-Dashboard/House-Dashboard/MainWindow.xaml b/House-Dashboard/House-Dashboard/MainWindow.xaml new file mode 100644 index 0000000..ee37d8e --- /dev/null +++ b/House-Dashboard/House-Dashboard/MainWindow.xaml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +