Change a lot of stuff
This commit is contained in:
parent
329375b7cb
commit
595fbf1465
24
.gitignore
vendored
24
.gitignore
vendored
@ -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
|
||||
|
43
House-Dashboard/House-Dashboard.sln
Normal file
43
House-Dashboard/House-Dashboard.sln
Normal file
@ -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
|
6
House-Dashboard/House-Dashboard/App.config
Normal file
6
House-Dashboard/House-Dashboard/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
|
||||
</startup>
|
||||
</configuration>
|
9
House-Dashboard/House-Dashboard/App.xaml
Normal file
9
House-Dashboard/House-Dashboard/App.xaml
Normal file
@ -0,0 +1,9 @@
|
||||
<Application x:Class="House_Dashboard.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:House_Dashboard"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
15
House-Dashboard/House-Dashboard/App.xaml.cs
Normal file
15
House-Dashboard/House-Dashboard/App.xaml.cs
Normal file
@ -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 {
|
||||
/// <summary>
|
||||
/// Interaktionslogik für "App.xaml"
|
||||
/// </summary>
|
||||
public partial class App : Application {
|
||||
}
|
||||
}
|
85
House-Dashboard/House-Dashboard/Functions/Tabs.cs
Normal file
85
House-Dashboard/House-Dashboard/Functions/Tabs.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
41
House-Dashboard/House-Dashboard/Functions/Workload.cs
Normal file
41
House-Dashboard/House-Dashboard/Functions/Workload.cs
Normal file
@ -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<DateTime, MqttEventArgs> list = new SortedDictionary<DateTime, MqttEventArgs>();
|
||||
|
||||
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<DateTime> remove = new List<DateTime>();
|
||||
foreach (KeyValuePair<DateTime, MqttEventArgs> 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);
|
||||
}
|
||||
}
|
||||
}
|
35
House-Dashboard/House-Dashboard/Graphics/AGraphics.cs
Normal file
35
House-Dashboard/House-Dashboard/Graphics/AGraphics.cs
Normal file
@ -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<String, String> settings;
|
||||
|
||||
protected AGraphics(Dictionary<String, String> settings, ADataBackend data) {
|
||||
this.data = data;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
internal static AGraphics GetInstance(Dictionary<String, String> 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<String, String>), typeof(ADataBackend) }).Invoke(new Object[] { settings, data });
|
||||
}
|
||||
|
||||
public abstract Grid Draw();
|
||||
}
|
||||
}
|
206
House-Dashboard/House-Dashboard/Graphics/Heater.cs
Normal file
206
House-Dashboard/House-Dashboard/Graphics/Heater.cs
Normal file
@ -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<Int32, Double> targetTemps = new Dictionary<Int32, Double>();
|
||||
private TextBlock mode;
|
||||
private TextBlock now;
|
||||
private String topic;
|
||||
private Dictionary<Int32, String> modes = new Dictionary<Int32, String>();
|
||||
private Int32 activemode = -1;
|
||||
private Dictionary<String, String> replace = new Dictionary<String, String> {
|
||||
{ "Heat", "Heizen" },
|
||||
{ "Energy Save Heat", "Nacht" }
|
||||
};
|
||||
|
||||
public Heater(Dictionary<String, String> 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() {
|
||||
//<TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" Text="0 °C" Grid.Column="1" FontWeight="Bold" FontSize="28" Margin="5,0,10,0"/>
|
||||
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 Height="45" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,0,0,0">
|
||||
// <Grid.RowDefinitions>
|
||||
// <RowDefinition Height="22"/>
|
||||
// <RowDefinition/>
|
||||
// </Grid.RowDefinitions>
|
||||
// <TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Text="0 °C" FontSize="18"/>
|
||||
// <TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Text="Mode" Grid.Row="1" FontSize="12"/>
|
||||
//</Grid>
|
||||
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() {
|
||||
//<Grid HorizontalAlignment="Left" Margin="x,y,0,0" VerticalAlignment="Top">
|
||||
// <Grid.RenderTransform>
|
||||
// <TransformGroup>
|
||||
// <ScaleTransform/>
|
||||
// <SkewTransform/>
|
||||
// <RotateTransform Angle="0"/>
|
||||
// <TranslateTransform/>
|
||||
// </TransformGroup>
|
||||
// </Grid.RenderTransform>
|
||||
// <Grid.Background>
|
||||
// <ImageBrush ImageSource = "pack://siteoforigin:,,,/Resources/graphics_heater.png" />
|
||||
// </Grid.Background>
|
||||
// <Grid.ColumnDefinitions>
|
||||
// <ColumnDefinition/>
|
||||
// <ColumnDefinition/>
|
||||
// </Grid.ColumnDefinitions>
|
||||
//</Grid>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
35
House-Dashboard/House-Dashboard/Helper.cs
Normal file
35
House-Dashboard/House-Dashboard/Helper.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
126
House-Dashboard/House-Dashboard/House-Dashboard.csproj
Normal file
126
House-Dashboard/House-Dashboard/House-Dashboard.csproj
Normal file
@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D1D4B67E-7BEB-4EDB-9D40-E29F0BE078C4}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>BlubbFish.House.Dashboard</RootNamespace>
|
||||
<AssemblyName>Dashboard</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="LitJson, Version=0.9.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\LitJson.0.9.0\lib\LitJson.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Functions\Tabs.cs" />
|
||||
<Compile Include="Functions\Workload.cs" />
|
||||
<Compile Include="Graphics\AGraphics.cs" />
|
||||
<Compile Include="Graphics\Heater.cs" />
|
||||
<Compile Include="Helper.cs" />
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Utils\IoT\Connector\Data\Mqtt\ConnectorDataMqtt.csproj">
|
||||
<Project>{ee6c8f68-ed46-4c1c-abdd-cfcdf75104f2}</Project>
|
||||
<Name>ConnectorDataMqtt</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Utils\IoT\Utils-IoT.csproj">
|
||||
<Project>{b870e4d5-6806-4a0b-b233-8907eedc5afc}</Project>
|
||||
<Name>Utils-IoT</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Utils\Utils\Utils.csproj">
|
||||
<Project>{fac8ce64-bf13-4ece-8097-aeb5dd060098}</Project>
|
||||
<Name>Utils</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\graphics_heater.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
87
House-Dashboard/House-Dashboard/MainWindow.xaml
Normal file
87
House-Dashboard/House-Dashboard/MainWindow.xaml
Normal file
@ -0,0 +1,87 @@
|
||||
<Window x:Class="House_Dashboard.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:House_Dashboard"
|
||||
mc:Ignorable="d"
|
||||
Title="Dashboard" WindowState="Maximized" Topmost="True" WindowStyle="None" Height="600" Width="800" Name="myWindow">
|
||||
<Grid>
|
||||
<TabControl x:Name="tabs" Padding="0" Margin="0,0,0,26">
|
||||
<TabItem Header="Home" FontSize="20">
|
||||
<Grid Background="#FFE5E5E5">
|
||||
<Image Source="E:\Eigene Dateien\Dokumente\Visual Studio 2017\Projects\House-Dashboard\House-Dashboard\bin\Debug\Images\Grundriss.png"/>
|
||||
<Grid HorizontalAlignment="Left" Margin="105,87,0,0" VerticalAlignment="Top">
|
||||
<Grid.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform/>
|
||||
<SkewTransform/>
|
||||
<RotateTransform Angle="90"/>
|
||||
<TranslateTransform/>
|
||||
</TransformGroup>
|
||||
</Grid.RenderTransform>
|
||||
<Grid.Background>
|
||||
<ImageBrush ImageSource="E:\Eigene Dateien\Dokumente\Visual Studio 2017\Projects\House-Dashboard\House-Dashboard\Resources\graphics_heater.png"/>
|
||||
</Grid.Background>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Height="45" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,0,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="22"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock HorizontalAlignment="Center" Text="0 °C" VerticalAlignment="Top" FontSize="18"/>
|
||||
<TextBlock HorizontalAlignment="Center" Text="Mode" VerticalAlignment="Top" Grid.Row="1" FontSize="12"/>
|
||||
</Grid>
|
||||
<TextBlock HorizontalAlignment="Left" Text="99 °C" VerticalAlignment="Top" Grid.Column="1" FontWeight="Bold" FontSize="28" Margin="5,0,10,0"/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
<StatusBar Margin="0" VerticalAlignment="Bottom" Height="26">
|
||||
<StatusBar.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
</Grid>
|
||||
</ItemsPanelTemplate>
|
||||
</StatusBar.ItemsPanel>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="Verbunden:" FontWeight="Bold" HorizontalAlignment="Left"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock x:Name="statusConnection" Text="Nein" Foreground="Red" Margin="71,0,0,0" HorizontalAlignment="Left"/>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="1"/>
|
||||
<StatusBarItem Grid.Column="2">
|
||||
<TextBlock Text="Auslastung:" FontWeight="Bold" HorizontalAlignment="Left"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem Grid.Column="2">
|
||||
<ProgressBar x:Name="statusLoadBar" Height="10" Width="100" HorizontalAlignment="Left" Margin="72,0,0,0"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem Grid.Column="2">
|
||||
<TextBlock x:Name="statusLoadValue" Text="0 M/30s (00:00:00)" HorizontalAlignment="Left" Margin="178,0,0,0"/>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="3"/>
|
||||
<StatusBarItem Grid.Column="4" HorizontalContentAlignment="Right">
|
||||
<Button Content="Beenden" Click="ApplicationShutdown"/>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
<Popup PlacementTarget="{Binding ElementName=myWindow}" Placement="Center" PopupAnimation="Slide" IsOpen="True">
|
||||
<Grid Background="White">
|
||||
<Border BorderBrush="Black" BorderThickness="1"/>
|
||||
<TextBlock Text="asdasdasd"/>
|
||||
|
||||
</Grid>
|
||||
</Popup>
|
||||
</Grid>
|
||||
</Window>
|
96
House-Dashboard/House-Dashboard/MainWindow.xaml.cs
Normal file
96
House-Dashboard/House-Dashboard/MainWindow.xaml.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using BlubbFish.House.Dashboard.Functions;
|
||||
using BlubbFish.Utils;
|
||||
using BlubbFish.Utils.IoT.Connector;
|
||||
|
||||
namespace House_Dashboard {
|
||||
/// <summary>
|
||||
/// Interaktionslogik für MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window {
|
||||
private ADataBackend mqtt;
|
||||
private Workload workload;
|
||||
|
||||
public MainWindow() {
|
||||
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;
|
||||
LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
|
||||
|
||||
InitializeComponent();
|
||||
InitMqtt();
|
||||
InitTabs();
|
||||
}
|
||||
|
||||
private void InitTabs() {
|
||||
if(File.Exists("tabs.ini")) {
|
||||
foreach (String item in InIReader.GetInstance("tabs.ini").GetSections()) {
|
||||
if(InIReader.GetInstance("tabs.ini").GetValue(item, "settings") != null && File.Exists(InIReader.GetInstance("tabs.ini").GetValue(item, "settings"))) {
|
||||
this.tabs.Items.Add(new Tabs(InIReader.GetInstance(InIReader.GetInstance("tabs.ini").GetValue(item, "settings")), this.mqtt).GetTab());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MessageBox.Show("tabs.ini nicht gefunden.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
this.ApplicationShutdown(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitMqtt() {
|
||||
if(File.Exists("mqtt.ini")) {
|
||||
this.mqtt = ADataBackend.GetInstance(InIReader.GetInstance("mqtt.ini").GetSection("settings"));
|
||||
if(this.mqtt == null) {
|
||||
MessageBox.Show("Der Mqtt Treiber konnte nicht geladen werden.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
this.ApplicationShutdown(null, null);
|
||||
}
|
||||
this.Dispatcher.BeginInvoke((Action)(() => {
|
||||
this.statusConnection.Text = "Ja";
|
||||
this.statusConnection.Foreground = Brushes.Green;
|
||||
}));
|
||||
this.mqtt.MessageIncomming += this.IncommingData;
|
||||
this.workload = new Workload();
|
||||
this.workload.Update += this.UpdateWorkload;
|
||||
} else {
|
||||
MessageBox.Show("mqtt.ini nicht gefunden.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
this.ApplicationShutdown(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void IncommingData(Object sender, MqttEventArgs e) {
|
||||
this.workload.SetMessage(e);
|
||||
}
|
||||
|
||||
private void UpdateWorkload(Object sender, EventArgs e) {
|
||||
Workload w = (Workload)sender;
|
||||
this.Dispatcher.BeginInvoke((Action)(() => {
|
||||
this.statusLoadBar.Maximum = w.Maximum;
|
||||
this.statusLoadBar.Value = w.Now;
|
||||
this.statusLoadValue.Text = w.Now + " M/30s (" + DateTime.Now.ToLocalTime() + ")";
|
||||
}));
|
||||
}
|
||||
|
||||
private void ApplicationShutdown(Object sender, RoutedEventArgs e) {
|
||||
if(this.mqtt != null) {
|
||||
this.mqtt.Dispose();
|
||||
}
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
57
House-Dashboard/House-Dashboard/Properties/AssemblyInfo.cs
Normal file
57
House-Dashboard/House-Dashboard/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// 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("Dashboard")]
|
||||
[assembly: AssemblyDescription("House Dashboard")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("BlubbFish")]
|
||||
[assembly: AssemblyProduct("Dashboard")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018 - 01.01.2018")]
|
||||
[assembly: AssemblyTrademark("BlubbFish")]
|
||||
[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)]
|
||||
|
||||
//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie
|
||||
//<UICulture>ImCodeVerwendeteKultur</UICulture> in der .csproj-Datei
|
||||
//in einer <PropertyGroup> fest. Wenn Sie in den Quelldateien beispielsweise Deutsch
|
||||
//(Deutschland) verwenden, legen Sie <UICulture> auf \"de-DE\" fest. Heben Sie dann die Auskommentierung
|
||||
//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile,
|
||||
//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher
|
||||
//(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird,
|
||||
// oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.)
|
||||
ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs
|
||||
//(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird,
|
||||
// designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.)
|
||||
)]
|
||||
|
||||
|
||||
// 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,
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: NeutralResourcesLanguage("de-DE")]
|
||||
|
73
House-Dashboard/House-Dashboard/Properties/Resources.Designer.cs
generated
Normal file
73
House-Dashboard/House-Dashboard/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Dieser Code wurde von einem Tool generiert.
|
||||
// Laufzeitversion:4.0.30319.42000
|
||||
//
|
||||
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||
// der Code erneut generiert wird.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace BlubbFish.House.Dashboard.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
/// </summary>
|
||||
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
|
||||
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
|
||||
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
|
||||
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BlubbFish.House.Dashboard.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
|
||||
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap graphics_heater {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("graphics_heater", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
House-Dashboard/House-Dashboard/Properties/Resources.resx
Normal file
124
House-Dashboard/House-Dashboard/Properties/Resources.resx
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="graphics_heater" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\graphics_heater.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
26
House-Dashboard/House-Dashboard/Properties/Settings.Designer.cs
generated
Normal file
26
House-Dashboard/House-Dashboard/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Dieser Code wurde von einem Tool generiert.
|
||||
// Laufzeitversion:4.0.30319.42000
|
||||
//
|
||||
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||
// der Code erneut generiert wird.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace BlubbFish.House.Dashboard.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
BIN
House-Dashboard/House-Dashboard/Resources/graphics_heater.png
Normal file
BIN
House-Dashboard/House-Dashboard/Resources/graphics_heater.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
4
House-Dashboard/House-Dashboard/packages.config
Normal file
4
House-Dashboard/House-Dashboard/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="LitJson" version="0.9.0" targetFramework="net471" />
|
||||
</packages>
|
61
Hue-Bot/Hue-Bot.sln
Normal file
61
Hue-Bot/Hue-Bot.sln
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
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}") = "Hue-Bot", "Hue-Bot\Hue-Bot.csproj", "{4C2F9593-4CF6-47DC-85D3-2D098C404C70}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hue", "..\Hue\Hue\Hue.csproj", "{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "litjson_4.7.1", "..\Librarys\litjson\litjson\litjson_4.7.1.csproj", "{91A14CD2-2940-4500-8193-56D37EDDDBAA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\Utils\Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}"
|
||||
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-IoT", "..\Utils\IoT\Utils-IoT.csproj", "{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "M2Mqtt", "..\Librarys\mqtt\M2Mqtt\M2Mqtt.csproj", "{A11AEF5A-B246-4FE8-8330-06DB73CC8074}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4C2F9593-4CF6-47DC-85D3-2D098C404C70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4C2F9593-4CF6-47DC-85D3-2D098C404C70}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4C2F9593-4CF6-47DC-85D3-2D098C404C70}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4C2F9593-4CF6-47DC-85D3-2D098C404C70}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.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
|
||||
{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
|
||||
{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
|
||||
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {15702E91-23B8-44F6-9544-A0C8E506A91E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
121
Hue-Bot/Hue-Bot/Hue-Bot.csproj
Normal file
121
Hue-Bot/Hue-Bot/Hue-Bot.csproj
Normal file
@ -0,0 +1,121 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{4C2F9593-4CF6-47DC-85D3-2D098C404C70}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>BlubbFish.IoT.Bot.HueBot</RootNamespace>
|
||||
<AssemblyName>Hue-Bot</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Resources\Icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="lib\Events.cs" />
|
||||
<Compile Include="lib\Helper.cs" />
|
||||
<Compile Include="Interfaces\AModul.cs" />
|
||||
<Compile Include="Moduls\Mqtt.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\Icon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Hue\Hue\Hue.csproj">
|
||||
<Project>{738a6137-8fca-4ce1-bd1c-042b21b6b5f2}</Project>
|
||||
<Name>Hue</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Librarys\litjson\litjson\litjson_4.7.1.csproj">
|
||||
<Project>{91a14cd2-2940-4500-8193-56d37edddbaa}</Project>
|
||||
<Name>litjson_4.7.1</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Utils\IoT\Connector\Data\Mqtt\ConnectorDataMqtt.csproj">
|
||||
<Project>{ee6c8f68-ed46-4c1c-abdd-cfcdf75104f2}</Project>
|
||||
<Name>ConnectorDataMqtt</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Utils\IoT\Utils-IoT.csproj">
|
||||
<Project>{b870e4d5-6806-4a0b-b233-8907eedc5afc}</Project>
|
||||
<Name>Utils-IoT</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Utils\Utils\Utils.csproj">
|
||||
<Project>{fac8ce64-bf13-4ece-8097-aeb5dd060098}</Project>
|
||||
<Name>Utils</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 und x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
13
Hue-Bot/Hue-Bot/Hue-Bot.csproj.user
Normal file
13
Hue-Bot/Hue-Bot/Hue-Bot.csproj.user
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PublishUrlHistory>publish\</PublishUrlHistory>
|
||||
<InstallUrlHistory />
|
||||
<SupportUrlHistory />
|
||||
<UpdateUrlHistory />
|
||||
<BootstrapperUrlHistory />
|
||||
<ErrorReportUrlHistory />
|
||||
<FallbackCulture>de-DE</FallbackCulture>
|
||||
<VerifyUploadedFiles>false</VerifyUploadedFiles>
|
||||
</PropertyGroup>
|
||||
</Project>
|
72
Hue-Bot/Hue-Bot/Interfaces/AModul.cs
Normal file
72
Hue-Bot/Hue-Bot/Interfaces/AModul.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BlubbFish.IoT.Bot.HueBot.lib;
|
||||
using BlubbFish.IoT.Hue;
|
||||
using BlubbFish.Utils;
|
||||
|
||||
namespace BlubbFish.IoT.Bot.HueBot.Interfaces {
|
||||
abstract class AModul {
|
||||
protected HueController hue;
|
||||
private InIReader settings;
|
||||
protected Dictionary<String, Dictionary<String, String>> config = new Dictionary<String, Dictionary<String, String>>();
|
||||
|
||||
public Boolean HasConfig { get; private set; }
|
||||
public Boolean ConfigPublic { get; private set; }
|
||||
|
||||
public delegate void ModulEvent(Object sender, ModulEventArgs e);
|
||||
public abstract event ModulEvent Update;
|
||||
|
||||
public AModul(HueController huec, InIReader settings) {
|
||||
this.HasConfig = false;
|
||||
this.ConfigPublic = false;
|
||||
this.hue = huec;
|
||||
this.settings = settings;
|
||||
this.ParseConfig();
|
||||
}
|
||||
|
||||
private void ParseConfig() {
|
||||
if (this.settings != null) {
|
||||
this.HasConfig = true;
|
||||
foreach (String item in this.settings.GetSections(false)) {
|
||||
this.config.Add(item, this.settings.GetSection(item));
|
||||
}
|
||||
if (this.config.ContainsKey("modul")) {
|
||||
this.ConfigPublic = this.config["modul"].ContainsKey("config") && this.config["modul"]["config"].ToLower() == "public";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<String, Dictionary<String, String>> GetConfig() {
|
||||
if (this.HasConfig && this.ConfigPublic) {
|
||||
Dictionary<String, Dictionary<String, String>> ret = new Dictionary<String, Dictionary<String, String>>(this.config);
|
||||
if (ret.ContainsKey("modul")) {
|
||||
ret.Remove("modul");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return new Dictionary<String, Dictionary<String, String>>();
|
||||
}
|
||||
|
||||
public virtual void Interconnect(Dictionary<String, AModul> moduls) { }
|
||||
|
||||
public virtual void SetInterconnection(String param, Action<Object> hook, Object data) { }
|
||||
|
||||
public abstract void Dispose();
|
||||
|
||||
internal void SetConfig(Dictionary<String, Dictionary<String, String>> newconf) {
|
||||
if (this.HasConfig && this.ConfigPublic) {
|
||||
if (newconf.ContainsKey("modul")) {
|
||||
newconf.Remove("modul");
|
||||
}
|
||||
if (this.config.ContainsKey("modul")) {
|
||||
newconf.Add("modul", this.config["modul"]);
|
||||
}
|
||||
this.config = newconf;
|
||||
this.settings.SetSections(this.config);
|
||||
this.UpdateConfig();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void UpdateConfig();
|
||||
}
|
||||
}
|
150
Hue-Bot/Hue-Bot/Moduls/Mqtt.cs
Normal file
150
Hue-Bot/Hue-Bot/Moduls/Mqtt.cs
Normal file
@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using BlubbFish.IoT.Bot.HueBot.Interfaces;
|
||||
using BlubbFish.IoT.Bot.HueBot.lib;
|
||||
using BlubbFish.IoT.Hue;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.Utils;
|
||||
using BlubbFish.Utils.IoT.Connector;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Bot.HueBot.Moduls {
|
||||
class Mqtt : AModul, IDisposable {
|
||||
private ADataBackend mqtt;
|
||||
private Dictionary<String, AModul> modules;
|
||||
|
||||
public override event ModulEvent Update;
|
||||
|
||||
public Mqtt(HueController hue, InIReader settings) : base(hue, settings) {
|
||||
if (this.config.ContainsKey("settings")) {
|
||||
this.mqtt = ADataBackend.GetInstance(this.config["settings"]);
|
||||
this.mqtt.MessageIncomming += this.Mqtt_MessageIncomming;
|
||||
this.hue.Update += this.ZwayEvent;
|
||||
}
|
||||
}
|
||||
|
||||
private void ZwayEvent(Object sender, AllUpdateEvent e) {
|
||||
String topic = "";
|
||||
String data = "";
|
||||
if (e.Parent.GetType().HasInterface("IMqtt")) {
|
||||
IMqtt sensor = (IMqtt)e.Parent;
|
||||
topic = "/hue/" + sensor.MqttTopic();
|
||||
data = sensor.ToJson();
|
||||
}
|
||||
if (topic != "" && data != "") {
|
||||
this.mqtt.Send(topic, data);
|
||||
this.Update?.Invoke(this, new MqttEvent(topic, data));
|
||||
}
|
||||
}
|
||||
|
||||
private void Mqtt_MessageIncomming(Object sender, MqttEventArgs e) {
|
||||
if (e.Topic.StartsWith("/hue/") && (e.Topic.EndsWith("/set") || e.Topic.EndsWith("/get"))) {
|
||||
//return "sensor/" + this.SensorId; (Int32)
|
||||
//return "scene/" + this.SceneId; (String)
|
||||
//return "light/" + this.LightId; (Int32)
|
||||
//return "group/" + this.GroupId; (Int32)
|
||||
//return "config";
|
||||
Match m = new Regex("^/hue/(config)/[gs]et$|^/hue/(scene)/([^/]+)/[gs]et$|^/hue/(sensor|light|group)/(\\d+)/[gs]et$").Match(e.Topic);
|
||||
String type = "";
|
||||
String id = "";
|
||||
if (m.Groups[1].Success) {
|
||||
type = m.Groups[1].Value;
|
||||
}
|
||||
if (m.Groups[2].Success) {
|
||||
type = m.Groups[2].Value;
|
||||
id = m.Groups[3].Value;
|
||||
}
|
||||
if (m.Groups[4].Success) {
|
||||
type = m.Groups[4].Value;
|
||||
id = m.Groups[5].Value;
|
||||
}
|
||||
AConnector c = this.hue.GetConnector(type, id);
|
||||
if (c == null) {
|
||||
return;
|
||||
}
|
||||
if (e.Topic.EndsWith("/set")) {
|
||||
try {
|
||||
JsonData a = JsonMapper.ToObject(e.Message);
|
||||
foreach (String item in a.Keys) {
|
||||
String key = item.ToUpperLower();
|
||||
if (c.HasProperty(key)) {
|
||||
c.SetProperty(key, a[item].ToString());
|
||||
this.Update?.Invoke(this, new MqttEvent(type + " " + id, a[item].ToString()));
|
||||
}
|
||||
}
|
||||
} catch (Exception) { }
|
||||
} else if (e.Topic.EndsWith("/get")) {
|
||||
c.PollOnce = true;
|
||||
this.mqtt.Send("/hue/" + ((IMqtt)c).MqttTopic(), ((IMqtt)c).ToJson());
|
||||
this.Update?.Invoke(this, new MqttEvent(e.Topic, "Dataget"));
|
||||
}
|
||||
}
|
||||
if (e.Topic.StartsWith("/huebot/config/") && (e.Topic.EndsWith("/set") || e.Topic.EndsWith("/get"))) {
|
||||
Match m = new Regex("^/huebot/config/(\\w+)/[gs]et$|").Match(e.Topic);
|
||||
if (!m.Groups[1].Success) {
|
||||
return;
|
||||
}
|
||||
AModul modul = null;
|
||||
foreach (KeyValuePair<String, AModul> item in this.modules) {
|
||||
if (item.Key.ToLower() == m.Groups[1].Value) {
|
||||
modul = item.Value;
|
||||
}
|
||||
}
|
||||
if (modul == null) {
|
||||
return;
|
||||
}
|
||||
if (e.Topic.EndsWith("/get") && modul.HasConfig && modul.ConfigPublic) {
|
||||
String topic = "/huebot/config/" + m.Groups[1].Value;
|
||||
String data = JsonMapper.ToJson(modul.GetConfig()).ToString();
|
||||
this.mqtt.Send(topic, data);
|
||||
this.Update?.Invoke(this, new MqttEvent(topic, data));
|
||||
}
|
||||
if (e.Topic.EndsWith("/set") && modul.HasConfig && modul.ConfigPublic) {
|
||||
try {
|
||||
JsonData a = JsonMapper.ToObject(e.Message);
|
||||
Dictionary<String, Dictionary<String, String>> newconf = new Dictionary<String, Dictionary<String, String>>();
|
||||
foreach (String section in a.Keys) {
|
||||
Dictionary<String, String> sectiondata = new Dictionary<String, String>();
|
||||
foreach (String item in a[section].Keys) {
|
||||
sectiondata.Add(item, a[section][item].ToString());
|
||||
}
|
||||
newconf.Add(section, sectiondata);
|
||||
}
|
||||
modul.SetConfig(newconf);
|
||||
this.Update?.Invoke(this, new MqttEvent("New Config", "Write"));
|
||||
} catch (Exception) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Interconnect(Dictionary<String, AModul> moduls) {
|
||||
this.modules = moduls;
|
||||
}
|
||||
|
||||
protected override void UpdateConfig() { }
|
||||
|
||||
#region IDisposable Support
|
||||
private Boolean disposedValue = false;
|
||||
|
||||
protected virtual void Dispose(Boolean disposing) {
|
||||
if (!this.disposedValue) {
|
||||
if (disposing) {
|
||||
this.mqtt.Dispose();
|
||||
}
|
||||
this.disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
~Mqtt() {
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
88
Hue-Bot/Hue-Bot/Program.cs
Normal file
88
Hue-Bot/Hue-Bot/Program.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using BlubbFish.IoT.Bot.HueBot.Interfaces;
|
||||
using BlubbFish.IoT.Bot.HueBot.lib;
|
||||
using BlubbFish.IoT.Hue;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.Utils;
|
||||
|
||||
namespace BlubbFish.IoT.Bot.HueBot {
|
||||
class Program {
|
||||
static void Main(String[] args) => new Program(args);
|
||||
|
||||
private HueController hue;
|
||||
private Dictionary<String, AModul> moduls = new Dictionary<String, AModul>();
|
||||
public Program(String[] args) {
|
||||
if (!File.Exists("settings.ini")) {
|
||||
Helper.WriteError("No settings.ini found. Abord!");
|
||||
return;
|
||||
}
|
||||
this.hue = new HueController(InIReader.GetInstance("settings.ini").GetSection("hue"));
|
||||
this.hue.Update += this.HueDataUpdate;
|
||||
this.ModulLoader();
|
||||
this.ModulInterconnect();
|
||||
this.ModulEvents();
|
||||
this.WaitForShutdown();
|
||||
this.ModulDispose();
|
||||
}
|
||||
|
||||
private void ModulLoader() {
|
||||
Assembly asm = Assembly.GetExecutingAssembly();
|
||||
foreach (Type item in asm.GetTypes()) {
|
||||
if (item.Namespace == "BlubbFish.IoT.Bot.HueBot.Moduls") {
|
||||
Type t = item;
|
||||
String name = t.Name;
|
||||
if (File.Exists(name.ToLower() + ".ini")) {
|
||||
this.moduls.Add(name, (AModul)t.GetConstructor(new Type[] { typeof(HueController), typeof(InIReader) }).Invoke(new Object[] { this.hue, InIReader.GetInstance(name.ToLower() + ".ini") }));
|
||||
Console.WriteLine("Load Modul " + name);
|
||||
} else if (t.HasInterface("IForceLoad")) {
|
||||
this.moduls.Add(name, (AModul)t.GetConstructor(new Type[] { typeof(HueController), typeof(InIReader) }).Invoke(new Object[] { this.hue, null }));
|
||||
Console.WriteLine("Load Modul Forced " + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ModulInterconnect() {
|
||||
foreach (KeyValuePair<String, AModul> item in this.moduls) {
|
||||
item.Value.Interconnect(this.moduls);
|
||||
}
|
||||
}
|
||||
|
||||
private void ModulEvents() {
|
||||
foreach (KeyValuePair<String, AModul> item in this.moduls) {
|
||||
item.Value.Update += this.ModulUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
private void WaitForShutdown() {
|
||||
while (true) {
|
||||
System.Threading.Thread.Sleep(100);
|
||||
if (Console.KeyAvailable) {
|
||||
ConsoleKeyInfo key = Console.ReadKey(false);
|
||||
if (key.Key == ConsoleKey.Escape) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ModulDispose() {
|
||||
foreach (KeyValuePair<String, AModul> item in this.moduls) {
|
||||
item.Value.Dispose();
|
||||
Console.WriteLine("Modul entladen: " + item.Key);
|
||||
}
|
||||
this.hue.Dispose();
|
||||
}
|
||||
|
||||
private void HueDataUpdate(Object sender, AllUpdateEvent e) {
|
||||
Console.WriteLine("-> Hue [" + e.UpdateTime + "]: " + e.Parent.ToString());
|
||||
}
|
||||
|
||||
private void ModulUpdate(Object sender, ModulEventArgs e) {
|
||||
Console.WriteLine(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
39
Hue-Bot/Hue-Bot/Properties/AssemblyInfo.cs
Normal file
39
Hue-Bot/Hue-Bot/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System.Resources;
|
||||
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("Hue-Bot")]
|
||||
[assembly: AssemblyDescription("Is a Bot for Hue Devices")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("BlubbFish")]
|
||||
[assembly: AssemblyProduct("Hue-Bot")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018 - 15.04.2018")]
|
||||
[assembly: AssemblyTrademark("BlubbFish")]
|
||||
[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("4c2f9593-4cf6-47dc-85d3-2d098c404c70")]
|
||||
|
||||
// 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,
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: NeutralResourcesLanguage("de-DE")]
|
||||
|
73
Hue-Bot/Hue-Bot/Properties/Resources.Designer.cs
generated
Normal file
73
Hue-Bot/Hue-Bot/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Dieser Code wurde von einem Tool generiert.
|
||||
// Laufzeitversion:4.0.30319.42000
|
||||
//
|
||||
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||
// der Code erneut generiert wird.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace BlubbFish.IoT.Bot.HueBot.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
/// </summary>
|
||||
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
|
||||
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
|
||||
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
|
||||
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BlubbFish.IoT.Bot.HueBot.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
|
||||
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol).
|
||||
/// </summary>
|
||||
internal static System.Drawing.Icon Icon {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("Icon", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
Hue-Bot/Hue-Bot/Properties/Resources.resx
Normal file
124
Hue-Bot/Hue-Bot/Properties/Resources.resx
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="Icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
BIN
Hue-Bot/Hue-Bot/Resources/Icon.ico
Normal file
BIN
Hue-Bot/Hue-Bot/Resources/Icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 216 KiB |
BIN
Hue-Bot/Hue-Bot/Resources/Icon.png
Normal file
BIN
Hue-Bot/Hue-Bot/Resources/Icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 124 KiB |
BIN
Hue-Bot/Hue-Bot/bin/Release/ConnectorDataMqtt.dll
Normal file
BIN
Hue-Bot/Hue-Bot/bin/Release/ConnectorDataMqtt.dll
Normal file
Binary file not shown.
BIN
Hue-Bot/Hue-Bot/bin/Release/Hue-Bot.exe
Normal file
BIN
Hue-Bot/Hue-Bot/bin/Release/Hue-Bot.exe
Normal file
Binary file not shown.
BIN
Hue-Bot/Hue-Bot/bin/Release/Hue.dll
Normal file
BIN
Hue-Bot/Hue-Bot/bin/Release/Hue.dll
Normal file
Binary file not shown.
BIN
Hue-Bot/Hue-Bot/bin/Release/M2Mqtt.dll
Normal file
BIN
Hue-Bot/Hue-Bot/bin/Release/M2Mqtt.dll
Normal file
Binary file not shown.
BIN
Hue-Bot/Hue-Bot/bin/Release/Utils-IoT.dll
Normal file
BIN
Hue-Bot/Hue-Bot/bin/Release/Utils-IoT.dll
Normal file
Binary file not shown.
BIN
Hue-Bot/Hue-Bot/bin/Release/Utils.dll
Normal file
BIN
Hue-Bot/Hue-Bot/bin/Release/Utils.dll
Normal file
Binary file not shown.
BIN
Hue-Bot/Hue-Bot/bin/Release/litjson.dll
Normal file
BIN
Hue-Bot/Hue-Bot/bin/Release/litjson.dll
Normal file
Binary file not shown.
72
Hue-Bot/Hue-Bot/lib/Events.cs
Normal file
72
Hue-Bot/Hue-Bot/lib/Events.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BlubbFish.IoT.Bot.HueBot.lib {
|
||||
public class CronEvent : ModulEventArgs {
|
||||
|
||||
public CronEvent() {
|
||||
}
|
||||
|
||||
public CronEvent(String addr, String prop, String value) {
|
||||
this.Address = addr;
|
||||
this.Property = prop;
|
||||
this.Value = value;
|
||||
this.Source = "Cronjob";
|
||||
}
|
||||
}
|
||||
public class OvertakerEvent : ModulEventArgs {
|
||||
|
||||
public OvertakerEvent() {
|
||||
}
|
||||
|
||||
public OvertakerEvent(String addr, String prop, String value) {
|
||||
this.Address = addr;
|
||||
this.Property = prop;
|
||||
this.Value = value;
|
||||
this.Source = "Overtaker";
|
||||
}
|
||||
}
|
||||
|
||||
public class MqttEvent : ModulEventArgs {
|
||||
public MqttEvent() {
|
||||
}
|
||||
public MqttEvent(String topic, String text) {
|
||||
this.Address = topic;
|
||||
this.Value = text;
|
||||
this.Source = "MQTT";
|
||||
}
|
||||
public override String ToString() {
|
||||
return this.Source + ": on " + this.Address + " set " + this.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public class StatusPollingEvent : ModulEventArgs {
|
||||
public StatusPollingEvent() {
|
||||
}
|
||||
|
||||
public StatusPollingEvent(String text, String node) {
|
||||
this.Value = text;
|
||||
this.Address = node;
|
||||
this.Source = "POLLING";
|
||||
}
|
||||
|
||||
public override String ToString() {
|
||||
return this.Source + ": " + this.Value + " on " + this.Address;
|
||||
}
|
||||
}
|
||||
|
||||
public class ModulEventArgs : EventArgs {
|
||||
public ModulEventArgs() {
|
||||
}
|
||||
public String Address { get; protected set; }
|
||||
public String Property { get; protected set; }
|
||||
public String Value { get; protected set; }
|
||||
public String Source { get; protected set; }
|
||||
public override String ToString() {
|
||||
return this.Source + ": " + this.Address + " set " + this.Property + " to " + this.Value;
|
||||
}
|
||||
}
|
||||
}
|
79
Hue-Bot/Hue-Bot/lib/Helper.cs
Normal file
79
Hue-Bot/Hue-Bot/lib/Helper.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BlubbFish.IoT.Bot.HueBot.lib {
|
||||
static class Helper {
|
||||
public static void SetProperty(this Object o, String name, String value) {
|
||||
PropertyInfo prop = o.GetType().GetProperty(name);
|
||||
if (prop.CanWrite) {
|
||||
if (prop.PropertyType == typeof(Boolean) && Boolean.TryParse(value, out Boolean vb)) {
|
||||
prop.SetValue(o, vb);
|
||||
} else if (prop.PropertyType == typeof(Byte) && Byte.TryParse(value, out Byte v8)) {
|
||||
prop.SetValue(o, v8);
|
||||
} else if (prop.PropertyType == typeof(Int32) && Int32.TryParse(value, out Int32 v32)) {
|
||||
prop.SetValue(o, v32);
|
||||
} else if (prop.PropertyType == typeof(Single) && Single.TryParse(value, out Single vs)) {
|
||||
prop.SetValue(o, vs);
|
||||
} else if (prop.PropertyType == typeof(Double) && Double.TryParse(value, out Double vd)) {
|
||||
prop.SetValue(o, vd);
|
||||
} else if (prop.PropertyType == typeof(Int64) && Int64.TryParse(value, out Int64 v64)) {
|
||||
prop.SetValue(o, v64);
|
||||
} else if (prop.PropertyType.BaseType == typeof(Enum)) {
|
||||
try {
|
||||
prop.SetValue(o, Enum.Parse(prop.PropertyType, value));
|
||||
} catch (Exception) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static Boolean HasProperty(this Object o, String type) {
|
||||
Type t = o.GetType();
|
||||
foreach (PropertyInfo item in t.GetProperties()) {
|
||||
if (item.Name == type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static Object GetProperty(this Object o, String name) {
|
||||
PropertyInfo prop = o.GetType().GetProperty(name);
|
||||
if (prop.CanRead) {
|
||||
return prop.GetValue(o);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static Boolean HasAbstract(this Object o, Type type) {
|
||||
if (o.GetType().BaseType == type) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static Boolean HasInterface(this Type o, String type) {
|
||||
foreach (Type item in o.GetInterfaces()) {
|
||||
if (item.Name == type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static void WriteError(String text) {
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.Error.WriteLine("ERROR: " + text);
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
internal static String ToUpperLower(this String s) {
|
||||
if (s.Length == 0) {
|
||||
return "";
|
||||
}
|
||||
if (s.Length == 1) {
|
||||
return s.ToUpper();
|
||||
}
|
||||
return s[0].ToString().ToUpper() + s.Substring(1).ToLower();
|
||||
}
|
||||
}
|
||||
}
|
25
Hue/Hue.sln
Normal file
25
Hue/Hue.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
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}") = "Hue", "Hue\Hue.csproj", "{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8F059288-842C-4EA3-AFD4-9AE2E17BD1B3}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
368
Hue/Hue/Devices/Configs/Config.cs
Normal file
368
Hue/Hue/Devices/Configs/Config.cs
Normal file
@ -0,0 +1,368 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Configs {
|
||||
public class Config : AConfig {
|
||||
#region Properties
|
||||
private String _name;
|
||||
public String Name {
|
||||
get {
|
||||
return this._name;
|
||||
}
|
||||
set {
|
||||
if(this.SetConfig(new Dictionary<String, Object>() { { "name", value } })) {
|
||||
this._name = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Boolean _linkbutton;
|
||||
public Boolean Linkbutton {
|
||||
get {
|
||||
return this._linkbutton;
|
||||
}
|
||||
set {
|
||||
if (this.SetConfig(new Dictionary<String, Object>() { { "linkbutton", value } })) {
|
||||
this._linkbutton = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private String _ipaddress;
|
||||
public String Ipaddress {
|
||||
get {
|
||||
return this._ipaddress;
|
||||
}
|
||||
set {
|
||||
if (this.SetConfig(new Dictionary<String, Object>() { { "ipaddress", value } })) {
|
||||
this._ipaddress = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private String _netmask;
|
||||
public String Netmask {
|
||||
get {
|
||||
return this._netmask;
|
||||
}
|
||||
set {
|
||||
if (this.SetConfig(new Dictionary<String, Object>() { { "netmask", value } })) {
|
||||
this._netmask = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private String _gateway;
|
||||
public String Gateway {
|
||||
get {
|
||||
return this._gateway;
|
||||
}
|
||||
set {
|
||||
if (this.SetConfig(new Dictionary<String, Object>() { { "gateway", value } })) {
|
||||
this._gateway = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Boolean _dhcp;
|
||||
public Boolean Dhcp {
|
||||
get {
|
||||
return this._dhcp;
|
||||
}
|
||||
set {
|
||||
if (this.SetConfig(new Dictionary<String, Object>() { { "dhcp", value } })) {
|
||||
this._dhcp = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private DateTime _utc;
|
||||
public DateTime Utc {
|
||||
get {
|
||||
return this._utc;
|
||||
}
|
||||
set {
|
||||
if (this.SetConfig(new Dictionary<String, Object>() { { "UTC", value } })) {
|
||||
this._utc = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private String _timezone;
|
||||
public String Timezone {
|
||||
get {
|
||||
return this._timezone;
|
||||
}
|
||||
set {
|
||||
if (this.SetConfig(new Dictionary<String, Object>() { { "timezone", value } })) {
|
||||
this._timezone = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Byte _zigbeechannel;
|
||||
public Byte Zigbeechannel {
|
||||
get {
|
||||
return this._zigbeechannel;
|
||||
}
|
||||
set {
|
||||
if (this.SetConfig(new Dictionary<String, Object>() { { "zigbeechannel", value } })) {
|
||||
this._zigbeechannel = value;
|
||||
this.NotifyClient<ConfigUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public String Apiversion { get; private set; }
|
||||
public String Swversion { get; private set; }
|
||||
public String Mac { get; private set; }
|
||||
public Boolean Portalservices { get; private set; }
|
||||
public DateTime Localtime { get; private set; }
|
||||
public String Modelid { get; private set; }
|
||||
public String Bridgeid { get; private set; }
|
||||
public String Replacesbridgeid { get; private set; }
|
||||
public Boolean Factorynew { get; private set; }
|
||||
public String Datastoreversion { get; private set; }
|
||||
public String Starterkitid { get; private set; }
|
||||
public SwUpdate SwUpdate2 { get; private set; }
|
||||
public Portalstate Portalstate { get; private set; }
|
||||
public ReadOnlyDictionary<String, Whitelist> Whitelist { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public Config(JsonData json, HttpConnection http, Boolean polling) : base(json, http, polling) {
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
this._name = json["name"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("apiversion") && json["apiversion"].IsString) {
|
||||
this.Apiversion = json["apiversion"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("swversion") && json["swversion"].IsString) {
|
||||
this.Swversion = json["swversion"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("linkbutton") && json["linkbutton"].IsBoolean) {
|
||||
this._linkbutton = (Boolean)json["linkbutton"];
|
||||
}
|
||||
if (json.ContainsKey("ipaddress") && json["ipaddress"].IsString) {
|
||||
this._ipaddress = json["ipaddress"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("mac") && json["mac"].IsString) {
|
||||
this.Mac = json["mac"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("netmask") && json["netmask"].IsString) {
|
||||
this._netmask = json["netmask"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("gateway") && json["gateway"].IsString) {
|
||||
this._gateway = json["gateway"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("dhcp") && json["dhcp"].IsBoolean) {
|
||||
this._dhcp = (Boolean)json["dhcp"];
|
||||
}
|
||||
if (json.ContainsKey("portalservices") && json["portalservices"].IsBoolean) {
|
||||
this.Portalservices = (Boolean)json["portalservices"];
|
||||
}
|
||||
if (json.ContainsKey("UTC") && json["UTC"].IsString) {
|
||||
this._utc = DateTime.Parse(json["UTC"].ToString());
|
||||
}
|
||||
if (json.ContainsKey("localtime") && json["localtime"].IsString) {
|
||||
this.Localtime = DateTime.Parse(json["localtime"].ToString());
|
||||
}
|
||||
if (json.ContainsKey("timezone") && json["timezone"].IsString) {
|
||||
this._timezone = json["timezone"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("zigbeechannel") && json["zigbeechannel"].IsInt) {
|
||||
this._zigbeechannel = (Byte)json["zigbeechannel"];
|
||||
}
|
||||
if (json.ContainsKey("modelid") && json["modelid"].IsString) {
|
||||
this.Modelid = json["modelid"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("bridgeid") && json["bridgeid"].IsString) {
|
||||
this.Bridgeid = json["bridgeid"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("replacesbridgeid") && json["replacesbridgeid"] != null && json["replacesbridgeid"].IsString) {
|
||||
this.Replacesbridgeid = json["replacesbridgeid"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("factorynew") && json["factorynew"].IsBoolean) {
|
||||
this.Factorynew = (Boolean)json["factorynew"];
|
||||
}
|
||||
if (json.ContainsKey("datastoreversion") && json["datastoreversion"].IsString) {
|
||||
this.Datastoreversion = json["datastoreversion"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("starterkitid") && json["starterkitid"].IsString) {
|
||||
this.Starterkitid = json["starterkitid"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("swupdate2") && json["swupdate2"].IsObject) {
|
||||
this.SwUpdate2 = new SwUpdate(json["swupdate2"], this.http, this.Polling);
|
||||
this.SwUpdate2.Update += this.NotifyClientChildren;
|
||||
}
|
||||
if (json.ContainsKey("whitelist") && json["whitelist"].IsObject) {
|
||||
this.CreateWhitelist(json["whitelist"]);
|
||||
}
|
||||
if (json.ContainsKey("portalstate") && json["portalstate"].IsObject) {
|
||||
this.Portalstate = new Portalstate(json["portalstate"], this.http, this.Polling);
|
||||
this.Portalstate.Update += this.NotifyClientChildren;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWhitelist(JsonData json) {
|
||||
Dictionary<String, Whitelist> whitelists = new Dictionary<String, Whitelist>();
|
||||
foreach (String item in json.Keys) {
|
||||
Whitelist w = new Whitelist(json[item], new Tuple<String>(item), this.http, this.Polling);
|
||||
w.Update += this.NotifyClientChildren;
|
||||
whitelists.Add(item, w);
|
||||
}
|
||||
this.Whitelist = new ReadOnlyDictionary<String, Whitelist>(whitelists);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
return "Config: " + this.Name + " Ip-" + this.Ipaddress + " DHCP-" + this.Dhcp + " Time-" + this.Localtime + " User-" + this.Whitelist.Count;
|
||||
}
|
||||
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
if (this.Name != json["name"].ToString()) {
|
||||
this._name = json["name"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Name);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("apiversion") && json["apiversion"].IsString) {
|
||||
if (this.Apiversion != json["apiversion"].ToString()) {
|
||||
this.Apiversion = json["apiversion"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Apiversion);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("swversion") && json["swversion"].IsString) {
|
||||
if (this.Swversion != json["swversion"].ToString()) {
|
||||
this.Swversion = json["swversion"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Swversion);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("linkbutton") && json["linkbutton"].IsBoolean) {
|
||||
if (this.Linkbutton != (Boolean)json["linkbutton"]) {
|
||||
this._linkbutton = (Boolean)json["linkbutton"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Linkbutton);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("ipaddress") && json["ipaddress"].IsString) {
|
||||
if (this.Ipaddress != json["ipaddress"].ToString()) {
|
||||
this._ipaddress = json["ipaddress"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Ipaddress);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("mac") && json["mac"].IsString) {
|
||||
if (this.Mac != json["mac"].ToString()) {
|
||||
this.Mac = json["mac"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Mac);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("netmask") && json["netmask"].IsString) {
|
||||
if (this.Netmask != json["netmask"].ToString()) {
|
||||
this._netmask = json["netmask"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Netmask);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("gateway") && json["gateway"].IsString) {
|
||||
if (this.Gateway != json["gateway"].ToString()) {
|
||||
this._gateway = json["gateway"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Gateway);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("dhcp") && json["dhcp"].IsBoolean) {
|
||||
if (this.Dhcp != (Boolean)json["dhcp"]) {
|
||||
this._dhcp = (Boolean)json["dhcp"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Dhcp);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("portalservices") && json["portalservices"].IsBoolean) {
|
||||
if (this.Portalservices != (Boolean)json["portalservices"]) {
|
||||
this.Portalservices = (Boolean)json["portalservices"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Portalservices);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("UTC") && json["UTC"].IsString) {
|
||||
if (this.Utc != DateTime.Parse(json["UTC"].ToString())) {
|
||||
this._utc = DateTime.Parse(json["UTC"].ToString());
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Utc);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("localtime") && json["localtime"].IsString) {
|
||||
if (this.Localtime != DateTime.Parse(json["localtime"].ToString())) {
|
||||
this.Localtime = DateTime.Parse(json["localtime"].ToString());
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Localtime);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("timezone") && json["timezone"].IsString) {
|
||||
if (this.Timezone != json["timezone"].ToString()) {
|
||||
this._timezone = json["timezone"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Timezone);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("zigbeechannel") && json["zigbeechannel"].IsInt) {
|
||||
if (this.Zigbeechannel != (Byte)json["zigbeechannel"]) {
|
||||
this._zigbeechannel = (Byte)json["zigbeechannel"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Zigbeechannel);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("modelid") && json["modelid"].IsString) {
|
||||
if (this.Modelid != json["modelid"].ToString()) {
|
||||
this.Modelid = json["modelid"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Modelid);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("bridgeid") && json["bridgeid"].IsString) {
|
||||
if (this.Bridgeid != json["bridgeid"].ToString()) {
|
||||
this.Bridgeid = json["bridgeid"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Bridgeid);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("replacesbridgeid") && json["replacesbridgeid"] != null && json["replacesbridgeid"].IsString) {
|
||||
if (this.Replacesbridgeid != json["replacesbridgeid"].ToString()) {
|
||||
this.Replacesbridgeid = json["replacesbridgeid"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Replacesbridgeid);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("factorynew") && json["factorynew"].IsBoolean) {
|
||||
if (this.Factorynew != (Boolean)json["factorynew"]) {
|
||||
this.Factorynew = (Boolean)json["factorynew"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Factorynew);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("datastoreversion") && json["datastoreversion"].IsString) {
|
||||
if (this.Datastoreversion != json["datastoreversion"].ToString()) {
|
||||
this.Datastoreversion = json["datastoreversion"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Datastoreversion);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("starterkitid") && json["starterkitid"].IsString) {
|
||||
if (this.Starterkitid != json["starterkitid"].ToString()) {
|
||||
this.Starterkitid = json["starterkitid"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Starterkitid);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("swupdate2") && json["swupdate2"].IsObject) {
|
||||
this.SwUpdate2?.SetUpdate(json["swupdate2"]);
|
||||
}
|
||||
if (json.ContainsKey("whitelist") && json["whitelist"].IsObject) {
|
||||
foreach (String item in json["whitelist"].Keys) {
|
||||
if(this.Whitelist.ContainsKey(item)) {
|
||||
this.Whitelist[item].SetUpdate(json["whitelist"][item]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("portalstate") && json["portalstate"].IsObject) {
|
||||
this.Portalstate?.SetUpdate(json["portalstate"]);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
71
Hue/Hue/Devices/Configs/Portalstate.cs
Normal file
71
Hue/Hue/Devices/Configs/Portalstate.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Configs {
|
||||
public class Portalstate : AConfig {
|
||||
|
||||
#region Properties
|
||||
public Boolean Signedon { get; private set; }
|
||||
public Boolean Incoming { get; private set; }
|
||||
public Boolean Outgoing { get; private set; }
|
||||
public String Communication { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Constrctor
|
||||
public Portalstate(JsonData json, HttpConnection http, Boolean polling) : base(json, http, polling) {
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if (json.ContainsKey("signedon") && json["signedon"].IsBoolean) {
|
||||
this.Signedon = (Boolean)json["signedon"];
|
||||
}
|
||||
if (json.ContainsKey("incoming") && json["incoming"].IsBoolean) {
|
||||
this.Incoming = (Boolean)json["incoming"];
|
||||
}
|
||||
if (json.ContainsKey("outgoing") && json["outgoing"].IsBoolean) {
|
||||
this.Outgoing = (Boolean)json["outgoing"];
|
||||
}
|
||||
if (json.ContainsKey("communication") && json["communication"].IsString) {
|
||||
this.Communication = json["communication"].ToString();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
return "Portalstate: On-" + this.Signedon + " In-" + this.Incoming + " Out-" + this.Outgoing + " Communication-" + this.Communication;
|
||||
}
|
||||
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if (json.ContainsKey("signedon") && json["signedon"].IsBoolean) {
|
||||
if (this.Signedon != (Boolean)json["signedon"]) {
|
||||
this.Signedon = (Boolean)json["signedon"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Signedon);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("incoming") && json["incoming"].IsBoolean) {
|
||||
if (this.Incoming != (Boolean)json["incoming"]) {
|
||||
this.Incoming = (Boolean)json["incoming"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Incoming);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("outgoing") && json["outgoing"].IsBoolean) {
|
||||
if (this.Outgoing != (Boolean)json["outgoing"]) {
|
||||
this.Outgoing = (Boolean)json["outgoing"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Outgoing);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("communication") && json["communication"].IsString) {
|
||||
if (this.Communication != json["communication"].ToString()) {
|
||||
this.Communication = json["communication"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Communication);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
108
Hue/Hue/Devices/Configs/SwUpdate.cs
Normal file
108
Hue/Hue/Devices/Configs/SwUpdate.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Configs {
|
||||
public class SwUpdate : AConfig {
|
||||
#region Properties
|
||||
public Boolean Checkforupdate { get; private set; }
|
||||
public DateTime Lastchange { get; private set; }
|
||||
public String Bridgestate { get; private set; }
|
||||
public DateTime Bridgelastinstall { get; private set; }
|
||||
public String State { get; private set; }
|
||||
public String Autoinstallupdatetime { get; private set; }
|
||||
public Boolean Autoinstallon { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public SwUpdate(JsonData json, HttpConnection http, Boolean polling) : base(json, http, polling) {
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if(json.ContainsKey("checkforupdate") && json["checkforupdate"].IsBoolean) {
|
||||
this.Checkforupdate = (Boolean)json["checkforupdate"];
|
||||
}
|
||||
if (json.ContainsKey("lastchange") && json["lastchange"].IsString) {
|
||||
this.Lastchange = DateTime.Parse(json["lastchange"].ToString()).ToLocalTime();
|
||||
}
|
||||
if (json.ContainsKey("bridge") && json["bridge"].IsObject) {
|
||||
if (json["bridge"].ContainsKey("state") && json["bridge"]["state"].IsString) {
|
||||
this.Bridgestate = json["bridge"]["state"].ToString();
|
||||
}
|
||||
if (json["bridge"].ContainsKey("lastinstall") && json["bridge"]["lastinstall"].IsString) {
|
||||
this.Bridgelastinstall = DateTime.Parse(json["bridge"]["lastinstall"].ToString()).ToLocalTime();
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].IsString) {
|
||||
this.State = json["state"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("autoinstall") && json["autoinstall"].IsObject) {
|
||||
if (json["autoinstall"].ContainsKey("updatetime") && json["autoinstall"]["updatetime"].IsString) {
|
||||
this.Autoinstallupdatetime = json["autoinstall"]["updatetime"].ToString();
|
||||
}
|
||||
if (json["autoinstall"].ContainsKey("on") && json["autoinstall"]["on"].IsBoolean) {
|
||||
this.Autoinstallon = (Boolean)json["autoinstall"]["on"];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
return "Updates: Check-" + this.Checkforupdate + " LatestCheck-" + this.Lastchange + " Updates-" + this.Bridgestate + " Installed-" + this.Bridgelastinstall + " State-" + this.State + " AutoTime-" + this.Autoinstallupdatetime + " AutoOn-" + this.Autoinstallon;
|
||||
}
|
||||
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if (json.ContainsKey("checkforupdate") && json["checkforupdate"].IsBoolean) {
|
||||
if (this.Checkforupdate != (Boolean)json["checkforupdate"]) {
|
||||
this.Checkforupdate = (Boolean)json["checkforupdate"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Checkforupdate);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("lastchange") && json["lastchange"].IsString) {
|
||||
if (this.Lastchange != DateTime.Parse(json["lastchange"].ToString()).ToLocalTime()) {
|
||||
this.Lastchange = DateTime.Parse(json["lastchange"].ToString()).ToLocalTime();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Lastchange);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("bridge") && json["bridge"].ContainsKey("state") && json["bridge"]["state"].IsString) {
|
||||
if (this.Bridgestate != json["bridge"]["state"].ToString()) {
|
||||
this.Bridgestate = json["bridge"]["state"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Bridgestate);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("bridge") && json["bridge"].ContainsKey("lastinstall") && json["bridge"]["lastinstall"].IsString) {
|
||||
if (this.Bridgelastinstall != DateTime.Parse(json["bridge"]["lastinstall"].ToString()).ToLocalTime()) {
|
||||
this.Bridgelastinstall = DateTime.Parse(json["bridge"]["lastinstall"].ToString()).ToLocalTime();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Bridgelastinstall);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].IsString) {
|
||||
if (this.State != json["state"].ToString()) {
|
||||
this.State = json["state"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.State);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("autoinstall") && json["autoinstall"].ContainsKey("updatetime") && json["autoinstall"]["updatetime"].IsString) {
|
||||
if (this.Autoinstallupdatetime != json["autoinstall"]["updatetime"].ToString()) {
|
||||
this.Autoinstallupdatetime = json["autoinstall"]["updatetime"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Autoinstallupdatetime);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("autoinstall") && json["autoinstall"].ContainsKey("on") && json["autoinstall"]["on"].IsBoolean) {
|
||||
if (this.Autoinstallon != (Boolean)json["autoinstall"]["on"]) {
|
||||
this.Autoinstallon = (Boolean)json["autoinstall"]["on"];
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Autoinstallon);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
62
Hue/Hue/Devices/Configs/Whitelist.cs
Normal file
62
Hue/Hue/Devices/Configs/Whitelist.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Configs {
|
||||
public class Whitelist : AConfig {
|
||||
#region Properties
|
||||
public DateTime Lastusedate { get; private set; }
|
||||
public DateTime Createdate { get; private set; }
|
||||
public String Name { get; private set; }
|
||||
public String UserId { get; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public Whitelist(JsonData json, Tuple<String> id, HttpConnection http, Boolean polling) : base(json, http, polling) {
|
||||
this.UserId = id.Item1;
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if (json.ContainsKey("last use date") && json["last use date"].IsString) {
|
||||
this.Lastusedate = DateTime.Parse(json["last use date"].ToString()).ToLocalTime();
|
||||
}
|
||||
if (json.ContainsKey("create date") && json["create date"].IsString) {
|
||||
this.Createdate = DateTime.Parse(json["create date"].ToString()).ToLocalTime();
|
||||
}
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
this.Name = json["name"].ToString();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
return "User [" + this.UserId + "]: " + this.Name + " (Create-" + this.Createdate + " LastOn-" + this.Lastusedate + ")";
|
||||
}
|
||||
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if (json.ContainsKey("last use date") && json["last use date"].IsString) {
|
||||
if (this.Lastusedate != DateTime.Parse(json["last use date"].ToString()).ToLocalTime()) {
|
||||
this.Lastusedate = DateTime.Parse(json["last use date"].ToString()).ToLocalTime();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Lastusedate);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("create date") && json["create date"].IsString) {
|
||||
if (this.Createdate != DateTime.Parse(json["create date"].ToString()).ToLocalTime()) {
|
||||
this.Createdate = DateTime.Parse(json["create date"].ToString()).ToLocalTime();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Createdate);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
if (this.Name != json["name"].ToString()) {
|
||||
this.Name = json["name"].ToString();
|
||||
this.NotifyClient<ConfigUpdateEvent>(this.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
110
Hue/Hue/Devices/Groups/Room.cs
Normal file
110
Hue/Hue/Devices/Groups/Room.cs
Normal file
@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Groups {
|
||||
public class Room : AGroup {
|
||||
public enum AlertEffect {
|
||||
none,
|
||||
select,
|
||||
lselect
|
||||
}
|
||||
|
||||
#region Properties
|
||||
private AlertEffect _alert;
|
||||
|
||||
private Boolean _state;
|
||||
public Boolean State {
|
||||
get {
|
||||
return this._state;
|
||||
}
|
||||
set {
|
||||
if(this.SetGroupAction(new Dictionary<String, Object>() { { "on", value } })) {
|
||||
this._state = value;
|
||||
this.NotifyClient<GroupUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Byte _brightness;
|
||||
public Byte Brightness {
|
||||
get {
|
||||
return this._brightness;
|
||||
}
|
||||
set {
|
||||
if(this.SetGroupAction(new Dictionary<String, Object>() { { "bri", value } })) {
|
||||
this._brightness = value;
|
||||
this.NotifyClient<GroupUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public AlertEffect Alert {
|
||||
get {
|
||||
return this._alert;
|
||||
}
|
||||
set {
|
||||
if(this.SetGroupAction(new Dictionary<String, Object>() { { "alert", value } })) {
|
||||
this._alert = value;
|
||||
this.NotifyClient<GroupUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public Room(JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) : base(json, id, http, polling, lights) {
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if (json.ContainsKey("action")) {
|
||||
JsonData state = json["action"];
|
||||
if (state.ContainsKey("on") && state["on"].IsBoolean) {
|
||||
this._state = (Boolean)state["on"];
|
||||
}
|
||||
if (state.ContainsKey("bri") && state["bri"].IsInt) {
|
||||
this._brightness = (Byte)state["bri"];
|
||||
}
|
||||
if (state.ContainsKey("alert") && state["alert"].IsString) {
|
||||
this._alert = (AlertEffect)Enum.Parse(typeof(AlertEffect), state["alert"].ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
List<String> lid = new List<String>();
|
||||
foreach (KeyValuePair<Int32, ALight> item in this.Lights) {
|
||||
lid.Add(item.Key.ToString());
|
||||
}
|
||||
return "Group " + this.Name + " [" + this.GroupId + "]: (Class-"+ Helper.GetEnumDescription(this.Class) + ", ["+String.Join(",",lid.ToArray())+"]) On-" + this.State.ToString() + " Bri-" + this.Brightness + " Alert-" + this.Alert.ToString() + " AllOn-" + this.StateAllOn.ToString() + " AnyOn-" + this.StateAnyOn.ToString();
|
||||
}
|
||||
|
||||
public override void SetUpdate(JsonData json) {
|
||||
base.SetUpdate(json);
|
||||
if (json.ContainsKey("on") && json["on"].IsBoolean) {
|
||||
if (this.State != (Boolean)json["on"]) {
|
||||
this._state = (Boolean)json["on"];
|
||||
this.NotifyClient<GroupUpdateEvent>(this.State);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("bri") && json["bri"].IsInt) {
|
||||
if (this.Brightness != (Byte)json["bri"]) {
|
||||
this._brightness = (Byte)json["bri"];
|
||||
this.NotifyClient<GroupUpdateEvent>(this.Brightness);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("alert") && json["alert"].IsString) {
|
||||
if (this.Alert != (AlertEffect)Enum.Parse(typeof(AlertEffect), json["alert"].ToString())) {
|
||||
this._alert = (AlertEffect)Enum.Parse(typeof(AlertEffect), json["alert"].ToString());
|
||||
this.NotifyClient<GroupUpdateEvent>(this.Alert);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
113
Hue/Hue/Devices/Lights/Dimmablelight.cs
Normal file
113
Hue/Hue/Devices/Lights/Dimmablelight.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Lights {
|
||||
public class Dimmablelight : ALight {
|
||||
public enum AlertEffect {
|
||||
none,
|
||||
select,
|
||||
lselect
|
||||
}
|
||||
|
||||
#region Properties
|
||||
private Boolean _state;
|
||||
public Boolean State {
|
||||
get {
|
||||
return this._state;
|
||||
}
|
||||
set {
|
||||
if(this.SetLightStateAttribute(new Dictionary<String, Object>() { { "on", value } })) {
|
||||
this._state = value;
|
||||
this.NotifyClient<LightUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Byte _brightness;
|
||||
public Byte Brightness {
|
||||
get {
|
||||
return this._brightness;
|
||||
}
|
||||
set {
|
||||
if(this.SetLightStateAttribute(new Dictionary<String, Object>() { { "bri", value } })) {
|
||||
this._brightness = value;
|
||||
this.NotifyClient<LightUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private AlertEffect _alert;
|
||||
public AlertEffect Alert {
|
||||
get {
|
||||
return this._alert;
|
||||
}
|
||||
set {
|
||||
if(this.SetLightStateAttribute(new Dictionary<String, Object>() { { "alert", value.ToString() } })) {
|
||||
this._alert = value;
|
||||
this.NotifyClient<LightUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Boolean Reachable { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public Dimmablelight(JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling) : base(json, id, http, polling) {
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if (json.ContainsKey("state")) {
|
||||
JsonData state = json["state"];
|
||||
if (state.ContainsKey("on") && state["on"].IsBoolean) {
|
||||
this._state = (Boolean)state["on"];
|
||||
}
|
||||
if (state.ContainsKey("bri") && state["bri"].IsInt) {
|
||||
this._brightness = (Byte)state["bri"];
|
||||
}
|
||||
if (state.ContainsKey("alert") && state["alert"].IsString) {
|
||||
this._alert = (AlertEffect)Enum.Parse(typeof(AlertEffect), state["alert"].ToString());
|
||||
}
|
||||
if (state.ContainsKey("reachable") && state["reachable"].IsBoolean) {
|
||||
this.Reachable = (Boolean)state["reachable"];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
return "Light " + this.Name + " [" + this.LightId + "]: On-" + this.State.ToString() + " Bri-" + this.Brightness + " Alert-" + this.Alert.ToString() + " Reachable-" + this.Reachable.ToString();
|
||||
}
|
||||
public override void SetUpdate(JsonData json) {
|
||||
base.SetUpdate(json);
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("on") && json["state"]["on"].IsBoolean) {
|
||||
if (this.State != (Boolean)json["state"]["on"]) {
|
||||
this._state = (Boolean)json["state"]["on"];
|
||||
this.NotifyClient<LightUpdateEvent>(this.State);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("bri") && json["state"]["bri"].IsInt) {
|
||||
if (this.Brightness != (Byte)json["state"]["bri"]) {
|
||||
this._brightness = (Byte)json["state"]["bri"];
|
||||
this.NotifyClient<LightUpdateEvent>(this.Brightness);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("alert") && json["state"]["alert"].IsString) {
|
||||
if (this.Alert != (AlertEffect)Enum.Parse(typeof(AlertEffect), json["state"]["alert"].ToString())) {
|
||||
this._alert = (AlertEffect)Enum.Parse(typeof(AlertEffect), json["state"]["alert"].ToString());
|
||||
this.NotifyClient<LightUpdateEvent>(this.Alert);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("reachable") && json["state"]["reachable"].IsBoolean) {
|
||||
if (this.Reachable != (Boolean)json["state"]["reachable"]) {
|
||||
this.Reachable = (Boolean)json["state"]["reachable"];
|
||||
this.NotifyClient<LightUpdateEvent>(this.Reachable);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
74
Hue/Hue/Devices/Scenes/LightState.cs
Normal file
74
Hue/Hue/Devices/Scenes/LightState.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Scenes {
|
||||
public class LightState : AScene {
|
||||
#region Properties
|
||||
private Boolean _state;
|
||||
public Boolean State {
|
||||
get {
|
||||
return this._state;
|
||||
}
|
||||
set {
|
||||
if (this.SetLightSceneAttribute(new Dictionary<String, Object>() { { "on", value } })) {
|
||||
this._state = value;
|
||||
this.NotifyClient<SceneUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Byte _brightness;
|
||||
public Byte Brightness {
|
||||
get {
|
||||
return this._brightness;
|
||||
}
|
||||
set {
|
||||
if(this.SetLightSceneAttribute(new Dictionary<String, Object>() { { "bri", value } })) {
|
||||
this._brightness = value;
|
||||
this.NotifyClient<SceneUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public LightState(JsonData json, Tuple<String, Int32> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) : base(json, id, http, polling, lights){
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if (json.ContainsKey("on") && json["on"].IsBoolean) {
|
||||
this._state = (Boolean)json["on"];
|
||||
}
|
||||
if (json.ContainsKey("bri") && json["bri"].IsInt) {
|
||||
this._brightness = (Byte)json["bri"];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
return "Scene LightState " + this.SceneId + " [" + this.LightStateId + "]: On-" + this.State.ToString() + " Bri-" + this.Brightness;
|
||||
}
|
||||
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if (json.ContainsKey("on") && json["on"].IsBoolean) {
|
||||
if (this.State != (Boolean)json["on"]) {
|
||||
this._state = (Boolean)json["on"];
|
||||
this.NotifyClient<SceneUpdateEvent>(this.State);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("bri") && json["bri"].IsInt) {
|
||||
if (this.Brightness != (Byte)json["bri"]) {
|
||||
this._brightness = (Byte)json["bri"];
|
||||
this.NotifyClient<SceneUpdateEvent>(this.Brightness);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
150
Hue/Hue/Devices/Scenes/Scene.cs
Normal file
150
Hue/Hue/Devices/Scenes/Scene.cs
Normal file
@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Scenes {
|
||||
class Scene : AScene {
|
||||
#region Properties
|
||||
private String _name;
|
||||
public String Name {
|
||||
get {
|
||||
return this._name;
|
||||
}
|
||||
set {
|
||||
if (this.SetSceneAttribute(new Dictionary<String, Object>() { { "name", value } })) {
|
||||
this._name = value;
|
||||
this.NotifyClient<SceneUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public String Owner { get; private set; }
|
||||
public Boolean Recycle { get; private set; }
|
||||
public Boolean Locked { get; private set; }
|
||||
public String Picture { get; private set; }
|
||||
public DateTime Lastupdated { get; private set; }
|
||||
public Int32 Version { get; private set; }
|
||||
public ReadOnlyDictionary<Int32, ALight> Lights { get; private set; }
|
||||
public ReadOnlyDictionary<Int32, LightState> LightStates { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public Scene(JsonData json, Tuple<String> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) : base(json, new Tuple<String, Int32>(id.Item1, 0), http, polling, lights) {
|
||||
this.ComplexInit(json, lights);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
this._name = json["name"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("owner") && json["owner"].IsString) {
|
||||
this.Owner = json["owner"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("recycle") && json["recycle"].IsBoolean) {
|
||||
this.Recycle = (Boolean)json["recycle"];
|
||||
}
|
||||
if (json.ContainsKey("locked") && json["locked"].IsBoolean) {
|
||||
this.Locked = (Boolean)json["locked"];
|
||||
}
|
||||
if (json.ContainsKey("picture") && json["picture"].IsString) {
|
||||
this.Picture = json["picture"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("lastupdated") && json["lastupdated"].IsString) {
|
||||
this.Lastupdated = DateTime.Parse(json["lastupdated"].ToString());
|
||||
}
|
||||
if (json.ContainsKey("version") && json["version"].IsInt) {
|
||||
this.Version = (Int32)json["version"];
|
||||
}
|
||||
if (json.ContainsKey("lights") && json["lights"].IsArray) {
|
||||
Dictionary<Int32, ALight> lightdict = new Dictionary<Int32, ALight>();
|
||||
foreach (JsonData item in json["lights"]) {
|
||||
if (Int32.TryParse(item.ToString(), out Int32 lampid)) {
|
||||
if (lights.ContainsKey(lampid)) {
|
||||
lightdict.Add(lampid, lights[lampid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Lights = new ReadOnlyDictionary<Int32, ALight>(lightdict);
|
||||
}
|
||||
if (json.ContainsKey("lightstates") && json["lightstates"].IsObject) {
|
||||
Dictionary<Int32, LightState> lightstates = new Dictionary<Int32, LightState>();
|
||||
foreach (String item in json["lightstates"].Keys) {
|
||||
LightState l = new LightState(json["lightstates"][item], new Tuple<String, Int32>(this.SceneId, Int32.Parse(item)), this.http, this.Polling, lights);
|
||||
l.Update += this.NotifyClientChildren;
|
||||
lightstates.Add(Int32.Parse(item), l);
|
||||
}
|
||||
this.LightStates = new ReadOnlyDictionary<Int32, LightState>(lightstates);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
List<String> lid = new List<String>();
|
||||
foreach (KeyValuePair<Int32, ALight> item in this.Lights) {
|
||||
lid.Add(item.Key.ToString());
|
||||
}
|
||||
List<String> lst = new List<String>();
|
||||
foreach (KeyValuePair<Int32, LightState> item in this.LightStates) {
|
||||
lst.Add(item.Value.ToString());
|
||||
}
|
||||
return "Scene " + this.Name + " [" + this.SceneId + "]: (["+ String.Join(",", lid.ToArray()) +"]) Light-States ["+ String.Join(",", lst.ToArray())+"]";
|
||||
}
|
||||
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
if (this.Name != json["name"].ToString()) {
|
||||
this._name = json["name"].ToString();
|
||||
this.NotifyClient<SceneUpdateEvent>(this.Name);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("owner") && json["owner"].IsString) {
|
||||
if (this.Owner != json["owner"].ToString()) {
|
||||
this.Owner = json["owner"].ToString();
|
||||
this.NotifyClient<SceneUpdateEvent>(this.Owner);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("recycle") && json["recycle"].IsBoolean) {
|
||||
if (this.Recycle != (Boolean)json["recycle"]) {
|
||||
this.Recycle = (Boolean)json["recycle"];
|
||||
this.NotifyClient<SceneUpdateEvent>(this.Recycle);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("locked") && json["locked"].IsBoolean) {
|
||||
if (this.Locked != (Boolean)json["locked"]) {
|
||||
this.Locked = (Boolean)json["locked"];
|
||||
this.NotifyClient<SceneUpdateEvent>(this.Locked);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("picture") && json["picture"].IsString) {
|
||||
if (this.Picture != json["picture"].ToString()) {
|
||||
this.Picture = json["picture"].ToString();
|
||||
this.NotifyClient<SceneUpdateEvent>(this.Picture);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("lastupdated") && json["lastupdated"].IsString) {
|
||||
if (this.Lastupdated != DateTime.Parse(json["lastupdated"].ToString())) {
|
||||
this.Lastupdated = DateTime.Parse(json["lastupdated"].ToString());
|
||||
this.NotifyClient<SceneUpdateEvent>(this.Lastupdated);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("version") && json["version"].IsInt) {
|
||||
if (this.Version != (Int32)json["version"]) {
|
||||
this.Version = (Int32)json["version"];
|
||||
this.NotifyClient<SceneUpdateEvent>(this.Version);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("lightstates") && json["lightstates"].IsObject) {
|
||||
foreach (String item in json["lightstates"].Keys) {
|
||||
if(this.LightStates.ContainsKey(Int32.Parse(item))) {
|
||||
this.LightStates[Int32.Parse(item)].SetUpdate(json["lightstates"][Int32.Parse(item)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
121
Hue/Hue/Devices/Sensors/Daylight.cs
Normal file
121
Hue/Hue/Devices/Sensors/Daylight.cs
Normal file
@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Devices.Sensors {
|
||||
class Daylight : ASensor {
|
||||
#region Properties
|
||||
private Boolean _on;
|
||||
public Boolean On {
|
||||
get {
|
||||
return this._on;
|
||||
}
|
||||
set {
|
||||
if(this.SetSensorConfig(new Dictionary<String, Object>() { { "on", value } })) {
|
||||
this._on = value;
|
||||
this.NotifyClient<SensorUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Boolean Configured { get; private set; }
|
||||
private Int32 _sunriseoffset;
|
||||
public Int32 Sunriseoffset {
|
||||
get {
|
||||
return this._sunriseoffset;
|
||||
}
|
||||
set {
|
||||
if(this.SetSensorConfig(new Dictionary<String, Object>() { { "sunriseoffset", value } })) {
|
||||
this._sunriseoffset = value;
|
||||
this.NotifyClient<SensorUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Int32 _sunsetoffset;
|
||||
public Int32 Sunsetoffset {
|
||||
get {
|
||||
return this._sunsetoffset;
|
||||
}
|
||||
set {
|
||||
if(this.SetSensorConfig(new Dictionary<String, Object>() { { "sunsetoffset", value } })) {
|
||||
this._sunsetoffset = value;
|
||||
this.NotifyClient<SensorUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Boolean IsDaylight { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public Daylight(JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling) : base(json, id, http, polling) {
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if(json.ContainsKey("config")) {
|
||||
JsonData config = json["config"];
|
||||
if(config.ContainsKey("on") && config["on"].IsBoolean) {
|
||||
this._on = (Boolean)config["on"];
|
||||
}
|
||||
if(config.ContainsKey("configured") && config["configured"].IsBoolean) {
|
||||
this.Configured = (Boolean)config["configured"];
|
||||
}
|
||||
if(config.ContainsKey("sunriseoffset") && config["sunriseoffset"].IsInt) {
|
||||
this._sunriseoffset = (Int32)config["sunriseoffset"];
|
||||
}
|
||||
if(config.ContainsKey("sunsetoffset") && config["sunsetoffset"].IsInt) {
|
||||
this._sunsetoffset = (Int32)config["sunsetoffset"];
|
||||
}
|
||||
}
|
||||
if(json.ContainsKey("state")) {
|
||||
JsonData state = json["state"];
|
||||
if(state.ContainsKey("daylight") && state["daylight"].IsBoolean) {
|
||||
this.IsDaylight = (Boolean)state["daylight"];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override String ToString() {
|
||||
return "Daylight " + this.Name + " [" + this.SensorId + "]: IsDaylight-" + this.IsDaylight.ToString() + " On-" + this.On.ToString() + " Configured-" + this.Configured.ToString() + " Sunriseoffset-" + this.Sunriseoffset.ToString() + " Sunsetoffset-" + this.Sunsetoffset.ToString();
|
||||
}
|
||||
|
||||
public override void SetUpdate(JsonData json) {
|
||||
base.SetUpdate(json);
|
||||
if (json.ContainsKey("config") && json["config"].ContainsKey("on") && json["config"]["on"].IsBoolean) {
|
||||
if (this.On != (Boolean)json["config"]["on"]) {
|
||||
this._on = (Boolean)json["config"]["on"];
|
||||
this.NotifyClient<SensorUpdateEvent>(this.On);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("config") && json["config"].ContainsKey("configured") && json["config"]["configured"].IsBoolean) {
|
||||
if (this.Configured != (Boolean)json["config"]["configured"]) {
|
||||
this.Configured = (Boolean)json["config"]["configured"];
|
||||
this.NotifyClient<SensorUpdateEvent>(this.Configured);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("config") && json["config"].ContainsKey("sunriseoffset") && json["config"]["sunriseoffset"].IsInt) {
|
||||
if (this.Sunriseoffset != (Int32)json["config"]["sunriseoffset"]) {
|
||||
this._sunriseoffset = (Int32)json["config"]["sunriseoffset"];
|
||||
this.NotifyClient<SensorUpdateEvent>(this.Sunriseoffset);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("config") && json["config"].ContainsKey("sunsetoffset") && json["config"]["sunsetoffset"].IsInt) {
|
||||
if (this.Sunsetoffset != (Int32)json["config"]["sunsetoffset"]) {
|
||||
this._sunsetoffset = (Int32)json["config"]["sunsetoffset"];
|
||||
this.NotifyClient<SensorUpdateEvent>(this.Sunsetoffset);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("daylight") && json["state"]["daylight"].IsBoolean) {
|
||||
if (this.IsDaylight != (Boolean)json["state"]["daylight"]) {
|
||||
this.IsDaylight = (Boolean)json["state"]["daylight"];
|
||||
this.NotifyClient<SensorUpdateEvent>(this.IsDaylight);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
59
Hue/Hue/Events/UpdateEvent.cs
Normal file
59
Hue/Hue/Events/UpdateEvent.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Events {
|
||||
public class AllUpdateEvent : EventArgs {
|
||||
|
||||
public AllUpdateEvent() {
|
||||
}
|
||||
|
||||
public AllUpdateEvent(Object value, DateTime time, Object parent) {
|
||||
this.GetValue = value;
|
||||
this.UpdateTime = time;
|
||||
this.Parent = parent;
|
||||
}
|
||||
|
||||
public Object GetValue { get; }
|
||||
public DateTime UpdateTime { get; }
|
||||
public Object Parent { get; private set; }
|
||||
}
|
||||
public class LightUpdateEvent : AllUpdateEvent {
|
||||
public LightUpdateEvent() {
|
||||
}
|
||||
|
||||
public LightUpdateEvent(Object value, DateTime time, Object parent) : base(value, time, parent) {
|
||||
}
|
||||
}
|
||||
public class GroupUpdateEvent : AllUpdateEvent {
|
||||
public GroupUpdateEvent() {
|
||||
}
|
||||
|
||||
public GroupUpdateEvent(Object value, DateTime time, Object parent) : base(value, time, parent) {
|
||||
}
|
||||
}
|
||||
|
||||
public class SceneUpdateEvent : AllUpdateEvent {
|
||||
public SceneUpdateEvent() {
|
||||
}
|
||||
|
||||
public SceneUpdateEvent(Object value, DateTime time, Object parent) : base(value, time, parent) {
|
||||
}
|
||||
}
|
||||
public class SensorUpdateEvent : AllUpdateEvent {
|
||||
public SensorUpdateEvent() {
|
||||
}
|
||||
|
||||
public SensorUpdateEvent(Object value, DateTime time, Object parent) : base(value, time, parent) {
|
||||
}
|
||||
}
|
||||
public class ConfigUpdateEvent : AllUpdateEvent {
|
||||
public ConfigUpdateEvent() {
|
||||
}
|
||||
|
||||
public ConfigUpdateEvent(Object value, DateTime time, Object parent) : base(value, time, parent) {
|
||||
}
|
||||
}
|
||||
}
|
12
Hue/Hue/Exceptions/HueExceptions.cs
Normal file
12
Hue/Hue/Exceptions/HueExceptions.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Exceptions {
|
||||
[Serializable]
|
||||
public class ConnectionException : Exception {
|
||||
public ConnectionException() { }
|
||||
public ConnectionException(String message) : base(message) { }
|
||||
public ConnectionException(String message, Exception innerException) : base(message, innerException) { }
|
||||
protected ConnectionException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
}
|
75
Hue/Hue/Hue.csproj
Normal file
75
Hue/Hue/Hue.csproj
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>BlubbFish.IoT.Hue</RootNamespace>
|
||||
<AssemblyName>Hue</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Devices\Configs\Config.cs" />
|
||||
<Compile Include="Devices\Configs\Portalstate.cs" />
|
||||
<Compile Include="Devices\Configs\SwUpdate.cs" />
|
||||
<Compile Include="Devices\Configs\Whitelist.cs" />
|
||||
<Compile Include="Devices\Scenes\LightState.cs" />
|
||||
<Compile Include="Devices\Scenes\Scene.cs" />
|
||||
<Compile Include="Devices\Sensors\Daylight.cs" />
|
||||
<Compile Include="Interfaces\AConfig.cs" />
|
||||
<Compile Include="Interfaces\AGroup.cs" />
|
||||
<Compile Include="Devices\Groups\Room.cs" />
|
||||
<Compile Include="Devices\Lights\Dimmablelight.cs" />
|
||||
<Compile Include="Interfaces\ALight.cs" />
|
||||
<Compile Include="Events\UpdateEvent.cs" />
|
||||
<Compile Include="Exceptions\HueExceptions.cs" />
|
||||
<Compile Include="Interfaces\AScene.cs" />
|
||||
<Compile Include="Interfaces\AConnector.cs" />
|
||||
<Compile Include="Interfaces\ASensor.cs" />
|
||||
<Compile Include="Interfaces\IMqtt.cs" />
|
||||
<Compile Include="HueController.cs" />
|
||||
<Compile Include="lib\Helper.cs" />
|
||||
<Compile Include="lib\HttpClient.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Librarys\litjson\litjson\litjson_4.7.1.csproj">
|
||||
<Project>{91a14cd2-2940-4500-8193-56d37edddbaa}</Project>
|
||||
<Name>litjson_4.7.1</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
192
Hue/Hue/HueController.cs
Normal file
192
Hue/Hue/HueController.cs
Normal file
@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.Exceptions;
|
||||
using BlubbFish.IoT.Hue.Interfaces;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue {
|
||||
public class HueController : IDisposable {
|
||||
private Boolean polling;
|
||||
private HttpConnection http;
|
||||
private Thread updatethread;
|
||||
private Thread pollthread;
|
||||
|
||||
public delegate void DataUpdate(Object sender, AllUpdateEvent e);
|
||||
public event DataUpdate Update;
|
||||
|
||||
public ReadOnlyDictionary<Int32, ALight> Lights { get; private set; }
|
||||
public ReadOnlyDictionary<Int32, AGroup> Groups { get; private set; }
|
||||
public ReadOnlyDictionary<String, AScene> Scenes { get; private set; }
|
||||
public ReadOnlyDictionary<Int32, ASensor> Sensors { get; private set; }
|
||||
public AConfig Config { get; private set; }
|
||||
|
||||
public HueController(Dictionary<String,String> settings, Boolean enablePoll = true) {
|
||||
this.polling = enablePoll;
|
||||
if(!settings.ContainsKey("server")) {
|
||||
throw new ArgumentException("Missing \"server\" in Configurationfile");
|
||||
}
|
||||
if(!settings.ContainsKey("key")) {
|
||||
this.CreateKey(settings["server"]);
|
||||
return;
|
||||
}
|
||||
this.Connect(settings["server"], settings["key"]);
|
||||
}
|
||||
|
||||
private void Connect(String server, String key) {
|
||||
this.http = new HttpConnection(server, key);
|
||||
this.CreateAll(this.http.GetJson(""));
|
||||
this.updatethread = new Thread(this.Updater);
|
||||
this.updatethread.Start();
|
||||
this.pollthread = new Thread(this.Poll);
|
||||
this.pollthread.Start();
|
||||
foreach (KeyValuePair<Int32, ALight> item in this.Lights) {
|
||||
item.Value.Update += this.AllUpdate;
|
||||
}
|
||||
foreach (KeyValuePair<Int32, AGroup> item in this.Groups) {
|
||||
item.Value.Update += this.AllUpdate;
|
||||
}
|
||||
foreach (KeyValuePair<String, AScene> item in this.Scenes) {
|
||||
item.Value.Update += this.AllUpdate;
|
||||
}
|
||||
foreach (KeyValuePair<Int32, ASensor> item in this.Sensors) {
|
||||
item.Value.Update += this.AllUpdate;
|
||||
}
|
||||
this.Config.Update += this.AllUpdate;
|
||||
}
|
||||
|
||||
private void Poll() {
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public AConnector GetConnector(String type, String id) {
|
||||
switch (type) {
|
||||
case "sensor":
|
||||
return this.Sensors.ContainsKey(Int32.Parse(id)) ? this.Sensors[Int32.Parse(id)] : null;
|
||||
case "scene":
|
||||
return this.Scenes.ContainsKey(id) ? this.Scenes[id] : null;
|
||||
case "light":
|
||||
return this.Lights.ContainsKey(Int32.Parse(id)) ? this.Lights[Int32.Parse(id)] : null;
|
||||
case "group":
|
||||
return this.Groups.ContainsKey(Int32.Parse(id)) ? this.Groups[Int32.Parse(id)] : null;
|
||||
case "config":
|
||||
return this.Config;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void AllUpdate(Object sender, AllUpdateEvent e) {
|
||||
this.Update?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
private void Updater() {
|
||||
while (true) {
|
||||
Thread.Sleep(1000 * 10); //Every Minute
|
||||
JsonData update = this.http.GetJson("");
|
||||
Helper.SetUpdate(this.Lights, update, "lights");
|
||||
Helper.SetUpdate(this.Groups, update, "groups");
|
||||
Helper.SetUpdate(this.Sensors, update, "sensors");
|
||||
Helper.SetUpdate(this.Scenes, update, "scenes");
|
||||
if (update.ContainsKey("config")) {
|
||||
this.Config.SetUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void CreateAll(JsonData json) {
|
||||
if(json.ContainsKey("lights")) {
|
||||
this.Lights = new ReadOnlyDictionary<Int32, ALight>(this.CreateItemsInt32<ALight>(json["lights"], false));
|
||||
}
|
||||
if(json.ContainsKey("groups")) {
|
||||
this.Groups = new ReadOnlyDictionary<Int32, AGroup>(this.CreateItemsInt32<AGroup>(json["groups"]));
|
||||
}
|
||||
if (json.ContainsKey("sensors")) {
|
||||
this.Sensors = new ReadOnlyDictionary<Int32, ASensor>(this.CreateItemsInt32<ASensor>(json["sensors"], false));
|
||||
}
|
||||
if (json.ContainsKey("scenes")) {
|
||||
this.CreateScenes(json["scenes"]);
|
||||
}
|
||||
if(json.ContainsKey("config")) {
|
||||
this.Config = AConfig.CreateInstanceConcrete(json["config"], this.http, this.polling);
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<Int32, T> CreateItemsInt32<T>(JsonData json, Boolean withLights = true) {
|
||||
Dictionary<Int32, T> items = new Dictionary<Int32, T>();
|
||||
foreach (String itemid in json.Keys) {
|
||||
T item = default(T);
|
||||
if (withLights) {
|
||||
item = (T)AConnector.CreateInstance(typeof(T), json[itemid], new Tuple<Int32>(Int32.Parse(itemid)), this.http, this.polling, this.Lights);
|
||||
} else {
|
||||
item = (T)AConnector.CreateInstance(typeof(T), json[itemid], new Tuple<Int32>(Int32.Parse(itemid)), this.http, this.polling);
|
||||
}
|
||||
if(item != null) {
|
||||
items.Add(Int32.Parse(itemid), item);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private void CreateScenes(JsonData json) {
|
||||
Dictionary<String, AScene> scenes = new Dictionary<String, AScene>();
|
||||
foreach (String sceneid in json.Keys) {
|
||||
AScene s = AScene.CreateInstanceConcrete(json[sceneid], new Tuple<String>(sceneid), this.http, this.polling, this.Lights);
|
||||
if (s != null) {
|
||||
scenes.Add(sceneid, s);
|
||||
}
|
||||
}
|
||||
this.Scenes = new ReadOnlyDictionary<String, AScene>(scenes);
|
||||
}
|
||||
|
||||
private void CreateKey(String server) {
|
||||
this.http = new HttpConnection(server);
|
||||
JsonData json = this.http.PostJson("", "{\"devicetype\": \"Huelib#BlubbFish\"}");
|
||||
if(json.IsArray && json[0].ContainsKey("error") && json[0]["error"].ContainsKey("type") && json[0]["error"]["type"].IsInt) {
|
||||
if((Int32)json[0]["error"]["type"] == 101) {
|
||||
Helper.WriteError("Please press the linkbutton on the Hue-Bridge! Then press return!");
|
||||
}
|
||||
}
|
||||
Console.ReadLine();
|
||||
json = this.http.PostJson("", "{\"devicetype\": \"Huelib#BlubbFish\"}");
|
||||
String key = "";
|
||||
if(json.IsArray && json[0].ContainsKey("success") && json[0]["success"].ContainsKey("username") && json[0]["success"]["username"].IsString) {
|
||||
key = json[0]["success"]["username"].ToString();
|
||||
}
|
||||
Helper.WriteError("Create \"key\" in config file! key=" + key);
|
||||
throw new ConnectionException("Create \"key\" in config file! key=" + key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#region IDisposable Support
|
||||
private Boolean disposedValue = false;
|
||||
|
||||
protected virtual void Dispose(Boolean disposing) {
|
||||
if (!this.disposedValue) {
|
||||
if (disposing) {
|
||||
this.updatethread.Abort();
|
||||
this.pollthread.Abort();
|
||||
}
|
||||
this.updatethread = null;
|
||||
this.pollthread = null;
|
||||
this.Lights = null;
|
||||
this.Groups = null;
|
||||
this.Scenes = null;
|
||||
this.Sensors = null;
|
||||
this.Config = null;
|
||||
this.disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
Dispose(true);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
31
Hue/Hue/Interfaces/AConfig.cs
Normal file
31
Hue/Hue/Interfaces/AConfig.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BlubbFish.IoT.Hue.Devices.Configs;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Interfaces {
|
||||
public abstract class AConfig : AConnector, IMqtt {
|
||||
#region Constructor
|
||||
public AConfig(JsonData json, HttpConnection http, Boolean polling) : base(http, polling){
|
||||
}
|
||||
|
||||
internal static AConfig CreateInstanceConcrete(JsonData json, HttpConnection http, Boolean polling) {
|
||||
return new Config(json, http, polling);
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected Boolean SetConfig(Dictionary<String, Object> dictionary) {
|
||||
return this.PutDictionary("config", dictionary);
|
||||
}
|
||||
|
||||
#region IMqtt
|
||||
public String MqttTopic() {
|
||||
return "config";
|
||||
}
|
||||
public String ToJson() {
|
||||
return JsonMapper.ToJson(this.ToDictionary());
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
84
Hue/Hue/Interfaces/AConnector.cs
Normal file
84
Hue/Hue/Interfaces/AConnector.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Interfaces {
|
||||
public abstract class AConnector {
|
||||
protected HttpConnection http;
|
||||
public delegate void UpdatedValue(Object sender, AllUpdateEvent e);
|
||||
public event UpdatedValue Update;
|
||||
|
||||
#region Properties
|
||||
public DateTime LastUpdate { get; private set; }
|
||||
public Boolean Polling { get; set; }
|
||||
public Boolean PollOnce { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public AConnector(HttpConnection http, Boolean polling) {
|
||||
this.http = http;
|
||||
this.Polling = polling;
|
||||
this.LastUpdate = DateTime.Now;
|
||||
}
|
||||
|
||||
internal static Object CreateInstance(Type type, JsonData json, Tuple<Int32> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||
return type.GetMethod("CreateInstanceConcrete", new Type[] { typeof(JsonData), typeof(Tuple<Int32>), typeof(HttpConnection), typeof(Boolean), typeof(ReadOnlyDictionary<Int32, ALight>) }).Invoke(null, new Object[] { json, id, http, polling, lights });
|
||||
}
|
||||
|
||||
internal static Object CreateInstance(Type type, JsonData json, Tuple<Int32> id, HttpConnection http, Boolean polling) {
|
||||
return type.GetMethod("CreateInstanceConcrete", new Type[] { typeof(JsonData), typeof(Tuple<Int32>), typeof(HttpConnection), typeof(Boolean) }).Invoke(null, new Object[] { json, id, http, polling });
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected Boolean PutDictionary(String address, Dictionary<String, Object> value) {
|
||||
JsonData json = this.http.PutJson(address, JsonMapper.ToJson(value));
|
||||
if (json.IsArray) {
|
||||
return json[0].ContainsKey("success");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual Dictionary<String, Object> ToDictionary() {
|
||||
Dictionary<String, Object> dictionary = new Dictionary<String, Object>();
|
||||
foreach (PropertyInfo item in this.GetType().GetProperties()) {
|
||||
if (item.CanRead && item.GetValue(this) != null) {
|
||||
if (item.GetValue(this).GetType().GetMethod("ToDictionary") != null) {
|
||||
dictionary.Add(item.Name, item.GetValue(this).GetType().GetMethod("ToDictionary").Invoke(item.GetValue(this), null));
|
||||
} else if (Helper.HasInterface(item.GetValue(this).GetType(), "IDictionary")) {
|
||||
Dictionary<String, Object> subdict = new Dictionary<String, Object>();
|
||||
foreach (DictionaryEntry subitem in (IDictionary)item.GetValue(this)) {
|
||||
if (subitem.Value.GetType().GetMethod("ToDictionary") != null) {
|
||||
subdict.Add(subitem.Key.ToString(), subitem.Value.GetType().GetMethod("ToDictionary").Invoke(subitem.Value, null));
|
||||
}
|
||||
}
|
||||
dictionary.Add(item.Name, subdict);
|
||||
} else if (item.GetValue(this).GetType().BaseType == typeof(Enum)) {
|
||||
dictionary.Add(item.Name, Helper.GetEnumDescription((Enum)item.GetValue(this)));
|
||||
} else {
|
||||
dictionary.Add(item.Name, item.GetValue(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
protected void NotifyClient<T>(Object value) {
|
||||
this.LastUpdate = DateTime.Now;
|
||||
this.Update?.Invoke(this, (AllUpdateEvent)Activator.CreateInstance(typeof(T), new Object[] { value, this.LastUpdate, this }));
|
||||
}
|
||||
|
||||
protected void NotifyClientChildren(Object sender, AllUpdateEvent e) {
|
||||
this.Update?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
#region Abstracts
|
||||
public abstract override String ToString();
|
||||
public abstract void SetUpdate(JsonData json);
|
||||
#endregion
|
||||
}
|
||||
}
|
183
Hue/Hue/Interfaces/AGroup.cs
Normal file
183
Hue/Hue/Interfaces/AGroup.cs
Normal file
@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Interfaces {
|
||||
public abstract class AGroup : AConnector, IMqtt {
|
||||
protected String _name;
|
||||
protected GroupClass _class;
|
||||
|
||||
public enum GroupClass {
|
||||
[Description("Living room")]
|
||||
Livingroom,
|
||||
Kitchen,
|
||||
Dining,
|
||||
Bedroom,
|
||||
[Description("Kids bedroom")]
|
||||
Kidsbedroom,
|
||||
Bathroom,
|
||||
Nursery,
|
||||
Recreation,
|
||||
Office,
|
||||
Gym,
|
||||
Hallway,
|
||||
Toilet,
|
||||
[Description("Front door")]
|
||||
Frontdoor,
|
||||
Garage,
|
||||
Terrace,
|
||||
Garden,
|
||||
Driveway,
|
||||
Carport,
|
||||
Other
|
||||
}
|
||||
public enum Types {
|
||||
Room
|
||||
}
|
||||
public enum TypesIgnore {
|
||||
Luminaire,
|
||||
Lightsource,
|
||||
LightGroup,
|
||||
Entertainment
|
||||
}
|
||||
|
||||
#region Properties
|
||||
public String Name { get {
|
||||
return this._name;
|
||||
} set {
|
||||
if(this.SetGroupAttribute(new Dictionary<String, Object>() { { "name", value } })) {
|
||||
this._name = value;
|
||||
this.NotifyClient<GroupUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Int32 GroupId { get; }
|
||||
public Types Groupclass { get; }
|
||||
public Boolean StateAnyOn { get; protected set; }
|
||||
public Boolean StateAllOn { get; protected set; }
|
||||
public ReadOnlyDictionary<Int32, ALight> Lights { get; protected set; }
|
||||
public GroupClass Class {
|
||||
get {
|
||||
return this._class;
|
||||
}
|
||||
set {
|
||||
if(this.SetGroupAttribute(new Dictionary<String, Object>() { { "class", Helper.GetEnumDescription(value) } })) {
|
||||
this._class = value;
|
||||
this.NotifyClient<GroupUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
protected AGroup(JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) : base(http, polling) {
|
||||
this.GroupId = id.Item1;
|
||||
this.Groupclass = id.Item2;
|
||||
this.ComplexInit(json, lights);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||
if (json.ContainsKey("lights") && json["lights"].IsArray) {
|
||||
Dictionary<Int32, ALight> lightdict = new Dictionary<Int32, ALight>();
|
||||
foreach (JsonData item in json["lights"]) {
|
||||
if (Int32.TryParse(item.ToString(), out Int32 lampid)) {
|
||||
if (lights.ContainsKey(lampid)) {
|
||||
lightdict.Add(lampid, lights[lampid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Lights = new ReadOnlyDictionary<Int32, ALight>(lightdict);
|
||||
}
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
this._name = json["name"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("any_on") && json["state"]["any_on"].IsBoolean) {
|
||||
this.StateAnyOn = (Boolean)json["state"]["any_on"];
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("all_on") && json["state"]["all_on"].IsBoolean) {
|
||||
this.StateAllOn = (Boolean)json["state"]["all_on"];
|
||||
}
|
||||
if (json.ContainsKey("class") && json["class"].IsString) {
|
||||
this._class = (GroupClass)Enum.Parse(typeof(GroupClass), json["class"].ToString().ToEnumString());
|
||||
}
|
||||
}
|
||||
|
||||
public static AGroup CreateInstanceConcrete(JsonData json, Tuple<Int32> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||
String type = "";
|
||||
if (json.ContainsKey("type")) {
|
||||
type = json["type"].ToString().ToEnumString();
|
||||
}
|
||||
if (type != "" && !Enum.IsDefined(typeof(TypesIgnore), type) && Enum.IsDefined(typeof(Types), type)) {
|
||||
String name = "BlubbFish.IoT.Hue.Devices.Groups." + type;
|
||||
return GetInstanceConcrete(name, json, new Tuple<Int32, Types>(id.Item1, (Types)Enum.Parse(typeof(Types), type)), http, polling, lights);
|
||||
}
|
||||
if (!Enum.IsDefined(typeof(TypesIgnore), type) && !Enum.IsDefined(typeof(Types), type)) {
|
||||
Helper.WriteError("Lightclass " + type + " not exist.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static AGroup GetInstanceConcrete(String name, JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||
Type t = null;
|
||||
try {
|
||||
t = Type.GetType(name, true);
|
||||
} catch (TypeLoadException) {
|
||||
Helper.WriteError("Konnte Type " + name + " nicht laden!");
|
||||
return null;
|
||||
}
|
||||
return (AGroup)t.GetConstructor(new Type[] { typeof(JsonData), typeof(Tuple<Int32, Types>), typeof(HttpConnection), typeof(Boolean), typeof(ReadOnlyDictionary<Int32, ALight>) }).Invoke(new Object[] { json, id, http, polling, lights });
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected Boolean SetGroupAttribute(Dictionary<String, Object> value) {
|
||||
return this.PutDictionary("groups/" + this.GroupId, value);
|
||||
}
|
||||
|
||||
protected Boolean SetGroupAction(Dictionary<String, Object> value) {
|
||||
return this.PutDictionary("groups/" + this.GroupId + "/action", value);
|
||||
}
|
||||
|
||||
#region AConnector
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
if (this.Name != json["name"].ToString()) {
|
||||
this._name = json["name"].ToString();
|
||||
this.NotifyClient<GroupUpdateEvent>(this.Name);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("any_on") && json["state"]["any_on"].IsBoolean) {
|
||||
if (this.StateAnyOn != (Boolean)json["state"]["any_on"]) {
|
||||
this.StateAnyOn = (Boolean)json["state"]["any_on"];
|
||||
this.NotifyClient<GroupUpdateEvent>(this.StateAnyOn);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("all_on") && json["state"]["all_on"].IsBoolean) {
|
||||
if (this.StateAllOn != (Boolean)json["state"]["all_on"]) {
|
||||
this.StateAllOn = (Boolean)json["state"]["all_on"];
|
||||
this.NotifyClient<GroupUpdateEvent>(this.StateAllOn);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("class") && json["class"].IsString) {
|
||||
if (this.Class != (GroupClass)Enum.Parse(typeof(GroupClass), json["class"].ToString().ToEnumString())) {
|
||||
this._class = (GroupClass)Enum.Parse(typeof(GroupClass), json["class"].ToString().ToEnumString());
|
||||
this.NotifyClient<GroupUpdateEvent>(this.Class);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IMqtt
|
||||
public String ToJson() {
|
||||
return JsonMapper.ToJson(this.ToDictionary());
|
||||
}
|
||||
|
||||
public String MqttTopic() {
|
||||
return "group/" + this.GroupId;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
101
Hue/Hue/Interfaces/ALight.cs
Normal file
101
Hue/Hue/Interfaces/ALight.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Interfaces {
|
||||
public abstract class ALight : AConnector, IMqtt {
|
||||
public enum Types {
|
||||
Dimmablelight
|
||||
}
|
||||
public enum TypesIgnore {
|
||||
Colorlight,
|
||||
Extendedcolorlight
|
||||
}
|
||||
|
||||
#region Properties
|
||||
public Int32 LightId { get; }
|
||||
public Types Lightclass { get; }
|
||||
private String _name;
|
||||
public String Name {
|
||||
get {
|
||||
return this._name;
|
||||
}
|
||||
set {
|
||||
if (this.SetLightAttribute(new Dictionary<String, Object>() { { "name", value } })) {
|
||||
this._name = value;
|
||||
this.NotifyClient<LightUpdateEvent>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
protected ALight(JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling): base(http, polling) {
|
||||
this.LightId = id.Item1;
|
||||
this.Lightclass = id.Item2;
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
private void ComplexInit(JsonData json) {
|
||||
if (json.ContainsKey("name")) {
|
||||
this._name = json["name"].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static ALight CreateInstanceConcrete(JsonData json, Tuple<Int32> id, HttpConnection http, Boolean polling) {
|
||||
String type = "";
|
||||
if (json.ContainsKey("type")) {
|
||||
type = json["type"].ToString().ToEnumString();
|
||||
}
|
||||
if (type != "" && !Enum.IsDefined(typeof(TypesIgnore), type) && Enum.IsDefined(typeof(Types), type)) {
|
||||
String name = "BlubbFish.IoT.Hue.Devices.Lights." + type;
|
||||
return GetInstanceConcrete(name, json, new Tuple<Int32, Types>(id.Item1, (Types)Enum.Parse(typeof(Types), type)), http, polling);
|
||||
}
|
||||
if(!Enum.IsDefined(typeof(TypesIgnore), type) && !Enum.IsDefined(typeof(Types), type)) {
|
||||
Helper.WriteError("Lightclass " + type + " not exist.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ALight GetInstanceConcrete(String name, JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling) {
|
||||
Type t = null;
|
||||
try {
|
||||
t = Type.GetType(name, true);
|
||||
} catch (TypeLoadException) {
|
||||
Helper.WriteError("Konnte Type " + name + " nicht laden!");
|
||||
return null;
|
||||
}
|
||||
return (ALight)t.GetConstructor(new Type[] { typeof(JsonData), typeof(Tuple<Int32, Types>), typeof(HttpConnection), typeof(Boolean) }).Invoke(new Object[] { json, id, http, polling });
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected Boolean SetLightStateAttribute(Dictionary<String, Object> value) {
|
||||
return this.PutDictionary("lights/" + this.LightId + "/state", value);
|
||||
}
|
||||
protected Boolean SetLightAttribute(Dictionary<String, Object> value) {
|
||||
return this.PutDictionary("lights/" + this.LightId, value);
|
||||
}
|
||||
|
||||
#region IMqtt
|
||||
public String MqttTopic() {
|
||||
return "light/" + this.LightId;
|
||||
}
|
||||
|
||||
public String ToJson() {
|
||||
return JsonMapper.ToJson(this.ToDictionary());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AConnector
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if(json.ContainsKey("name") && json["name"].IsString) {
|
||||
if(this.Name != json["name"].ToString()) {
|
||||
this._name = json["name"].ToString();
|
||||
this.NotifyClient<LightUpdateEvent>(this.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
43
Hue/Hue/Interfaces/AScene.cs
Normal file
43
Hue/Hue/Interfaces/AScene.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using BlubbFish.IoT.Hue.Devices.Scenes;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Interfaces {
|
||||
public abstract class AScene : AConnector, IMqtt {
|
||||
#region Properties
|
||||
public String SceneId { get; }
|
||||
public Int32 LightStateId { get; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
protected AScene(JsonData json, Tuple<String, Int32> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) : base(http, polling) {
|
||||
this.SceneId = id.Item1;
|
||||
this.LightStateId = id.Item2;
|
||||
}
|
||||
|
||||
public static AScene CreateInstanceConcrete(JsonData json, Tuple<String> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||
return new Scene(http.GetJson("scenes/" + id.Item1), id, http, polling, lights);
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected Boolean SetSceneAttribute(Dictionary<String, Object> dictionary) {
|
||||
return this.PutDictionary("scenes/" + this.SceneId, dictionary);
|
||||
}
|
||||
protected Boolean SetLightSceneAttribute(Dictionary<String, Object> value) {
|
||||
return this.PutDictionary("scenes/" + this.SceneId + "/lights/" + this.LightStateId + "/state", value);
|
||||
}
|
||||
|
||||
#region IMqtt
|
||||
public String ToJson() {
|
||||
return JsonMapper.ToJson(this.ToDictionary());
|
||||
}
|
||||
|
||||
public String MqttTopic() {
|
||||
return "scene/" + this.SceneId;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
125
Hue/Hue/Interfaces/ASensor.cs
Normal file
125
Hue/Hue/Interfaces/ASensor.cs
Normal file
@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BlubbFish.IoT.Hue.Events;
|
||||
using BlubbFish.IoT.Hue.lib;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Interfaces {
|
||||
public abstract class ASensor : AConnector, IMqtt {
|
||||
public enum Types {
|
||||
Daylight
|
||||
}
|
||||
public enum TypesIgnore {
|
||||
Zgpswitch,
|
||||
Zllswitch,
|
||||
Zllpresence,
|
||||
Zlltemperature,
|
||||
Clipswitch,
|
||||
Clipopenclose,
|
||||
Clippresence,
|
||||
Cliptemperature,
|
||||
Cliphumidity,
|
||||
Cliplightlevel,
|
||||
Zlllightlevel,
|
||||
Clipgenericflag,
|
||||
Clipgenericstatus
|
||||
}
|
||||
|
||||
#region Properties
|
||||
public Int32 SensorId { get; }
|
||||
public Types Sensorclass { get; }
|
||||
public DateTime Lastupdated { get; protected set; }
|
||||
private String _name;
|
||||
public String Name {
|
||||
get {
|
||||
return this._name;
|
||||
}
|
||||
set {
|
||||
this._name = value;
|
||||
this.SetSensorAttribute(new Dictionary<String, Object>() { { "name", value } });
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
protected ASensor(JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling) : base(http, polling) {
|
||||
this.SensorId = id.Item1;
|
||||
this.Sensorclass = id.Item2;
|
||||
this.ComplexInit(json);
|
||||
}
|
||||
|
||||
private void ComplexInit(JsonData json) {
|
||||
if (json.ContainsKey("name")) {
|
||||
this._name = json["name"].ToString();
|
||||
}
|
||||
if (json.ContainsKey("state")) {
|
||||
JsonData state = json["state"];
|
||||
if (state.ContainsKey("lastupdated") && state["lastupdated"].IsString) {
|
||||
this.Lastupdated = DateTime.Parse(state["lastupdated"].ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ASensor CreateInstanceConcrete(JsonData json, Tuple<Int32> id, HttpConnection http, Boolean polling) {
|
||||
String type = "";
|
||||
if (json.ContainsKey("type")) {
|
||||
type = json["type"].ToString().ToEnumString();
|
||||
}
|
||||
if (type != "" && !Enum.IsDefined(typeof(TypesIgnore), type) && Enum.IsDefined(typeof(Types), type)) {
|
||||
String name = "BlubbFish.IoT.Hue.Devices.Sensors." + type;
|
||||
return GetInstanceConcrete(name, json, new Tuple<Int32, Types>(id.Item1, (Types)Enum.Parse(typeof(Types), type)), http, polling);
|
||||
}
|
||||
if (!Enum.IsDefined(typeof(TypesIgnore), type) && !Enum.IsDefined(typeof(Types), type)) {
|
||||
Helper.WriteError("Sensorclass " + type + " not exist.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ASensor GetInstanceConcrete(String name, JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling) {
|
||||
Type t = null;
|
||||
try {
|
||||
t = Type.GetType(name, true);
|
||||
} catch (TypeLoadException) {
|
||||
Helper.WriteError("Konnte Type " + name + " nicht laden!");
|
||||
return null;
|
||||
}
|
||||
return (ASensor)t.GetConstructor(new Type[] { typeof(JsonData), typeof(Tuple<Int32, Types>), typeof(HttpConnection), typeof(Boolean) }).Invoke(new Object[] { json, id, http, polling });
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected void SetSensorAttribute(Dictionary<String, Object> dictionary) {
|
||||
this.PutDictionary("sensors/" + this.SensorId, dictionary);
|
||||
}
|
||||
|
||||
protected Boolean SetSensorConfig(Dictionary<String, Object> dictionary) {
|
||||
return this.PutDictionary("sensors/" + this.SensorId + "/config", dictionary);
|
||||
}
|
||||
|
||||
#region AConnector
|
||||
public override void SetUpdate(JsonData json) {
|
||||
if (json.ContainsKey("name") && json["name"].IsString) {
|
||||
if (this.Name != json["name"].ToString()) {
|
||||
this._name = json["name"].ToString();
|
||||
this.NotifyClient<SensorUpdateEvent>(this.Name);
|
||||
}
|
||||
}
|
||||
if (json.ContainsKey("state") && json["state"].ContainsKey("lastupdated") && json["state"]["lastupdated"].IsString) {
|
||||
if (this.Lastupdated != DateTime.Parse(json["state"]["lastupdated"].ToString())) {
|
||||
this.Lastupdated = DateTime.Parse(json["state"]["lastupdated"].ToString());
|
||||
this.NotifyClient<SensorUpdateEvent>(this.Lastupdated);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IMqtt
|
||||
public String MqttTopic() {
|
||||
return "sensor/" + this.SensorId;
|
||||
}
|
||||
|
||||
public String ToJson() {
|
||||
return JsonMapper.ToJson(this.ToDictionary());
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
20
Hue/Hue/Interfaces/IMqtt.cs
Normal file
20
Hue/Hue/Interfaces/IMqtt.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.Interfaces {
|
||||
public interface IMqtt {
|
||||
/// <summary>
|
||||
/// Gibt einen JSON-String der Eigenschaften eines Objekts zurück
|
||||
/// </summary>
|
||||
/// <returns>JSON-String</returns>
|
||||
String ToJson();
|
||||
/// <summary>
|
||||
/// Gibt das MQTT-Topic als String zurück unter dem die Daten des Objekts Publiziert werden sollen
|
||||
/// </summary>
|
||||
/// <returns>MQTT-Topic</returns>
|
||||
String MqttTopic();
|
||||
}
|
||||
}
|
36
Hue/Hue/Properties/AssemblyInfo.cs
Normal file
36
Hue/Hue/Properties/AssemblyInfo.cs
Normal file
@ -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("Hue")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Hue")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[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("738a6137-8fca-4ce1-bd1c-042b21b6b5f2")]
|
||||
|
||||
// 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")]
|
BIN
Hue/Hue/bin/Release/Hue.dll
Normal file
BIN
Hue/Hue/bin/Release/Hue.dll
Normal file
Binary file not shown.
BIN
Hue/Hue/bin/Release/litjson.dll
Normal file
BIN
Hue/Hue/bin/Release/litjson.dll
Normal file
Binary file not shown.
67
Hue/Hue/lib/Helper.cs
Normal file
67
Hue/Hue/lib/Helper.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.lib {
|
||||
class Helper {
|
||||
internal static void WriteError(String text) {
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.Error.WriteLine("ERROR: " + text);
|
||||
Console.ResetColor();
|
||||
}
|
||||
public static String GetEnumDescription(Enum value) {
|
||||
FieldInfo fi = value.GetType().GetField(value.ToString());
|
||||
|
||||
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
|
||||
if (attributes != null && attributes.Length > 0) {
|
||||
return attributes[0].Description;
|
||||
} else {
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
internal static Boolean HasInterface(Type o, String type) {
|
||||
foreach (Type item in o.GetInterfaces()) {
|
||||
if (item.Name == type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SetUpdate<T>(ReadOnlyDictionary<Int32, T> list, JsonData json, String key) {
|
||||
if (json.ContainsKey(key)) {
|
||||
foreach (String item in json[key].Keys) {
|
||||
if (list.ContainsKey(Int32.Parse(item))) {
|
||||
list[Int32.Parse(item)].GetType().GetMethod("SetUpdate").Invoke(list[Int32.Parse(item)], new Object[] { json[key][item] });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetUpdate<T>(ReadOnlyDictionary<String, T> list, JsonData json, String key) {
|
||||
if (json.ContainsKey(key)) {
|
||||
foreach (String item in json[key].Keys) {
|
||||
if (list.ContainsKey(item)) {
|
||||
list[item].GetType().GetMethod("SetUpdate").Invoke(list[item], new Object[] { json[key][item] });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static class StringHelper {
|
||||
public static String ToEnumString(this String text) {
|
||||
if(text.Length == 0) {
|
||||
return text;
|
||||
}
|
||||
if(text.Length == 1) {
|
||||
return text.ToUpper();
|
||||
}
|
||||
text = text.Replace(" ", "");
|
||||
text = text.ToLower();
|
||||
return text[0].ToString().ToUpper() + text.Substring(1);
|
||||
}
|
||||
}
|
||||
}
|
96
Hue/Hue/lib/HttpClient.cs
Normal file
96
Hue/Hue/lib/HttpClient.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using LitJson;
|
||||
|
||||
namespace BlubbFish.IoT.Hue.lib {
|
||||
public class HttpConnection {
|
||||
private String server;
|
||||
private Object getLock = new Object();
|
||||
private enum RequestMethod {
|
||||
GET,
|
||||
POST,
|
||||
PUT
|
||||
}
|
||||
|
||||
public HttpConnection(String server) {
|
||||
this.server = "http://" + server + "/api/";
|
||||
this.Init(false);
|
||||
}
|
||||
|
||||
public HttpConnection(String server, String key) {
|
||||
this.server = "http://" + server + "/api/" + key + "/";
|
||||
this.Init(true);
|
||||
}
|
||||
|
||||
private void Init(Boolean withuser = true) {
|
||||
this.RequestString("config", "", false);
|
||||
if(withuser) {
|
||||
String i = this.RequestString("", "", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal JsonData PostJson(String address, String json) {
|
||||
return this.ToJson(this.RequestString(address, json, true, RequestMethod.POST));
|
||||
}
|
||||
|
||||
internal JsonData PutJson(String address, String json) {
|
||||
return this.ToJson(this.RequestString(address, json, true, RequestMethod.PUT));
|
||||
}
|
||||
|
||||
internal JsonData GetJson(String address) {
|
||||
return this.ToJson(this.RequestString(address));
|
||||
}
|
||||
|
||||
private JsonData ToJson(String text) {
|
||||
if (text == null) {
|
||||
return new JsonData();
|
||||
}
|
||||
try {
|
||||
return JsonMapper.ToObject(text);
|
||||
} catch (Exception) {
|
||||
return new JsonData();
|
||||
}
|
||||
}
|
||||
|
||||
private String RequestString(String address, String json = "", Boolean withoutput = true, RequestMethod method = RequestMethod.GET) {
|
||||
String ret = null;
|
||||
lock (this.getLock) {
|
||||
HttpWebRequest request = WebRequest.CreateHttp(this.server + address);
|
||||
request.Timeout = 5000;
|
||||
if(method == RequestMethod.POST || method == RequestMethod.PUT) {
|
||||
Byte[] requestdata = Encoding.ASCII.GetBytes(json);
|
||||
request.ContentLength = requestdata.Length;
|
||||
request.Method = method.ToString();
|
||||
request.ContentType = "application/x-www-form-urlencoded";
|
||||
using (Stream stream = request.GetRequestStream()) {
|
||||
stream.Write(requestdata, 0, requestdata.Length);
|
||||
}
|
||||
}
|
||||
try {
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized) {
|
||||
Console.Error.WriteLine("Benutzer oder Passwort falsch!");
|
||||
throw new Exceptions.ConnectionException("Benutzer oder Passwort falsch!");
|
||||
}
|
||||
if (withoutput) {
|
||||
StreamReader reader = new StreamReader(response.GetResponseStream());
|
||||
ret = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Helper.WriteError("Konnte keine Verbindung zum Razzbery Server herstellen. Resource: \"" + this.server + address + "\" Fehler: " + e.Message);
|
||||
return null;
|
||||
//throw new Exceptions.ConnectionException("Konnte keine Verbindung zum Razzbery Server herstellen: " + e.Message);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
25
Librarys/litjson/litjson.sln
Normal file
25
Librarys/litjson/litjson.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
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}") = "litjson_4.7.1", "litjson\litjson_4.7.1.csproj", "{91A14CD2-2940-4500-8193-56D37EDDDBAA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {AF2398AC-1EAA-4615-B21A-33C68CD44849}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
60
Librarys/litjson/litjson/IJsonWrapper.cs
Normal file
60
Librarys/litjson/litjson/IJsonWrapper.cs
Normal file
@ -0,0 +1,60 @@
|
||||
#region Header
|
||||
/**
|
||||
* IJsonWrapper.cs
|
||||
* Interface that represents a type capable of handling all kinds of JSON
|
||||
* data. This is mainly used when mapping objects through JsonMapper, and
|
||||
* it's implemented by JsonData.
|
||||
*
|
||||
* The authors disclaim copyright to this source code. For more details, see
|
||||
* the COPYING file included with this distribution.
|
||||
**/
|
||||
#endregion
|
||||
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
|
||||
namespace LitJson
|
||||
{
|
||||
public enum JsonType
|
||||
{
|
||||
None,
|
||||
|
||||
Object,
|
||||
Array,
|
||||
String,
|
||||
Int,
|
||||
Long,
|
||||
Double,
|
||||
Boolean
|
||||
}
|
||||
|
||||
public interface IJsonWrapper : IList, IOrderedDictionary
|
||||
{
|
||||
bool IsArray { get; }
|
||||
bool IsBoolean { get; }
|
||||
bool IsDouble { get; }
|
||||
bool IsInt { get; }
|
||||
bool IsLong { get; }
|
||||
bool IsObject { get; }
|
||||
bool IsString { get; }
|
||||
|
||||
bool GetBoolean ();
|
||||
double GetDouble ();
|
||||
int GetInt ();
|
||||
JsonType GetJsonType ();
|
||||
long GetLong ();
|
||||
string GetString ();
|
||||
|
||||
void SetBoolean (bool val);
|
||||
void SetDouble (double val);
|
||||
void SetInt (int val);
|
||||
void SetJsonType (JsonType type);
|
||||
void SetLong (long val);
|
||||
void SetString (string val);
|
||||
|
||||
string ToJson ();
|
||||
void ToJson (JsonWriter writer);
|
||||
}
|
||||
}
|
1012
Librarys/litjson/litjson/JsonData.cs
Normal file
1012
Librarys/litjson/litjson/JsonData.cs
Normal file
File diff suppressed because it is too large
Load Diff
65
Librarys/litjson/litjson/JsonException.cs
Normal file
65
Librarys/litjson/litjson/JsonException.cs
Normal file
@ -0,0 +1,65 @@
|
||||
#region Header
|
||||
/**
|
||||
* JsonException.cs
|
||||
* Base class throwed by LitJSON when a parsing error occurs.
|
||||
*
|
||||
* The authors disclaim copyright to this source code. For more details, see
|
||||
* the COPYING file included with this distribution.
|
||||
**/
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
|
||||
namespace LitJson
|
||||
{
|
||||
public class JsonException :
|
||||
#if NETSTANDARD1_5
|
||||
Exception
|
||||
#else
|
||||
ApplicationException
|
||||
#endif
|
||||
{
|
||||
public JsonException () : base ()
|
||||
{
|
||||
}
|
||||
|
||||
internal JsonException (ParserToken token) :
|
||||
base (String.Format (
|
||||
"Invalid token '{0}' in input string", token))
|
||||
{
|
||||
}
|
||||
|
||||
internal JsonException (ParserToken token,
|
||||
Exception inner_exception) :
|
||||
base (String.Format (
|
||||
"Invalid token '{0}' in input string", token),
|
||||
inner_exception)
|
||||
{
|
||||
}
|
||||
|
||||
internal JsonException (int c) :
|
||||
base (String.Format (
|
||||
"Invalid character '{0}' in input string", (char) c))
|
||||
{
|
||||
}
|
||||
|
||||
internal JsonException (int c, Exception inner_exception) :
|
||||
base (String.Format (
|
||||
"Invalid character '{0}' in input string", (char) c),
|
||||
inner_exception)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public JsonException (string message) : base (message)
|
||||
{
|
||||
}
|
||||
|
||||
public JsonException (string message, Exception inner_exception) :
|
||||
base (message, inner_exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
944
Librarys/litjson/litjson/JsonMapper.cs
Normal file
944
Librarys/litjson/litjson/JsonMapper.cs
Normal file
@ -0,0 +1,944 @@
|
||||
#region Header
|
||||
/**
|
||||
* JsonMapper.cs
|
||||
* JSON to .Net object and object to JSON conversions.
|
||||
*
|
||||
* The authors disclaim copyright to this source code. For more details, see
|
||||
* the COPYING file included with this distribution.
|
||||
**/
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace LitJson
|
||||
{
|
||||
internal struct PropertyMetadata
|
||||
{
|
||||
public MemberInfo Info;
|
||||
public bool IsField;
|
||||
public Type Type;
|
||||
}
|
||||
|
||||
|
||||
internal struct ArrayMetadata
|
||||
{
|
||||
private Type element_type;
|
||||
private bool is_array;
|
||||
private bool is_list;
|
||||
|
||||
|
||||
public Type ElementType {
|
||||
get {
|
||||
if (element_type == null)
|
||||
return typeof (JsonData);
|
||||
|
||||
return element_type;
|
||||
}
|
||||
|
||||
set { element_type = value; }
|
||||
}
|
||||
|
||||
public bool IsArray {
|
||||
get { return is_array; }
|
||||
set { is_array = value; }
|
||||
}
|
||||
|
||||
public bool IsList {
|
||||
get { return is_list; }
|
||||
set { is_list = value; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal struct ObjectMetadata
|
||||
{
|
||||
private Type element_type;
|
||||
private bool is_dictionary;
|
||||
|
||||
private IDictionary<string, PropertyMetadata> properties;
|
||||
|
||||
|
||||
public Type ElementType {
|
||||
get {
|
||||
if (element_type == null)
|
||||
return typeof (JsonData);
|
||||
|
||||
return element_type;
|
||||
}
|
||||
|
||||
set { element_type = value; }
|
||||
}
|
||||
|
||||
public bool IsDictionary {
|
||||
get { return is_dictionary; }
|
||||
set { is_dictionary = value; }
|
||||
}
|
||||
|
||||
public IDictionary<string, PropertyMetadata> Properties {
|
||||
get { return properties; }
|
||||
set { properties = value; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal delegate void ExporterFunc (object obj, JsonWriter writer);
|
||||
public delegate void ExporterFunc<T> (T obj, JsonWriter writer);
|
||||
|
||||
internal delegate object ImporterFunc (object input);
|
||||
public delegate TValue ImporterFunc<TJson, TValue> (TJson input);
|
||||
|
||||
public delegate IJsonWrapper WrapperFactory ();
|
||||
|
||||
|
||||
public class JsonMapper
|
||||
{
|
||||
#region Fields
|
||||
private static readonly int max_nesting_depth;
|
||||
|
||||
private static readonly IFormatProvider datetime_format;
|
||||
|
||||
private static readonly IDictionary<Type, ExporterFunc> base_exporters_table;
|
||||
private static readonly IDictionary<Type, ExporterFunc> custom_exporters_table;
|
||||
|
||||
private static readonly IDictionary<Type,
|
||||
IDictionary<Type, ImporterFunc>> base_importers_table;
|
||||
private static readonly IDictionary<Type,
|
||||
IDictionary<Type, ImporterFunc>> custom_importers_table;
|
||||
|
||||
private static readonly IDictionary<Type, ArrayMetadata> array_metadata;
|
||||
private static readonly object array_metadata_lock = new Object ();
|
||||
|
||||
private static readonly IDictionary<Type,
|
||||
IDictionary<Type, MethodInfo>> conv_ops;
|
||||
private static readonly object conv_ops_lock = new Object ();
|
||||
|
||||
private static readonly IDictionary<Type, ObjectMetadata> object_metadata;
|
||||
private static readonly object object_metadata_lock = new Object ();
|
||||
|
||||
private static readonly IDictionary<Type,
|
||||
IList<PropertyMetadata>> type_properties;
|
||||
private static readonly object type_properties_lock = new Object ();
|
||||
|
||||
private static readonly JsonWriter static_writer;
|
||||
private static readonly object static_writer_lock = new Object ();
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
static JsonMapper ()
|
||||
{
|
||||
max_nesting_depth = 100;
|
||||
|
||||
array_metadata = new Dictionary<Type, ArrayMetadata> ();
|
||||
conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>> ();
|
||||
object_metadata = new Dictionary<Type, ObjectMetadata> ();
|
||||
type_properties = new Dictionary<Type,
|
||||
IList<PropertyMetadata>> ();
|
||||
|
||||
static_writer = new JsonWriter ();
|
||||
|
||||
datetime_format = DateTimeFormatInfo.InvariantInfo;
|
||||
|
||||
base_exporters_table = new Dictionary<Type, ExporterFunc> ();
|
||||
custom_exporters_table = new Dictionary<Type, ExporterFunc> ();
|
||||
|
||||
base_importers_table = new Dictionary<Type,
|
||||
IDictionary<Type, ImporterFunc>> ();
|
||||
custom_importers_table = new Dictionary<Type,
|
||||
IDictionary<Type, ImporterFunc>> ();
|
||||
|
||||
RegisterBaseExporters ();
|
||||
RegisterBaseImporters ();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Methods
|
||||
private static void AddArrayMetadata (Type type)
|
||||
{
|
||||
if (array_metadata.ContainsKey (type))
|
||||
return;
|
||||
|
||||
ArrayMetadata data = new ArrayMetadata ();
|
||||
|
||||
data.IsArray = type.IsArray;
|
||||
|
||||
if (type.GetInterface ("System.Collections.IList") != null)
|
||||
data.IsList = true;
|
||||
|
||||
foreach (PropertyInfo p_info in type.GetProperties ()) {
|
||||
if (p_info.Name != "Item")
|
||||
continue;
|
||||
|
||||
ParameterInfo[] parameters = p_info.GetIndexParameters ();
|
||||
|
||||
if (parameters.Length != 1)
|
||||
continue;
|
||||
|
||||
if (parameters[0].ParameterType == typeof (int))
|
||||
data.ElementType = p_info.PropertyType;
|
||||
}
|
||||
|
||||
lock (array_metadata_lock) {
|
||||
try {
|
||||
array_metadata.Add (type, data);
|
||||
} catch (ArgumentException) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddObjectMetadata (Type type)
|
||||
{
|
||||
if (object_metadata.ContainsKey (type))
|
||||
return;
|
||||
|
||||
ObjectMetadata data = new ObjectMetadata ();
|
||||
|
||||
if (type.GetInterface ("System.Collections.IDictionary") != null)
|
||||
data.IsDictionary = true;
|
||||
|
||||
data.Properties = new Dictionary<string, PropertyMetadata> ();
|
||||
|
||||
foreach (PropertyInfo p_info in type.GetProperties ()) {
|
||||
if (p_info.Name == "Item") {
|
||||
ParameterInfo[] parameters = p_info.GetIndexParameters ();
|
||||
|
||||
if (parameters.Length != 1)
|
||||
continue;
|
||||
|
||||
if (parameters[0].ParameterType == typeof (string))
|
||||
data.ElementType = p_info.PropertyType;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
PropertyMetadata p_data = new PropertyMetadata ();
|
||||
p_data.Info = p_info;
|
||||
p_data.Type = p_info.PropertyType;
|
||||
|
||||
data.Properties.Add (p_info.Name, p_data);
|
||||
}
|
||||
|
||||
foreach (FieldInfo f_info in type.GetFields ()) {
|
||||
PropertyMetadata p_data = new PropertyMetadata ();
|
||||
p_data.Info = f_info;
|
||||
p_data.IsField = true;
|
||||
p_data.Type = f_info.FieldType;
|
||||
|
||||
data.Properties.Add (f_info.Name, p_data);
|
||||
}
|
||||
|
||||
lock (object_metadata_lock) {
|
||||
try {
|
||||
object_metadata.Add (type, data);
|
||||
} catch (ArgumentException) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddTypeProperties (Type type)
|
||||
{
|
||||
if (type_properties.ContainsKey (type))
|
||||
return;
|
||||
|
||||
IList<PropertyMetadata> props = new List<PropertyMetadata> ();
|
||||
|
||||
foreach (PropertyInfo p_info in type.GetProperties ()) {
|
||||
if (p_info.Name == "Item")
|
||||
continue;
|
||||
|
||||
PropertyMetadata p_data = new PropertyMetadata ();
|
||||
p_data.Info = p_info;
|
||||
p_data.IsField = false;
|
||||
props.Add (p_data);
|
||||
}
|
||||
|
||||
foreach (FieldInfo f_info in type.GetFields ()) {
|
||||
PropertyMetadata p_data = new PropertyMetadata ();
|
||||
p_data.Info = f_info;
|
||||
p_data.IsField = true;
|
||||
|
||||
props.Add (p_data);
|
||||
}
|
||||
|
||||
lock (type_properties_lock) {
|
||||
try {
|
||||
type_properties.Add (type, props);
|
||||
} catch (ArgumentException) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodInfo GetConvOp (Type t1, Type t2)
|
||||
{
|
||||
lock (conv_ops_lock) {
|
||||
if (! conv_ops.ContainsKey (t1))
|
||||
conv_ops.Add (t1, new Dictionary<Type, MethodInfo> ());
|
||||
}
|
||||
|
||||
if (conv_ops[t1].ContainsKey (t2))
|
||||
return conv_ops[t1][t2];
|
||||
|
||||
MethodInfo op = t1.GetMethod (
|
||||
"op_Implicit", new Type[] { t2 });
|
||||
|
||||
lock (conv_ops_lock) {
|
||||
try {
|
||||
conv_ops[t1].Add (t2, op);
|
||||
} catch (ArgumentException) {
|
||||
return conv_ops[t1][t2];
|
||||
}
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
private static object ReadValue (Type inst_type, JsonReader reader)
|
||||
{
|
||||
reader.Read ();
|
||||
|
||||
if (reader.Token == JsonToken.ArrayEnd)
|
||||
return null;
|
||||
|
||||
Type underlying_type = Nullable.GetUnderlyingType(inst_type);
|
||||
Type value_type = underlying_type ?? inst_type;
|
||||
|
||||
if (reader.Token == JsonToken.Null) {
|
||||
#if NETSTANDARD1_5
|
||||
if (inst_type.IsClass() || underlying_type != null) {
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
if (inst_type.IsClass || underlying_type != null) {
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
throw new JsonException (String.Format (
|
||||
"Can't assign null to an instance of type {0}",
|
||||
inst_type));
|
||||
}
|
||||
|
||||
if (reader.Token == JsonToken.Double ||
|
||||
reader.Token == JsonToken.Int ||
|
||||
reader.Token == JsonToken.Long ||
|
||||
reader.Token == JsonToken.String ||
|
||||
reader.Token == JsonToken.Boolean) {
|
||||
|
||||
Type json_type = reader.Value.GetType ();
|
||||
|
||||
if (value_type.IsAssignableFrom (json_type))
|
||||
return reader.Value;
|
||||
|
||||
// If there's a custom importer that fits, use it
|
||||
if (custom_importers_table.ContainsKey (json_type) &&
|
||||
custom_importers_table[json_type].ContainsKey (
|
||||
value_type)) {
|
||||
|
||||
ImporterFunc importer =
|
||||
custom_importers_table[json_type][value_type];
|
||||
|
||||
return importer (reader.Value);
|
||||
}
|
||||
|
||||
// Maybe there's a base importer that works
|
||||
if (base_importers_table.ContainsKey (json_type) &&
|
||||
base_importers_table[json_type].ContainsKey (
|
||||
value_type)) {
|
||||
|
||||
ImporterFunc importer =
|
||||
base_importers_table[json_type][value_type];
|
||||
|
||||
return importer (reader.Value);
|
||||
}
|
||||
|
||||
// Maybe it's an enum
|
||||
#if NETSTANDARD1_5
|
||||
if (value_type.IsEnum())
|
||||
return Enum.ToObject (value_type, reader.Value);
|
||||
#else
|
||||
if (value_type.IsEnum)
|
||||
return Enum.ToObject (value_type, reader.Value);
|
||||
#endif
|
||||
// Try using an implicit conversion operator
|
||||
MethodInfo conv_op = GetConvOp (value_type, json_type);
|
||||
|
||||
if (conv_op != null)
|
||||
return conv_op.Invoke (null,
|
||||
new object[] { reader.Value });
|
||||
|
||||
// No luck
|
||||
throw new JsonException (String.Format (
|
||||
"Can't assign value '{0}' (type {1}) to type {2}",
|
||||
reader.Value, json_type, inst_type));
|
||||
}
|
||||
|
||||
object instance = null;
|
||||
|
||||
if (reader.Token == JsonToken.ArrayStart) {
|
||||
|
||||
AddArrayMetadata (inst_type);
|
||||
ArrayMetadata t_data = array_metadata[inst_type];
|
||||
|
||||
if (! t_data.IsArray && ! t_data.IsList)
|
||||
throw new JsonException (String.Format (
|
||||
"Type {0} can't act as an array",
|
||||
inst_type));
|
||||
|
||||
IList list;
|
||||
Type elem_type;
|
||||
|
||||
if (! t_data.IsArray) {
|
||||
list = (IList) Activator.CreateInstance (inst_type);
|
||||
elem_type = t_data.ElementType;
|
||||
} else {
|
||||
list = new ArrayList ();
|
||||
elem_type = inst_type.GetElementType ();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
object item = ReadValue (elem_type, reader);
|
||||
if (item == null && reader.Token == JsonToken.ArrayEnd)
|
||||
break;
|
||||
|
||||
list.Add (item);
|
||||
}
|
||||
|
||||
if (t_data.IsArray) {
|
||||
int n = list.Count;
|
||||
instance = Array.CreateInstance (elem_type, n);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
((Array) instance).SetValue (list[i], i);
|
||||
} else
|
||||
instance = list;
|
||||
|
||||
} else if (reader.Token == JsonToken.ObjectStart) {
|
||||
AddObjectMetadata (value_type);
|
||||
ObjectMetadata t_data = object_metadata[value_type];
|
||||
|
||||
instance = Activator.CreateInstance (value_type);
|
||||
|
||||
while (true) {
|
||||
reader.Read ();
|
||||
|
||||
if (reader.Token == JsonToken.ObjectEnd)
|
||||
break;
|
||||
|
||||
string property = (string) reader.Value;
|
||||
|
||||
if (t_data.Properties.ContainsKey (property)) {
|
||||
PropertyMetadata prop_data =
|
||||
t_data.Properties[property];
|
||||
|
||||
if (prop_data.IsField) {
|
||||
((FieldInfo) prop_data.Info).SetValue (
|
||||
instance, ReadValue (prop_data.Type, reader));
|
||||
} else {
|
||||
PropertyInfo p_info =
|
||||
(PropertyInfo) prop_data.Info;
|
||||
|
||||
if (p_info.CanWrite)
|
||||
p_info.SetValue (
|
||||
instance,
|
||||
ReadValue (prop_data.Type, reader),
|
||||
null);
|
||||
else
|
||||
ReadValue (prop_data.Type, reader);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (! t_data.IsDictionary) {
|
||||
|
||||
if (! reader.SkipNonMembers) {
|
||||
throw new JsonException (String.Format (
|
||||
"The type {0} doesn't have the " +
|
||||
"property '{1}'",
|
||||
inst_type, property));
|
||||
} else {
|
||||
ReadSkip (reader);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
((IDictionary) instance).Add (
|
||||
property, ReadValue (
|
||||
t_data.ElementType, reader));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static IJsonWrapper ReadValue (WrapperFactory factory,
|
||||
JsonReader reader)
|
||||
{
|
||||
reader.Read ();
|
||||
|
||||
if (reader.Token == JsonToken.ArrayEnd ||
|
||||
reader.Token == JsonToken.Null)
|
||||
return null;
|
||||
|
||||
IJsonWrapper instance = factory ();
|
||||
|
||||
if (reader.Token == JsonToken.String) {
|
||||
instance.SetString ((string) reader.Value);
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (reader.Token == JsonToken.Double) {
|
||||
instance.SetDouble ((double) reader.Value);
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (reader.Token == JsonToken.Int) {
|
||||
instance.SetInt ((int) reader.Value);
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (reader.Token == JsonToken.Long) {
|
||||
instance.SetLong ((long) reader.Value);
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (reader.Token == JsonToken.Boolean) {
|
||||
instance.SetBoolean ((bool) reader.Value);
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (reader.Token == JsonToken.ArrayStart) {
|
||||
instance.SetJsonType (JsonType.Array);
|
||||
|
||||
while (true) {
|
||||
IJsonWrapper item = ReadValue (factory, reader);
|
||||
if (item == null && reader.Token == JsonToken.ArrayEnd)
|
||||
break;
|
||||
|
||||
((IList) instance).Add (item);
|
||||
}
|
||||
}
|
||||
else if (reader.Token == JsonToken.ObjectStart) {
|
||||
instance.SetJsonType (JsonType.Object);
|
||||
|
||||
while (true) {
|
||||
reader.Read ();
|
||||
|
||||
if (reader.Token == JsonToken.ObjectEnd)
|
||||
break;
|
||||
|
||||
string property = (string) reader.Value;
|
||||
|
||||
((IDictionary) instance)[property] = ReadValue (
|
||||
factory, reader);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static void ReadSkip (JsonReader reader)
|
||||
{
|
||||
ToWrapper (
|
||||
delegate { return new JsonMockWrapper (); }, reader);
|
||||
}
|
||||
|
||||
private static void RegisterBaseExporters ()
|
||||
{
|
||||
base_exporters_table[typeof (byte)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write (Convert.ToInt32 ((byte) obj));
|
||||
};
|
||||
|
||||
base_exporters_table[typeof (char)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write (Convert.ToString ((char) obj));
|
||||
};
|
||||
|
||||
base_exporters_table[typeof (DateTime)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write (Convert.ToString ((DateTime) obj,
|
||||
datetime_format));
|
||||
};
|
||||
|
||||
base_exporters_table[typeof (decimal)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write ((decimal) obj);
|
||||
};
|
||||
|
||||
base_exporters_table[typeof (sbyte)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write (Convert.ToInt32 ((sbyte) obj));
|
||||
};
|
||||
|
||||
base_exporters_table[typeof (short)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write (Convert.ToInt32 ((short) obj));
|
||||
};
|
||||
|
||||
base_exporters_table[typeof (ushort)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write (Convert.ToInt32 ((ushort) obj));
|
||||
};
|
||||
|
||||
base_exporters_table[typeof (uint)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write (Convert.ToUInt64 ((uint) obj));
|
||||
};
|
||||
|
||||
base_exporters_table[typeof (ulong)] =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
writer.Write ((ulong) obj);
|
||||
};
|
||||
}
|
||||
|
||||
private static void RegisterBaseImporters ()
|
||||
{
|
||||
ImporterFunc importer;
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToByte ((int) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (int),
|
||||
typeof (byte), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToUInt64 ((int) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (int),
|
||||
typeof (ulong), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToSByte ((int) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (int),
|
||||
typeof (sbyte), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToInt16 ((int) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (int),
|
||||
typeof (short), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToUInt16 ((int) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (int),
|
||||
typeof (ushort), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToUInt32 ((int) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (int),
|
||||
typeof (uint), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToSingle ((int) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (int),
|
||||
typeof (float), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToDouble ((int) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (int),
|
||||
typeof (double), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToDecimal ((double) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (double),
|
||||
typeof (decimal), importer);
|
||||
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToUInt32 ((long) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (long),
|
||||
typeof (uint), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToChar ((string) input);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (string),
|
||||
typeof (char), importer);
|
||||
|
||||
importer = delegate (object input) {
|
||||
return Convert.ToDateTime ((string) input, datetime_format);
|
||||
};
|
||||
RegisterImporter (base_importers_table, typeof (string),
|
||||
typeof (DateTime), importer);
|
||||
}
|
||||
|
||||
private static void RegisterImporter (
|
||||
IDictionary<Type, IDictionary<Type, ImporterFunc>> table,
|
||||
Type json_type, Type value_type, ImporterFunc importer)
|
||||
{
|
||||
if (! table.ContainsKey (json_type))
|
||||
table.Add (json_type, new Dictionary<Type, ImporterFunc> ());
|
||||
|
||||
table[json_type][value_type] = importer;
|
||||
}
|
||||
|
||||
private static void WriteValue (object obj, JsonWriter writer,
|
||||
bool writer_is_private,
|
||||
int depth)
|
||||
{
|
||||
if (depth > max_nesting_depth)
|
||||
throw new JsonException (
|
||||
String.Format ("Max allowed object depth reached while " +
|
||||
"trying to export from type {0}",
|
||||
obj.GetType ()));
|
||||
|
||||
if (obj == null) {
|
||||
writer.Write (null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is IJsonWrapper) {
|
||||
if (writer_is_private)
|
||||
writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ());
|
||||
else
|
||||
((IJsonWrapper) obj).ToJson (writer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is String) {
|
||||
writer.Write ((string) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is Double) {
|
||||
writer.Write ((double) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is Int32) {
|
||||
writer.Write ((int) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is Boolean) {
|
||||
writer.Write ((bool) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is Int64) {
|
||||
writer.Write ((long) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is Array) {
|
||||
writer.WriteArrayStart ();
|
||||
|
||||
foreach (object elem in (Array) obj)
|
||||
WriteValue (elem, writer, writer_is_private, depth + 1);
|
||||
|
||||
writer.WriteArrayEnd ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is IList) {
|
||||
writer.WriteArrayStart ();
|
||||
foreach (object elem in (IList) obj)
|
||||
WriteValue (elem, writer, writer_is_private, depth + 1);
|
||||
writer.WriteArrayEnd ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is IDictionary) {
|
||||
writer.WriteObjectStart ();
|
||||
foreach (DictionaryEntry entry in (IDictionary) obj) {
|
||||
writer.WritePropertyName ((string) entry.Key);
|
||||
WriteValue (entry.Value, writer, writer_is_private,
|
||||
depth + 1);
|
||||
}
|
||||
writer.WriteObjectEnd ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Type obj_type = obj.GetType ();
|
||||
|
||||
// See if there's a custom exporter for the object
|
||||
if (custom_exporters_table.ContainsKey (obj_type)) {
|
||||
ExporterFunc exporter = custom_exporters_table[obj_type];
|
||||
exporter (obj, writer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If not, maybe there's a base exporter
|
||||
if (base_exporters_table.ContainsKey (obj_type)) {
|
||||
ExporterFunc exporter = base_exporters_table[obj_type];
|
||||
exporter (obj, writer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Last option, let's see if it's an enum
|
||||
if (obj is Enum) {
|
||||
Type e_type = Enum.GetUnderlyingType (obj_type);
|
||||
|
||||
if (e_type == typeof (long)
|
||||
|| e_type == typeof (uint)
|
||||
|| e_type == typeof (ulong))
|
||||
writer.Write ((ulong) obj);
|
||||
else
|
||||
writer.Write ((int) obj);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Okay, so it looks like the input should be exported as an
|
||||
// object
|
||||
AddTypeProperties (obj_type);
|
||||
IList<PropertyMetadata> props = type_properties[obj_type];
|
||||
|
||||
writer.WriteObjectStart ();
|
||||
foreach (PropertyMetadata p_data in props) {
|
||||
if (p_data.IsField) {
|
||||
writer.WritePropertyName (p_data.Info.Name);
|
||||
WriteValue (((FieldInfo) p_data.Info).GetValue (obj),
|
||||
writer, writer_is_private, depth + 1);
|
||||
}
|
||||
else {
|
||||
PropertyInfo p_info = (PropertyInfo) p_data.Info;
|
||||
|
||||
if (p_info.CanRead) {
|
||||
writer.WritePropertyName (p_data.Info.Name);
|
||||
WriteValue (p_info.GetValue (obj, null),
|
||||
writer, writer_is_private, depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.WriteObjectEnd ();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
public static string ToJson (object obj)
|
||||
{
|
||||
lock (static_writer_lock) {
|
||||
static_writer.Reset ();
|
||||
|
||||
WriteValue (obj, static_writer, true, 0);
|
||||
|
||||
return static_writer.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ToJson (object obj, JsonWriter writer)
|
||||
{
|
||||
WriteValue (obj, writer, false, 0);
|
||||
}
|
||||
|
||||
public static JsonData ToObject (JsonReader reader)
|
||||
{
|
||||
return (JsonData) ToWrapper (
|
||||
delegate { return new JsonData (); }, reader);
|
||||
}
|
||||
|
||||
public static JsonData ToObject (TextReader reader)
|
||||
{
|
||||
JsonReader json_reader = new JsonReader (reader);
|
||||
|
||||
return (JsonData) ToWrapper (
|
||||
delegate { return new JsonData (); }, json_reader);
|
||||
}
|
||||
|
||||
public static JsonData ToObject (string json)
|
||||
{
|
||||
return (JsonData) ToWrapper (
|
||||
delegate { return new JsonData (); }, json);
|
||||
}
|
||||
|
||||
public static T ToObject<T> (JsonReader reader)
|
||||
{
|
||||
return (T) ReadValue (typeof (T), reader);
|
||||
}
|
||||
|
||||
public static T ToObject<T> (TextReader reader)
|
||||
{
|
||||
JsonReader json_reader = new JsonReader (reader);
|
||||
|
||||
return (T) ReadValue (typeof (T), json_reader);
|
||||
}
|
||||
|
||||
public static T ToObject<T> (string json)
|
||||
{
|
||||
JsonReader reader = new JsonReader (json);
|
||||
|
||||
return (T) ReadValue (typeof (T), reader);
|
||||
}
|
||||
|
||||
public static object ToObject(string json, Type ConvertType )
|
||||
{
|
||||
JsonReader reader = new JsonReader(json);
|
||||
|
||||
return ReadValue(ConvertType, reader);
|
||||
}
|
||||
|
||||
public static IJsonWrapper ToWrapper (WrapperFactory factory,
|
||||
JsonReader reader)
|
||||
{
|
||||
return ReadValue (factory, reader);
|
||||
}
|
||||
|
||||
public static IJsonWrapper ToWrapper (WrapperFactory factory,
|
||||
string json)
|
||||
{
|
||||
JsonReader reader = new JsonReader (json);
|
||||
|
||||
return ReadValue (factory, reader);
|
||||
}
|
||||
|
||||
public static void RegisterExporter<T> (ExporterFunc<T> exporter)
|
||||
{
|
||||
ExporterFunc exporter_wrapper =
|
||||
delegate (object obj, JsonWriter writer) {
|
||||
exporter ((T) obj, writer);
|
||||
};
|
||||
|
||||
custom_exporters_table[typeof (T)] = exporter_wrapper;
|
||||
}
|
||||
|
||||
public static void RegisterImporter<TJson, TValue> (
|
||||
ImporterFunc<TJson, TValue> importer)
|
||||
{
|
||||
ImporterFunc importer_wrapper =
|
||||
delegate (object input) {
|
||||
return importer ((TJson) input);
|
||||
};
|
||||
|
||||
RegisterImporter (custom_importers_table, typeof (TJson),
|
||||
typeof (TValue), importer_wrapper);
|
||||
}
|
||||
|
||||
public static void UnregisterExporters ()
|
||||
{
|
||||
custom_exporters_table.Clear ();
|
||||
}
|
||||
|
||||
public static void UnregisterImporters ()
|
||||
{
|
||||
custom_importers_table.Clear ();
|
||||
}
|
||||
}
|
||||
}
|
105
Librarys/litjson/litjson/JsonMockWrapper.cs
Normal file
105
Librarys/litjson/litjson/JsonMockWrapper.cs
Normal file
@ -0,0 +1,105 @@
|
||||
#region Header
|
||||
/**
|
||||
* JsonMockWrapper.cs
|
||||
* Mock object implementing IJsonWrapper, to facilitate actions like
|
||||
* skipping data more efficiently.
|
||||
*
|
||||
* The authors disclaim copyright to this source code. For more details, see
|
||||
* the COPYING file included with this distribution.
|
||||
**/
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
|
||||
namespace LitJson
|
||||
{
|
||||
public class JsonMockWrapper : IJsonWrapper
|
||||
{
|
||||
public bool IsArray { get { return false; } }
|
||||
public bool IsBoolean { get { return false; } }
|
||||
public bool IsDouble { get { return false; } }
|
||||
public bool IsInt { get { return false; } }
|
||||
public bool IsLong { get { return false; } }
|
||||
public bool IsObject { get { return false; } }
|
||||
public bool IsString { get { return false; } }
|
||||
|
||||
public bool GetBoolean () { return false; }
|
||||
public double GetDouble () { return 0.0; }
|
||||
public int GetInt () { return 0; }
|
||||
public JsonType GetJsonType () { return JsonType.None; }
|
||||
public long GetLong () { return 0L; }
|
||||
public string GetString () { return ""; }
|
||||
|
||||
public void SetBoolean (bool val) {}
|
||||
public void SetDouble (double val) {}
|
||||
public void SetInt (int val) {}
|
||||
public void SetJsonType (JsonType type) {}
|
||||
public void SetLong (long val) {}
|
||||
public void SetString (string val) {}
|
||||
|
||||
public string ToJson () { return ""; }
|
||||
public void ToJson (JsonWriter writer) {}
|
||||
|
||||
|
||||
bool IList.IsFixedSize { get { return true; } }
|
||||
bool IList.IsReadOnly { get { return true; } }
|
||||
|
||||
object IList.this[int index] {
|
||||
get { return null; }
|
||||
set {}
|
||||
}
|
||||
|
||||
int IList.Add (object value) { return 0; }
|
||||
void IList.Clear () {}
|
||||
bool IList.Contains (object value) { return false; }
|
||||
int IList.IndexOf (object value) { return -1; }
|
||||
void IList.Insert (int i, object v) {}
|
||||
void IList.Remove (object value) {}
|
||||
void IList.RemoveAt (int index) {}
|
||||
|
||||
|
||||
int ICollection.Count { get { return 0; } }
|
||||
bool ICollection.IsSynchronized { get { return false; } }
|
||||
object ICollection.SyncRoot { get { return null; } }
|
||||
|
||||
void ICollection.CopyTo (Array array, int index) {}
|
||||
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator () { return null; }
|
||||
|
||||
|
||||
bool IDictionary.IsFixedSize { get { return true; } }
|
||||
bool IDictionary.IsReadOnly { get { return true; } }
|
||||
|
||||
ICollection IDictionary.Keys { get { return null; } }
|
||||
ICollection IDictionary.Values { get { return null; } }
|
||||
|
||||
object IDictionary.this[object key] {
|
||||
get { return null; }
|
||||
set {}
|
||||
}
|
||||
|
||||
void IDictionary.Add (object k, object v) {}
|
||||
void IDictionary.Clear () {}
|
||||
bool IDictionary.Contains (object key) { return false; }
|
||||
void IDictionary.Remove (object key) {}
|
||||
|
||||
IDictionaryEnumerator IDictionary.GetEnumerator () { return null; }
|
||||
|
||||
|
||||
object IOrderedDictionary.this[int idx] {
|
||||
get { return null; }
|
||||
set {}
|
||||
}
|
||||
|
||||
IDictionaryEnumerator IOrderedDictionary.GetEnumerator () {
|
||||
return null;
|
||||
}
|
||||
void IOrderedDictionary.Insert (int i, object k, object v) {}
|
||||
void IOrderedDictionary.RemoveAt (int i) {}
|
||||
}
|
||||
}
|
478
Librarys/litjson/litjson/JsonReader.cs
Normal file
478
Librarys/litjson/litjson/JsonReader.cs
Normal file
@ -0,0 +1,478 @@
|
||||
#region Header
|
||||
/**
|
||||
* JsonReader.cs
|
||||
* Stream-like access to JSON text.
|
||||
*
|
||||
* The authors disclaim copyright to this source code. For more details, see
|
||||
* the COPYING file included with this distribution.
|
||||
**/
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace LitJson
|
||||
{
|
||||
public enum JsonToken
|
||||
{
|
||||
None,
|
||||
|
||||
ObjectStart,
|
||||
PropertyName,
|
||||
ObjectEnd,
|
||||
|
||||
ArrayStart,
|
||||
ArrayEnd,
|
||||
|
||||
Int,
|
||||
Long,
|
||||
Double,
|
||||
|
||||
String,
|
||||
|
||||
Boolean,
|
||||
Null
|
||||
}
|
||||
|
||||
|
||||
public class JsonReader
|
||||
{
|
||||
#region Fields
|
||||
private static readonly IDictionary<int, IDictionary<int, int[]>> parse_table;
|
||||
|
||||
private Stack<int> automaton_stack;
|
||||
private int current_input;
|
||||
private int current_symbol;
|
||||
private bool end_of_json;
|
||||
private bool end_of_input;
|
||||
private Lexer lexer;
|
||||
private bool parser_in_string;
|
||||
private bool parser_return;
|
||||
private bool read_started;
|
||||
private TextReader reader;
|
||||
private bool reader_is_owned;
|
||||
private bool skip_non_members;
|
||||
private object token_value;
|
||||
private JsonToken token;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Properties
|
||||
public bool AllowComments {
|
||||
get { return lexer.AllowComments; }
|
||||
set { lexer.AllowComments = value; }
|
||||
}
|
||||
|
||||
public bool AllowSingleQuotedStrings {
|
||||
get { return lexer.AllowSingleQuotedStrings; }
|
||||
set { lexer.AllowSingleQuotedStrings = value; }
|
||||
}
|
||||
|
||||
public bool SkipNonMembers {
|
||||
get { return skip_non_members; }
|
||||
set { skip_non_members = value; }
|
||||
}
|
||||
|
||||
public bool EndOfInput {
|
||||
get { return end_of_input; }
|
||||
}
|
||||
|
||||
public bool EndOfJson {
|
||||
get { return end_of_json; }
|
||||
}
|
||||
|
||||
public JsonToken Token {
|
||||
get { return token; }
|
||||
}
|
||||
|
||||
public object Value {
|
||||
get { return token_value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
static JsonReader ()
|
||||
{
|
||||
parse_table = PopulateParseTable ();
|
||||
}
|
||||
|
||||
public JsonReader (string json_text) :
|
||||
this (new StringReader (json_text), true)
|
||||
{
|
||||
}
|
||||
|
||||
public JsonReader (TextReader reader) :
|
||||
this (reader, false)
|
||||
{
|
||||
}
|
||||
|
||||
private JsonReader (TextReader reader, bool owned)
|
||||
{
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException ("reader");
|
||||
|
||||
parser_in_string = false;
|
||||
parser_return = false;
|
||||
|
||||
read_started = false;
|
||||
automaton_stack = new Stack<int> ();
|
||||
automaton_stack.Push ((int) ParserToken.End);
|
||||
automaton_stack.Push ((int) ParserToken.Text);
|
||||
|
||||
lexer = new Lexer (reader);
|
||||
|
||||
end_of_input = false;
|
||||
end_of_json = false;
|
||||
|
||||
skip_non_members = true;
|
||||
|
||||
this.reader = reader;
|
||||
reader_is_owned = owned;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Static Methods
|
||||
private static IDictionary<int, IDictionary<int, int[]>> PopulateParseTable ()
|
||||
{
|
||||
// See section A.2. of the manual for details
|
||||
IDictionary<int, IDictionary<int, int[]>> parse_table = new Dictionary<int, IDictionary<int, int[]>> ();
|
||||
|
||||
TableAddRow (parse_table, ParserToken.Array);
|
||||
TableAddCol (parse_table, ParserToken.Array, '[',
|
||||
'[',
|
||||
(int) ParserToken.ArrayPrime);
|
||||
|
||||
TableAddRow (parse_table, ParserToken.ArrayPrime);
|
||||
TableAddCol (parse_table, ParserToken.ArrayPrime, '"',
|
||||
(int) ParserToken.Value,
|
||||
|
||||
(int) ParserToken.ValueRest,
|
||||
']');
|
||||
TableAddCol (parse_table, ParserToken.ArrayPrime, '[',
|
||||
(int) ParserToken.Value,
|
||||
(int) ParserToken.ValueRest,
|
||||
']');
|
||||
TableAddCol (parse_table, ParserToken.ArrayPrime, ']',
|
||||
']');
|
||||
TableAddCol (parse_table, ParserToken.ArrayPrime, '{',
|
||||
(int) ParserToken.Value,
|
||||
(int) ParserToken.ValueRest,
|
||||
']');
|
||||
TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Number,
|
||||
(int) ParserToken.Value,
|
||||
(int) ParserToken.ValueRest,
|
||||
']');
|
||||
TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.True,
|
||||
(int) ParserToken.Value,
|
||||
(int) ParserToken.ValueRest,
|
||||
']');
|
||||
TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.False,
|
||||
(int) ParserToken.Value,
|
||||
(int) ParserToken.ValueRest,
|
||||
']');
|
||||
TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Null,
|
||||
(int) ParserToken.Value,
|
||||
(int) ParserToken.ValueRest,
|
||||
']');
|
||||
|
||||
TableAddRow (parse_table, ParserToken.Object);
|
||||
TableAddCol (parse_table, ParserToken.Object, '{',
|
||||
'{',
|
||||
(int) ParserToken.ObjectPrime);
|
||||
|
||||
TableAddRow (parse_table, ParserToken.ObjectPrime);
|
||||
TableAddCol (parse_table, ParserToken.ObjectPrime, '"',
|
||||
(int) ParserToken.Pair,
|
||||
(int) ParserToken.PairRest,
|
||||
'}');
|
||||
TableAddCol (parse_table, ParserToken.ObjectPrime, '}',
|
||||
'}');
|
||||
|
||||
TableAddRow (parse_table, ParserToken.Pair);
|
||||
TableAddCol (parse_table, ParserToken.Pair, '"',
|
||||
(int) ParserToken.String,
|
||||
':',
|
||||
(int) ParserToken.Value);
|
||||
|
||||
TableAddRow (parse_table, ParserToken.PairRest);
|
||||
TableAddCol (parse_table, ParserToken.PairRest, ',',
|
||||
',',
|
||||
(int) ParserToken.Pair,
|
||||
(int) ParserToken.PairRest);
|
||||
TableAddCol (parse_table, ParserToken.PairRest, '}',
|
||||
(int) ParserToken.Epsilon);
|
||||
|
||||
TableAddRow (parse_table, ParserToken.String);
|
||||
TableAddCol (parse_table, ParserToken.String, '"',
|
||||
'"',
|
||||
(int) ParserToken.CharSeq,
|
||||
'"');
|
||||
|
||||
TableAddRow (parse_table, ParserToken.Text);
|
||||
TableAddCol (parse_table, ParserToken.Text, '[',
|
||||
(int) ParserToken.Array);
|
||||
TableAddCol (parse_table, ParserToken.Text, '{',
|
||||
(int) ParserToken.Object);
|
||||
|
||||
TableAddRow (parse_table, ParserToken.Value);
|
||||
TableAddCol (parse_table, ParserToken.Value, '"',
|
||||
(int) ParserToken.String);
|
||||
TableAddCol (parse_table, ParserToken.Value, '[',
|
||||
(int) ParserToken.Array);
|
||||
TableAddCol (parse_table, ParserToken.Value, '{',
|
||||
(int) ParserToken.Object);
|
||||
TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Number,
|
||||
(int) ParserToken.Number);
|
||||
TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.True,
|
||||
(int) ParserToken.True);
|
||||
TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.False,
|
||||
(int) ParserToken.False);
|
||||
TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Null,
|
||||
(int) ParserToken.Null);
|
||||
|
||||
TableAddRow (parse_table, ParserToken.ValueRest);
|
||||
TableAddCol (parse_table, ParserToken.ValueRest, ',',
|
||||
',',
|
||||
(int) ParserToken.Value,
|
||||
(int) ParserToken.ValueRest);
|
||||
TableAddCol (parse_table, ParserToken.ValueRest, ']',
|
||||
(int) ParserToken.Epsilon);
|
||||
|
||||
return parse_table;
|
||||
}
|
||||
|
||||
private static void TableAddCol (IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken row, int col,
|
||||
params int[] symbols)
|
||||
{
|
||||
parse_table[(int) row].Add (col, symbols);
|
||||
}
|
||||
|
||||
private static void TableAddRow (IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken rule)
|
||||
{
|
||||
parse_table.Add ((int) rule, new Dictionary<int, int[]> ());
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Methods
|
||||
private void ProcessNumber (string number)
|
||||
{
|
||||
if (number.IndexOf ('.') != -1 ||
|
||||
number.IndexOf ('e') != -1 ||
|
||||
number.IndexOf ('E') != -1) {
|
||||
|
||||
double n_double;
|
||||
if (double.TryParse (number, NumberStyles.Any, CultureInfo.InvariantCulture, out n_double)) {
|
||||
token = JsonToken.Double;
|
||||
token_value = n_double;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int n_int32;
|
||||
if (int.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int32)) {
|
||||
token = JsonToken.Int;
|
||||
token_value = n_int32;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
long n_int64;
|
||||
if (long.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int64)) {
|
||||
token = JsonToken.Long;
|
||||
token_value = n_int64;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ulong n_uint64;
|
||||
if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_uint64))
|
||||
{
|
||||
token = JsonToken.Long;
|
||||
token_value = n_uint64;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Shouldn't happen, but just in case, return something
|
||||
token = JsonToken.Int;
|
||||
token_value = 0;
|
||||
}
|
||||
|
||||
private void ProcessSymbol ()
|
||||
{
|
||||
if (current_symbol == '[') {
|
||||
token = JsonToken.ArrayStart;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == ']') {
|
||||
token = JsonToken.ArrayEnd;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == '{') {
|
||||
token = JsonToken.ObjectStart;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == '}') {
|
||||
token = JsonToken.ObjectEnd;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == '"') {
|
||||
if (parser_in_string) {
|
||||
parser_in_string = false;
|
||||
|
||||
parser_return = true;
|
||||
|
||||
} else {
|
||||
if (token == JsonToken.None)
|
||||
token = JsonToken.String;
|
||||
|
||||
parser_in_string = true;
|
||||
}
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.CharSeq) {
|
||||
token_value = lexer.StringValue;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.False) {
|
||||
token = JsonToken.Boolean;
|
||||
token_value = false;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.Null) {
|
||||
token = JsonToken.Null;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.Number) {
|
||||
ProcessNumber (lexer.StringValue);
|
||||
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.Pair) {
|
||||
token = JsonToken.PropertyName;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.True) {
|
||||
token = JsonToken.Boolean;
|
||||
token_value = true;
|
||||
parser_return = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReadToken ()
|
||||
{
|
||||
if (end_of_input)
|
||||
return false;
|
||||
|
||||
lexer.NextToken ();
|
||||
|
||||
if (lexer.EndOfInput) {
|
||||
Close ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
current_input = lexer.Token;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
if (end_of_input)
|
||||
return;
|
||||
|
||||
end_of_input = true;
|
||||
end_of_json = true;
|
||||
|
||||
if (reader_is_owned)
|
||||
{
|
||||
using(reader){}
|
||||
}
|
||||
|
||||
reader = null;
|
||||
}
|
||||
|
||||
public bool Read ()
|
||||
{
|
||||
if (end_of_input)
|
||||
return false;
|
||||
|
||||
if (end_of_json) {
|
||||
end_of_json = false;
|
||||
automaton_stack.Clear ();
|
||||
automaton_stack.Push ((int) ParserToken.End);
|
||||
automaton_stack.Push ((int) ParserToken.Text);
|
||||
}
|
||||
|
||||
parser_in_string = false;
|
||||
parser_return = false;
|
||||
|
||||
token = JsonToken.None;
|
||||
token_value = null;
|
||||
|
||||
if (! read_started) {
|
||||
read_started = true;
|
||||
|
||||
if (! ReadToken ())
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int[] entry_symbols;
|
||||
|
||||
while (true) {
|
||||
if (parser_return) {
|
||||
if (automaton_stack.Peek () == (int) ParserToken.End)
|
||||
end_of_json = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
current_symbol = automaton_stack.Pop ();
|
||||
|
||||
ProcessSymbol ();
|
||||
|
||||
if (current_symbol == current_input) {
|
||||
if (! ReadToken ()) {
|
||||
if (automaton_stack.Peek () != (int) ParserToken.End)
|
||||
throw new JsonException (
|
||||
"Input doesn't evaluate to proper JSON text");
|
||||
|
||||
if (parser_return)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
entry_symbols =
|
||||
parse_table[current_symbol][current_input];
|
||||
|
||||
} catch (KeyNotFoundException e) {
|
||||
throw new JsonException ((ParserToken) current_input, e);
|
||||
}
|
||||
|
||||
if (entry_symbols[0] == (int) ParserToken.Epsilon)
|
||||
continue;
|
||||
|
||||
for (int i = entry_symbols.Length - 1; i >= 0; i--)
|
||||
automaton_stack.Push (entry_symbols[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
473
Librarys/litjson/litjson/JsonWriter.cs
Normal file
473
Librarys/litjson/litjson/JsonWriter.cs
Normal file
@ -0,0 +1,473 @@
|
||||
#region Header
|
||||
/**
|
||||
* JsonWriter.cs
|
||||
* Stream-like facility to output JSON text.
|
||||
*
|
||||
* The authors disclaim copyright to this source code. For more details, see
|
||||
* the COPYING file included with this distribution.
|
||||
**/
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace LitJson
|
||||
{
|
||||
internal enum Condition
|
||||
{
|
||||
InArray,
|
||||
InObject,
|
||||
NotAProperty,
|
||||
Property,
|
||||
Value
|
||||
}
|
||||
|
||||
internal class WriterContext
|
||||
{
|
||||
public int Count;
|
||||
public bool InArray;
|
||||
public bool InObject;
|
||||
public bool ExpectingValue;
|
||||
public int Padding;
|
||||
}
|
||||
|
||||
public class JsonWriter
|
||||
{
|
||||
#region Fields
|
||||
private static readonly NumberFormatInfo number_format;
|
||||
|
||||
private WriterContext context;
|
||||
private Stack<WriterContext> ctx_stack;
|
||||
private bool has_reached_end;
|
||||
private char[] hex_seq;
|
||||
private int indentation;
|
||||
private int indent_value;
|
||||
private StringBuilder inst_string_builder;
|
||||
private bool pretty_print;
|
||||
private bool validate;
|
||||
private bool lower_case_properties;
|
||||
private TextWriter writer;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
public int IndentValue {
|
||||
get { return indent_value; }
|
||||
set {
|
||||
indentation = (indentation / indent_value) * value;
|
||||
indent_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool PrettyPrint {
|
||||
get { return pretty_print; }
|
||||
set { pretty_print = value; }
|
||||
}
|
||||
|
||||
public TextWriter TextWriter {
|
||||
get { return writer; }
|
||||
}
|
||||
|
||||
public bool Validate {
|
||||
get { return validate; }
|
||||
set { validate = value; }
|
||||
}
|
||||
|
||||
public bool LowerCaseProperties {
|
||||
get { return lower_case_properties; }
|
||||
set { lower_case_properties = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
static JsonWriter ()
|
||||
{
|
||||
number_format = NumberFormatInfo.InvariantInfo;
|
||||
}
|
||||
|
||||
public JsonWriter ()
|
||||
{
|
||||
inst_string_builder = new StringBuilder ();
|
||||
writer = new StringWriter (inst_string_builder);
|
||||
|
||||
Init ();
|
||||
}
|
||||
|
||||
public JsonWriter (StringBuilder sb) :
|
||||
this (new StringWriter (sb))
|
||||
{
|
||||
}
|
||||
|
||||
public JsonWriter (TextWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException ("writer");
|
||||
|
||||
this.writer = writer;
|
||||
|
||||
Init ();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Methods
|
||||
private void DoValidation (Condition cond)
|
||||
{
|
||||
if (! context.ExpectingValue)
|
||||
context.Count++;
|
||||
|
||||
if (! validate)
|
||||
return;
|
||||
|
||||
if (has_reached_end)
|
||||
throw new JsonException (
|
||||
"A complete JSON symbol has already been written");
|
||||
|
||||
switch (cond) {
|
||||
case Condition.InArray:
|
||||
if (! context.InArray)
|
||||
throw new JsonException (
|
||||
"Can't close an array here");
|
||||
break;
|
||||
|
||||
case Condition.InObject:
|
||||
if (! context.InObject || context.ExpectingValue)
|
||||
throw new JsonException (
|
||||
"Can't close an object here");
|
||||
break;
|
||||
|
||||
case Condition.NotAProperty:
|
||||
if (context.InObject && ! context.ExpectingValue)
|
||||
throw new JsonException (
|
||||
"Expected a property");
|
||||
break;
|
||||
|
||||
case Condition.Property:
|
||||
if (! context.InObject || context.ExpectingValue)
|
||||
throw new JsonException (
|
||||
"Can't add a property here");
|
||||
break;
|
||||
|
||||
case Condition.Value:
|
||||
if (! context.InArray &&
|
||||
(! context.InObject || ! context.ExpectingValue))
|
||||
throw new JsonException (
|
||||
"Can't add a value here");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Init ()
|
||||
{
|
||||
has_reached_end = false;
|
||||
hex_seq = new char[4];
|
||||
indentation = 0;
|
||||
indent_value = 4;
|
||||
pretty_print = false;
|
||||
validate = true;
|
||||
lower_case_properties = false;
|
||||
|
||||
ctx_stack = new Stack<WriterContext> ();
|
||||
context = new WriterContext ();
|
||||
ctx_stack.Push (context);
|
||||
}
|
||||
|
||||
private static void IntToHex (int n, char[] hex)
|
||||
{
|
||||
int num;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
num = n % 16;
|
||||
|
||||
if (num < 10)
|
||||
hex[3 - i] = (char) ('0' + num);
|
||||
else
|
||||
hex[3 - i] = (char) ('A' + (num - 10));
|
||||
|
||||
n >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
private void Indent ()
|
||||
{
|
||||
if (pretty_print)
|
||||
indentation += indent_value;
|
||||
}
|
||||
|
||||
|
||||
private void Put (string str)
|
||||
{
|
||||
if (pretty_print && ! context.ExpectingValue)
|
||||
for (int i = 0; i < indentation; i++)
|
||||
writer.Write (' ');
|
||||
|
||||
writer.Write (str);
|
||||
}
|
||||
|
||||
private void PutNewline ()
|
||||
{
|
||||
PutNewline (true);
|
||||
}
|
||||
|
||||
private void PutNewline (bool add_comma)
|
||||
{
|
||||
if (add_comma && ! context.ExpectingValue &&
|
||||
context.Count > 1)
|
||||
writer.Write (',');
|
||||
|
||||
if (pretty_print && ! context.ExpectingValue)
|
||||
writer.Write (Environment.NewLine);
|
||||
}
|
||||
|
||||
private void PutString (string str)
|
||||
{
|
||||
Put (String.Empty);
|
||||
|
||||
writer.Write ('"');
|
||||
|
||||
int n = str.Length;
|
||||
for (int i = 0; i < n; i++) {
|
||||
switch (str[i]) {
|
||||
case '\n':
|
||||
writer.Write ("\\n");
|
||||
continue;
|
||||
|
||||
case '\r':
|
||||
writer.Write ("\\r");
|
||||
continue;
|
||||
|
||||
case '\t':
|
||||
writer.Write ("\\t");
|
||||
continue;
|
||||
|
||||
case '"':
|
||||
case '\\':
|
||||
writer.Write ('\\');
|
||||
writer.Write (str[i]);
|
||||
continue;
|
||||
|
||||
case '\f':
|
||||
writer.Write ("\\f");
|
||||
continue;
|
||||
|
||||
case '\b':
|
||||
writer.Write ("\\b");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int) str[i] >= 32 && (int) str[i] <= 126) {
|
||||
writer.Write (str[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Default, turn into a \uXXXX sequence
|
||||
IntToHex ((int) str[i], hex_seq);
|
||||
writer.Write ("\\u");
|
||||
writer.Write (hex_seq);
|
||||
}
|
||||
|
||||
writer.Write ('"');
|
||||
}
|
||||
|
||||
private void Unindent ()
|
||||
{
|
||||
if (pretty_print)
|
||||
indentation -= indent_value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
if (inst_string_builder == null)
|
||||
return String.Empty;
|
||||
|
||||
return inst_string_builder.ToString ();
|
||||
}
|
||||
|
||||
public void Reset ()
|
||||
{
|
||||
has_reached_end = false;
|
||||
|
||||
ctx_stack.Clear ();
|
||||
context = new WriterContext ();
|
||||
ctx_stack.Push (context);
|
||||
|
||||
if (inst_string_builder != null)
|
||||
inst_string_builder.Remove (0, inst_string_builder.Length);
|
||||
}
|
||||
|
||||
public void Write (bool boolean)
|
||||
{
|
||||
DoValidation (Condition.Value);
|
||||
PutNewline ();
|
||||
|
||||
Put (boolean ? "true" : "false");
|
||||
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
public void Write (decimal number)
|
||||
{
|
||||
DoValidation (Condition.Value);
|
||||
PutNewline ();
|
||||
|
||||
Put (Convert.ToString (number, number_format));
|
||||
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
public void Write (double number)
|
||||
{
|
||||
DoValidation (Condition.Value);
|
||||
PutNewline ();
|
||||
|
||||
string str = Convert.ToString (number, number_format);
|
||||
Put (str);
|
||||
|
||||
if (str.IndexOf ('.') == -1 &&
|
||||
str.IndexOf ('E') == -1)
|
||||
writer.Write (".0");
|
||||
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
public void Write (int number)
|
||||
{
|
||||
DoValidation (Condition.Value);
|
||||
PutNewline ();
|
||||
|
||||
Put (Convert.ToString (number, number_format));
|
||||
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
public void Write (long number)
|
||||
{
|
||||
DoValidation (Condition.Value);
|
||||
PutNewline ();
|
||||
|
||||
Put (Convert.ToString (number, number_format));
|
||||
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
public void Write (string str)
|
||||
{
|
||||
DoValidation (Condition.Value);
|
||||
PutNewline ();
|
||||
|
||||
if (str == null)
|
||||
Put ("null");
|
||||
else
|
||||
PutString (str);
|
||||
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public void Write (ulong number)
|
||||
{
|
||||
DoValidation (Condition.Value);
|
||||
PutNewline ();
|
||||
|
||||
Put (Convert.ToString (number, number_format));
|
||||
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
public void WriteArrayEnd ()
|
||||
{
|
||||
DoValidation (Condition.InArray);
|
||||
PutNewline (false);
|
||||
|
||||
ctx_stack.Pop ();
|
||||
if (ctx_stack.Count == 1)
|
||||
has_reached_end = true;
|
||||
else {
|
||||
context = ctx_stack.Peek ();
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
Unindent ();
|
||||
Put ("]");
|
||||
}
|
||||
|
||||
public void WriteArrayStart ()
|
||||
{
|
||||
DoValidation (Condition.NotAProperty);
|
||||
PutNewline ();
|
||||
|
||||
Put ("[");
|
||||
|
||||
context = new WriterContext ();
|
||||
context.InArray = true;
|
||||
ctx_stack.Push (context);
|
||||
|
||||
Indent ();
|
||||
}
|
||||
|
||||
public void WriteObjectEnd ()
|
||||
{
|
||||
DoValidation (Condition.InObject);
|
||||
PutNewline (false);
|
||||
|
||||
ctx_stack.Pop ();
|
||||
if (ctx_stack.Count == 1)
|
||||
has_reached_end = true;
|
||||
else {
|
||||
context = ctx_stack.Peek ();
|
||||
context.ExpectingValue = false;
|
||||
}
|
||||
|
||||
Unindent ();
|
||||
Put ("}");
|
||||
}
|
||||
|
||||
public void WriteObjectStart ()
|
||||
{
|
||||
DoValidation (Condition.NotAProperty);
|
||||
PutNewline ();
|
||||
|
||||
Put ("{");
|
||||
|
||||
context = new WriterContext ();
|
||||
context.InObject = true;
|
||||
ctx_stack.Push (context);
|
||||
|
||||
Indent ();
|
||||
}
|
||||
|
||||
public void WritePropertyName (string property_name)
|
||||
{
|
||||
DoValidation (Condition.Property);
|
||||
PutNewline ();
|
||||
string propertyName = (property_name == null || !lower_case_properties)
|
||||
? property_name
|
||||
: property_name.ToLowerInvariant();
|
||||
|
||||
PutString (propertyName);
|
||||
|
||||
if (pretty_print) {
|
||||
if (propertyName.Length > context.Padding)
|
||||
context.Padding = propertyName.Length;
|
||||
|
||||
for (int i = context.Padding - propertyName.Length;
|
||||
i >= 0; i--)
|
||||
writer.Write (' ');
|
||||
|
||||
writer.Write (": ");
|
||||
} else
|
||||
writer.Write (':');
|
||||
|
||||
context.ExpectingValue = true;
|
||||
}
|
||||
}
|
||||
}
|
912
Librarys/litjson/litjson/Lexer.cs
Normal file
912
Librarys/litjson/litjson/Lexer.cs
Normal file
@ -0,0 +1,912 @@
|
||||
#region Header
|
||||
/**
|
||||
* Lexer.cs
|
||||
* JSON lexer implementation based on a finite state machine.
|
||||
*
|
||||
* The authors disclaim copyright to this source code. For more details, see
|
||||
* the COPYING file included with this distribution.
|
||||
**/
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace LitJson
|
||||
{
|
||||
internal class FsmContext
|
||||
{
|
||||
public bool Return;
|
||||
public int NextState;
|
||||
public Lexer L;
|
||||
public int StateStack;
|
||||
}
|
||||
|
||||
|
||||
internal class Lexer
|
||||
{
|
||||
#region Fields
|
||||
private delegate bool StateHandler (FsmContext ctx);
|
||||
|
||||
private static readonly int[] fsm_return_table;
|
||||
private static readonly StateHandler[] fsm_handler_table;
|
||||
|
||||
private bool allow_comments;
|
||||
private bool allow_single_quoted_strings;
|
||||
private bool end_of_input;
|
||||
private FsmContext fsm_context;
|
||||
private int input_buffer;
|
||||
private int input_char;
|
||||
private TextReader reader;
|
||||
private int state;
|
||||
private StringBuilder string_buffer;
|
||||
private string string_value;
|
||||
private int token;
|
||||
private int unichar;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
public bool AllowComments {
|
||||
get { return allow_comments; }
|
||||
set { allow_comments = value; }
|
||||
}
|
||||
|
||||
public bool AllowSingleQuotedStrings {
|
||||
get { return allow_single_quoted_strings; }
|
||||
set { allow_single_quoted_strings = value; }
|
||||
}
|
||||
|
||||
public bool EndOfInput {
|
||||
get { return end_of_input; }
|
||||
}
|
||||
|
||||
public int Token {
|
||||
get { return token; }
|
||||
}
|
||||
|
||||
public string StringValue {
|
||||
get { return string_value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
static Lexer ()
|
||||
{
|
||||
PopulateFsmTables (out fsm_handler_table, out fsm_return_table);
|
||||
}
|
||||
|
||||
public Lexer (TextReader reader)
|
||||
{
|
||||
allow_comments = true;
|
||||
allow_single_quoted_strings = true;
|
||||
|
||||
input_buffer = 0;
|
||||
string_buffer = new StringBuilder (128);
|
||||
state = 1;
|
||||
end_of_input = false;
|
||||
this.reader = reader;
|
||||
|
||||
fsm_context = new FsmContext ();
|
||||
fsm_context.L = this;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Static Methods
|
||||
private static int HexValue (int digit)
|
||||
{
|
||||
switch (digit) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
return 10;
|
||||
|
||||
case 'b':
|
||||
case 'B':
|
||||
return 11;
|
||||
|
||||
case 'c':
|
||||
case 'C':
|
||||
return 12;
|
||||
|
||||
case 'd':
|
||||
case 'D':
|
||||
return 13;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
return 14;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
return 15;
|
||||
|
||||
default:
|
||||
return digit - '0';
|
||||
}
|
||||
}
|
||||
|
||||
private static void PopulateFsmTables (out StateHandler[] fsm_handler_table, out int[] fsm_return_table)
|
||||
{
|
||||
// See section A.1. of the manual for details of the finite
|
||||
// state machine.
|
||||
fsm_handler_table = new StateHandler[28] {
|
||||
State1,
|
||||
State2,
|
||||
State3,
|
||||
State4,
|
||||
State5,
|
||||
State6,
|
||||
State7,
|
||||
State8,
|
||||
State9,
|
||||
State10,
|
||||
State11,
|
||||
State12,
|
||||
State13,
|
||||
State14,
|
||||
State15,
|
||||
State16,
|
||||
State17,
|
||||
State18,
|
||||
State19,
|
||||
State20,
|
||||
State21,
|
||||
State22,
|
||||
State23,
|
||||
State24,
|
||||
State25,
|
||||
State26,
|
||||
State27,
|
||||
State28
|
||||
};
|
||||
|
||||
fsm_return_table = new int[28] {
|
||||
(int) ParserToken.Char,
|
||||
0,
|
||||
(int) ParserToken.Number,
|
||||
(int) ParserToken.Number,
|
||||
0,
|
||||
(int) ParserToken.Number,
|
||||
0,
|
||||
(int) ParserToken.Number,
|
||||
0,
|
||||
0,
|
||||
(int) ParserToken.True,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(int) ParserToken.False,
|
||||
0,
|
||||
0,
|
||||
(int) ParserToken.Null,
|
||||
(int) ParserToken.CharSeq,
|
||||
(int) ParserToken.Char,
|
||||
0,
|
||||
0,
|
||||
(int) ParserToken.CharSeq,
|
||||
(int) ParserToken.Char,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
private static char ProcessEscChar (int esc_char)
|
||||
{
|
||||
switch (esc_char) {
|
||||
case '"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
case '/':
|
||||
return Convert.ToChar (esc_char);
|
||||
|
||||
case 'n':
|
||||
return '\n';
|
||||
|
||||
case 't':
|
||||
return '\t';
|
||||
|
||||
case 'r':
|
||||
return '\r';
|
||||
|
||||
case 'b':
|
||||
return '\b';
|
||||
|
||||
case 'f':
|
||||
return '\f';
|
||||
|
||||
default:
|
||||
// Unreachable
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State1 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
if (ctx.L.input_char == ' ' ||
|
||||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
|
||||
continue;
|
||||
|
||||
if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9') {
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case '"':
|
||||
ctx.NextState = 19;
|
||||
ctx.Return = true;
|
||||
return true;
|
||||
|
||||
case ',':
|
||||
case ':':
|
||||
case '[':
|
||||
case ']':
|
||||
case '{':
|
||||
case '}':
|
||||
ctx.NextState = 1;
|
||||
ctx.Return = true;
|
||||
return true;
|
||||
|
||||
case '-':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 2;
|
||||
return true;
|
||||
|
||||
case '0':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 4;
|
||||
return true;
|
||||
|
||||
case 'f':
|
||||
ctx.NextState = 12;
|
||||
return true;
|
||||
|
||||
case 'n':
|
||||
ctx.NextState = 16;
|
||||
return true;
|
||||
|
||||
case 't':
|
||||
ctx.NextState = 9;
|
||||
return true;
|
||||
|
||||
case '\'':
|
||||
if (! ctx.L.allow_single_quoted_strings)
|
||||
return false;
|
||||
|
||||
ctx.L.input_char = '"';
|
||||
ctx.NextState = 23;
|
||||
ctx.Return = true;
|
||||
return true;
|
||||
|
||||
case '/':
|
||||
if (! ctx.L.allow_comments)
|
||||
return false;
|
||||
|
||||
ctx.NextState = 25;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State2 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
if (ctx.L.input_char >= '1' && ctx.L.input_char<= '9') {
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case '0':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 4;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State3 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx.L.input_char == ' ' ||
|
||||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case ',':
|
||||
case ']':
|
||||
case '}':
|
||||
ctx.L.UngetChar ();
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
case '.':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 5;
|
||||
return true;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 7;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State4 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
if (ctx.L.input_char == ' ' ||
|
||||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case ',':
|
||||
case ']':
|
||||
case '}':
|
||||
ctx.L.UngetChar ();
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
case '.':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 5;
|
||||
return true;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 7;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State5 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 6;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool State6 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx.L.input_char == ' ' ||
|
||||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case ',':
|
||||
case ']':
|
||||
case '}':
|
||||
ctx.L.UngetChar ();
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 7;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State7 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') {
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 8;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case '+':
|
||||
case '-':
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
ctx.NextState = 8;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State8 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') {
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx.L.input_char == ' ' ||
|
||||
ctx.L.input_char >= '\t' && ctx.L.input_char<= '\r') {
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case ',':
|
||||
case ']':
|
||||
case '}':
|
||||
ctx.L.UngetChar ();
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State9 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'r':
|
||||
ctx.NextState = 10;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State10 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'u':
|
||||
ctx.NextState = 11;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State11 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'e':
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State12 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'a':
|
||||
ctx.NextState = 13;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State13 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'l':
|
||||
ctx.NextState = 14;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State14 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 's':
|
||||
ctx.NextState = 15;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State15 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'e':
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State16 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'u':
|
||||
ctx.NextState = 17;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State17 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'l':
|
||||
ctx.NextState = 18;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State18 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'l':
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State19 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
switch (ctx.L.input_char) {
|
||||
case '"':
|
||||
ctx.L.UngetChar ();
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 20;
|
||||
return true;
|
||||
|
||||
case '\\':
|
||||
ctx.StateStack = 19;
|
||||
ctx.NextState = 21;
|
||||
return true;
|
||||
|
||||
default:
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State20 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case '"':
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State21 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case 'u':
|
||||
ctx.NextState = 22;
|
||||
return true;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
case '/':
|
||||
case '\\':
|
||||
case 'b':
|
||||
case 'f':
|
||||
case 'n':
|
||||
case 'r':
|
||||
case 't':
|
||||
ctx.L.string_buffer.Append (
|
||||
ProcessEscChar (ctx.L.input_char));
|
||||
ctx.NextState = ctx.StateStack;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State22 (FsmContext ctx)
|
||||
{
|
||||
int counter = 0;
|
||||
int mult = 4096;
|
||||
|
||||
ctx.L.unichar = 0;
|
||||
|
||||
while (ctx.L.GetChar ()) {
|
||||
|
||||
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9' ||
|
||||
ctx.L.input_char >= 'A' && ctx.L.input_char <= 'F' ||
|
||||
ctx.L.input_char >= 'a' && ctx.L.input_char <= 'f') {
|
||||
|
||||
ctx.L.unichar += HexValue (ctx.L.input_char) * mult;
|
||||
|
||||
counter++;
|
||||
mult /= 16;
|
||||
|
||||
if (counter == 4) {
|
||||
ctx.L.string_buffer.Append (
|
||||
Convert.ToChar (ctx.L.unichar));
|
||||
ctx.NextState = ctx.StateStack;
|
||||
return true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State23 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
switch (ctx.L.input_char) {
|
||||
case '\'':
|
||||
ctx.L.UngetChar ();
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 24;
|
||||
return true;
|
||||
|
||||
case '\\':
|
||||
ctx.StateStack = 23;
|
||||
ctx.NextState = 21;
|
||||
return true;
|
||||
|
||||
default:
|
||||
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State24 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case '\'':
|
||||
ctx.L.input_char = '"';
|
||||
ctx.Return = true;
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State25 (FsmContext ctx)
|
||||
{
|
||||
ctx.L.GetChar ();
|
||||
|
||||
switch (ctx.L.input_char) {
|
||||
case '*':
|
||||
ctx.NextState = 27;
|
||||
return true;
|
||||
|
||||
case '/':
|
||||
ctx.NextState = 26;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool State26 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
if (ctx.L.input_char == '\n') {
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State27 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
if (ctx.L.input_char == '*') {
|
||||
ctx.NextState = 28;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool State28 (FsmContext ctx)
|
||||
{
|
||||
while (ctx.L.GetChar ()) {
|
||||
if (ctx.L.input_char == '*')
|
||||
continue;
|
||||
|
||||
if (ctx.L.input_char == '/') {
|
||||
ctx.NextState = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
ctx.NextState = 27;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
private bool GetChar ()
|
||||
{
|
||||
if ((input_char = NextChar ()) != -1)
|
||||
return true;
|
||||
|
||||
end_of_input = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private int NextChar ()
|
||||
{
|
||||
if (input_buffer != 0) {
|
||||
int tmp = input_buffer;
|
||||
input_buffer = 0;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
return reader.Read ();
|
||||
}
|
||||
|
||||
public bool NextToken ()
|
||||
{
|
||||
StateHandler handler;
|
||||
fsm_context.Return = false;
|
||||
|
||||
while (true) {
|
||||
handler = fsm_handler_table[state - 1];
|
||||
|
||||
if (! handler (fsm_context))
|
||||
throw new JsonException (input_char);
|
||||
|
||||
if (end_of_input)
|
||||
return false;
|
||||
|
||||
if (fsm_context.Return) {
|
||||
string_value = string_buffer.ToString ();
|
||||
string_buffer.Remove (0, string_buffer.Length);
|
||||
token = fsm_return_table[state - 1];
|
||||
|
||||
if (token == (int) ParserToken.Char)
|
||||
token = input_char;
|
||||
|
||||
state = fsm_context.NextState;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
state = fsm_context.NextState;
|
||||
}
|
||||
}
|
||||
|
||||
private void UngetChar ()
|
||||
{
|
||||
input_buffer = input_char;
|
||||
}
|
||||
}
|
||||
}
|
24
Librarys/litjson/litjson/Netstandard15Polyfill.cs
Normal file
24
Librarys/litjson/litjson/Netstandard15Polyfill.cs
Normal file
@ -0,0 +1,24 @@
|
||||
#if NETSTANDARD1_5
|
||||
using System;
|
||||
using System.Reflection;
|
||||
namespace LitJson
|
||||
{
|
||||
internal static class Netstandard15Polyfill
|
||||
{
|
||||
internal static Type GetInterface(this Type type, string name)
|
||||
{
|
||||
return type.GetTypeInfo().GetInterface(name);
|
||||
}
|
||||
|
||||
internal static bool IsClass(this Type type)
|
||||
{
|
||||
return type.GetTypeInfo().IsClass;
|
||||
}
|
||||
|
||||
internal static bool IsEnum(this Type type)
|
||||
{
|
||||
return type.GetTypeInfo().IsEnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
44
Librarys/litjson/litjson/ParserToken.cs
Normal file
44
Librarys/litjson/litjson/ParserToken.cs
Normal file
@ -0,0 +1,44 @@
|
||||
#region Header
|
||||
/**
|
||||
* ParserToken.cs
|
||||
* Internal representation of the tokens used by the lexer and the parser.
|
||||
*
|
||||
* The authors disclaim copyright to this source code. For more details, see
|
||||
* the COPYING file included with this distribution.
|
||||
**/
|
||||
#endregion
|
||||
|
||||
|
||||
namespace LitJson
|
||||
{
|
||||
internal enum ParserToken
|
||||
{
|
||||
// Lexer tokens (see section A.1.1. of the manual)
|
||||
None = System.Char.MaxValue + 1,
|
||||
Number,
|
||||
True,
|
||||
False,
|
||||
Null,
|
||||
CharSeq,
|
||||
// Single char
|
||||
Char,
|
||||
|
||||
// Parser Rules (see section A.2.1 of the manual)
|
||||
Text,
|
||||
Object,
|
||||
ObjectPrime,
|
||||
Pair,
|
||||
PairRest,
|
||||
Array,
|
||||
ArrayPrime,
|
||||
Value,
|
||||
ValueRest,
|
||||
String,
|
||||
|
||||
// End of input
|
||||
End,
|
||||
|
||||
// The empty rule
|
||||
Epsilon
|
||||
}
|
||||
}
|
36
Librarys/litjson/litjson/Properties/AssemblyInfo.cs
Normal file
36
Librarys/litjson/litjson/Properties/AssemblyInfo.cs
Normal file
@ -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("LitJson")]
|
||||
[assembly: AssemblyDescription("LitJSON library")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("LitJSON")]
|
||||
[assembly: AssemblyCopyright("The authors disclaim copyright to this source code")]
|
||||
[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("91a14cd2-2940-4500-8193-56d37edddbaa")]
|
||||
|
||||
// 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("0.12.0")]
|
||||
[assembly: AssemblyFileVersion("0.12.0")]
|
BIN
Librarys/litjson/litjson/bin/Release/litjson.dll
Normal file
BIN
Librarys/litjson/litjson/bin/Release/litjson.dll
Normal file
Binary file not shown.
57
Librarys/litjson/litjson/litjson_4.7.1.csproj
Normal file
57
Librarys/litjson/litjson/litjson_4.7.1.csproj
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{91A14CD2-2940-4500-8193-56D37EDDDBAA}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>LitJson</RootNamespace>
|
||||
<AssemblyName>litjson</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="IJsonWrapper.cs" />
|
||||
<Compile Include="JsonData.cs" />
|
||||
<Compile Include="JsonException.cs" />
|
||||
<Compile Include="JsonMapper.cs" />
|
||||
<Compile Include="JsonMockWrapper.cs" />
|
||||
<Compile Include="JsonReader.cs" />
|
||||
<Compile Include="JsonWriter.cs" />
|
||||
<Compile Include="Lexer.cs" />
|
||||
<Compile Include="Netstandard15Polyfill.cs" />
|
||||
<Compile Include="ParserToken.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
25
Librarys/mqtt/M2Mqtt.sln
Normal file
25
Librarys/mqtt/M2Mqtt.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
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}") = "M2Mqtt", "M2Mqtt\M2Mqtt.csproj", "{A11AEF5A-B246-4FE8-8330-06DB73CC8074}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {135814CF-A469-4436-9C51-3CFE4B93D2FE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
132
Librarys/mqtt/M2Mqtt/Exceptions/MqttClientException.cs
Normal file
132
Librarys/mqtt/M2Mqtt/Exceptions/MqttClientException.cs
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// MQTT client exception
|
||||
/// </summary>
|
||||
public class MqttClientException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="code">Error code</param>
|
||||
public MqttClientException(MqttClientErrorCode errorCode)
|
||||
{
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
// error code
|
||||
private MqttClientErrorCode errorCode;
|
||||
|
||||
/// <summary>
|
||||
/// Error code
|
||||
/// </summary>
|
||||
public MqttClientErrorCode ErrorCode
|
||||
{
|
||||
get { return this.errorCode; }
|
||||
set { this.errorCode = value; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MQTT client erroro code
|
||||
/// </summary>
|
||||
public enum MqttClientErrorCode
|
||||
{
|
||||
/// <summary>
|
||||
/// Will error (topic, message or QoS level)
|
||||
/// </summary>
|
||||
WillWrong = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Keep alive period too large
|
||||
/// </summary>
|
||||
KeepAliveWrong,
|
||||
|
||||
/// <summary>
|
||||
/// Topic contains wildcards
|
||||
/// </summary>
|
||||
TopicWildcard,
|
||||
|
||||
/// <summary>
|
||||
/// Topic length wrong
|
||||
/// </summary>
|
||||
TopicLength,
|
||||
|
||||
/// <summary>
|
||||
/// QoS level not allowed
|
||||
/// </summary>
|
||||
QosNotAllowed,
|
||||
|
||||
/// <summary>
|
||||
/// Topics list empty for subscribe
|
||||
/// </summary>
|
||||
TopicsEmpty,
|
||||
|
||||
/// <summary>
|
||||
/// Qos levels list empty for subscribe
|
||||
/// </summary>
|
||||
QosLevelsEmpty,
|
||||
|
||||
/// <summary>
|
||||
/// Topics / Qos Levels not match in subscribe
|
||||
/// </summary>
|
||||
TopicsQosLevelsNotMatch,
|
||||
|
||||
/// <summary>
|
||||
/// Wrong message from broker
|
||||
/// </summary>
|
||||
WrongBrokerMessage,
|
||||
|
||||
/// <summary>
|
||||
/// Wrong Message Id
|
||||
/// </summary>
|
||||
WrongMessageId,
|
||||
|
||||
/// <summary>
|
||||
/// Inflight queue is full
|
||||
/// </summary>
|
||||
InflightQueueFull,
|
||||
|
||||
// [v3.1.1]
|
||||
/// <summary>
|
||||
/// Invalid flag bits received
|
||||
/// </summary>
|
||||
InvalidFlagBits,
|
||||
|
||||
// [v3.1.1]
|
||||
/// <summary>
|
||||
/// Invalid connect flags received
|
||||
/// </summary>
|
||||
InvalidConnectFlags,
|
||||
|
||||
// [v3.1.1]
|
||||
/// <summary>
|
||||
/// Invalid client id
|
||||
/// </summary>
|
||||
InvalidClientId,
|
||||
|
||||
// [v3.1.1]
|
||||
/// <summary>
|
||||
/// Invalid protocol name
|
||||
/// </summary>
|
||||
InvalidProtocolName
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception due to error communication with broker on socket
|
||||
/// </summary>
|
||||
public class MqttCommunicationException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public MqttCommunicationException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="e">Inner Exception</param>
|
||||
public MqttCommunicationException(Exception e)
|
||||
: base(String.Empty, e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
31
Librarys/mqtt/M2Mqtt/Exceptions/MqttConnectionException.cs
Normal file
31
Librarys/mqtt/M2Mqtt/Exceptions/MqttConnectionException.cs
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Connection to the broker exception
|
||||
/// </summary>
|
||||
public class MqttConnectionException : Exception
|
||||
{
|
||||
public MqttConnectionException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
27
Librarys/mqtt/M2Mqtt/Exceptions/MqttTimeoutException.cs
Normal file
27
Librarys/mqtt/M2Mqtt/Exceptions/MqttTimeoutException.cs
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Timeout on receiving from broker exception
|
||||
/// </summary>
|
||||
public class MqttTimeoutException : Exception
|
||||
{
|
||||
}
|
||||
}
|
69
Librarys/mqtt/M2Mqtt/IMqttNetworkChannel.cs
Normal file
69
Librarys/mqtt/M2Mqtt/IMqttNetworkChannel.cs
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for channel under MQTT library
|
||||
/// </summary>
|
||||
public interface IMqttNetworkChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// Data available on channel
|
||||
/// </summary>
|
||||
bool DataAvailable { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Receive data from the network channel
|
||||
/// </summary>
|
||||
/// <param name="buffer">Data buffer for receiving data</param>
|
||||
/// <returns>Number of bytes received</returns>
|
||||
int Receive(byte[] buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Receive data from the network channel with a specified timeout
|
||||
/// </summary>
|
||||
/// <param name="buffer">Data buffer for receiving data</param>
|
||||
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
|
||||
/// <returns>Number of bytes received</returns>
|
||||
int Receive(byte[] buffer, int timeout);
|
||||
|
||||
/// <summary>
|
||||
/// Send data on the network channel to the broker
|
||||
/// </summary>
|
||||
/// <param name="buffer">Data buffer to send</param>
|
||||
/// <returns>Number of byte sent</returns>
|
||||
int Send(byte[] buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Close the network channel
|
||||
/// </summary>
|
||||
void Close();
|
||||
|
||||
/// <summary>
|
||||
/// Connect to remote server
|
||||
/// </summary>
|
||||
void Connect();
|
||||
|
||||
/// <summary>
|
||||
/// Accept client connection
|
||||
/// </summary>
|
||||
void Accept();
|
||||
}
|
||||
}
|
25
Librarys/mqtt/M2Mqtt/Internal/InternalEvent.cs
Normal file
25
Librarys/mqtt/M2Mqtt/Internal/InternalEvent.cs
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic internal event for dispatching
|
||||
/// </summary>
|
||||
public abstract class InternalEvent
|
||||
{
|
||||
}
|
||||
}
|
51
Librarys/mqtt/M2Mqtt/Internal/MsgInternalEvent.cs
Normal file
51
Librarys/mqtt/M2Mqtt/Internal/MsgInternalEvent.cs
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using uPLibrary.Networking.M2Mqtt.Messages;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal event with a message
|
||||
/// </summary>
|
||||
public class MsgInternalEvent : InternalEvent
|
||||
{
|
||||
#region Properties ...
|
||||
|
||||
/// <summary>
|
||||
/// Related message
|
||||
/// </summary>
|
||||
public MqttMsgBase Message
|
||||
{
|
||||
get { return this.msg; }
|
||||
set { this.msg = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// related message
|
||||
protected MqttMsgBase msg;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="msg">Related message</param>
|
||||
public MsgInternalEvent(MqttMsgBase msg)
|
||||
{
|
||||
this.msg = msg;
|
||||
}
|
||||
}
|
||||
}
|
53
Librarys/mqtt/M2Mqtt/Internal/MsgPublishedInternalEvent.cs
Normal file
53
Librarys/mqtt/M2Mqtt/Internal/MsgPublishedInternalEvent.cs
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using uPLibrary.Networking.M2Mqtt.Messages;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal event for a published message
|
||||
/// </summary>
|
||||
public class MsgPublishedInternalEvent : MsgInternalEvent
|
||||
{
|
||||
#region Properties...
|
||||
|
||||
/// <summary>
|
||||
/// Message published (or failed due to retries)
|
||||
/// </summary>
|
||||
public bool IsPublished
|
||||
{
|
||||
get { return this.isPublished; }
|
||||
internal set { this.isPublished = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// published flag
|
||||
bool isPublished;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="msg">Message published</param>
|
||||
/// <param name="isPublished">Publish flag</param>
|
||||
public MsgPublishedInternalEvent(MqttMsgBase msg, bool isPublished)
|
||||
: base(msg)
|
||||
{
|
||||
this.isPublished = isPublished;
|
||||
}
|
||||
}
|
||||
}
|
93
Librarys/mqtt/M2Mqtt/M2Mqtt.csproj
Normal file
93
Librarys/mqtt/M2Mqtt/M2Mqtt.csproj
Normal file
@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{A11AEF5A-B246-4FE8-8330-06DB73CC8074}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>uPLibrary.Networking.M2Mqtt</RootNamespace>
|
||||
<AssemblyName>M2Mqtt</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\4.7.1\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\4.7.1\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Exceptions\MqttClientException.cs" />
|
||||
<Compile Include="Exceptions\MqttCommunicationException.cs" />
|
||||
<Compile Include="Exceptions\MqttConnectionException.cs" />
|
||||
<Compile Include="Exceptions\MqttTimeoutException.cs" />
|
||||
<Compile Include="IMqttNetworkChannel.cs" />
|
||||
<Compile Include="Internal\InternalEvent.cs" />
|
||||
<Compile Include="Internal\MsgInternalEvent.cs" />
|
||||
<Compile Include="Internal\MsgPublishedInternalEvent.cs" />
|
||||
<Compile Include="Messages\MqttMsgBase.cs" />
|
||||
<Compile Include="Messages\MqttMsgConnack.cs" />
|
||||
<Compile Include="Messages\MqttMsgConnect.cs" />
|
||||
<Compile Include="Messages\MqttMsgConnectEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgContext.cs" />
|
||||
<Compile Include="Messages\MqttMsgDisconnect.cs" />
|
||||
<Compile Include="Messages\MqttMsgPingReq.cs" />
|
||||
<Compile Include="Messages\MqttMsgPingResp.cs" />
|
||||
<Compile Include="Messages\MqttMsgPuback.cs" />
|
||||
<Compile Include="Messages\MqttMsgPubcomp.cs" />
|
||||
<Compile Include="Messages\MqttMsgPublish.cs" />
|
||||
<Compile Include="Messages\MqttMsgPublishedEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgPublishEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgPubrec.cs" />
|
||||
<Compile Include="Messages\MqttMsgPubrel.cs" />
|
||||
<Compile Include="Messages\MqttMsgSuback.cs" />
|
||||
<Compile Include="Messages\MqttMsgSubscribe.cs" />
|
||||
<Compile Include="Messages\MqttMsgSubscribedEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgSubscribeEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgUnsuback.cs" />
|
||||
<Compile Include="Messages\MqttMsgUnsubscribe.cs" />
|
||||
<Compile Include="Messages\MqttMsgUnsubscribedEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgUnsubscribeEventArgs.cs" />
|
||||
<Compile Include="MqttClient.cs" />
|
||||
<Compile Include="MqttSecurity.cs" />
|
||||
<Compile Include="Net\Fx.cs" />
|
||||
<Compile Include="Net\MqttNetworkChannel.cs" />
|
||||
<Compile Include="MqttSettings.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Session\MqttBrokerSession.cs" />
|
||||
<Compile Include="Session\MqttClientSession.cs" />
|
||||
<Compile Include="Session\MqttSession.cs" />
|
||||
<Compile Include="Utility\Trace.cs" />
|
||||
<Compile Include="Utility\QueueExtension.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- 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.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
93
Librarys/mqtt/M2Mqtt/M2Mqtt_2.csproj
Normal file
93
Librarys/mqtt/M2Mqtt/M2Mqtt_2.csproj
Normal file
@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{A11AEF5A-B246-4FE8-8330-06DB73CC8074}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>uPLibrary.Networking.M2Mqtt</RootNamespace>
|
||||
<AssemblyName>M2Mqtt</AssemblyName>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\2.0\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\2.0\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Exceptions\MqttClientException.cs" />
|
||||
<Compile Include="Exceptions\MqttCommunicationException.cs" />
|
||||
<Compile Include="Exceptions\MqttConnectionException.cs" />
|
||||
<Compile Include="Exceptions\MqttTimeoutException.cs" />
|
||||
<Compile Include="IMqttNetworkChannel.cs" />
|
||||
<Compile Include="Internal\InternalEvent.cs" />
|
||||
<Compile Include="Internal\MsgInternalEvent.cs" />
|
||||
<Compile Include="Internal\MsgPublishedInternalEvent.cs" />
|
||||
<Compile Include="Messages\MqttMsgBase.cs" />
|
||||
<Compile Include="Messages\MqttMsgConnack.cs" />
|
||||
<Compile Include="Messages\MqttMsgConnect.cs" />
|
||||
<Compile Include="Messages\MqttMsgConnectEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgContext.cs" />
|
||||
<Compile Include="Messages\MqttMsgDisconnect.cs" />
|
||||
<Compile Include="Messages\MqttMsgPingReq.cs" />
|
||||
<Compile Include="Messages\MqttMsgPingResp.cs" />
|
||||
<Compile Include="Messages\MqttMsgPuback.cs" />
|
||||
<Compile Include="Messages\MqttMsgPubcomp.cs" />
|
||||
<Compile Include="Messages\MqttMsgPublish.cs" />
|
||||
<Compile Include="Messages\MqttMsgPublishedEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgPublishEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgPubrec.cs" />
|
||||
<Compile Include="Messages\MqttMsgPubrel.cs" />
|
||||
<Compile Include="Messages\MqttMsgSuback.cs" />
|
||||
<Compile Include="Messages\MqttMsgSubscribe.cs" />
|
||||
<Compile Include="Messages\MqttMsgSubscribedEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgSubscribeEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgUnsuback.cs" />
|
||||
<Compile Include="Messages\MqttMsgUnsubscribe.cs" />
|
||||
<Compile Include="Messages\MqttMsgUnsubscribedEventArgs.cs" />
|
||||
<Compile Include="Messages\MqttMsgUnsubscribeEventArgs.cs" />
|
||||
<Compile Include="MqttClient.cs" />
|
||||
<Compile Include="MqttSecurity.cs" />
|
||||
<Compile Include="Net\Fx.cs" />
|
||||
<Compile Include="Net\MqttNetworkChannel.cs" />
|
||||
<Compile Include="MqttSettings.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Session\MqttBrokerSession.cs" />
|
||||
<Compile Include="Session\MqttClientSession.cs" />
|
||||
<Compile Include="Session\MqttSession.cs" />
|
||||
<Compile Include="Utility\Trace.cs" />
|
||||
<Compile Include="Utility\QueueExtension.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- 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.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
275
Librarys/mqtt/M2Mqtt/Messages/MqttMsgBase.cs
Normal file
275
Librarys/mqtt/M2Mqtt/Messages/MqttMsgBase.cs
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for all MQTT messages
|
||||
/// </summary>
|
||||
public abstract class MqttMsgBase
|
||||
{
|
||||
#region Constants...
|
||||
|
||||
// mask, offset and size for fixed header fields
|
||||
internal const byte MSG_TYPE_MASK = 0xF0;
|
||||
internal const byte MSG_TYPE_OFFSET = 0x04;
|
||||
internal const byte MSG_TYPE_SIZE = 0x04;
|
||||
internal const byte MSG_FLAG_BITS_MASK = 0x0F; // [v3.1.1]
|
||||
internal const byte MSG_FLAG_BITS_OFFSET = 0x00; // [v3.1.1]
|
||||
internal const byte MSG_FLAG_BITS_SIZE = 0x04; // [v3.1.1]
|
||||
internal const byte DUP_FLAG_MASK = 0x08;
|
||||
internal const byte DUP_FLAG_OFFSET = 0x03;
|
||||
internal const byte DUP_FLAG_SIZE = 0x01;
|
||||
internal const byte QOS_LEVEL_MASK = 0x06;
|
||||
internal const byte QOS_LEVEL_OFFSET = 0x01;
|
||||
internal const byte QOS_LEVEL_SIZE = 0x02;
|
||||
internal const byte RETAIN_FLAG_MASK = 0x01;
|
||||
internal const byte RETAIN_FLAG_OFFSET = 0x00;
|
||||
internal const byte RETAIN_FLAG_SIZE = 0x01;
|
||||
|
||||
// MQTT message types
|
||||
internal const byte MQTT_MSG_CONNECT_TYPE = 0x01;
|
||||
internal const byte MQTT_MSG_CONNACK_TYPE = 0x02;
|
||||
internal const byte MQTT_MSG_PUBLISH_TYPE = 0x03;
|
||||
internal const byte MQTT_MSG_PUBACK_TYPE = 0x04;
|
||||
internal const byte MQTT_MSG_PUBREC_TYPE = 0x05;
|
||||
internal const byte MQTT_MSG_PUBREL_TYPE = 0x06;
|
||||
internal const byte MQTT_MSG_PUBCOMP_TYPE = 0x07;
|
||||
internal const byte MQTT_MSG_SUBSCRIBE_TYPE = 0x08;
|
||||
internal const byte MQTT_MSG_SUBACK_TYPE = 0x09;
|
||||
internal const byte MQTT_MSG_UNSUBSCRIBE_TYPE = 0x0A;
|
||||
internal const byte MQTT_MSG_UNSUBACK_TYPE = 0x0B;
|
||||
internal const byte MQTT_MSG_PINGREQ_TYPE = 0x0C;
|
||||
internal const byte MQTT_MSG_PINGRESP_TYPE = 0x0D;
|
||||
internal const byte MQTT_MSG_DISCONNECT_TYPE = 0x0E;
|
||||
|
||||
// [v3.1.1] MQTT flag bits
|
||||
internal const byte MQTT_MSG_CONNECT_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_CONNACK_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_PUBLISH_FLAG_BITS = 0x00; // just defined as 0x00 but depends on publish props (dup, qos, retain)
|
||||
internal const byte MQTT_MSG_PUBACK_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_PUBREC_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_PUBREL_FLAG_BITS = 0x02;
|
||||
internal const byte MQTT_MSG_PUBCOMP_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_SUBSCRIBE_FLAG_BITS = 0x02;
|
||||
internal const byte MQTT_MSG_SUBACK_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_UNSUBSCRIBE_FLAG_BITS = 0x02;
|
||||
internal const byte MQTT_MSG_UNSUBACK_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_PINGREQ_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_PINGRESP_FLAG_BITS = 0x00;
|
||||
internal const byte MQTT_MSG_DISCONNECT_FLAG_BITS = 0x00;
|
||||
|
||||
// QOS levels
|
||||
public const byte QOS_LEVEL_AT_MOST_ONCE = 0x00;
|
||||
public const byte QOS_LEVEL_AT_LEAST_ONCE = 0x01;
|
||||
public const byte QOS_LEVEL_EXACTLY_ONCE = 0x02;
|
||||
|
||||
// SUBSCRIBE QoS level granted failure [v3.1.1]
|
||||
public const byte QOS_LEVEL_GRANTED_FAILURE = 0x80;
|
||||
|
||||
internal const ushort MAX_TOPIC_LENGTH = 65535;
|
||||
internal const ushort MIN_TOPIC_LENGTH = 1;
|
||||
internal const byte MESSAGE_ID_SIZE = 2;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties...
|
||||
|
||||
/// <summary>
|
||||
/// Message type
|
||||
/// </summary>
|
||||
public byte Type
|
||||
{
|
||||
get { return this.type; }
|
||||
set { this.type = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Duplicate message flag
|
||||
/// </summary>
|
||||
public bool DupFlag
|
||||
{
|
||||
get { return this.dupFlag; }
|
||||
set { this.dupFlag = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quality of Service level
|
||||
/// </summary>
|
||||
public byte QosLevel
|
||||
{
|
||||
get { return this.qosLevel; }
|
||||
set { this.qosLevel = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retain message flag
|
||||
/// </summary>
|
||||
public bool Retain
|
||||
{
|
||||
get { return this.retain; }
|
||||
set { this.retain = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message identifier for the message
|
||||
/// </summary>
|
||||
public ushort MessageId
|
||||
{
|
||||
get { return this.messageId; }
|
||||
set { this.messageId = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// message type
|
||||
protected byte type;
|
||||
// duplicate delivery
|
||||
protected bool dupFlag;
|
||||
// quality of service level
|
||||
protected byte qosLevel;
|
||||
// retain flag
|
||||
protected bool retain;
|
||||
// message identifier
|
||||
protected ushort messageId;
|
||||
|
||||
/// <summary>
|
||||
/// Returns message bytes rapresentation
|
||||
/// </summary>
|
||||
/// <param name="protocolVersion">Protocol version</param>
|
||||
/// <returns>Bytes rapresentation</returns>
|
||||
public abstract byte[] GetBytes(byte protocolVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Encode remaining length and insert it into message buffer
|
||||
/// </summary>
|
||||
/// <param name="remainingLength">Remaining length value to encode</param>
|
||||
/// <param name="buffer">Message buffer for inserting encoded value</param>
|
||||
/// <param name="index">Index from which insert encoded value into buffer</param>
|
||||
/// <returns>Index updated</returns>
|
||||
protected int encodeRemainingLength(int remainingLength, byte[] buffer, int index)
|
||||
{
|
||||
int digit = 0;
|
||||
do
|
||||
{
|
||||
digit = remainingLength % 128;
|
||||
remainingLength /= 128;
|
||||
if (remainingLength > 0)
|
||||
digit = digit | 0x80;
|
||||
buffer[index++] = (byte)digit;
|
||||
} while (remainingLength > 0);
|
||||
return index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode remaining length reading bytes from socket
|
||||
/// </summary>
|
||||
/// <param name="channel">Channel from reading bytes</param>
|
||||
/// <returns>Decoded remaining length</returns>
|
||||
protected static int decodeRemainingLength(IMqttNetworkChannel channel)
|
||||
{
|
||||
int multiplier = 1;
|
||||
int value = 0;
|
||||
int digit = 0;
|
||||
byte[] nextByte = new byte[1];
|
||||
do
|
||||
{
|
||||
// next digit from stream
|
||||
channel.Receive(nextByte);
|
||||
digit = nextByte[0];
|
||||
value += ((digit & 127) * multiplier);
|
||||
multiplier *= 128;
|
||||
} while ((digit & 128) != 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
/// <summary>
|
||||
/// Returns a string representation of the message for tracing
|
||||
/// </summary>
|
||||
/// <param name="name">Message name</param>
|
||||
/// <param name="fieldNames">Message fields name</param>
|
||||
/// <param name="fieldValues">Message fields value</param>
|
||||
/// <returns>String representation of the message</returns>
|
||||
protected string GetTraceString(string name, object[] fieldNames, object[] fieldValues)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(name);
|
||||
|
||||
if ((fieldNames != null) && (fieldValues != null))
|
||||
{
|
||||
sb.Append("(");
|
||||
bool addComma = false;
|
||||
for (int i = 0; i < fieldValues.Length; i++)
|
||||
{
|
||||
if (fieldValues[i] != null)
|
||||
{
|
||||
if (addComma)
|
||||
{
|
||||
sb.Append(",");
|
||||
}
|
||||
|
||||
sb.Append(fieldNames[i]);
|
||||
sb.Append(":");
|
||||
sb.Append(GetStringObject(fieldValues[i]));
|
||||
addComma = true;
|
||||
}
|
||||
}
|
||||
sb.Append(")");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
object GetStringObject(object value)
|
||||
{
|
||||
byte[] binary = value as byte[];
|
||||
if (binary != null)
|
||||
{
|
||||
string hexChars = "0123456789ABCDEF";
|
||||
StringBuilder sb = new StringBuilder(binary.Length * 2);
|
||||
for (int i = 0; i < binary.Length; ++i)
|
||||
{
|
||||
sb.Append(hexChars[binary[i] >> 4]);
|
||||
sb.Append(hexChars[binary[i] & 0x0F]);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
object[] list = value as object[];
|
||||
if (list != null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
for (int i = 0; i < list.Length; ++i)
|
||||
{
|
||||
if (i > 0) sb.Append(',');
|
||||
sb.Append(list[i]);
|
||||
}
|
||||
sb.Append(']');
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
191
Librarys/mqtt/M2Mqtt/Messages/MqttMsgConnack.cs
Normal file
191
Librarys/mqtt/M2Mqtt/Messages/MqttMsgConnack.cs
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
using uPLibrary.Networking.M2Mqtt.Exceptions;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for CONNACK message from broker to client
|
||||
/// </summary>
|
||||
public class MqttMsgConnack : MqttMsgBase
|
||||
{
|
||||
#region Constants...
|
||||
|
||||
// return codes for CONNACK message
|
||||
public const byte CONN_ACCEPTED = 0x00;
|
||||
public const byte CONN_REFUSED_PROT_VERS = 0x01;
|
||||
public const byte CONN_REFUSED_IDENT_REJECTED = 0x02;
|
||||
public const byte CONN_REFUSED_SERVER_UNAVAILABLE = 0x03;
|
||||
public const byte CONN_REFUSED_USERNAME_PASSWORD = 0x04;
|
||||
public const byte CONN_REFUSED_NOT_AUTHORIZED = 0x05;
|
||||
|
||||
private const byte TOPIC_NAME_COMP_RESP_BYTE_OFFSET = 0;
|
||||
private const byte TOPIC_NAME_COMP_RESP_BYTE_SIZE = 1;
|
||||
// [v3.1.1] connect acknowledge flags replace "old" topic name compression respone (not used in 3.1)
|
||||
private const byte CONN_ACK_FLAGS_BYTE_OFFSET = 0;
|
||||
private const byte CONN_ACK_FLAGS_BYTE_SIZE = 1;
|
||||
// [v3.1.1] session present flag
|
||||
private const byte SESSION_PRESENT_FLAG_MASK = 0x01;
|
||||
private const byte SESSION_PRESENT_FLAG_OFFSET = 0x00;
|
||||
private const byte SESSION_PRESENT_FLAG_SIZE = 0x01;
|
||||
private const byte CONN_RETURN_CODE_BYTE_OFFSET = 1;
|
||||
private const byte CONN_RETURN_CODE_BYTE_SIZE = 1;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties...
|
||||
|
||||
// [v3.1.1] session present flag
|
||||
/// <summary>
|
||||
/// Session present flag
|
||||
/// </summary>
|
||||
public bool SessionPresent
|
||||
{
|
||||
get { return this.sessionPresent; }
|
||||
set { this.sessionPresent = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return Code
|
||||
/// </summary>
|
||||
public byte ReturnCode
|
||||
{
|
||||
get { return this.returnCode; }
|
||||
set { this.returnCode = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// [v3.1.1] session present flag
|
||||
private bool sessionPresent;
|
||||
|
||||
// return code for CONNACK message
|
||||
private byte returnCode;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public MqttMsgConnack()
|
||||
{
|
||||
this.type = MQTT_MSG_CONNACK_TYPE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse bytes for a CONNACK message
|
||||
/// </summary>
|
||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||
/// <param name="protocolVersion">Protocol Version</param>
|
||||
/// <param name="channel">Channel connected to the broker</param>
|
||||
/// <returns>CONNACK message instance</returns>
|
||||
public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
||||
{
|
||||
byte[] buffer;
|
||||
MqttMsgConnack msg = new MqttMsgConnack();
|
||||
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
{
|
||||
// [v3.1.1] check flag bits
|
||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS)
|
||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||
}
|
||||
|
||||
// get remaining length and allocate buffer
|
||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
||||
buffer = new byte[remainingLength];
|
||||
|
||||
// read bytes from socket...
|
||||
channel.Receive(buffer);
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
{
|
||||
// [v3.1.1] ... set session present flag ...
|
||||
msg.sessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
|
||||
}
|
||||
// ...and set return code from broker
|
||||
msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public override byte[] GetBytes(byte ProtocolVersion)
|
||||
{
|
||||
int fixedHeaderSize = 0;
|
||||
int varHeaderSize = 0;
|
||||
int payloadSize = 0;
|
||||
int remainingLength = 0;
|
||||
byte[] buffer;
|
||||
int index = 0;
|
||||
|
||||
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
// flags byte and connect return code
|
||||
varHeaderSize += (CONN_ACK_FLAGS_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE);
|
||||
else
|
||||
// topic name compression response and connect return code
|
||||
varHeaderSize += (TOPIC_NAME_COMP_RESP_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE);
|
||||
|
||||
remainingLength += (varHeaderSize + payloadSize);
|
||||
|
||||
// first byte of fixed header
|
||||
fixedHeaderSize = 1;
|
||||
|
||||
int temp = remainingLength;
|
||||
// increase fixed header size based on remaining length
|
||||
// (each remaining length byte can encode until 128)
|
||||
do
|
||||
{
|
||||
fixedHeaderSize++;
|
||||
temp = temp / 128;
|
||||
} while (temp > 0);
|
||||
|
||||
// allocate buffer for message
|
||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||
|
||||
// first fixed header byte
|
||||
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
buffer[index++] = (MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNACK_FLAG_BITS; // [v.3.1.1]
|
||||
else
|
||||
buffer[index++] = (byte)(MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET);
|
||||
|
||||
// encode remaining length
|
||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
||||
|
||||
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
// [v3.1.1] session present flag
|
||||
buffer[index++] = this.sessionPresent ? (byte)(1 << SESSION_PRESENT_FLAG_OFFSET) : (byte)0x00;
|
||||
else
|
||||
// topic name compression response (reserved values. not used);
|
||||
buffer[index++] = 0x00;
|
||||
|
||||
// connect return code
|
||||
buffer[index++] = this.returnCode;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
#if TRACE
|
||||
return this.GetTraceString(
|
||||
"CONNACK",
|
||||
new object[] { "returnCode" },
|
||||
new object[] { this.returnCode });
|
||||
#else
|
||||
return base.ToString();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
582
Librarys/mqtt/M2Mqtt/Messages/MqttMsgConnect.cs
Normal file
582
Librarys/mqtt/M2Mqtt/Messages/MqttMsgConnect.cs
Normal file
@ -0,0 +1,582 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using uPLibrary.Networking.M2Mqtt.Exceptions;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for CONNECT message from client to broker
|
||||
/// </summary>
|
||||
public class MqttMsgConnect : MqttMsgBase
|
||||
{
|
||||
#region Constants...
|
||||
|
||||
// protocol name supported
|
||||
internal const string PROTOCOL_NAME_V3_1 = "MQIsdp";
|
||||
internal const string PROTOCOL_NAME_V3_1_1 = "MQTT"; // [v.3.1.1]
|
||||
|
||||
// max length for client id (removed in 3.1.1)
|
||||
internal const int CLIENT_ID_MAX_LENGTH = 23;
|
||||
|
||||
// variable header fields
|
||||
internal const byte PROTOCOL_NAME_LEN_SIZE = 2;
|
||||
internal const byte PROTOCOL_NAME_V3_1_SIZE = 6;
|
||||
internal const byte PROTOCOL_NAME_V3_1_1_SIZE = 4; // [v.3.1.1]
|
||||
internal const byte PROTOCOL_VERSION_SIZE = 1;
|
||||
internal const byte CONNECT_FLAGS_SIZE = 1;
|
||||
internal const byte KEEP_ALIVE_TIME_SIZE = 2;
|
||||
|
||||
internal const byte PROTOCOL_VERSION_V3_1 = 0x03;
|
||||
internal const byte PROTOCOL_VERSION_V3_1_1 = 0x04; // [v.3.1.1]
|
||||
internal const ushort KEEP_ALIVE_PERIOD_DEFAULT = 60; // seconds
|
||||
internal const ushort MAX_KEEP_ALIVE = 65535; // 16 bit
|
||||
|
||||
// connect flags
|
||||
internal const byte USERNAME_FLAG_MASK = 0x80;
|
||||
internal const byte USERNAME_FLAG_OFFSET = 0x07;
|
||||
internal const byte USERNAME_FLAG_SIZE = 0x01;
|
||||
internal const byte PASSWORD_FLAG_MASK = 0x40;
|
||||
internal const byte PASSWORD_FLAG_OFFSET = 0x06;
|
||||
internal const byte PASSWORD_FLAG_SIZE = 0x01;
|
||||
internal const byte WILL_RETAIN_FLAG_MASK = 0x20;
|
||||
internal const byte WILL_RETAIN_FLAG_OFFSET = 0x05;
|
||||
internal const byte WILL_RETAIN_FLAG_SIZE = 0x01;
|
||||
internal const byte WILL_QOS_FLAG_MASK = 0x18;
|
||||
internal const byte WILL_QOS_FLAG_OFFSET = 0x03;
|
||||
internal const byte WILL_QOS_FLAG_SIZE = 0x02;
|
||||
internal const byte WILL_FLAG_MASK = 0x04;
|
||||
internal const byte WILL_FLAG_OFFSET = 0x02;
|
||||
internal const byte WILL_FLAG_SIZE = 0x01;
|
||||
internal const byte CLEAN_SESSION_FLAG_MASK = 0x02;
|
||||
internal const byte CLEAN_SESSION_FLAG_OFFSET = 0x01;
|
||||
internal const byte CLEAN_SESSION_FLAG_SIZE = 0x01;
|
||||
// [v.3.1.1] lsb (reserved) must be now 0
|
||||
internal const byte RESERVED_FLAG_MASK = 0x01;
|
||||
internal const byte RESERVED_FLAG_OFFSET = 0x00;
|
||||
internal const byte RESERVED_FLAG_SIZE = 0x01;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties...
|
||||
|
||||
/// <summary>
|
||||
/// Protocol name
|
||||
/// </summary>
|
||||
public string ProtocolName
|
||||
{
|
||||
get { return this.protocolName; }
|
||||
set { this.protocolName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Protocol version
|
||||
/// </summary>
|
||||
public byte ProtocolVersion
|
||||
{
|
||||
get { return this.protocolVersion; }
|
||||
set { this.protocolVersion = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Client identifier
|
||||
/// </summary>
|
||||
public string ClientId
|
||||
{
|
||||
get { return this.clientId; }
|
||||
set { this.clientId = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will retain flag
|
||||
/// </summary>
|
||||
public bool WillRetain
|
||||
{
|
||||
get { return this.willRetain; }
|
||||
set { this.willRetain = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will QOS level
|
||||
/// </summary>
|
||||
public byte WillQosLevel
|
||||
{
|
||||
get { return this.willQosLevel; }
|
||||
set { this.willQosLevel = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will flag
|
||||
/// </summary>
|
||||
public bool WillFlag
|
||||
{
|
||||
get { return this.willFlag; }
|
||||
set { this.willFlag = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will topic
|
||||
/// </summary>
|
||||
public string WillTopic
|
||||
{
|
||||
get { return this.willTopic; }
|
||||
set { this.willTopic = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will message
|
||||
/// </summary>
|
||||
public string WillMessage
|
||||
{
|
||||
get { return this.willMessage; }
|
||||
set { this.willMessage = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Username
|
||||
/// </summary>
|
||||
public string Username
|
||||
{
|
||||
get { return this.username; }
|
||||
set { this.username = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Password
|
||||
/// </summary>
|
||||
public string Password
|
||||
{
|
||||
get { return this.password; }
|
||||
set { this.password = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean session flag
|
||||
/// </summary>
|
||||
public bool CleanSession
|
||||
{
|
||||
get { return this.cleanSession; }
|
||||
set { this.cleanSession = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keep alive period
|
||||
/// </summary>
|
||||
public ushort KeepAlivePeriod
|
||||
{
|
||||
get { return this.keepAlivePeriod; }
|
||||
set { this.keepAlivePeriod = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// protocol name
|
||||
private string protocolName;
|
||||
// protocol version
|
||||
private byte protocolVersion;
|
||||
// client identifier
|
||||
private string clientId;
|
||||
// will retain flag
|
||||
protected bool willRetain;
|
||||
// will quality of service level
|
||||
protected byte willQosLevel;
|
||||
// will flag
|
||||
private bool willFlag;
|
||||
// will topic
|
||||
private string willTopic;
|
||||
// will message
|
||||
private string willMessage;
|
||||
// username
|
||||
private string username;
|
||||
// password
|
||||
private string password;
|
||||
// clean session flag
|
||||
private bool cleanSession;
|
||||
// keep alive period (in sec)
|
||||
private ushort keepAlivePeriod;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public MqttMsgConnect()
|
||||
{
|
||||
this.type = MQTT_MSG_CONNECT_TYPE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="clientId">Client identifier</param>
|
||||
public MqttMsgConnect(string clientId) :
|
||||
this(clientId, null, null, false, QOS_LEVEL_AT_LEAST_ONCE, false, null, null, true, KEEP_ALIVE_PERIOD_DEFAULT, PROTOCOL_VERSION_V3_1_1)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="clientId">Client identifier</param>
|
||||
/// <param name="username">Username</param>
|
||||
/// <param name="password">Password</param>
|
||||
/// <param name="willRetain">Will retain flag</param>
|
||||
/// <param name="willQosLevel">Will QOS level</param>
|
||||
/// <param name="willFlag">Will flag</param>
|
||||
/// <param name="willTopic">Will topic</param>
|
||||
/// <param name="willMessage">Will message</param>
|
||||
/// <param name="cleanSession">Clean sessione flag</param>
|
||||
/// <param name="keepAlivePeriod">Keep alive period</param>
|
||||
/// <param name="protocolVersion">Protocol version</param>
|
||||
public MqttMsgConnect(string clientId,
|
||||
string username,
|
||||
string password,
|
||||
bool willRetain,
|
||||
byte willQosLevel,
|
||||
bool willFlag,
|
||||
string willTopic,
|
||||
string willMessage,
|
||||
bool cleanSession,
|
||||
ushort keepAlivePeriod,
|
||||
byte protocolVersion
|
||||
)
|
||||
{
|
||||
this.type = MQTT_MSG_CONNECT_TYPE;
|
||||
|
||||
this.clientId = clientId;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.willRetain = willRetain;
|
||||
this.willQosLevel = willQosLevel;
|
||||
this.willFlag = willFlag;
|
||||
this.willTopic = willTopic;
|
||||
this.willMessage = willMessage;
|
||||
this.cleanSession = cleanSession;
|
||||
this.keepAlivePeriod = keepAlivePeriod;
|
||||
// [v.3.1.1] added new protocol name and version
|
||||
this.protocolVersion = protocolVersion;
|
||||
this.protocolName = (this.protocolVersion == PROTOCOL_VERSION_V3_1_1) ? PROTOCOL_NAME_V3_1_1 : PROTOCOL_NAME_V3_1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse bytes for a CONNECT message
|
||||
/// </summary>
|
||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||
/// <param name="protocolVersion">Protocol Version</param>
|
||||
/// <param name="channel">Channel connected to the broker</param>
|
||||
/// <returns>CONNECT message instance</returns>
|
||||
public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
||||
{
|
||||
byte[] buffer;
|
||||
int index = 0;
|
||||
int protNameUtf8Length;
|
||||
byte[] protNameUtf8;
|
||||
bool isUsernameFlag;
|
||||
bool isPasswordFlag;
|
||||
int clientIdUtf8Length;
|
||||
byte[] clientIdUtf8;
|
||||
int willTopicUtf8Length;
|
||||
byte[] willTopicUtf8;
|
||||
int willMessageUtf8Length;
|
||||
byte[] willMessageUtf8;
|
||||
int usernameUtf8Length;
|
||||
byte[] usernameUtf8;
|
||||
int passwordUtf8Length;
|
||||
byte[] passwordUtf8;
|
||||
MqttMsgConnect msg = new MqttMsgConnect();
|
||||
|
||||
// get remaining length and allocate buffer
|
||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
||||
buffer = new byte[remainingLength];
|
||||
|
||||
// read bytes from socket...
|
||||
channel.Receive(buffer);
|
||||
|
||||
// protocol name
|
||||
protNameUtf8Length = ((buffer[index++] << 8) & 0xFF00);
|
||||
protNameUtf8Length |= buffer[index++];
|
||||
protNameUtf8 = new byte[protNameUtf8Length];
|
||||
Array.Copy(buffer, index, protNameUtf8, 0, protNameUtf8Length);
|
||||
index += protNameUtf8Length;
|
||||
msg.protocolName = new String(Encoding.UTF8.GetChars(protNameUtf8));
|
||||
|
||||
// [v3.1.1] wrong protocol name
|
||||
if (!msg.protocolName.Equals(PROTOCOL_NAME_V3_1) && !msg.protocolName.Equals(PROTOCOL_NAME_V3_1_1))
|
||||
throw new MqttClientException(MqttClientErrorCode.InvalidProtocolName);
|
||||
|
||||
// protocol version
|
||||
msg.protocolVersion = buffer[index];
|
||||
index += PROTOCOL_VERSION_SIZE;
|
||||
|
||||
// connect flags
|
||||
// [v3.1.1] check lsb (reserved) must be 0
|
||||
if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) &&
|
||||
((buffer[index] & RESERVED_FLAG_MASK) != 0x00))
|
||||
throw new MqttClientException(MqttClientErrorCode.InvalidConnectFlags);
|
||||
|
||||
isUsernameFlag = (buffer[index] & USERNAME_FLAG_MASK) != 0x00;
|
||||
isPasswordFlag = (buffer[index] & PASSWORD_FLAG_MASK) != 0x00;
|
||||
msg.willRetain = (buffer[index] & WILL_RETAIN_FLAG_MASK) != 0x00;
|
||||
msg.willQosLevel = (byte)((buffer[index] & WILL_QOS_FLAG_MASK) >> WILL_QOS_FLAG_OFFSET);
|
||||
msg.willFlag = (buffer[index] & WILL_FLAG_MASK) != 0x00;
|
||||
msg.cleanSession = (buffer[index] & CLEAN_SESSION_FLAG_MASK) != 0x00;
|
||||
index += CONNECT_FLAGS_SIZE;
|
||||
|
||||
// keep alive timer
|
||||
msg.keepAlivePeriod = (ushort)((buffer[index++] << 8) & 0xFF00);
|
||||
msg.keepAlivePeriod |= buffer[index++];
|
||||
|
||||
// client identifier [v3.1.1] it may be zero bytes long (empty string)
|
||||
clientIdUtf8Length = ((buffer[index++] << 8) & 0xFF00);
|
||||
clientIdUtf8Length |= buffer[index++];
|
||||
clientIdUtf8 = new byte[clientIdUtf8Length];
|
||||
Array.Copy(buffer, index, clientIdUtf8, 0, clientIdUtf8Length);
|
||||
index += clientIdUtf8Length;
|
||||
msg.clientId = new String(Encoding.UTF8.GetChars(clientIdUtf8));
|
||||
// [v3.1.1] if client identifier is zero bytes long, clean session must be true
|
||||
if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) && (clientIdUtf8Length == 0) && (!msg.cleanSession))
|
||||
throw new MqttClientException(MqttClientErrorCode.InvalidClientId);
|
||||
|
||||
// will topic and will message
|
||||
if (msg.willFlag)
|
||||
{
|
||||
willTopicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
|
||||
willTopicUtf8Length |= buffer[index++];
|
||||
willTopicUtf8 = new byte[willTopicUtf8Length];
|
||||
Array.Copy(buffer, index, willTopicUtf8, 0, willTopicUtf8Length);
|
||||
index += willTopicUtf8Length;
|
||||
msg.willTopic = new String(Encoding.UTF8.GetChars(willTopicUtf8));
|
||||
|
||||
willMessageUtf8Length = ((buffer[index++] << 8) & 0xFF00);
|
||||
willMessageUtf8Length |= buffer[index++];
|
||||
willMessageUtf8 = new byte[willMessageUtf8Length];
|
||||
Array.Copy(buffer, index, willMessageUtf8, 0, willMessageUtf8Length);
|
||||
index += willMessageUtf8Length;
|
||||
msg.willMessage = new String(Encoding.UTF8.GetChars(willMessageUtf8));
|
||||
}
|
||||
|
||||
// username
|
||||
if (isUsernameFlag)
|
||||
{
|
||||
usernameUtf8Length = ((buffer[index++] << 8) & 0xFF00);
|
||||
usernameUtf8Length |= buffer[index++];
|
||||
usernameUtf8 = new byte[usernameUtf8Length];
|
||||
Array.Copy(buffer, index, usernameUtf8, 0, usernameUtf8Length);
|
||||
index += usernameUtf8Length;
|
||||
msg.username = new String(Encoding.UTF8.GetChars(usernameUtf8));
|
||||
}
|
||||
|
||||
// password
|
||||
if (isPasswordFlag)
|
||||
{
|
||||
passwordUtf8Length = ((buffer[index++] << 8) & 0xFF00);
|
||||
passwordUtf8Length |= buffer[index++];
|
||||
passwordUtf8 = new byte[passwordUtf8Length];
|
||||
Array.Copy(buffer, index, passwordUtf8, 0, passwordUtf8Length);
|
||||
index += passwordUtf8Length;
|
||||
msg.password = new String(Encoding.UTF8.GetChars(passwordUtf8));
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public override byte[] GetBytes(byte protocolVersion)
|
||||
{
|
||||
int fixedHeaderSize = 0;
|
||||
int varHeaderSize = 0;
|
||||
int payloadSize = 0;
|
||||
int remainingLength = 0;
|
||||
byte[] buffer;
|
||||
int index = 0;
|
||||
|
||||
byte[] clientIdUtf8 = Encoding.UTF8.GetBytes(this.clientId);
|
||||
byte[] willTopicUtf8 = (this.willFlag && (this.willTopic != null)) ? Encoding.UTF8.GetBytes(this.willTopic) : null;
|
||||
byte[] willMessageUtf8 = (this.willFlag && (this.willMessage != null)) ? Encoding.UTF8.GetBytes(this.willMessage) : null;
|
||||
byte[] usernameUtf8 = ((this.username != null) && (this.username.Length > 0)) ? Encoding.UTF8.GetBytes(this.username) : null;
|
||||
byte[] passwordUtf8 = ((this.password != null) && (this.password.Length > 0)) ? Encoding.UTF8.GetBytes(this.password) : null;
|
||||
|
||||
// [v3.1.1]
|
||||
if (this.protocolVersion == PROTOCOL_VERSION_V3_1_1)
|
||||
{
|
||||
// will flag set, will topic and will message MUST be present
|
||||
if (this.willFlag && ((this.willQosLevel >= 0x03) ||
|
||||
(willTopicUtf8 == null) || (willMessageUtf8 == null) ||
|
||||
((willTopicUtf8 != null) && (willTopicUtf8.Length == 0)) ||
|
||||
((willMessageUtf8 != null) && (willMessageUtf8.Length == 0))))
|
||||
throw new MqttClientException(MqttClientErrorCode.WillWrong);
|
||||
// willflag not set, retain must be 0 and will topic and message MUST NOT be present
|
||||
else if (!this.willFlag && ((this.willRetain) ||
|
||||
(willTopicUtf8 != null) || (willMessageUtf8 != null) ||
|
||||
((willTopicUtf8 != null) && (willTopicUtf8.Length != 0)) ||
|
||||
((willMessageUtf8 != null) && (willMessageUtf8.Length != 0))))
|
||||
throw new MqttClientException(MqttClientErrorCode.WillWrong);
|
||||
}
|
||||
|
||||
if (this.keepAlivePeriod > MAX_KEEP_ALIVE)
|
||||
throw new MqttClientException(MqttClientErrorCode.KeepAliveWrong);
|
||||
|
||||
// check on will QoS Level
|
||||
if ((this.willQosLevel < MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE) ||
|
||||
(this.willQosLevel > MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE))
|
||||
throw new MqttClientException(MqttClientErrorCode.WillWrong);
|
||||
|
||||
// protocol name field size
|
||||
// MQTT version 3.1
|
||||
if (this.protocolVersion == PROTOCOL_VERSION_V3_1)
|
||||
{
|
||||
varHeaderSize += (PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_SIZE);
|
||||
}
|
||||
// MQTT version 3.1.1
|
||||
else
|
||||
{
|
||||
varHeaderSize += (PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_1_SIZE);
|
||||
}
|
||||
// protocol level field size
|
||||
varHeaderSize += PROTOCOL_VERSION_SIZE;
|
||||
// connect flags field size
|
||||
varHeaderSize += CONNECT_FLAGS_SIZE;
|
||||
// keep alive timer field size
|
||||
varHeaderSize += KEEP_ALIVE_TIME_SIZE;
|
||||
|
||||
// client identifier field size
|
||||
payloadSize += clientIdUtf8.Length + 2;
|
||||
// will topic field size
|
||||
payloadSize += (willTopicUtf8 != null) ? (willTopicUtf8.Length + 2) : 0;
|
||||
// will message field size
|
||||
payloadSize += (willMessageUtf8 != null) ? (willMessageUtf8.Length + 2) : 0;
|
||||
// username field size
|
||||
payloadSize += (usernameUtf8 != null) ? (usernameUtf8.Length + 2) : 0;
|
||||
// password field size
|
||||
payloadSize += (passwordUtf8 != null) ? (passwordUtf8.Length + 2) : 0;
|
||||
|
||||
remainingLength += (varHeaderSize + payloadSize);
|
||||
|
||||
// first byte of fixed header
|
||||
fixedHeaderSize = 1;
|
||||
|
||||
int temp = remainingLength;
|
||||
// increase fixed header size based on remaining length
|
||||
// (each remaining length byte can encode until 128)
|
||||
do
|
||||
{
|
||||
fixedHeaderSize++;
|
||||
temp = temp / 128;
|
||||
} while (temp > 0);
|
||||
|
||||
// allocate buffer for message
|
||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||
|
||||
// first fixed header byte
|
||||
buffer[index++] = (MQTT_MSG_CONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNECT_FLAG_BITS; // [v.3.1.1]
|
||||
|
||||
// encode remaining length
|
||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
||||
|
||||
// protocol name
|
||||
buffer[index++] = 0; // MSB protocol name size
|
||||
// MQTT version 3.1
|
||||
if (this.protocolVersion == PROTOCOL_VERSION_V3_1)
|
||||
{
|
||||
buffer[index++] = PROTOCOL_NAME_V3_1_SIZE; // LSB protocol name size
|
||||
Array.Copy(Encoding.UTF8.GetBytes(PROTOCOL_NAME_V3_1), 0, buffer, index, PROTOCOL_NAME_V3_1_SIZE);
|
||||
index += PROTOCOL_NAME_V3_1_SIZE;
|
||||
// protocol version
|
||||
buffer[index++] = PROTOCOL_VERSION_V3_1;
|
||||
}
|
||||
// MQTT version 3.1.1
|
||||
else
|
||||
{
|
||||
buffer[index++] = PROTOCOL_NAME_V3_1_1_SIZE; // LSB protocol name size
|
||||
Array.Copy(Encoding.UTF8.GetBytes(PROTOCOL_NAME_V3_1_1), 0, buffer, index, PROTOCOL_NAME_V3_1_1_SIZE);
|
||||
index += PROTOCOL_NAME_V3_1_1_SIZE;
|
||||
// protocol version
|
||||
buffer[index++] = PROTOCOL_VERSION_V3_1_1;
|
||||
}
|
||||
|
||||
// connect flags
|
||||
byte connectFlags = 0x00;
|
||||
connectFlags |= (usernameUtf8 != null) ? (byte)(1 << USERNAME_FLAG_OFFSET) : (byte)0x00;
|
||||
connectFlags |= (passwordUtf8 != null) ? (byte)(1 << PASSWORD_FLAG_OFFSET) : (byte)0x00;
|
||||
connectFlags |= (this.willRetain) ? (byte)(1 << WILL_RETAIN_FLAG_OFFSET) : (byte)0x00;
|
||||
// only if will flag is set, we have to use will QoS level (otherwise is MUST be 0)
|
||||
if (this.willFlag)
|
||||
connectFlags |= (byte)(this.willQosLevel << WILL_QOS_FLAG_OFFSET);
|
||||
connectFlags |= (this.willFlag) ? (byte)(1 << WILL_FLAG_OFFSET) : (byte)0x00;
|
||||
connectFlags |= (this.cleanSession) ? (byte)(1 << CLEAN_SESSION_FLAG_OFFSET) : (byte)0x00;
|
||||
buffer[index++] = connectFlags;
|
||||
|
||||
// keep alive period
|
||||
buffer[index++] = (byte)((this.keepAlivePeriod >> 8) & 0x00FF); // MSB
|
||||
buffer[index++] = (byte)(this.keepAlivePeriod & 0x00FF); // LSB
|
||||
|
||||
// client identifier
|
||||
buffer[index++] = (byte)((clientIdUtf8.Length >> 8) & 0x00FF); // MSB
|
||||
buffer[index++] = (byte)(clientIdUtf8.Length & 0x00FF); // LSB
|
||||
Array.Copy(clientIdUtf8, 0, buffer, index, clientIdUtf8.Length);
|
||||
index += clientIdUtf8.Length;
|
||||
|
||||
// will topic
|
||||
if (this.willFlag && (willTopicUtf8 != null))
|
||||
{
|
||||
buffer[index++] = (byte)((willTopicUtf8.Length >> 8) & 0x00FF); // MSB
|
||||
buffer[index++] = (byte)(willTopicUtf8.Length & 0x00FF); // LSB
|
||||
Array.Copy(willTopicUtf8, 0, buffer, index, willTopicUtf8.Length);
|
||||
index += willTopicUtf8.Length;
|
||||
}
|
||||
|
||||
// will message
|
||||
if (this.willFlag && (willMessageUtf8 != null))
|
||||
{
|
||||
buffer[index++] = (byte)((willMessageUtf8.Length >> 8) & 0x00FF); // MSB
|
||||
buffer[index++] = (byte)(willMessageUtf8.Length & 0x00FF); // LSB
|
||||
Array.Copy(willMessageUtf8, 0, buffer, index, willMessageUtf8.Length);
|
||||
index += willMessageUtf8.Length;
|
||||
}
|
||||
|
||||
// username
|
||||
if (usernameUtf8 != null)
|
||||
{
|
||||
buffer[index++] = (byte)((usernameUtf8.Length >> 8) & 0x00FF); // MSB
|
||||
buffer[index++] = (byte)(usernameUtf8.Length & 0x00FF); // LSB
|
||||
Array.Copy(usernameUtf8, 0, buffer, index, usernameUtf8.Length);
|
||||
index += usernameUtf8.Length;
|
||||
}
|
||||
|
||||
// password
|
||||
if (passwordUtf8 != null)
|
||||
{
|
||||
buffer[index++] = (byte)((passwordUtf8.Length >> 8) & 0x00FF); // MSB
|
||||
buffer[index++] = (byte)(passwordUtf8.Length & 0x00FF); // LSB
|
||||
Array.Copy(passwordUtf8, 0, buffer, index, passwordUtf8.Length);
|
||||
index += passwordUtf8.Length;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
#if TRACE
|
||||
return this.GetTraceString(
|
||||
"CONNECT",
|
||||
new object[] { "protocolName", "protocolVersion", "clientId", "willFlag", "willRetain", "willQosLevel", "willTopic", "willMessage", "username", "password", "cleanSession", "keepAlivePeriod" },
|
||||
new object[] { this.protocolName, this.protocolVersion, this.clientId, this.willFlag, this.willRetain, this.willQosLevel, this.willTopic, this.willMessage, this.username, this.password, this.cleanSession, this.keepAlivePeriod });
|
||||
#else
|
||||
return base.ToString();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
44
Librarys/mqtt/M2Mqtt/Messages/MqttMsgConnectEventArgs.cs
Normal file
44
Librarys/mqtt/M2Mqtt/Messages/MqttMsgConnectEventArgs.cs
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
|
||||
using System;
|
||||
#else
|
||||
using Microsoft.SPOT;
|
||||
#endif
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Event Args class for CONNECT message received from client
|
||||
/// </summary>
|
||||
public class MqttMsgConnectEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Message received from client
|
||||
/// </summary>
|
||||
public MqttMsgConnect Message { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="msg">CONNECT message received from client</param>
|
||||
public MqttMsgConnectEventArgs(MqttMsgConnect connect)
|
||||
{
|
||||
this.Message = connect;
|
||||
}
|
||||
}
|
||||
}
|
159
Librarys/mqtt/M2Mqtt/Messages/MqttMsgContext.cs
Normal file
159
Librarys/mqtt/M2Mqtt/Messages/MqttMsgContext.cs
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Context for MQTT message
|
||||
/// </summary>
|
||||
public class MqttMsgContext
|
||||
{
|
||||
/// <summary>
|
||||
/// MQTT message
|
||||
/// </summary>
|
||||
public MqttMsgBase Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MQTT message state
|
||||
/// </summary>
|
||||
public MqttMsgState State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flow of the message
|
||||
/// </summary>
|
||||
public MqttMsgFlow Flow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp in ticks (for retry)
|
||||
/// </summary>
|
||||
public int Timestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attempt (for retry)
|
||||
/// </summary>
|
||||
public int Attempt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unique key
|
||||
/// </summary>
|
||||
public string Key
|
||||
{
|
||||
get { return this.Flow + "_" + this.Message.MessageId; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flow of the message
|
||||
/// </summary>
|
||||
public enum MqttMsgFlow
|
||||
{
|
||||
/// <summary>
|
||||
/// To publish to subscribers
|
||||
/// </summary>
|
||||
ToPublish,
|
||||
|
||||
/// <summary>
|
||||
/// To acknowledge to publisher
|
||||
/// </summary>
|
||||
ToAcknowledge
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MQTT message state
|
||||
/// </summary>
|
||||
public enum MqttMsgState
|
||||
{
|
||||
/// <summary>
|
||||
/// QOS = 0, Message queued
|
||||
/// </summary>
|
||||
QueuedQos0,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 1, Message queued
|
||||
/// </summary>
|
||||
QueuedQos1,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 2, Message queued
|
||||
/// </summary>
|
||||
QueuedQos2,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 1, PUBLISH sent, wait for PUBACK
|
||||
/// </summary>
|
||||
WaitForPuback,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 2, PUBLISH sent, wait for PUBREC
|
||||
/// </summary>
|
||||
WaitForPubrec,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 2, PUBREC sent, wait for PUBREL
|
||||
/// </summary>
|
||||
WaitForPubrel,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 2, PUBREL sent, wait for PUBCOMP
|
||||
/// </summary>
|
||||
WaitForPubcomp,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 2, start first phase handshake send PUBREC
|
||||
/// </summary>
|
||||
SendPubrec,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 2, start second phase handshake send PUBREL
|
||||
/// </summary>
|
||||
SendPubrel,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 2, end second phase handshake send PUBCOMP
|
||||
/// </summary>
|
||||
SendPubcomp,
|
||||
|
||||
/// <summary>
|
||||
/// QOS = 1, PUBLISH received, send PUBACK
|
||||
/// </summary>
|
||||
SendPuback,
|
||||
|
||||
// [v3.1.1] SUBSCRIBE isn't "officially" QOS = 1
|
||||
/// <summary>
|
||||
/// Send SUBSCRIBE message
|
||||
/// </summary>
|
||||
SendSubscribe,
|
||||
|
||||
// [v3.1.1] UNSUBSCRIBE isn't "officially" QOS = 1
|
||||
/// <summary>
|
||||
/// Send UNSUBSCRIBE message
|
||||
/// </summary>
|
||||
SendUnsubscribe,
|
||||
|
||||
/// <summary>
|
||||
/// (QOS = 1), SUBSCRIBE sent, wait for SUBACK
|
||||
/// </summary>
|
||||
WaitForSuback,
|
||||
|
||||
/// <summary>
|
||||
/// (QOS = 1), UNSUBSCRIBE sent, wait for UNSUBACK
|
||||
/// </summary>
|
||||
WaitForUnsuback
|
||||
}
|
||||
}
|
86
Librarys/mqtt/M2Mqtt/Messages/MqttMsgDisconnect.cs
Normal file
86
Librarys/mqtt/M2Mqtt/Messages/MqttMsgDisconnect.cs
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using uPLibrary.Networking.M2Mqtt.Exceptions;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for DISCONNECT message from client to broker
|
||||
/// </summary>
|
||||
public class MqttMsgDisconnect : MqttMsgBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public MqttMsgDisconnect()
|
||||
{
|
||||
this.type = MQTT_MSG_DISCONNECT_TYPE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse bytes for a DISCONNECT message
|
||||
/// </summary>
|
||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||
/// <param name="protocolVersion">Protocol Version</param>
|
||||
/// <param name="channel">Channel connected to the broker</param>
|
||||
/// <returns>DISCONNECT message instance</returns>
|
||||
public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
||||
{
|
||||
MqttMsgDisconnect msg = new MqttMsgDisconnect();
|
||||
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
{
|
||||
// [v3.1.1] check flag bits
|
||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS)
|
||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||
}
|
||||
|
||||
// get remaining length and allocate buffer
|
||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
||||
// NOTE : remainingLength must be 0
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public override byte[] GetBytes(byte protocolVersion)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
int index = 0;
|
||||
|
||||
// first fixed header byte
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_DISCONNECT_FLAG_BITS; // [v.3.1.1]
|
||||
else
|
||||
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
|
||||
buffer[index++] = 0x00;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
#if TRACE
|
||||
return this.GetTraceString(
|
||||
"DISCONNECT",
|
||||
null,
|
||||
null);
|
||||
#else
|
||||
return base.ToString();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
86
Librarys/mqtt/M2Mqtt/Messages/MqttMsgPingReq.cs
Normal file
86
Librarys/mqtt/M2Mqtt/Messages/MqttMsgPingReq.cs
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using uPLibrary.Networking.M2Mqtt.Exceptions;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for PINGREQ message from client to broker
|
||||
/// </summary>
|
||||
public class MqttMsgPingReq : MqttMsgBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public MqttMsgPingReq()
|
||||
{
|
||||
this.type = MQTT_MSG_PINGREQ_TYPE;
|
||||
}
|
||||
|
||||
public override byte[] GetBytes(byte protocolVersion)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
int index = 0;
|
||||
|
||||
// first fixed header byte
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGREQ_FLAG_BITS; // [v.3.1.1]
|
||||
else
|
||||
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET);
|
||||
buffer[index++] = 0x00;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse bytes for a PINGREQ message
|
||||
/// </summary>
|
||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||
/// <param name="protocolVersion">Protocol Version</param>
|
||||
/// <param name="channel">Channel connected to the broker</param>
|
||||
/// <returns>PINGREQ message instance</returns>
|
||||
public static MqttMsgPingReq Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
||||
{
|
||||
MqttMsgPingReq msg = new MqttMsgPingReq();
|
||||
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
{
|
||||
// [v3.1.1] check flag bits
|
||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_FLAG_BITS)
|
||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||
}
|
||||
|
||||
// already know remaininglength is zero (MQTT specification),
|
||||
// so it isn't necessary to read other data from socket
|
||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
#if TRACE
|
||||
return this.GetTraceString(
|
||||
"PINGREQ",
|
||||
null,
|
||||
null);
|
||||
#else
|
||||
return base.ToString();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
87
Librarys/mqtt/M2Mqtt/Messages/MqttMsgPingResp.cs
Normal file
87
Librarys/mqtt/M2Mqtt/Messages/MqttMsgPingResp.cs
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using System;
|
||||
using uPLibrary.Networking.M2Mqtt.Exceptions;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for PINGRESP message from client to broker
|
||||
/// </summary>
|
||||
public class MqttMsgPingResp : MqttMsgBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public MqttMsgPingResp()
|
||||
{
|
||||
this.type = MQTT_MSG_PINGRESP_TYPE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse bytes for a PINGRESP message
|
||||
/// </summary>
|
||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||
/// <param name="protocolVersion">Protocol Version</param>
|
||||
/// <param name="channel">Channel connected to the broker</param>
|
||||
/// <returns>PINGRESP message instance</returns>
|
||||
public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
||||
{
|
||||
MqttMsgPingResp msg = new MqttMsgPingResp();
|
||||
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
{
|
||||
// [v3.1.1] check flag bits
|
||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS)
|
||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||
}
|
||||
|
||||
// already know remaininglength is zero (MQTT specification),
|
||||
// so it isn't necessary to read other data from socket
|
||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public override byte[] GetBytes(byte protocolVersion)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
int index = 0;
|
||||
|
||||
// first fixed header byte
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGRESP_FLAG_BITS; // [v.3.1.1]
|
||||
else
|
||||
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET);
|
||||
buffer[index++] = 0x00;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
#if TRACE
|
||||
return this.GetTraceString(
|
||||
"PINGRESP",
|
||||
null,
|
||||
null);
|
||||
#else
|
||||
return base.ToString();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
125
Librarys/mqtt/M2Mqtt/Messages/MqttMsgPuback.cs
Normal file
125
Librarys/mqtt/M2Mqtt/Messages/MqttMsgPuback.cs
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright (c) 2013, 2014 Paolo Patierno
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Paolo Patierno - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
|
||||
using uPLibrary.Networking.M2Mqtt.Exceptions;
|
||||
|
||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for PUBACK message from broker to client
|
||||
/// </summary>
|
||||
public class MqttMsgPuback : MqttMsgBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public MqttMsgPuback()
|
||||
{
|
||||
this.type = MQTT_MSG_PUBACK_TYPE;
|
||||
}
|
||||
|
||||
public override byte[] GetBytes(byte protocolVersion)
|
||||
{
|
||||
int fixedHeaderSize = 0;
|
||||
int varHeaderSize = 0;
|
||||
int payloadSize = 0;
|
||||
int remainingLength = 0;
|
||||
byte[] buffer;
|
||||
int index = 0;
|
||||
|
||||
// message identifier
|
||||
varHeaderSize += MESSAGE_ID_SIZE;
|
||||
|
||||
remainingLength += (varHeaderSize + payloadSize);
|
||||
|
||||
// first byte of fixed header
|
||||
fixedHeaderSize = 1;
|
||||
|
||||
int temp = remainingLength;
|
||||
// increase fixed header size based on remaining length
|
||||
// (each remaining length byte can encode until 128)
|
||||
do
|
||||
{
|
||||
fixedHeaderSize++;
|
||||
temp = temp / 128;
|
||||
} while (temp > 0);
|
||||
|
||||
// allocate buffer for message
|
||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||
|
||||
// first fixed header byte
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBACK_FLAG_BITS; // [v.3.1.1]
|
||||
else
|
||||
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET);
|
||||
|
||||
// encode remaining length
|
||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
||||
|
||||
// get message identifier
|
||||
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
|
||||
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse bytes for a PUBACK message
|
||||
/// </summary>
|
||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||
/// <param name="protocolVersion">Protocol Version</param>
|
||||
/// <param name="channel">Channel connected to the broker</param>
|
||||
/// <returns>PUBACK message instance</returns>
|
||||
public static MqttMsgPuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
||||
{
|
||||
byte[] buffer;
|
||||
int index = 0;
|
||||
MqttMsgPuback msg = new MqttMsgPuback();
|
||||
|
||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
||||
{
|
||||
// [v3.1.1] check flag bits
|
||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS)
|
||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||
}
|
||||
|
||||
// get remaining length and allocate buffer
|
||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
||||
buffer = new byte[remainingLength];
|
||||
|
||||
// read bytes from socket...
|
||||
channel.Receive(buffer);
|
||||
|
||||
// message id
|
||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
||||
msg.messageId |= (buffer[index++]);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
#if TRACE
|
||||
return this.GetTraceString(
|
||||
"PUBACK",
|
||||
new object[] { "messageId" },
|
||||
new object[] { this.messageId });
|
||||
#else
|
||||
return base.ToString();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user