Change a lot of stuff

This commit is contained in:
BlubbFish 2018-05-02 18:33:27 +02:00
parent 329375b7cb
commit 595fbf1465
199 changed files with 17496 additions and 396 deletions

24
.gitignore vendored
View File

@ -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

View 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

View 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>

View 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>

View 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 {
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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();
}
}

View 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;
}
}
}

View 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;
}
}
}
}

View 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>

View 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>

View 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();
}
}
}

View 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")]

View 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));
}
}
}
}

View 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>

View 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;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View 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
View 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

View 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>

View 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>

View 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();
}
}

View 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
}
}

View 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());
}
}
}

View 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")]

View 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));
}
}
}
}

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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;
}
}
}

View 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
View 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

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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) {
}
}
}

View 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
View 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
View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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();
}
}

View 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

Binary file not shown.

Binary file not shown.

67
Hue/Hue/lib/Helper.cs Normal file
View 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
View 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;
}
}
}

View 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

View 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);
}
}

File diff suppressed because it is too large Load Diff

View 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)
{
}
}
}

View 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 ();
}
}
}

View 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) {}
}
}

View 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]);
}
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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

View 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
}
}

View 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")]

Binary file not shown.

View 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
View 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

View 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
}
}

View File

@ -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)
{
}
}
}

View 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)
{
}
}
}

View 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
{
}
}

View 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();
}
}

View 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
{
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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>

View 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>

View 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
}
}

View 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
}
}
}

View 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
}
}
}

View 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;
}
}
}

View 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
}
}

View 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
}
}
}

View 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
}
}
}

View 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
}
}
}

View 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