/// <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);
        }
示例#4
0
        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);
        }
示例#5
0
        public void sendSupportedGet(ZWaveNode node)
        {
            var message = ZWaveMessage.CreateRequest(node.Id, new byte[] {
                (byte)CommandClass.Security,
                (byte)SecurityCommand.SupportedGet
            });

            encryptAndSend(node, message);
        }
示例#6
0
        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);
            }
        }
示例#8
0
        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);
        }
示例#9
0
 public void ResendLastMessage()
 {
     if (_pendingmsgs.Count > 0)
     {
         ZWaveMessage msg = _pendingmsgs[_pendingmsgs.Count - 1];
         _pendingmsgs.Remove(msg);
         if (msg.ResendCount < 3)
         {
             msg.ResendCount++;
             SendMessage(msg);
         }
     }
 }
示例#10
0
        /// <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;
                }
            }
        }
示例#11
0
        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);
                }
            }
        }
示例#12
0
        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);
            }
        }
示例#13
0
        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));
            }
        }
示例#15
0
        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);
        }
示例#16
0
 /// <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);
 }
示例#17
0
 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;
            }
        }
        /// <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));
            }
        }
 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;
 }
示例#23
0
        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;
            }
        }
示例#24
0
 /// <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;
 }
示例#25
0
 internal byte SendMessage(byte[] message, bool disableCallback = false)
 {
     var msg = new ZWaveMessage() { Node = this, Message = message };
     return zwavePort.SendMessage(msg, disableCallback);
 }
示例#26
0
 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;
         }
     }
 }
示例#28
0
 public void SendRequest(byte[] request)
 {
     SendMessage(ZWaveMessage.CreateRequest(this.Id, request));
 }
示例#29
0
 public MessageReceivedEventArgs(ZWaveMessage message)
 {
     Message   = message;
     Timestamp = DateTime.UtcNow;
 }