[WP] Hue library added
This commit is contained in:
commit
62c3c5815c
25
Hue.sln
Normal file
25
Hue.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27004.2010
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hue", "Hue\Hue.csproj", "{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{738A6137-8FCA-4CE1-BD1C-042B21B6B5F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {8F059288-842C-4EA3-AFD4-9AE2E17BD1B3}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
86
Hue/Devices/Groups/Room.cs
Normal file
86
Hue/Devices/Groups/Room.cs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using BlubbFish.IoT.Hue.Interfaces;
|
||||||
|
using BlubbFish.IoT.Hue.lib;
|
||||||
|
using LitJson;
|
||||||
|
|
||||||
|
namespace BlubbFish.IoT.Hue.Devices.Groups {
|
||||||
|
public class Room : AGroup {
|
||||||
|
public override event UpdatedValue Update;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
private AlertEffect _alert;
|
||||||
|
public enum AlertEffect {
|
||||||
|
none,
|
||||||
|
select,
|
||||||
|
lselect
|
||||||
|
}
|
||||||
|
private Boolean _state;
|
||||||
|
public Boolean State {
|
||||||
|
get {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this.SetGroupAction(new Dictionary<String, Object>() { { "on", value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Byte _brightness;
|
||||||
|
public Byte Brightness {
|
||||||
|
get {
|
||||||
|
return this._brightness;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this.SetGroupAction(new Dictionary<String, Object>() { { "bri", value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public AlertEffect Alert {
|
||||||
|
get {
|
||||||
|
return this._alert;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this.SetGroupAction(new Dictionary<String, Object>() { { "alert", 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 Dictionary<String, Object> ToDictionary() {
|
||||||
|
return new Dictionary<String, Object> {
|
||||||
|
{ "State", this.State },
|
||||||
|
{ "Brightness", this.Brightness },
|
||||||
|
{ "Alert", this.Alert.ToString() }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
86
Hue/Devices/Lights/Dimmablelight.cs
Normal file
86
Hue/Devices/Lights/Dimmablelight.cs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using BlubbFish.IoT.Hue.Interfaces;
|
||||||
|
using BlubbFish.IoT.Hue.lib;
|
||||||
|
using LitJson;
|
||||||
|
|
||||||
|
namespace BlubbFish.IoT.Hue.Devices.Lights {
|
||||||
|
public class Dimmablelight : ALight {
|
||||||
|
public override event UpdatedValue Update;
|
||||||
|
public enum AlertEffect {
|
||||||
|
none,
|
||||||
|
select,
|
||||||
|
lselect
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
private Boolean _state;
|
||||||
|
public Boolean State {
|
||||||
|
get {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this.SetLightState(new Dictionary<String, Object>() { { "on", value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Byte _brightness;
|
||||||
|
public Byte Brightness {
|
||||||
|
get {
|
||||||
|
return this._brightness;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this.SetLightState(new Dictionary<String, Object>() { { "bri", value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private AlertEffect _alert;
|
||||||
|
public AlertEffect Alert {
|
||||||
|
get {
|
||||||
|
return this._alert;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this.SetLightState(new Dictionary<String, Object>() { { "alert", 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 Dictionary<String, Object> ToDictionary() {
|
||||||
|
return new Dictionary<String, Object> {
|
||||||
|
{ "State", this.State },
|
||||||
|
{ "Brightness", this.Brightness },
|
||||||
|
{ "Alert", this.Alert.ToString() },
|
||||||
|
{ "Reachable", this.Reachable }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
69
Hue/Devices/Scenes/LightState.cs
Normal file
69
Hue/Devices/Scenes/LightState.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using BlubbFish.IoT.Hue.Interfaces;
|
||||||
|
using BlubbFish.IoT.Hue.lib;
|
||||||
|
using LitJson;
|
||||||
|
|
||||||
|
namespace BlubbFish.IoT.Hue.Devices.Scenes {
|
||||||
|
public class LightState : AConnector {
|
||||||
|
public override event UpdatedValue Update;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
private Boolean _state;
|
||||||
|
public Boolean State {
|
||||||
|
get {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this.SetLightScene(new Dictionary<String, Object>() { { "on", value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Byte _brightness;
|
||||||
|
public Byte Brightness {
|
||||||
|
get {
|
||||||
|
return this._brightness;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this.SetLightScene(new Dictionary<String, Object>() { { "bri", value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public String SceneId { get; }
|
||||||
|
public Int32 LightStateId { get; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
public LightState(JsonData json, Tuple<String, Int32> id, HttpConnection http) {
|
||||||
|
this.http = http;
|
||||||
|
this.SceneId = id.Item1;
|
||||||
|
this.LightStateId = id.Item2;
|
||||||
|
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
|
||||||
|
|
||||||
|
private void SetLightScene(Dictionary<String, Object> value) {
|
||||||
|
this.PutDictionary("scenes/" + this.SceneId + "/lights/" + this.LightStateId + "/state", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region AConnector
|
||||||
|
public override Dictionary<String, Object> ToDictionary() {
|
||||||
|
return new Dictionary<String, Object> {
|
||||||
|
{ "State", this.State.ToString() },
|
||||||
|
{ "Brightness", this.Brightness }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override String ToString() {
|
||||||
|
return "Scene LightState " + this.SceneId + " [" + this.LightStateId + "]: On-" + this.State.ToString() + " Bri-" + this.Brightness;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
73
Hue/Devices/Scenes/Scene.cs
Normal file
73
Hue/Devices/Scenes/Scene.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using BlubbFish.IoT.Hue.Interfaces;
|
||||||
|
using BlubbFish.IoT.Hue.lib;
|
||||||
|
using LitJson;
|
||||||
|
|
||||||
|
namespace BlubbFish.IoT.Hue.Devices.Scenes {
|
||||||
|
class Scene : AScene {
|
||||||
|
public override event UpdatedValue Update;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
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; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
public Scene(JsonData json, Tuple<String> 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("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"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region AConnector
|
||||||
|
public override Dictionary<String, Object> ToDictionary() {
|
||||||
|
return new Dictionary<String, Object> {
|
||||||
|
{ "owner", this.Owner },
|
||||||
|
{ "recycle", this.Recycle },
|
||||||
|
{ "locked", this.Locked },
|
||||||
|
{ "picture", this.Picture },
|
||||||
|
{ "lastupdated", this.Lastupdated },
|
||||||
|
{ "version", this.Version }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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())+"]";
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
45
Hue/Events/UpdateEvent.cs
Normal file
45
Hue/Events/UpdateEvent.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Hue/Exceptions/HueExceptions.cs
Normal file
12
Hue/Exceptions/HueExceptions.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace BlubbFish.IoT.Hue.Exceptions {
|
||||||
|
[Serializable]
|
||||||
|
public class ConnectionException : Exception {
|
||||||
|
public ConnectionException() { }
|
||||||
|
public ConnectionException(String message) : base(message) { }
|
||||||
|
public ConnectionException(String message, Exception innerException) : base(message, innerException) { }
|
||||||
|
protected ConnectionException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||||
|
}
|
||||||
|
}
|
68
Hue/Hue.csproj
Normal file
68
Hue/Hue.csproj
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?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\Scenes\LightState.cs" />
|
||||||
|
<Compile Include="Devices\Scenes\Scene.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\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>
|
162
Hue/HueController.cs
Normal file
162
Hue/HueController.cs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
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 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, Sensor> item in this.Sensors) {
|
||||||
|
item.Value.Update += this.AllUpdate;
|
||||||
|
}
|
||||||
|
this.Config.Update += this.AllUpdate;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Poll() {
|
||||||
|
//throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AllUpdate(Object sender, AllUpdateEvent e) {
|
||||||
|
this.Update?.Invoke(sender, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Updater() {
|
||||||
|
//throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateAll(JsonData json) {
|
||||||
|
if(json.ContainsKey("lights")) {
|
||||||
|
this.CreateLights(json["lights"]);
|
||||||
|
}
|
||||||
|
if(json.ContainsKey("groups")) {
|
||||||
|
this.CreateGroups(json["groups"]);
|
||||||
|
}
|
||||||
|
if(json.ContainsKey("scenes")) {
|
||||||
|
this.CreateScenes(json["scenes"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateScenes(JsonData json) {
|
||||||
|
Dictionary<String, AScene> scenes = new Dictionary<String, AScene>();
|
||||||
|
foreach (String sceneid in json.Keys) {
|
||||||
|
AScene s = AScene.CreateScene(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 CreateGroups(JsonData json) {
|
||||||
|
Dictionary<Int32, AGroup> groups = new Dictionary<Int32, AGroup>();
|
||||||
|
foreach (String groupid in json.Keys) {
|
||||||
|
AGroup g = AGroup.CreateGroup(json[groupid], new Tuple<Int32>(Int32.Parse(groupid)), this.http, this.polling, this.Lights);
|
||||||
|
if (g != null) {
|
||||||
|
groups.Add(Int32.Parse(groupid), g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Groups = new ReadOnlyDictionary<Int32, AGroup>(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateLights(JsonData json) {
|
||||||
|
Dictionary<Int32, ALight> lights = new Dictionary<Int32, ALight>();
|
||||||
|
foreach (String lightid in json.Keys) {
|
||||||
|
ALight l = ALight.CreateLight(json[lightid], new Tuple<Int32>(Int32.Parse(lightid)), this.http, this.polling);
|
||||||
|
if(l != null) {
|
||||||
|
lights.Add(Int32.Parse(lightid), l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Lights = new ReadOnlyDictionary<Int32, ALight>(lights);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
20
Hue/Interfaces/AConnector.cs
Normal file
20
Hue/Interfaces/AConnector.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
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 AConnector {
|
||||||
|
protected HttpConnection http;
|
||||||
|
|
||||||
|
protected void PutDictionary(String address, Dictionary<String, Object> value) {
|
||||||
|
this.http.PutJson(address, JsonMapper.ToJson(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void UpdatedValue(Object sender, AllUpdateEvent e);
|
||||||
|
public abstract override String ToString();
|
||||||
|
public abstract Dictionary<String, Object> ToDictionary();
|
||||||
|
public abstract event UpdatedValue Update;
|
||||||
|
}
|
||||||
|
}
|
165
Hue/Interfaces/AGroup.cs
Normal file
165
Hue/Interfaces/AGroup.cs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
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 DateTime LastUpdate { get; protected set; }
|
||||||
|
public Boolean Polling { get; set; }
|
||||||
|
public String Name { get {
|
||||||
|
return this._name;
|
||||||
|
} set {
|
||||||
|
this._name = value;
|
||||||
|
this.SetGroupAttribute(new Dictionary<String, Object>() { { "name", value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Int32 GroupId { get; }
|
||||||
|
public Types Groupclass { get; }
|
||||||
|
public Boolean StateAnyOn { get; protected set; }
|
||||||
|
public Boolean StateAllOn { get; protected set; }
|
||||||
|
public Dictionary<Int32, ALight> Lights { get; protected set; }
|
||||||
|
public GroupClass Class {
|
||||||
|
get {
|
||||||
|
return this._class;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this._class = value;
|
||||||
|
this.SetGroupAttribute(new Dictionary<String, Object>() { { "class", Helper.GetEnumDescription(value) } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
protected AGroup(JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||||
|
this.GroupId = id.Item1;
|
||||||
|
this.Groupclass = id.Item2;
|
||||||
|
this.http = http;
|
||||||
|
this.LastUpdate = DateTime.Now;
|
||||||
|
this.Polling = polling;
|
||||||
|
this.ComplexInit(json, lights);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static AGroup CreateGroup(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
|
||||||
|
|
||||||
|
private void ComplexInit(JsonData json, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||||
|
if (json.ContainsKey("lights") && json["lights"].IsArray) {
|
||||||
|
this.Lights = new Dictionary<Int32, ALight>();
|
||||||
|
foreach (JsonData item in json["lights"]) {
|
||||||
|
if (Int32.TryParse(item.ToString(), out Int32 lampid)) {
|
||||||
|
if (lights.ContainsKey(lampid)) {
|
||||||
|
this.Lights.Add(lampid, lights[lampid]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (json.ContainsKey("name")) {
|
||||||
|
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")) {
|
||||||
|
this._class = (GroupClass)Enum.Parse(typeof(GroupClass), json["class"].ToString().ToEnumString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetGroupAttribute(Dictionary<String, Object> value) {
|
||||||
|
this.PutDictionary("groups/" + this.GroupId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetGroupAction(Dictionary<String, Object> value) {
|
||||||
|
this.PutDictionary("groups/" + this.GroupId + "/action", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IMqtt
|
||||||
|
public String ToJson() {
|
||||||
|
Dictionary<String, Object> json = this.ToDictionary();
|
||||||
|
json.Add("StateAnyOn", this.StateAnyOn.ToString());
|
||||||
|
json.Add("StateAllOn", this.StateAllOn.ToString());
|
||||||
|
json.Add("Class", Helper.GetEnumDescription(this.Class));
|
||||||
|
json.Add("LastUpdate", this.LastUpdate.ToString());
|
||||||
|
json.Add("Name", this.Name);
|
||||||
|
json.Add("Lightclass", this.Groupclass.ToString());
|
||||||
|
Dictionary<String, Object> lights = new Dictionary<String, Object>();
|
||||||
|
foreach (KeyValuePair<Int32, ALight> item in this.Lights) {
|
||||||
|
lights.Add(item.Key.ToString(), item.Value.ToDictionary());
|
||||||
|
}
|
||||||
|
json.Add("lights", lights);
|
||||||
|
return JsonMapper.ToJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String MqttTopic() {
|
||||||
|
return "groups/" + this.GroupId + "/" + this.Groupclass.ToString();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
87
Hue/Interfaces/ALight.cs
Normal file
87
Hue/Interfaces/ALight.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
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; }
|
||||||
|
public DateTime LastUpdate { get; protected set; }
|
||||||
|
public String Name { get; protected set; }
|
||||||
|
public Boolean Polling { get; set; }
|
||||||
|
public Boolean PollOnce { get; set; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
protected ALight(JsonData json, Tuple<Int32, Types> id, HttpConnection http, Boolean polling) {
|
||||||
|
this.LightId = id.Item1;
|
||||||
|
this.Lightclass = id.Item2;
|
||||||
|
this.http = http;
|
||||||
|
this.LastUpdate = DateTime.Now;
|
||||||
|
this.Polling = polling;
|
||||||
|
this.ComplexInit(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ALight CreateLight(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
|
||||||
|
|
||||||
|
private void ComplexInit(JsonData json) {
|
||||||
|
if (json.ContainsKey("name")) {
|
||||||
|
this.Name = json["name"].ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetLightState(Dictionary<String, Object> value) {
|
||||||
|
this.PutDictionary("lights/" + this.LightId + "/state", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IMqtt
|
||||||
|
public String MqttTopic() {
|
||||||
|
return "lights/" + this.LightId + "/" + this.Lightclass.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String ToJson() {
|
||||||
|
Dictionary<String, Object> json = this.ToDictionary();
|
||||||
|
json.Add("LastUpdate", this.LastUpdate.ToString());
|
||||||
|
json.Add("Name", this.Name);
|
||||||
|
json.Add("Lightclass", this.Lightclass.ToString());
|
||||||
|
return JsonMapper.ToJson(json);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
105
Hue/Interfaces/AScene.cs
Normal file
105
Hue/Interfaces/AScene.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
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 {
|
||||||
|
private Boolean Polling;
|
||||||
|
private String _name;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public String SceneId { get; }
|
||||||
|
public DateTime LastUpdate { get; }
|
||||||
|
public Dictionary<Int32, ALight> Lights { get; private set; }
|
||||||
|
public Dictionary<Int32, LightState> LightStates { get; private set; }
|
||||||
|
public String Name {
|
||||||
|
get {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this._name = value;
|
||||||
|
this.SetSceneAttribute(new Dictionary<String, Object>() { { "name", value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
protected AScene(JsonData json, Tuple<String> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||||
|
this.SceneId = id.Item1;
|
||||||
|
this.http = http;
|
||||||
|
this.LastUpdate = DateTime.Now;
|
||||||
|
this.Polling = polling;
|
||||||
|
this.ComplexInit(json, lights);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static AScene CreateScene(JsonData json, Tuple<String> id, HttpConnection http, Boolean polling, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||||
|
String name = "BlubbFish.IoT.Hue.Devices.Scenes.Scene";
|
||||||
|
JsonData scenedata = http.GetJson("scenes/" + id.Item1);
|
||||||
|
return GetInstanceConcrete(name, scenedata, id, http, polling, lights);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AScene GetInstanceConcrete(String name, JsonData json, Tuple<String> 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 (AScene)t.GetConstructor(new Type[] { typeof(JsonData), typeof(Tuple<String>), typeof(HttpConnection), typeof(Boolean), typeof(ReadOnlyDictionary<Int32, ALight>) }).Invoke(new Object[] { json, id, http, polling, lights });
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void ComplexInit(JsonData json, ReadOnlyDictionary<Int32, ALight> lights) {
|
||||||
|
if (json.ContainsKey("lights") && json["lights"].IsArray) {
|
||||||
|
this.Lights = new Dictionary<Int32, ALight>();
|
||||||
|
foreach (JsonData item in json["lights"]) {
|
||||||
|
if (Int32.TryParse(item.ToString(), out Int32 lampid)) {
|
||||||
|
if (lights.ContainsKey(lampid)) {
|
||||||
|
this.Lights.Add(lampid, lights[lampid]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (json.ContainsKey("name")) {
|
||||||
|
this._name = json["name"].ToString();
|
||||||
|
}
|
||||||
|
if (json.ContainsKey("lightstates")) {
|
||||||
|
this.LightStates = new Dictionary<Int32, LightState>();
|
||||||
|
foreach (String item in json["lightstates"].Keys) {
|
||||||
|
this.LightStates.Add(Int32.Parse(item), new LightState(json["lightstates"][item], new Tuple<String, Int32>(this.SceneId, Int32.Parse(item)), this.http));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetSceneAttribute(Dictionary<String, Object> dictionary) {
|
||||||
|
this.PutDictionary("scenes/" + this.SceneId, dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IMqtt
|
||||||
|
public String ToJson() {
|
||||||
|
Dictionary<String, Object> json = this.ToDictionary();
|
||||||
|
json.Add("LastUpdate", this.LastUpdate.ToString());
|
||||||
|
json.Add("Name", this.Name);
|
||||||
|
Dictionary<String, Object> lights = new Dictionary<String, Object>();
|
||||||
|
foreach (KeyValuePair<Int32, ALight> item in this.Lights) {
|
||||||
|
lights.Add(item.Key.ToString(), item.Value.ToDictionary());
|
||||||
|
}
|
||||||
|
json.Add("lights", lights);
|
||||||
|
Dictionary<String, Object> states = new Dictionary<String, Object>();
|
||||||
|
foreach (KeyValuePair<Int32, LightState> item in this.LightStates) {
|
||||||
|
states.Add(item.Key.ToString(), item.Value.ToDictionary());
|
||||||
|
}
|
||||||
|
json.Add("lightstates", states);
|
||||||
|
return JsonMapper.ToJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String MqttTopic() {
|
||||||
|
return "groups/" + this.SceneId;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
12
Hue/Interfaces/IMqtt.cs
Normal file
12
Hue/Interfaces/IMqtt.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BlubbFish.IoT.Hue.Interfaces {
|
||||||
|
interface IMqtt {
|
||||||
|
String ToJson();
|
||||||
|
String MqttTopic();
|
||||||
|
}
|
||||||
|
}
|
36
Hue/Properties/AssemblyInfo.cs
Normal file
36
Hue/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||||
|
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||||
|
// die einer Assembly zugeordnet sind.
|
||||||
|
[assembly: AssemblyTitle("Hue")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("Hue")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
|
||||||
|
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
|
||||||
|
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||||
|
[assembly: Guid("738a6137-8fca-4ce1-bd1c-042b21b6b5f2")]
|
||||||
|
|
||||||
|
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||||
|
//
|
||||||
|
// Hauptversion
|
||||||
|
// Nebenversion
|
||||||
|
// Buildnummer
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
|
||||||
|
// indem Sie "*" wie unten gezeigt eingeben:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
37
Hue/lib/Helper.cs
Normal file
37
Hue/lib/Helper.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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/lib/HttpClient.cs
Normal file
96
Hue/lib/HttpClient.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LitJson;
|
||||||
|
|
||||||
|
namespace BlubbFish.IoT.Hue.lib {
|
||||||
|
public class HttpConnection {
|
||||||
|
private String server;
|
||||||
|
private Object getLock = new Object();
|
||||||
|
private enum RequestMethod {
|
||||||
|
GET,
|
||||||
|
POST,
|
||||||
|
PUT
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpConnection(String server) {
|
||||||
|
this.server = "http://" + server + "/api/";
|
||||||
|
this.Init(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpConnection(String server, String key) {
|
||||||
|
this.server = "http://" + server + "/api/" + key + "/";
|
||||||
|
this.Init(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Init(Boolean withuser = true) {
|
||||||
|
this.RequestString("config", "", false);
|
||||||
|
if(withuser) {
|
||||||
|
String i = this.RequestString("", "", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
internal JsonData PostJson(String address, String json) {
|
||||||
|
return this.ToJson(this.RequestString(address, json, true, RequestMethod.POST));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal JsonData PutJson(String address, String json) {
|
||||||
|
return this.ToJson(this.RequestString(address, json, true, RequestMethod.PUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal JsonData GetJson(String address) {
|
||||||
|
return this.ToJson(this.RequestString(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonData ToJson(String text) {
|
||||||
|
if (text == null) {
|
||||||
|
return new JsonData();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JsonMapper.ToObject(text);
|
||||||
|
} catch (Exception) {
|
||||||
|
return new JsonData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String RequestString(String address, String json = "", Boolean withoutput = true, RequestMethod method = RequestMethod.GET) {
|
||||||
|
String ret = null;
|
||||||
|
lock (this.getLock) {
|
||||||
|
HttpWebRequest request = WebRequest.CreateHttp(this.server + address);
|
||||||
|
request.Timeout = 5000;
|
||||||
|
if(method == RequestMethod.POST || method == RequestMethod.PUT) {
|
||||||
|
Byte[] requestdata = Encoding.ASCII.GetBytes(json);
|
||||||
|
request.ContentLength = requestdata.Length;
|
||||||
|
request.Method = method.ToString();
|
||||||
|
request.ContentType = "application/x-www-form-urlencoded";
|
||||||
|
using (Stream stream = request.GetRequestStream()) {
|
||||||
|
stream.Write(requestdata, 0, requestdata.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
|
||||||
|
if (response.StatusCode == HttpStatusCode.Unauthorized) {
|
||||||
|
Console.Error.WriteLine("Benutzer oder Passwort falsch!");
|
||||||
|
throw new Exceptions.ConnectionException("Benutzer oder Passwort falsch!");
|
||||||
|
}
|
||||||
|
if (withoutput) {
|
||||||
|
StreamReader reader = new StreamReader(response.GetResponseStream());
|
||||||
|
ret = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Helper.WriteError("Konnte keine Verbindung zum Razzbery Server herstellen. Resource: \"" + this.server + address + "\" Fehler: " + e.Message);
|
||||||
|
return null;
|
||||||
|
//throw new Exceptions.ConnectionException("Konnte keine Verbindung zum Razzbery Server herstellen: " + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user