From 5304c9d5d75d35a0c9ba544bc0d916aa6b414486 Mon Sep 17 00:00:00 2001 From: spud Date: Wed, 21 Feb 2024 14:48:15 -0500 Subject: [PATCH 1/3] Refactor library to support multiple drivers. --- .../ZWaveJS.NET/ZWaveJS.NET/Controller.cs | 127 +++++++++--------- .../ZWaveJS.NET/ZWaveJS.NET/Driver.cs | 67 ++++----- .../ZWaveJS.NET/ZWaveJS.NET/Endpoint.cs | 16 ++- .../ZWaveJS.NET/ZWaveJS.NET/Server.cs | 21 +-- .../ZWaveJS.NET/ZWaveJS.NET/VirtualNode.cs | 25 ++-- .../ZWaveJS.NET/ZWJSSJsonConverter.cs | 53 ++++++++ .../ZWaveJS.NET/ZWaveJS.NET/ZWaveNode.cs | 105 ++++++++------- 7 files changed, 237 insertions(+), 177 deletions(-) create mode 100644 Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/ZWJSSJsonConverter.cs diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Controller.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Controller.cs index 2ec63a9..f0248c5 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Controller.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Controller.cs @@ -9,9 +9,10 @@ namespace ZWaveJS.NET { public class Controller { - internal Controller() + private Driver _driver; + internal Controller(Driver driver) { - + _driver = driver; } public delegate void BackupNVMProgress(int BytesRead, int Total); @@ -150,7 +151,7 @@ public Task GetAvailableFirmwareUpdates(int NodeID, bool IncludePrere return Result.Task; } - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); @@ -171,7 +172,7 @@ public Task GetAvailableFirmwareUpdates(int NodeID, bool IncludePrere Request.Add("includePrereleases", IncludePrereleases); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -183,7 +184,7 @@ public Task FirmwareUpdateOTA(int NodeID, FirmwareUpdateInfo Update) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -204,7 +205,7 @@ public Task FirmwareUpdateOTA(int NodeID, FirmwareUpdateInfo Update) Request.Add("updateInfo", Update); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -216,7 +217,7 @@ public Task GetRFRegion() TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); @@ -234,7 +235,7 @@ public Task GetRFRegion() Request.Add("command", Enums.Commands.GetRFRegion); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -246,7 +247,7 @@ public Task SetRFRegion(Enums.RFRegion Region) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -259,7 +260,7 @@ public Task SetRFRegion(Enums.RFRegion Region) Request.Add("region", Region); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -271,7 +272,7 @@ public Task GetPowerLevel() TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); @@ -290,7 +291,7 @@ public Task GetPowerLevel() string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -302,7 +303,7 @@ public Task SetPowerLevel(decimal PowerLevel, decimal Measured0dBm) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -316,7 +317,7 @@ public Task SetPowerLevel(decimal PowerLevel, decimal Measured0dBm) Request.Add("measured0dBm", Measured0dBm); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -324,7 +325,7 @@ public Task SetPowerLevel(decimal PowerLevel, decimal Measured0dBm) // LOCAL public VirtualNode GetMulticastGroup(int[] Nodes) { - VirtualNode VN = new VirtualNode(Nodes); + VirtualNode VN = new VirtualNode(_driver, Nodes); return VN; } @@ -345,7 +346,7 @@ public Task FirmwareUpdateOTW(FirmwareUpdate Update) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); @@ -366,7 +367,7 @@ public Task FirmwareUpdateOTW(FirmwareUpdate Update) Request.Add("filename", Update.filename); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -376,7 +377,7 @@ public Task GetProvisioningEntries() { Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); @@ -397,7 +398,7 @@ public Task GetProvisioningEntries() string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -407,7 +408,7 @@ public Task RemoveAssociations(AssociationAddress Source, int Group, { Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -424,7 +425,7 @@ public Task RemoveAssociations(AssociationAddress Source, int Group, string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -434,7 +435,7 @@ public Task AddAssociations(AssociationAddress Source, int Group, Ass { Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -451,7 +452,7 @@ public Task AddAssociations(AssociationAddress Source, int Group, Ass string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -461,7 +462,7 @@ public Task GetAssociations(int Node, int Endpoint) { Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -481,7 +482,7 @@ public Task GetAssociations(int Node, int Endpoint) Request.Add("endpoint", Endpoint); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -491,7 +492,7 @@ public Task GetAssociationGroups(int Node, int Endpoint) { Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -512,7 +513,7 @@ public Task GetAssociationGroups(int Node, int Endpoint) Request.Add("endpoint", Endpoint); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -525,12 +526,12 @@ public Task RestoreNVM(byte[] NVMData, ConvertRestoreNVMProgress Conv Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) { - Driver.Instance.Restart(); + _driver.Restart(); } Result.SetResult(Res); @@ -542,7 +543,7 @@ public Task RestoreNVM(byte[] NVMData, ConvertRestoreNVMProgress Conv Request.Add("nvmData", Convert.ToBase64String(NVMData)); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -554,7 +555,7 @@ public Task BackupNVMRaw(BackupNVMProgress OnProgress = null) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -572,7 +573,7 @@ public Task BackupNVMRaw(BackupNVMProgress OnProgress = null) Request.Add("command", Enums.Commands.BackUpNVM); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -611,7 +612,7 @@ public Task ReplaceFailedNode(int NodeID, InclusionOptions Options) return Result.Task; } - if (Driver.Instance.Options != null && Driver.Instance.Options.MissingKeys(true, false)) + if (_driver.Options != null && _driver.Options.MissingKeys(true, false)) { CMDResult Res = new CMDResult(Enums.ErrorCodes.MissingKeys, "Missing Security Keys in Options", false); Result.SetResult(Res); @@ -621,7 +622,7 @@ public Task ReplaceFailedNode(int NodeID, InclusionOptions Options) if (Options.strategy == Enums.InclusionStrategy.Security_S0) { - if (Driver.Instance.Options != null && Driver.Instance.Options.MissingKeys(false, true)) + if (_driver.Options != null && _driver.Options.MissingKeys(false, true)) { CMDResult Res = new CMDResult(Enums.ErrorCodes.MissingKeys, "Missing Security Keys in Options", false); Result.SetResult(Res); @@ -629,7 +630,7 @@ public Task ReplaceFailedNode(int NodeID, InclusionOptions Options) } } - if (Driver.Instance.Options != null && !Driver.Instance.Options.CheckKeyLength()) + if (_driver.Options != null && !_driver.Options.CheckKeyLength()) { CMDResult Res = new CMDResult(Enums.ErrorCodes.InvalidkeyLength, "Invalid Key length. All Security Keys must be a 32 character hexadecimal string (representing 16 bytes)", false); Result.SetResult(Res); @@ -637,7 +638,7 @@ public Task ReplaceFailedNode(int NodeID, InclusionOptions Options) } - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -653,7 +654,7 @@ public Task ReplaceFailedNode(int NodeID, InclusionOptions Options) Request.Add("options", _Options); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -664,7 +665,7 @@ public Task RemoveFailedNode(int NodeID) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult RES = new CMDResult(JO); Result.SetResult(RES); @@ -677,7 +678,7 @@ public Task RemoveFailedNode(int NodeID) Request.Add("nodeId", NodeID); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -688,7 +689,7 @@ public Task RebuildNodeRoutes(int NodeID) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -706,7 +707,7 @@ public Task RebuildNodeRoutes(int NodeID) Request.Add("nodeId", NodeID); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -717,7 +718,7 @@ public Task BeginRebuildingRoutes(RebuildRoutesOptions Options) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -740,7 +741,7 @@ public Task BeginRebuildingRoutes(RebuildRoutesOptions Options) Request.Add("options", Options); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -752,7 +753,7 @@ public Task StopRebuildingRoutes() Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -769,7 +770,7 @@ public Task StopRebuildingRoutes() Request.Add("command", Enums.Commands.StopRebuildingRoutes); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -804,7 +805,7 @@ public Task BeginInclusion(InclusionOptions Options) return Result.Task; } - if (Driver.Instance.Options != null && Driver.Instance.Options.MissingKeys(true, true)) + if (_driver.Options != null && _driver.Options.MissingKeys(true, true)) { CMDResult Res = new CMDResult(Enums.ErrorCodes.MissingKeys, "Missing Security Keys in Options", false); Result.SetResult(Res); @@ -822,7 +823,7 @@ public Task BeginInclusion(InclusionOptions Options) return Result.Task; } - if (Driver.Instance.Options != null && Driver.Instance.Options.MissingKeys(true, false)) + if (_driver.Options != null && _driver.Options.MissingKeys(true, false)) { CMDResult Res = new CMDResult(Enums.ErrorCodes.MissingKeys, "Missing Security Keys in Options", false); Result.SetResult(Res); @@ -832,7 +833,7 @@ public Task BeginInclusion(InclusionOptions Options) if (Options.strategy == Enums.InclusionStrategy.Security_S0) { - if (Driver.Instance.Options != null && Driver.Instance.Options.MissingKeys(false, true)) + if (_driver.Options != null && _driver.Options.MissingKeys(false, true)) { CMDResult Res = new CMDResult(Enums.ErrorCodes.MissingKeys, "Missing Security Keys in Options", false); Result.SetResult(Res); @@ -842,14 +843,14 @@ public Task BeginInclusion(InclusionOptions Options) - if (Driver.Instance.Options != null && !Driver.Instance.Options.CheckKeyLength()) + if (_driver.Options != null && !_driver.Options.CheckKeyLength()) { CMDResult Res = new CMDResult(Enums.ErrorCodes.InvalidkeyLength, "Invalid Key length. All Security Keys must be a 32 character hexadecimal string (representing 16 bytes)", false); Result.SetResult(Res); return Result.Task; } - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -865,7 +866,7 @@ public Task BeginInclusion(InclusionOptions Options) Request.Add("options", _Options); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -876,7 +877,7 @@ public Task StopInclusion() Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -887,7 +888,7 @@ public Task StopInclusion() Request.Add("command", Enums.Commands.StopInclusion); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -910,7 +911,7 @@ private Task _UnprovisionSmartStartNode(object dskOrNodeId) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -923,7 +924,7 @@ private Task _UnprovisionSmartStartNode(object dskOrNodeId) Request.Add("dskOrNodeId", dskOrNodeId); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -934,21 +935,21 @@ public Task ProvisionSmartStartNode(string QRCode) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - if (Driver.Instance.Options != null && Driver.Instance.Options.MissingKeys(true, true)) + if (_driver.Options != null && _driver.Options.MissingKeys(true, true)) { CMDResult Res = new CMDResult(Enums.ErrorCodes.MissingKeys, "Missing Security Keys in Options", false); Result.SetResult(Res); return Result.Task; } - if (Driver.Instance.Options != null && !Driver.Instance.Options.CheckKeyLength()) + if (_driver.Options != null && !_driver.Options.CheckKeyLength()) { CMDResult Res = new CMDResult(Enums.ErrorCodes.InvalidkeyLength, "Invalid Key length. All Security Keys must be a 32 character hexadecimal string (representing 16 bytes)", false); Result.SetResult(Res); return Result.Task; } - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -961,7 +962,7 @@ public Task ProvisionSmartStartNode(string QRCode) Request.Add("entry", QRCode); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -973,7 +974,7 @@ public Task BeginExclusion(ExclusionOptions Options) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -986,7 +987,7 @@ public Task BeginExclusion(ExclusionOptions Options) Request.Add("options", Options); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -998,7 +999,7 @@ public Task StopExclusion() TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -1010,7 +1011,7 @@ public Task StopExclusion() Request.Add("command", Enums.Commands.StopExclusion); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs index 622cb89..796c42c 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs @@ -11,8 +11,6 @@ namespace ZWaveJS.NET { public class Driver { - internal static volatile Driver Instance; - internal Websocket.Client.WebsocketClient ClientWebSocket; internal Dictionary> Callbacks; internal bool Inited = false; @@ -22,13 +20,15 @@ public class Driver private Dictionary> NodeEventMap; private Dictionary> ControllerEventMap; private Dictionary> DriverEventMap; - private static Semver.SemVersion SchemaVersionID = new Semver.SemVersion(1, 33, 0); + private Semver.SemVersion SchemaVersionID = new Semver.SemVersion(1, 33, 0); private string SerialPort; private bool RequestedExit = false; + private JsonSerializer _jsonSerializer; private Uri WSAddress; private bool Host = true; + private Server _server; private string _ZWaveJSDriverVersion; public string ZWJSS_DriverVersion @@ -48,8 +48,8 @@ public string ZWJSS_ServerVersion } } - public static int ServerCommunicationPort = 50001; - public static int ServerErrorThrottleTime = 10000; + public int ServerCommunicationPort { get; private set; } + public int ServerErrorThrottleTime { get; private set; } private DateTime LastError; public Controller Controller { get; internal set; } @@ -226,7 +226,7 @@ private void MapNodeEvents() NodeEventMap.Add("ready", (JO) => { int NID = JO.SelectToken("event.nodeId").ToObject(); - ZWaveNode NNI = JO.SelectToken("event.nodeState").ToObject(); + ZWaveNode NNI = JO.SelectToken("event.nodeState").ToObject(_jsonSerializer); ZWaveNode N = this.Controller.Nodes.Get(NID); this.Controller.Nodes.ReplaceInformation(NNI, N); @@ -402,7 +402,7 @@ private void MapControllerEvents() int NID = JO.SelectToken("event.node.nodeId").ToObject(); InclusionResultArgs IR = JO.SelectToken("event.result").ToObject(); - ZWaveNode NN = new ZWaveNode(); + ZWaveNode NN = new ZWaveNode(this); NN.id = NID; this.Controller.Nodes.AddNodeToCollection(NN); @@ -516,15 +516,19 @@ private void MapEvents() } // Client Mode - public Driver(Uri Server, int SchemaVersion = 0) + public Driver(Uri Server, int SchemaVersion = 0, int ServerErrorThrottleTime = 10000) { - - Instance = this; - Newtonsoft.Json.JsonConvert.DefaultSettings = () => new JsonSerializerSettings { - NullValueHandling = NullValueHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore + }; + + var settings = new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore }; + settings.Converters.Add(new ZWJSSJsonConverter(this)); + _jsonSerializer = JsonSerializer.Create(settings); if (SchemaVersion > 0) { @@ -536,32 +540,38 @@ public Driver(Uri Server, int SchemaVersion = 0) this.WSAddress = Server; this.Host = false; + this.ServerErrorThrottleTime = ServerErrorThrottleTime; InternalPrep(); - } // Host Mode - public Driver(string SerialPort, ZWaveOptions Options) + public Driver(string SerialPort, ZWaveOptions Options, int ServerCommunicationPort = 50001, int ServerErrorThrottleTime = 10000) { - - Instance = this; - Newtonsoft.Json.JsonConvert.DefaultSettings = () => new JsonSerializerSettings { - NullValueHandling = NullValueHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore + }; + + var settings = new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore }; + settings.Converters.Add(new ZWJSSJsonConverter(this)); + _jsonSerializer = JsonSerializer.Create(settings); Callbacks = new Dictionary>(); MapEvents(); this.SerialPort = SerialPort; this.Options = Options; + this.ServerCommunicationPort = ServerCommunicationPort; this.WSAddress = new Uri("ws://localhost:" + ServerCommunicationPort); this.Host = true; + this.ServerErrorThrottleTime = ServerErrorThrottleTime; + this._server = new Server(); InternalPrep(); - } // Prep @@ -569,10 +579,9 @@ private void InternalPrep() { if (this.Host) { - - Server.Start(SerialPort, Options, ServerCommunicationPort); - Server.Exited += Server_Exited; - Server.FatalError += Server_FatalError; + _server.Start(SerialPort, Options, ServerCommunicationPort); + _server.Exited += Server_Exited; + _server.FatalError += Server_FatalError; } var Factory = new Func(() => new ClientWebSocket @@ -664,7 +673,7 @@ private void DestroySocket() private void DestroyServer() { - Server.Terminate(); + _server?.Terminate(); } public void Destroy() @@ -678,10 +687,7 @@ public void Destroy() } DestroySocket(); - DestroyServer(); - - - + DestroyServer(); } async internal void Restart() @@ -767,9 +773,10 @@ private void StartListetningCB(JObject JO) { if (JO.Value("success")) { - Controller C = JO.SelectToken("result.state.controller").ToObject(); + Controller C = JO.SelectToken("result.state.controller").ToObject(_jsonSerializer); + - ZWaveNode[] Nodes = JO.SelectToken("result.state.nodes").ToObject(); + ZWaveNode[] Nodes = JO.SelectToken("result.state.nodes").ToObject(_jsonSerializer); C.deviceConfig = Nodes.FirstOrDefault((N) => N.isControllerNode).deviceConfig; Nodes = Nodes.Where((N) => !N.isControllerNode).ToArray(); diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Endpoint.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Endpoint.cs index 0b25214..45bc3b0 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Endpoint.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Endpoint.cs @@ -8,15 +8,19 @@ namespace ZWaveJS.NET { public class Endpoint { - internal Endpoint() { } - + private Driver _driver; + internal Endpoint(Driver driver = null) + { + _driver = driver; + } + // CHECKED public Task SupportsCCAPI(int CommandClass) { Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -36,7 +40,7 @@ public Task SupportsCCAPI(int CommandClass) Request.Add("commandClass", CommandClass); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -48,7 +52,7 @@ public Task InvokeCCAPI(int CommandClass, string Method, params objec Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -71,7 +75,7 @@ public Task InvokeCCAPI(int CommandClass, string Method, params objec string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Server.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Server.cs index 51c55cf..6d8e7f8 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Server.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Server.cs @@ -8,16 +8,15 @@ namespace ZWaveJS.NET { internal class Server { - - private static Process ServerProcess; + private Process ServerProcess; internal delegate void FatalErrorEvent(); - internal static event FatalErrorEvent FatalError; + internal event FatalErrorEvent FatalError; internal delegate void ProcessdExitedEvent(); - internal static event ProcessdExitedEvent Exited; + internal event ProcessdExitedEvent Exited; - internal static void Terminate() + internal void Terminate() { if (ServerProcess != null && !ServerProcess.HasExited) { @@ -26,10 +25,8 @@ internal static void Terminate() } } - internal static void Start(string SerialPort, ZWaveOptions Config, int WSPort) + internal void Start(string SerialPort, ZWaveOptions Config, int WSPort) { - - Process[] Zombies = Process.GetProcessesByName("server.psi"); foreach(Process Zombie in Zombies) { @@ -70,17 +67,15 @@ internal static void Start(string SerialPort, ZWaveOptions Config, int WSPort) ServerProcess.StartInfo = PSI; ServerProcess.Start(); ServerProcess.BeginErrorReadLine(); - - } - private static void ServerProcess_Exited(object sender, EventArgs e) + private void ServerProcess_Exited(object sender, EventArgs e) { // Exited?.Invoke(); I think this will be indirectly handled by the socket client now ServerProcess.Dispose(); } - private static void ServerProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e) + private void ServerProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e) { int Code; if (int.TryParse(e.Data, out Code)) @@ -92,8 +87,6 @@ private static void ServerProcess_ErrorDataReceived(object sender, DataReceivedE break; } } - - } } } diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/VirtualNode.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/VirtualNode.cs index 38f1886..febf21a 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/VirtualNode.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/VirtualNode.cs @@ -8,9 +8,9 @@ namespace ZWaveJS.NET { public class VirtualNode { - - internal VirtualNode(int[] Nodes) + internal VirtualNode(Driver driver, int[] Nodes) { + _driver = driver; this.Nodes = Nodes; } @@ -20,7 +20,7 @@ public Task GetEndpointCount() TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -36,7 +36,7 @@ public Task GetEndpointCount() Request.Add("nodeIDs", this.Nodes); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -46,7 +46,7 @@ public Task SetValue(ValueID ValueID, object Value, SetValueAPIOption Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -65,7 +65,7 @@ public Task SetValue(ValueID ValueID, object Value, SetValueAPIOption } string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -75,7 +75,7 @@ public Task GetDefinedValueIDs() Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -93,7 +93,7 @@ public Task GetDefinedValueIDs() string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -103,7 +103,7 @@ public Task SupportsCCAPI(int CommandClass) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -121,7 +121,7 @@ public Task SupportsCCAPI(int CommandClass) Request.Add("commandClass", CommandClass); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -131,7 +131,7 @@ public Task InvokeCCAPI(int CommandClass, string Method, params objec Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -151,12 +151,13 @@ public Task InvokeCCAPI(int CommandClass, string Method, params objec Request.Add("args", Params); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } private int[] Nodes { get; set; } + private Driver _driver { get; set; } } diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/ZWJSSJsonConverter.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/ZWJSSJsonConverter.cs new file mode 100644 index 0000000..8edef5c --- /dev/null +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/ZWJSSJsonConverter.cs @@ -0,0 +1,53 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Reflection; + +namespace ZWaveJS.NET +{ + + internal class ZWJSSJsonConverter : JsonConverter + { + private Driver _driver; + + public ZWJSSJsonConverter(Driver driver) : + base() + { + _driver = driver; + } + public override bool CanConvert(Type objectType) + { + return typeof(ZWaveNode).IsAssignableFrom(objectType) || + typeof(Endpoint).IsAssignableFrom(objectType) || + typeof(Controller).IsAssignableFrom(objectType); + } + + public override bool CanWrite + { + get { return false; } + } + + public override object ReadJson(JsonReader reader, + Type objectType, + object existingValue, + JsonSerializer serializer) + { + // Load JObject from stream + JObject jObject = JObject.Load(reader); + + // Create target object based on JObject + object target = Activator.CreateInstance(objectType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, + null, new object[] { _driver }, null); + + // Populate the object properties + serializer.Populate(jObject.CreateReader(), target); + + return target; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + } +} diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/ZWaveNode.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/ZWaveNode.cs index d8403bc..a2fb606 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/ZWaveNode.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/ZWaveNode.cs @@ -9,9 +9,10 @@ namespace ZWaveJS.NET { public class ZWaveNode { - internal ZWaveNode() + private Driver _driver; + internal ZWaveNode(Driver driver = null) { - + _driver = driver; } public delegate void LifelineHealthCheckProgress(int Round, int TotalRounds, int LastRating); @@ -137,7 +138,7 @@ public Task Ping() Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -155,7 +156,7 @@ public Task Ping() string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -166,7 +167,7 @@ public Task Interview() Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -179,7 +180,7 @@ public Task Interview() string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -192,7 +193,7 @@ public Task CheckLifelineHealth(int Rounds, LifelineHealthCheckProgre Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -212,7 +213,7 @@ public Task CheckLifelineHealth(int Rounds, LifelineHealthCheckProgre string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -223,7 +224,7 @@ public Task AbortFirmwareUpdate() Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -236,7 +237,7 @@ public Task AbortFirmwareUpdate() string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -260,7 +261,7 @@ public Task UpdateFirmware(FirmwareUpdate[] Updates) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if(JO.ContainsKey("result")) @@ -277,7 +278,7 @@ public Task UpdateFirmware(FirmwareUpdate[] Updates) Request.Add("updates", Updates); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -288,7 +289,7 @@ public Task RefreshInfo(RefreshInfoOptions Options = null) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -303,7 +304,7 @@ public Task RefreshInfo(RefreshInfoOptions Options = null) Request.Add("options", Options); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -314,7 +315,7 @@ public Task GetValue(ValueID ValueID) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -333,7 +334,7 @@ public Task GetValue(ValueID ValueID) Request.Add("nodeId", this.id); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -344,7 +345,7 @@ public Task SetValue(ValueID ValueID, object Value, SetValueAPIOption Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -368,7 +369,7 @@ public Task SetValue(ValueID ValueID, object Value, SetValueAPIOption } string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -379,7 +380,7 @@ public Task PollValue(ValueID ValueID) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -397,7 +398,7 @@ public Task PollValue(ValueID ValueID) Request.Add("valueId", ValueID); string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -408,7 +409,7 @@ public Task ZWJSS_SetRawConfigParameterValue(int Parameter, int Value Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -423,7 +424,7 @@ public Task ZWJSS_SetRawConfigParameterValue(int Parameter, int Value string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -434,7 +435,7 @@ public Task ZWJSS_SetRawConfigParameterValue(int Parameter, int Value Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -451,7 +452,7 @@ public Task ZWJSS_SetRawConfigParameterValue(int Parameter, int Value string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -462,7 +463,7 @@ public Task ZWJSS_SetRawConfigParameterValue(int Parameter, int Bitma Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -478,7 +479,7 @@ public Task ZWJSS_SetRawConfigParameterValue(int Parameter, int Bitma string RequestPL = Newtonsoft.Json.JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -489,7 +490,7 @@ public Task RefreshValues() Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -502,7 +503,7 @@ public Task RefreshValues() string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -513,7 +514,7 @@ public Task RefreshCCValues(int CommandClass) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -527,7 +528,7 @@ public Task RefreshCCValues(int CommandClass) string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -538,7 +539,7 @@ public Task GetDefinedValueIDs() Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -556,7 +557,7 @@ public Task GetDefinedValueIDs() string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -567,7 +568,7 @@ public Task GetValueMetadata(ValueID VID) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -587,7 +588,7 @@ public Task GetValueMetadata(ValueID VID) string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -598,7 +599,7 @@ public Task SupportsCCAPI(int CommandClass) Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -616,7 +617,7 @@ public Task SupportsCCAPI(int CommandClass) Request.Add("commandClass", CommandClass); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -627,7 +628,7 @@ public Task InvokeCCAPI(int CommandClass, string Method, params objec Guid ID = Guid.NewGuid(); TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -647,7 +648,7 @@ public Task InvokeCCAPI(int CommandClass, string Method, params objec Request.Add("args", Params); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -666,7 +667,7 @@ public Task GetEndpointCount() TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -682,7 +683,7 @@ public Task GetEndpointCount() Request.Add("nodeId", this.id); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -694,7 +695,7 @@ public Task GetHighestSecurityClass() TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -713,7 +714,7 @@ public Task GetHighestSecurityClass() Request.Add("nodeId", this.id); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -725,7 +726,7 @@ public Task HasSecurityClass(Enums.SecurityClass Class) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -743,7 +744,7 @@ public Task HasSecurityClass(Enums.SecurityClass Class) Request.Add("securityClass", Class); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -755,7 +756,7 @@ public Task WaitForWakeup() TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); Result.SetResult(Res); @@ -768,7 +769,7 @@ public Task WaitForWakeup() Request.Add("nodeId", this.id); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -843,7 +844,7 @@ public Task SetKeepAwake(bool Option) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -861,7 +862,7 @@ public Task SetKeepAwake(bool Option) Request.Add("keepAwake", Option); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -874,7 +875,7 @@ public Task SetName(string Name, bool UpdateCC = true) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -893,7 +894,7 @@ public Task SetName(string Name, bool UpdateCC = true) Request.Add("updateCC", UpdateCC); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } @@ -906,7 +907,7 @@ public Task SetLocation(string Location, bool UpdateCC = true) TaskCompletionSource Result = new TaskCompletionSource(); - Driver.Instance.Callbacks.Add(ID, (JO) => + _driver.Callbacks.Add(ID, (JO) => { CMDResult Res = new CMDResult(JO); if (Res.Success) @@ -925,7 +926,7 @@ public Task SetLocation(string Location, bool UpdateCC = true) Request.Add("updateCC", UpdateCC); string RequestPL = JsonConvert.SerializeObject(Request); - Driver.Instance.ClientWebSocket.SendInstant(RequestPL); + _driver.ClientWebSocket.SendInstant(RequestPL); return Result.Task; } From 7c5c546bdc4729c139b9cb3bc287a7571cba5f0c Mon Sep 17 00:00:00 2001 From: Marcus Davies <55892693+marcus-j-davies@users.noreply.github.com> Date: Sat, 24 Feb 2024 10:15:21 +0000 Subject: [PATCH 2/3] Patch server class to handle multiple hosts + check for used ports --- .../ZWaveJS.NET/ZWaveJS.NET/Driver.cs | 16 ++++++++++++++++ .../ZWaveJS.NET/ZWaveJS.NET/Server.cs | 14 ++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs index 796c42c..e6a65aa 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs @@ -11,6 +11,9 @@ namespace ZWaveJS.NET { public class Driver { + // Global List of Socket Ports that are registered + internal static List UsedPorts = new List(); + internal Websocket.Client.WebsocketClient ClientWebSocket; internal Dictionary> Callbacks; internal bool Inited = false; @@ -548,6 +551,14 @@ public Driver(Uri Server, int SchemaVersion = 0, int ServerErrorThrottleTime = 1 // Host Mode public Driver(string SerialPort, ZWaveOptions Options, int ServerCommunicationPort = 50001, int ServerErrorThrottleTime = 10000) { + + if (UsedPorts.Contains(ServerCommunicationPort)) + { + throw new Exception(string.Format("Web Socket Port: {0} already in use", ServerCommunicationPort)); + } + + UsedPorts.Add(ServerCommunicationPort); + Newtonsoft.Json.JsonConvert.DefaultSettings = () => new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore @@ -666,6 +677,11 @@ private void DestroySocket() ClientWebSocket.Stop(WebSocketCloseStatus.NormalClosure, "Destroy"); } + if (Host) + { + UsedPorts.Remove(WSAddress.Port); + } + ClientWebSocket.Dispose(); ClientWebSocket = null; } diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Server.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Server.cs index 6d8e7f8..ea046f1 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Server.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Server.cs @@ -8,6 +8,9 @@ namespace ZWaveJS.NET { internal class Server { + + + private Process ServerProcess; internal delegate void FatalErrorEvent(); @@ -27,10 +30,15 @@ internal void Terminate() internal void Start(string SerialPort, ZWaveOptions Config, int WSPort) { - Process[] Zombies = Process.GetProcessesByName("server.psi"); + + + string ProcessName = string.Format("server.{0}.psi", WSPort); + + Process[] Zombies = Process.GetProcessesByName(ProcessName); foreach(Process Zombie in Zombies) { Zombie.Kill(); + File.Delete(ProcessName); } if (!File.Exists("server.psi")) @@ -38,6 +46,8 @@ internal void Start(string SerialPort, ZWaveOptions Config, int WSPort) throw new FileNotFoundException("No Platform Snapshot Image (server.psi) found"); } + File.Copy("server.psi",ProcessName, true); + JsonSerializerSettings JSS = new JsonSerializerSettings(); JSS.NullValueHandling = NullValueHandling.Ignore; string _Config = JsonConvert.SerializeObject(Config, JSS); @@ -55,7 +65,7 @@ internal void Start(string SerialPort, ZWaveOptions Config, int WSPort) PSI.EnvironmentVariables.Add("WS_PORT", WSPort.ToString()); PSI.EnvironmentVariables.Add("NODE_ENV", "production"); - PSI.FileName = "server.psi"; + PSI.FileName = ProcessName; PSI.UseShellExecute = false; PSI.WindowStyle = ProcessWindowStyle.Hidden; PSI.CreateNoWindow = true; From b427fe23035a8c4c9134bae276ab3495d6db396e Mon Sep 17 00:00:00 2001 From: Marcus Davies <55892693+marcus-j-davies@users.noreply.github.com> Date: Sun, 25 Feb 2024 10:07:36 +0000 Subject: [PATCH 3/3] Bump schema + swtich to yao-pkg/pkg --- PSI/package.json | 8 ++++---- Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PSI/package.json b/PSI/package.json index 8abf94e..d98367d 100644 --- a/PSI/package.json +++ b/PSI/package.json @@ -3,12 +3,12 @@ "name": "server", "bin": "./server.js", "dependencies": { - "@zwave-js/server": "1.33.0", - "zwave-js": "12.2.1" + "@zwave-js/server": "1.34.0", + "zwave-js": "12.4.4" }, "devDependencies": { - "pkg": "^5.8.1", - "esbuild": "^0.19.5" + "@yao-pkg/pkg": "^5.11.4", + "esbuild": "^0.20.1" }, "scripts": { "build": "npm run do_esbuild && npm run do_pkgbuild", diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs index e6a65aa..10684f6 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs @@ -23,7 +23,7 @@ public class Driver private Dictionary> NodeEventMap; private Dictionary> ControllerEventMap; private Dictionary> DriverEventMap; - private Semver.SemVersion SchemaVersionID = new Semver.SemVersion(1, 33, 0); + private Semver.SemVersion SchemaVersionID = new Semver.SemVersion(1, 34, 0); private string SerialPort; private bool RequestedExit = false; private JsonSerializer _jsonSerializer;