/// <summary> /// Queues the message. /// </summary> /// <returns>The ZWaveMessage object itself.</returns> /// <param name="message">Message.</param> public ZWaveMessage QueueMessage(ZWaveMessage message) { queuedMessages.Add(message); queueEmptyAck.Reset(); message.sentAck.Reset(); return(message); }
/// <summary> /// Processes a ZWave message. /// </summary> /// <param name="zm">Zm.</param> private void ProcessMessage(ZWaveMessage zm) { if (zm.Header == FrameHeader.SOF) { if (ZWaveMessage.VerifyChecksum(zm.RawData)) { // Some replies do not include the Id of the node // so we take it from the pending request message if (pendingRequest != null && zm.NodeId == 0) { zm.NodeId = pendingRequest.NodeId; zm.CallbackId = pendingRequest.CallbackId; } SendAck(); ReceiveMessage(zm); UpdateQueryStage(zm); } else { SendNack(); Utility.logger.Warn("Bad message checksum"); } } else if (zm.Header == FrameHeader.CAN) { SetQueryStage(QueryStage.Error); } else { Utility.logger.Warn("Unhandled message type: {0}", BitConverter.ToString(zm.RawData)); } }
internal ZWaveMessage SendMessage(byte[] message) { var msg = new ZWaveMessage(message, MessageDirection.Outbound, true); controller.QueueMessage(msg); return(msg); }
public byte SendMessage(ZWaveMessage msg, bool disablecallback = false) { byte callbackid = 0x00; // if (!disablecallback) { _ackwait.WaitOne(); _ackwait.Reset(); //// //// discard timed-out messages (prevent flooding) //// //TimeSpan ttl = new TimeSpan(DateTime.UtcNow.Ticks - msg.Timestamp.Ticks); //if (ttl.TotalSeconds > 5) //{ // return 0; //} // if (msg.ResendCount == 0) { // Insert the callback id into the message callbackid = GetCallbackId(); msg.Message[msg.Message.Length - 2] = callbackid; msg.CallbackId = callbackid; } } // Insert checksum msg.Message[msg.Message.Length - 1] = GenerateChecksum(msg.Message); _pendingmsgs.Add(msg); // _serialport.SendMessage(msg.Message); // // wait for any previous message callback response int maxwait = 50; // 5 seconds max wait while (_pendingmsgs.Contains(msg) && maxwait > 0) { Thread.Sleep(100); maxwait--; } _pendingmsgs.Remove(msg); // // remove timed out messages (requeued messages after failure) // _pendingmsgs.RemoveAll(zm => { TimeSpan ttl = new TimeSpan(DateTime.UtcNow.Ticks - zm.Timestamp.Ticks); if (ttl.TotalSeconds >= 5) { return(true); } return(false); }); // Thread.Sleep(300); _ackwait.Set(); // return(callbackid); }
public void sendSupportedGet(ZWaveNode node) { var message = ZWaveMessage.CreateRequest(node.Id, new byte[] { (byte)CommandClass.Security, (byte)SecurityCommand.SupportedGet }); encryptAndSend(node, message); }
internal byte SendMessage(byte[] message, bool disableCallback = false) { var msg = new ZWaveMessage() { Node = this, Message = message }; return(zwavePort.SendMessage(msg, disableCallback)); }
/// <summary> /// Sends the data request. /// </summary> /// <param name="request">Request.</param> public void SendDataRequest2(byte[] request) { byte cmdClass = request[0]; byte[] message = ZWaveMessage.BuildSendDataRequest(Id, request); for (int i = 0; i < 100; i++) { SendMessage(message); } }
public byte SendMessage(ZWaveMessage message, bool disableCallback = false) { byte callbackId = 0x00; lock (sendLock) { // Insert checksum if (disableCallback) { message.Message[message.Message.Length - 1] = GenerateChecksum(message.Message); Utility.logMessage(" Sent1 : " + Utility.ByteArrayToString(message.Message)); serialPort.SendMessage(message.Message); } else { if (message.ResendCount == 0) { // Insert the callback id into the message callbackId = GetCallbackId(); message.Message[message.Message.Length - 2] = callbackId; message.CallbackId = callbackId; } message.Message[message.Message.Length - 1] = GenerateChecksum(message.Message); pendingMessages.Add(message); // Utility.logMessage(" Sent1 : " + Utility.ByteArrayToString(message.Message)); serialPort.SendMessage(message.Message); // // wait for any previous message callback response int maxWait = 50; // 5 seconds max wait while (pendingMessages.Contains(message) && maxWait > 0) { Thread.Sleep(100); maxWait--; } pendingMessages.Remove(message); } // // remove timed out messages (requeued messages after failure) // pendingMessages.RemoveAll(zm => { TimeSpan ttl = new TimeSpan(DateTime.UtcNow.Ticks - zm.Timestamp.Ticks); if (ttl.TotalSeconds >= 5) { return(true); } return(false); }); Thread.Sleep(100); } // return(callbackId); }
public void ResendLastMessage() { if (_pendingmsgs.Count > 0) { ZWaveMessage msg = _pendingmsgs[_pendingmsgs.Count - 1]; _pendingmsgs.Remove(msg); if (msg.ResendCount < 3) { msg.ResendCount++; SendMessage(msg); } } }
/// <summary> /// Updates the query stage. /// </summary> /// <param name="zm">Zm.</param> private void UpdateQueryStage(ZWaveMessage zm) { if (currentStage != QueryStage.Complete && currentStage != QueryStage.NotSet && currentStage != QueryStage.Error) { //Utility.logger.Trace("Query Stage {0} Type {1} Function {2}={3} Node {4}={5} Callback {6}={7}", currentStage, zm.Type, zm.Function, currentMessage.Function, zm.NodeId, currentMessage.NodeId, zm.CallbackId, currentMessage.CallbackId); switch (currentStage) { case QueryStage.WaitAck: // The controller accepted a request if (zm.Type == MessageType.Response && zm.Function == pendingRequest.Function) { if (pendingRequest.CallbackId == 0) { SetQueryStage(QueryStage.Complete); } else { // The controller needs querying data from the node SetQueryStage(QueryStage.SendDataReady); } } break; case QueryStage.SendDataReady: // The controller requested data from the node if (zm.Type == MessageType.Request && zm.Function == pendingRequest.Function) { if (zm.CallbackStatus != CallbackStatus.Ack) { SetQueryStage(QueryStage.Error); // TODO: Dump Diagnostic Statistics } else { SetQueryStage(QueryStage.WaitData); zm.NodeId = pendingRequest.NodeId; } } break; case QueryStage.WaitData: // got the data from the node zm.NodeId = pendingRequest.NodeId; zm.CallbackId = pendingRequest.CallbackId; SetQueryStage(QueryStage.Complete); break; } } }
public void ResendLastMessage(byte callbackid) { ZWaveMessage msg = _pendingmsgs.Find(zm => zm.CallbackId == callbackid); if (msg != null) { _pendingmsgs.Remove(msg); if (msg.ResendCount < 3) { msg.ResendCount++; SendMessage(msg); } } }
public void SendRequest(byte[] request) { byte cmdClass = request[0]; byte[] message = ZWaveMessage.CreateRequest(this.Id, request); // when cmdClass belongs to SecuredNodeInformationFrame we need to encrypt the message if (cmdClass != (byte)CommandClass.Security && IsSecuredCommandClass((CommandClass)cmdClass)) { Security.SendMessage(this, message); } else { SendMessage(message); } }
public void SendRequest(byte[] request) { // lookup request[0] in supportedClasses to see if we need to encrypt the message or NOT // we don't encrypt the message if it's sent by the Security Class byte cmd = request[0]; SupportedCommandClasses scc = supportedClasses.Find(x => x.cclass == cmd); byte[] msg = ZWaveMessage.CreateRequest(this.Id, request); if (scc != null && scc.secure && cmd != (byte)CommandClass.Security) { security.encryptAndSend(this, msg); } else { SendMessage(msg); } }
/// <summary> /// Sends the data request. /// </summary> /// <param name="request">Request.</param> public ZWaveMessage SendDataRequest(byte[] request) { byte cmdClass = request[0]; byte[] message = ZWaveMessage.BuildSendDataRequest(Id, request); // when cmdClass belongs to SecuredNodeInformationFrame we need to encrypt the message if (cmdClass != (byte)CommandClass.Security && IsSecuredCommandClass((CommandClass)cmdClass)) { Security.SendMessage(this, message); // TODO: not yet supported for Security Command Classs, // TODO: update Security.cs class return(null); } else { return(SendMessage(message)); } }
private bool DupeMessageCheck(ZWaveMessage msg) { // Discard repeated messages within last 2 seconds time range bool repeated = false; if (lastMessage != null) { var elapsed = (DateTime.UtcNow - lastMessageTimestamp); if (elapsed.TotalSeconds <= 2 && lastMessage.SequenceEqual(msg.RawData)) { repeated = true; } } lastMessageTimestamp = DateTime.UtcNow; lastMessage = new byte[msg.RawData.Length]; Buffer.BlockCopy(msg.RawData, 0, lastMessage, 0, msg.RawData.Length * sizeof(byte)); return(repeated); }
/// <summary> /// Sends the message. /// </summary> /// <returns>True if sending succesfull, False otherwise.</returns> /// <param name="message">Message.</param> public bool SendMessage(ZWaveMessage message) { #region Debug Utility.logger.Trace("[[[ BEGIN REQUEST ]]]"); var stopWatch = new Stopwatch(); stopWatch.Start(); #endregion SetQueryStage(QueryStage.WaitAck); pendingRequest = message; sendMessageAck.Reset(); Utility.logger.Trace("Sending Message (Node={0}, CallbackId={1}, Function={2}, CommandClass={3})", pendingRequest.NodeId, pendingRequest.CallbackId.ToString("X2"), pendingRequest.Function, pendingRequest.CommandClass); if (serialPort.SendMessage(message.RawData)) { if (!sendMessageAck.WaitOne(ZWaveMessage.SendMessageTimeoutMs)) { SetQueryStage(QueryStage.Error); // TODO: Dump Diagnostic Statistics Utility.logger.Warn("Message timeout (Node={0}, CallbackId={0}, Function={1}, CommandClass={2})", pendingRequest.NodeId, pendingRequest.CallbackId.ToString("X2"), pendingRequest.Function, pendingRequest.CommandClass); if (message.NodeId > 1) { UpdateOperationProgress(message.NodeId, NodeQueryStatus.Timeout); } //System.Diagnostics.Debugger.Break(); } } else { SetQueryStage(QueryStage.Error); Utility.logger.Warn("Controller status error (Node={0}, CallbackId={0}, Function={1}, CommandClass={2})", pendingRequest.NodeId, pendingRequest.CallbackId.ToString("X2"), pendingRequest.Function, pendingRequest.CommandClass); } pendingRequest = null; #region Debug stopWatch.Stop(); Utility.logger.Trace("[[[ END REQUEST ]]] took {0} ms", stopWatch.ElapsedMilliseconds); #endregion return(currentStage != QueryStage.Error); }
public byte SendMessage(ZWaveMessage message, bool disableCallback = false) { byte callbackId = 0x00; // if (!disableCallback) { ackWait.WaitOne(); ackWait.Reset(); //// //// discard timed-out messages (prevent flooding) //// //TimeSpan ttl = new TimeSpan(DateTime.UtcNow.Ticks - msg.Timestamp.Ticks); //if (ttl.TotalSeconds > 5) //{ // return 0; //} // if (message.ResendCount == 0) { // Insert the callback id into the message callbackId = GetCallbackId(); message.Message[message.Message.Length - 2] = callbackId; message.CallbackId = callbackId; } } // Insert checksum message.Message[message.Message.Length - 1] = GenerateChecksum(message.Message); pendingMessages.Add(message); // serialPort.SendMessage(message.Message); // // wait for any previous message callback response int maxWait = 50; // 5 seconds max wait while (pendingMessages.Contains(message) && maxWait > 0) { Thread.Sleep(100); maxWait--; } pendingMessages.Remove(message); // // remove timed out messages (requeued messages after failure) // pendingMessages.RemoveAll(zm => { TimeSpan ttl = new TimeSpan(DateTime.UtcNow.Ticks - zm.Timestamp.Ticks); if (ttl.TotalSeconds >= 5) { return true; } return false; }); // Thread.Sleep(300); ackWait.Set(); // return callbackId; }
private void ReceiveMessage(ZWaveMessage msg) { if (DupeMessageCheck(msg)) { Utility.logger.Warn("Repeated message discarded."); return; } var rawData = msg.RawData; switch (msg.Type) { case MessageType.Request: if (nodeList.Count == 0) break; switch (msg.Function) { case ZWaveFunction.NotSet: break; case ZWaveFunction.NodeAdd: var nodeAddStatus = NodeAddStatus.None; Enum.TryParse(rawData[5].ToString(), out nodeAddStatus); switch (nodeAddStatus) { case NodeAddStatus.LearnReady: UpdateOperationProgress(0x01, NodeQueryStatus.NodeAddReady); SetQueryStage(QueryStage.Complete); break; case NodeAddStatus.AddingSlave: var newNode = CreateNode(rawData[6], 0x00); // Extract node information frame int nodeInfoLength = (int)rawData[7]; byte[] nodeInfo = new byte[nodeInfoLength]; Array.Copy(rawData, 8, nodeInfo, 0, nodeInfoLength); // Update node properties newNode.NodeInformationFrame = nodeInfo; newNode.ProtocolInfo.BasicType = rawData[8]; newNode.ProtocolInfo.GenericType = rawData[9]; newNode.ProtocolInfo.SpecificType = rawData[10]; // Add it to the node list and save it nodeList.Add(newNode); SaveNodesConfig(); UpdateOperationProgress(newNode.Id, NodeQueryStatus.NodeAddStarted); if (newNode.SupportCommandClass(CommandClass.Security)) { var nodeSecurityData = Security.GetSecurityData(newNode); nodeSecurityData.IsAddingNode = true; Security.GetScheme(newNode); } else { NodeInformationFrameDone(newNode); } break; case NodeAddStatus.ProtocolDone: GetNodeProtocolInfo(rawData[6]); var addedNode = GetNode(rawData[6]); if (addedNode != null) { ManufacturerSpecific.Get(addedNode); UpdateOperationProgress(addedNode.Id, NodeQueryStatus.NodeAddDone); } else { UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeAddFailed); } SetQueryStage(QueryStage.Complete); break; case NodeAddStatus.Done: UpdateOperationProgress(0x01, NodeQueryStatus.NodeAddDone); SetQueryStage(QueryStage.Complete); break; case NodeAddStatus.Failed: UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeAddFailed); SetQueryStage(QueryStage.Complete); break; } break; case ZWaveFunction.NodeRemove: var nodeRemoveStatus = NodeRemoveStatus.None; Enum.TryParse(rawData[5].ToString(), out nodeRemoveStatus); switch (nodeRemoveStatus) { case NodeRemoveStatus.LearnReady: UpdateOperationProgress(0x01, NodeQueryStatus.NodeRemoveReady); SetQueryStage(QueryStage.Complete); break; case NodeRemoveStatus.RemovingSlave: UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeRemoveStarted); break; case NodeRemoveStatus.Done: if (rawData[6] != 0x00) { RemoveNode(rawData[6]); SaveNodesConfig(); } UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeRemoveDone); SetQueryStage(QueryStage.Complete); break; case NodeRemoveStatus.Failed: UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeRemoveFailed); SetQueryStage(QueryStage.Complete); break; } break; case ZWaveFunction.RequestNodeNeighborsUpdateOptions: case ZWaveFunction.RequestNodeNeighborsUpdate: var neighborUpdateStatus = NeighborsUpdateStatus.None; Enum.TryParse(rawData[5].ToString(), out neighborUpdateStatus); switch (neighborUpdateStatus) { case NeighborsUpdateStatus.NeighborsUpdateStared: UpdateOperationProgress(msg.NodeId, NodeQueryStatus.NeighborUpdateStarted); break; case NeighborsUpdateStatus.NeighborsUpdateDone: UpdateOperationProgress(msg.NodeId, NodeQueryStatus.NeighborUpdateDone); SetQueryStage(QueryStage.Complete); break; case NeighborsUpdateStatus.NeighborsUpdateFailed: UpdateOperationProgress(msg.NodeId, NodeQueryStatus.NeighborUpdateFailed); SetQueryStage(QueryStage.Complete); break; default: Utility.logger.Warn("Unhandled Node Neighbor Update request: {0}", BitConverter.ToString(rawData)); break; } break; case ZWaveFunction.SendData: byte callbackId = rawData[4]; if (callbackId == 0x01) // 0x01 is "SEND DATA OK" { // TODO: ... is there anything to be done here? } else { switch (msg.CallbackStatus) { case CallbackStatus.Ack: //System.Diagnostics.Debugger.Break(); break; case CallbackStatus.Nack: //System.Diagnostics.Debugger.Break(); break; } } break; case ZWaveFunction.ApplicationCommandHandler: var node = GetNode(rawData[5]); if (node != null) { try { node.ApplicationCommandHandler(rawData); } catch (Exception ex) { Utility.logger.Error(ex); } } else { Utility.logger.Error("Unknown node id {0}", rawData[5]); } break; case ZWaveFunction.ApplicationUpdate: int nifLength = (int)rawData[6]; var znode = GetNode(rawData[5]); if (znode != null) { // we don't need to exclude the last 2 CommandClasses byte[] nodeInfo = new byte[nifLength]; Array.Copy(rawData, 7, nodeInfo, 0, nifLength); znode.NodeInformationFrame = nodeInfo; if (znode.SupportCommandClass(CommandClass.Security)) { // ask the node what security command classes are supported Security.GetSupported(znode); } else { NodeInformationFrameDone(znode); SetQueryStage(QueryStage.Complete); } } else { SetQueryStage(QueryStage.Error); } break; default: Utility.logger.Warn("Unhandled request message: {0}", BitConverter.ToString(rawData)); break; } break; case MessageType.Response: switch (msg.Function) { case ZWaveFunction.GetInitData: InitializeNodes(rawData); SetQueryStage(QueryStage.Complete); break; case ZWaveFunction.GetNodeProtocolInfo: var node = GetNode(msg.NodeId); node.ProtocolInfo.BasicType = rawData[7]; node.ProtocolInfo.GenericType = rawData[8]; node.ProtocolInfo.SpecificType = rawData[9]; break; case ZWaveFunction.RequestNodeInfo: SetQueryStage(QueryStage.SendDataReady); break; case ZWaveFunction.SendData: // TODO: shall we do something here? break; case ZWaveFunction.GetRoutingInfo: var routingInfo = Utility.ExtractRoutingFromBitMask(rawData); if (routingInfo.Length > 0) { var routedNode = GetNode(msg.NodeId); if (routedNode != null) { routedNode.UpdateData("RoutingInfo", routingInfo); routedNode.OnNodeUpdated(new NodeEvent(routedNode, EventParameter.RoutingInfo, String.Join(" ", routingInfo), 0)); } } else { Utility.logger.Warn("No routing nodes reported."); } break; default: Utility.logger.Warn("Unhandled response message: {0}", BitConverter.ToString(rawData)); break; } break; default: Utility.logger.Warn("Unhandled message type: {0}", BitConverter.ToString(rawData)); break; } }
private bool DupeMessageCheck(ZWaveMessage msg) { // Discard repeated messages within last 2 seconds time range bool repeated = false; if (lastMessage != null) { var elapsed = (DateTime.UtcNow - lastMessageTimestamp); if (elapsed.TotalSeconds <= 2 && lastMessage.SequenceEqual(msg.RawData)) { repeated = true; } } lastMessageTimestamp = DateTime.UtcNow; lastMessage = new byte[msg.RawData.Length]; Buffer.BlockCopy(msg.RawData, 0, lastMessage, 0, msg.RawData.Length * sizeof(byte)); return repeated; }
/// <summary> /// Sends the message without waiting other pending requests to complete. /// </summary> /// <returns>True if sending succesfull, False otherwise.</returns> /// <param name="message">Message.</param> public bool SendMessage(ZWaveMessage message) { #region Debug Utility.logger.Trace("[[[ BEGIN REQUEST ]]]"); var stopWatch = new Stopwatch(); stopWatch.Start(); #endregion SetQueryStage(QueryStage.WaitAck); pendingRequest = message; sendMessageAck.Reset(); Utility.logger.Trace("Sending Message (Node={0}, CallbackId={1}, Function={2}, CommandClass={3})", pendingRequest.NodeId, pendingRequest.CallbackId.ToString("X2"), pendingRequest.Function, pendingRequest.CommandClass); if (serialPort.SendMessage(message.RawData)) { if (!sendMessageAck.WaitOne(ZWaveMessage.SendMessageTimeoutMs)) { SetQueryStage(QueryStage.Error); // TODO: Dump Diagnostic Statistics Utility.logger.Warn("Message timeout (Node={0}, CallbackId={0}, Function={1}, CommandClass={2})", pendingRequest.NodeId, pendingRequest.CallbackId.ToString("X2"), pendingRequest.Function, pendingRequest.CommandClass); if (message.NodeId > 1) UpdateOperationProgress(message.NodeId, NodeQueryStatus.Timeout); //System.Diagnostics.Debugger.Break(); } } else { SetQueryStage(QueryStage.Error); Utility.logger.Warn("Controller status error (Node={0}, CallbackId={0}, Function={1}, CommandClass={2})", pendingRequest.NodeId, pendingRequest.CallbackId.ToString("X2"), pendingRequest.Function, pendingRequest.CommandClass); } pendingRequest = null; #region Debug stopWatch.Stop(); Utility.logger.Trace("[[[ END REQUEST ]]] took {0} ms", stopWatch.ElapsedMilliseconds); #endregion return (currentStage != QueryStage.Error); }
/// <summary> /// Queues the message. /// </summary> /// <returns>The ZWaveMessage object itself.</returns> /// <param name="message">Message.</param> public ZWaveMessage QueueMessage(ZWaveMessage message) { queuedMessages.Add(message); message.sentAck.Reset(); return message; }
private void ReceiveMessage(ZWaveMessage msg) { if (DupeMessageCheck(msg)) { Utility.logger.Warn("Repeated message discarded."); return; } var rawData = msg.RawData; switch (msg.Type) { case MessageType.Request: if (nodeList.Count == 0) { break; } switch (msg.Function) { case ZWaveFunction.NotSet: break; case ZWaveFunction.NodeAdd: var nodeAddStatus = NodeAddStatus.None; Enum.TryParse(rawData[5].ToString(), out nodeAddStatus); switch (nodeAddStatus) { case NodeAddStatus.LearnReady: UpdateOperationProgress(0x01, NodeQueryStatus.NodeAddReady); SetQueryStage(QueryStage.Complete); break; case NodeAddStatus.AddingSlave: var newNode = AddNode(rawData[6], 0x00); // Extract node information frame int nodeInfoLength = (int)rawData[7]; // we don't need to exclude the last 2 CommandClasses byte[] nodeInfo = new byte[nodeInfoLength]; Array.Copy(rawData, 8, nodeInfo, 0, nodeInfoLength); newNode.NodeInformationFrame = nodeInfo; newNode.ProtocolInfo.BasicType = rawData[8]; newNode.ProtocolInfo.GenericType = rawData[9]; newNode.ProtocolInfo.SpecificType = rawData[10]; nodeList.Add(newNode); UpdateOperationProgress(newNode.Id, NodeQueryStatus.NodeAddStarted); if (newNode.SupportCommandClass(CommandClass.Security)) { var nodeSecurityData = Security.GetSecurityData(newNode); nodeSecurityData.IsAddingNode = true; Security.GetScheme(newNode); } else { NodeInformationFrameDone(newNode); } break; case NodeAddStatus.ProtocolDone: GetNodeProtocolInfo(rawData[6]); var addedNode = GetNode(rawData[6]); if (addedNode != null) { ManufacturerSpecific.Get(addedNode); UpdateOperationProgress(addedNode.Id, NodeQueryStatus.NodeAddDone); } else { UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeAddFailed); } SetQueryStage(QueryStage.Complete); break; case NodeAddStatus.Done: UpdateOperationProgress(0x01, NodeQueryStatus.NodeAddDone); SetQueryStage(QueryStage.Complete); break; case NodeAddStatus.Failed: UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeAddFailed); SetQueryStage(QueryStage.Complete); break; } break; case ZWaveFunction.NodeRemove: var nodeRemoveStatus = NodeRemoveStatus.None; Enum.TryParse(rawData[5].ToString(), out nodeRemoveStatus); switch (nodeRemoveStatus) { case NodeRemoveStatus.LearnReady: UpdateOperationProgress(0x01, NodeQueryStatus.NodeRemoveReady); SetQueryStage(QueryStage.Complete); break; case NodeRemoveStatus.RemovingSlave: UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeRemoveStarted); break; case NodeRemoveStatus.Done: if (rawData[6] != 0x00) { RemoveNode(rawData[6]); } UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeRemoveDone); SetQueryStage(QueryStage.Complete); break; case NodeRemoveStatus.Failed: UpdateOperationProgress(rawData[6], NodeQueryStatus.NodeRemoveFailed); SetQueryStage(QueryStage.Complete); break; } break; case ZWaveFunction.RequestNodeNeighborsUpdateOptions: case ZWaveFunction.RequestNodeNeighborsUpdate: var neighborUpdateStatus = NeighborsUpdateStatus.None; Enum.TryParse(rawData[5].ToString(), out neighborUpdateStatus); switch (neighborUpdateStatus) { case NeighborsUpdateStatus.NeighborsUpdateStared: UpdateOperationProgress(msg.NodeId, NodeQueryStatus.NeighborUpdateStarted); break; case NeighborsUpdateStatus.NeighborsUpdateDone: UpdateOperationProgress(msg.NodeId, NodeQueryStatus.NeighborUpdateDone); //GetNeighborsRoutingInfo(msg.NodeId); SetQueryStage(QueryStage.Complete); break; case NeighborsUpdateStatus.NeighborsUpdateFailed: UpdateOperationProgress(msg.NodeId, NodeQueryStatus.NeighborUpdateFailed); SetQueryStage(QueryStage.Complete); break; default: Utility.logger.Warn("Unhandled Node Neighbor Update request: {0}", BitConverter.ToString(rawData)); break; } break; case ZWaveFunction.SendData: byte callbackId = rawData[4]; if (callbackId == 0x01) // 0x01 is "SEND DATA OK" { // TODO: ... is there anything to be done here? } else { switch (msg.CallbackStatus) { case CallbackStatus.Ack: //System.Diagnostics.Debugger.Break(); break; case CallbackStatus.Nack: //System.Diagnostics.Debugger.Break(); break; } } break; case ZWaveFunction.ApplicationCommandHandler: var node = GetNode(rawData[5]); if (node != null) { try { node.ApplicationCommandHandler(rawData); } catch (Exception ex) { Utility.logger.Error(ex); } } else { Utility.logger.Error("Unknown node id {0}", rawData[5]); } break; case ZWaveFunction.ApplicationUpdate: int nifLength = (int)rawData[6]; var znode = GetNode(rawData[5]); if (znode != null) { // we don't need to exclude the last 2 CommandClasses byte[] nodeInfo = new byte[nifLength]; Array.Copy(rawData, 7, nodeInfo, 0, nifLength); znode.NodeInformationFrame = nodeInfo; if (znode.SupportCommandClass(CommandClass.Security)) { // ask the node what security command classes are supported Security.GetSupported(znode); } else { NodeInformationFrameDone(znode); SetQueryStage(QueryStage.Complete); } } else { SetQueryStage(QueryStage.Error); } break; default: Utility.logger.Warn("Unhandled request message: {0}", BitConverter.ToString(rawData)); break; } break; case MessageType.Response: switch (msg.Function) { case ZWaveFunction.GetInitData: InitializeNodes(rawData); SetQueryStage(QueryStage.Complete); break; case ZWaveFunction.GetNodeProtocolInfo: var node = GetNode(msg.NodeId); node.ProtocolInfo.BasicType = rawData[7]; node.ProtocolInfo.GenericType = rawData[8]; node.ProtocolInfo.SpecificType = rawData[9]; break; case ZWaveFunction.RequestNodeInfo: SetQueryStage(QueryStage.SendDataReady); break; case ZWaveFunction.SendData: // TODO: shall we do something here? break; case ZWaveFunction.GetRoutingInfo: var routingInfo = Utility.ExtractRoutingFromBitMask(rawData); if (routingInfo.Length > 0) { var routedNode = GetNode(msg.NodeId); if (routedNode != null) { routedNode.UpdateData("RoutingInfo", routingInfo); routedNode.OnNodeUpdated(new NodeEvent(routedNode, EventParameter.RoutingInfo, String.Join(" ", routingInfo), 0)); } } else { Utility.logger.Warn("No routing nodes reported."); } break; default: Utility.logger.Warn("Unhandled response message: {0}", BitConverter.ToString(rawData)); break; } break; default: Utility.logger.Warn("Unhandled message type: {0}", BitConverter.ToString(rawData)); break; } }
/// <summary> /// Queues the message. /// </summary> /// <returns>The ZWaveMessage object itself.</returns> /// <param name="message">Message.</param> public ZWaveMessage QueueMessage(ZWaveMessage message) { bool addToQueue = true; var node = GetNode(message.NodeId); if (node != null && node.SupportCommandClass(CommandClass.WakeUp)) { var wakeUpStatus = node.GetData("WakeUpStatus"); if (wakeUpStatus != null && wakeUpStatus.Value != null && ((WakeUpStatus)wakeUpStatus.Value).IsSleeping) { Utility.logger.Warn("Node is flagged as sleeping, message will be re-sent on Wake Up (Node={0}, CallbackId={0}, Function={1}, CommandClass={2})", message.NodeId, message.CallbackId.ToString("X2"), message.Function, message.CommandClass); WakeUp.ResendOnWakeUp(node, message.RawData); addToQueue = false; } } if (addToQueue) { queuedMessages.Add(message); message.sentAck.Reset(); } else { message.sentAck.Set(); } return message; }
internal byte SendMessage(byte[] message, bool disableCallback = false) { var msg = new ZWaveMessage() { Node = this, Message = message }; return zwavePort.SendMessage(msg, disableCallback); }
internal ZWaveMessage SendMessage(byte[] message) { var msg = new ZWaveMessage(message, MessageDirection.Outbound, true); controller.QueueMessage(msg); return msg; }
/// <summary> /// Updates the query stage. /// </summary> /// <param name="zm">Zm.</param> private void UpdateQueryStage(ZWaveMessage zm) { if (currentStage != QueryStage.Complete && currentStage != QueryStage.NotSet && currentStage != QueryStage.Error) { //Utility.logger.Trace("Query Stage {0} Type {1} Function {2}={3} Node {4}={5} Callback {6}={7}", currentStage, zm.Type, zm.Function, currentMessage.Function, zm.NodeId, currentMessage.NodeId, zm.CallbackId, currentMessage.CallbackId); switch (currentStage) { case QueryStage.WaitAck: // The controller accepted a request if (zm.Type == MessageType.Response && zm.Function == pendingRequest.Function) { if (pendingRequest.CallbackId == 0) { SetQueryStage(QueryStage.Complete); } else { // The controller needs querying data from the node SetQueryStage(QueryStage.SendDataReady); } } break; case QueryStage.SendDataReady: // The controller requested data from the node if (zm.Type == MessageType.Request && zm.Function == pendingRequest.Function) { if (zm.CallbackStatus != CallbackStatus.Ack) { SetQueryStage(QueryStage.Error); // TODO: Dump Diagnostic Statistics } else { SetQueryStage(QueryStage.Complete); } } break; } } }
public void SendRequest(byte[] request) { SendMessage(ZWaveMessage.CreateRequest(this.Id, request)); }
public MessageReceivedEventArgs(ZWaveMessage message) { Message = message; Timestamp = DateTime.UtcNow; }