193 lines
7.7 KiB
C#
193 lines
7.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using BlubbFish.IoT.Zway.Devices;
|
|
using BlubbFish.IoT.Zway.Events;
|
|
using BlubbFish.IoT.Zway.Interfaces;
|
|
using BlubbFish.IoT.Zway.lib;
|
|
using LitJson;
|
|
|
|
namespace BlubbFish.IoT.Zway {
|
|
public class ZwayController : IDisposable {
|
|
private HttpConnection http;
|
|
private Thread updatethread;
|
|
private Thread pollthread;
|
|
public static ReadOnlyDictionary<String, String> namelist;
|
|
private Boolean polling;
|
|
|
|
public delegate void DataUpdate(Object sender, DeviceUpdateEvent e);
|
|
public event DataUpdate Update;
|
|
|
|
public ReadOnlyDictionary<Int32, Device> Devices { get; private set; }
|
|
|
|
public ZwayController(String server, String user, String pass, Dictionary<String, String> names, Boolean enablePoll = true) {
|
|
namelist = new ReadOnlyDictionary<String, String>(names);
|
|
this.polling = enablePoll;
|
|
this.Connect(server, user, pass);
|
|
}
|
|
|
|
public ZwayController(Dictionary<String, String> settings, Dictionary<String, String> names, Boolean enablePoll = true) {
|
|
namelist = new ReadOnlyDictionary<String, String>(names);
|
|
this.polling = enablePoll;
|
|
this.Connect(settings["server"], settings["user"], settings["pass"]);
|
|
}
|
|
|
|
private void Connect(String server, String user, String pass) {
|
|
this.http = new HttpConnection(server, user, pass);
|
|
CultureInfo info = new CultureInfo("de-DE");
|
|
info.NumberFormat.NumberDecimalSeparator = ".";
|
|
CultureInfo.DefaultThreadCurrentCulture = info;
|
|
CultureInfo.DefaultThreadCurrentUICulture = info;
|
|
Thread.CurrentThread.CurrentCulture = info;
|
|
Thread.CurrentThread.CurrentUICulture = info;
|
|
this.CreateDevices(this.http.GetJson("ZWaveAPI/Run/devices"));
|
|
this.updatethread = new Thread(this.Updater);
|
|
this.updatethread.Start();
|
|
this.pollthread = new Thread(this.Poll);
|
|
this.pollthread.Start();
|
|
foreach (KeyValuePair<Int32, Device> item in this.Devices) {
|
|
item.Value.Update += this.DeviceUpdate;
|
|
}
|
|
}
|
|
|
|
private void DeviceUpdate(Object sender, DeviceUpdateEvent e) {
|
|
this.Update?.Invoke(sender, e);
|
|
}
|
|
|
|
private void Poll() {
|
|
CultureInfo info = new CultureInfo("de-DE");
|
|
info.NumberFormat.NumberDecimalSeparator = ".";
|
|
CultureInfo.DefaultThreadCurrentCulture = info;
|
|
CultureInfo.DefaultThreadCurrentUICulture = info;
|
|
Thread.CurrentThread.CurrentCulture = info;
|
|
Thread.CurrentThread.CurrentUICulture = info;
|
|
while(true) {
|
|
foreach (KeyValuePair<Int32, Device> item in this.Devices) {
|
|
item.Value.Poll();
|
|
}
|
|
Thread.Sleep(1000);
|
|
}
|
|
}
|
|
|
|
public ACommandClass GetCommandClass(String id) {
|
|
String[] addr = id.Split('-');
|
|
if (addr.Length == 3 || addr.Length == 4) {
|
|
return this.GetCommandClass(Int32.Parse(addr[0]), Int32.Parse(addr[1]), (ACommandClass.Classes)Int32.Parse(addr[2]), (addr.Length == 4 ? Int32.Parse(addr[3]) : -1));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public ACommandClass GetCommandClass(Int32 deviceid, Int32 instanceid, ACommandClass.Classes classid, Int32 subcid = -1) {
|
|
if(this.Devices.ContainsKey(deviceid) && this.Devices[deviceid].Instances.ContainsKey(instanceid) && this.Devices[deviceid].Instances[instanceid].CommandClasses.ContainsKey(classid)) {
|
|
ACommandClass commandclass = this.Devices[deviceid].Instances[instanceid].CommandClasses[classid];
|
|
if(subcid == -1) {
|
|
return commandclass;
|
|
}
|
|
if (commandclass != null) {
|
|
if(commandclass.HasSub) {
|
|
if(commandclass.Sub.ContainsKey(subcid)) {
|
|
return commandclass.Sub[subcid];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void Updater() {
|
|
CultureInfo info = new CultureInfo("de-DE");
|
|
info.NumberFormat.NumberDecimalSeparator = ".";
|
|
CultureInfo.DefaultThreadCurrentCulture = info;
|
|
CultureInfo.DefaultThreadCurrentUICulture = info;
|
|
Thread.CurrentThread.CurrentCulture = info;
|
|
Thread.CurrentThread.CurrentUICulture = info;
|
|
while (true) {
|
|
Int64 date = ((DateTimeOffset)DateTime.Now.AddSeconds(-2)).ToUnixTimeSeconds();
|
|
JsonData notifications = this.http.GetJson("ZWave.zway/Data/"+date);
|
|
foreach (String item in notifications.Keys) {
|
|
Match match = new Regex("^devices\\.([0-9]+)\\.instances\\.([0-9]+)\\.commandClasses\\.([0-9]+)(\\.data\\.([0-9]+)|\\.data\\.[a-z].*|\\.data)$", RegexOptions.IgnoreCase).Match(item);
|
|
if(match.Success) {
|
|
Int32 deviceid = Int32.Parse(match.Groups[1].Value);
|
|
Int32 instanceid = Int32.Parse(match.Groups[2].Value);
|
|
ACommandClass.Classes commandid = (ACommandClass.Classes)Int32.Parse(match.Groups[3].Value);
|
|
if (this.Devices.ContainsKey(deviceid) && this.Devices[deviceid].Instances.ContainsKey(instanceid) && this.Devices[deviceid].Instances[instanceid].CommandClasses.ContainsKey(commandid)) {
|
|
this.Devices[deviceid].Instances[instanceid].CommandClasses[commandid].SetUpdate(notifications[item], match);
|
|
}
|
|
} /*else {
|
|
if(item.StartsWith("controller.")) { }
|
|
else if(item == "updateTime") { }
|
|
else {
|
|
match = new Regex("^devices\\.([0-9]+)\\.(data.*)", RegexOptions.IgnoreCase).Match(item);
|
|
if(!match.Success) {
|
|
|
|
}
|
|
}
|
|
}*/
|
|
match = new Regex("^devices\\.([0-9]+)\\.(data.*)", RegexOptions.IgnoreCase).Match(item);
|
|
if(match.Success) {
|
|
Int32 deviceid = Int32.Parse(match.Groups[1].Value);
|
|
if (this.Devices.ContainsKey(deviceid)) {
|
|
this.Devices[deviceid].SetUpdate(notifications[item], match);
|
|
}
|
|
}
|
|
}
|
|
Thread.Sleep(1500);
|
|
}
|
|
}
|
|
|
|
private void CreateDevices(JsonData json) {
|
|
Dictionary<Int32, Device> devices = new Dictionary<Int32, Device>();
|
|
foreach (String deviceid in json.Keys) {
|
|
Device d = Device.CreateDevice(json[deviceid], new Tuple<Int32>(Int32.Parse(deviceid)), this.http, this.polling);
|
|
if (d != null) {
|
|
devices.Add(Int32.Parse(deviceid), d);
|
|
}
|
|
}
|
|
this.Devices = new ReadOnlyDictionary<Int32, Device>(devices);
|
|
}
|
|
|
|
public Dictionary<String, ACommandClass> GetCommandClasses(ACommandClass.Classes classes) {
|
|
Dictionary<String, ACommandClass> ret = new Dictionary<String, ACommandClass>();
|
|
foreach (KeyValuePair<Int32, Device> device in this.Devices) {
|
|
foreach (KeyValuePair<Int32, Instance> instance in device.Value.Instances) {
|
|
foreach (KeyValuePair<ACommandClass.Classes, ACommandClass> commandclass in instance.Value.CommandClasses) {
|
|
if (commandclass.Key == classes) {
|
|
ret.Add(commandclass.Value.Id, commandclass.Value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#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.Devices = null;
|
|
this.disposedValue = true;
|
|
}
|
|
}
|
|
|
|
~ZwayController() {
|
|
Dispose(false);
|
|
}
|
|
|
|
public void Dispose() {
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
#endregion
|
|
}
|
|
}
|