Example #1
0
        public override bool ParseResponse(byte[] buffer)
        {
            if (!IsResponseOK(buffer))
            {
                // response not OK => do nothing
                return(false);
            }

            m_networkAddress = AdapterHelper.UInt16FromXbeeFrame(buffer, DATA_OFFSET_IN_RESPONSE_BUFFER);

            return(true);
        }
Example #2
0
        protected bool IsResponseOK(byte[] buffer)
        {
            int offset = 0;

            // verify cluster Id
            offset  = AdapterHelper.MAC_ADDR_LENGTH;
            offset += AdapterHelper.NETWORK_ADDRESS_LENGTH;
            offset += SOURCE_ENDPOINT.Length;
            offset += DESTINATION_ENDPOINT.Length;

            UInt16 tempValue = AdapterHelper.UInt16FromXbeeFrame(buffer, offset);

            if (tempValue != m_responseClusterId)
            {
                return(false);
            }

            if (!m_isZdoCommand)
            {
                // there is nothing more to control for ZCL
                //
                //  - cluster ID is hard to control (Phillips Hue light bulb respond with ZHA profile even though they are ZLL profile)
                //  - status of ZCL command is inside ZCL payload and depends on each ZCL command
                return(true);
            }

            // verify profile Id
            offset += DEFAULT_CLUSTER_ID.Length;
            byte[] profileId = PROFILE_ID;

            for (int index = 0; index < profileId.Length; index++)
            {
                if (buffer[index + offset] != profileId[index])
                {
                    return(false);
                }
            }

            // verify status only for response to ZDO command (ZDO notification don't have status)
            if (!m_isNotification)
            {
                offset = GetZdoPayloadOffset() - ZIGBEE_STATUS_LENGTH;
                if (buffer[offset] != ZdoHelper.ZDO_ERROR_SUCCESS)
                {
                    return(false);
                }
            }

            return(true);
        }
Example #3
0
        private bool CheckResponse()
        {
            bool checkNextResponse = false;

            int  headerSize             = 0;
            bool signalResponseReceived = false;

            byte[]        response      = null;
            XBeeATCommand atCommand     = null;
            ZigBeeCommand zigBeeCommand = null;

            lock (m_locker)
            {
                if (COMMAND_PREFIX[0] != m_currentResponse[0])
                {
                    // response buffer is invalid => discard
                    m_currentResponse = null;
                    return(checkNextResponse);
                }

                headerSize = COMMAND_PREFIX.Length + sizeof(UInt16);
                if (m_currentResponse.Length <= headerSize)
                {
                    // not enough bytes => wait for more
                    return(checkNextResponse);
                }

                // get size of response
                int payloadLength      = (int)AdapterHelper.UInt16FromXbeeFrame(m_currentResponse, COMMAND_PREFIX.Length);
                int fullResponseLength = payloadLength + headerSize + CHECKSUM_LENGTH;

                if (m_currentResponse.Length < fullResponseLength)
                {
                    // not enough bytes => wait for more
                    return(checkNextResponse);
                }

                // verify checksum
                if (IsCheckSumOk(ref m_currentResponse, headerSize, payloadLength + CHECKSUM_LENGTH))
                {
                    // trace Rx buffer to debug output
                    Logger.TraceRxBuffer(m_currentResponse);

                    // get frame type
                    byte frameType = m_currentResponse[headerSize];

                    // find corresponding command or corresponding notification
                    if (frameType == AT_COMMAND_LOCAL_RECEIVE[0] ||
                        frameType == AT_COMMAND_REMOTE_RECEIVE[0])
                    {
                        // get command ID
                        byte commandId = m_currentResponse[headerSize + AT_COMMAND_LOCAL_RECEIVE.Length];
                        if (m_pendingATCmdList.TryGetValue(commandId, out atCommand))
                        {
                            Debug.WriteLineIf(Logger.IsVerbose(), "got response", atCommand.ToString());

                            // command found => parse response and remove from list
                            int responseHeaderLength = sizeof(byte) + AT_COMMAND_LOCAL_RECEIVE.Length;
                            payloadLength -= responseHeaderLength;
                            response       = new byte[payloadLength];
                            Array.Copy(m_currentResponse, headerSize + responseHeaderLength, response, 0, payloadLength);

                            atCommand.ParseResponse(response);
                            RemovePendingATCmd(commandId);
                            signalResponseReceived = true;
                        }
                        else
                        {
                            Debug.WriteLineIf(Logger.IsVerbose(), "unmanaged response to AT COMMAND or AT COMMAND notification");
                        }
                    }
                    else if (frameType == EXPLICIT_RX_INDICATOR[0])
                    {
                        int responseHeaderLength = sizeof(byte);
                        payloadLength -= responseHeaderLength;
                        response       = new byte[payloadLength];
                        Array.Copy(m_currentResponse, headerSize + responseHeaderLength, response, 0, payloadLength);

                        byte zdoSequenceNumber = m_currentResponse[headerSize + EXPLICIT_RX_INDICATOR.Length + ZigBeeCommand.GetSequenceNumberOffestInZdoFrame()];
                        byte zclSequenceNumber = m_currentResponse[headerSize + EXPLICIT_RX_INDICATOR.Length + ZigBeeCommand.GetSequenceNumberOffestInZclFrame()];
                        if ((m_pendingZigBeeCmdList.TryGetValue(zdoSequenceNumber, out zigBeeCommand) && zigBeeCommand.IsZdoCommand)
                            ||
                            (m_pendingZigBeeCmdList.TryGetValue(zclSequenceNumber, out zigBeeCommand) && !zigBeeCommand.IsZdoCommand))
                        {
                            Debug.WriteLineIf(Logger.IsVerbose(), "got response to ZDO or ZCL command", zigBeeCommand.ToString());

                            zigBeeCommand.ParseResponse(response);
                            if (zigBeeCommand.IsZdoCommand)
                            {
                                RemovePendingZigBeeCmd(zdoSequenceNumber);
                            }
                            else
                            {
                                RemovePendingZigBeeCmd(zclSequenceNumber);
                            }
                            signalResponseReceived = true;
                        }
                        else
                        {
                            // check if this is an awaited notification
                            foreach (var notification in m_ZigBeeNotificationList)
                            {
                                // "try" parsing response to figure out if it
                                // correspond to a awaited notification
                                if (notification.Value.ParseResponse(response))
                                {
                                    // corresponding notification found
                                    Debug.WriteLineIf(Logger.IsVerbose(), "notification of ZDO or ZCL command", notification.Value.ToString());
                                    break;
                                }
                            }
                            Debug.WriteLineIf(Logger.IsVerbose(), "unmanaged response to ZDO or ZCL command");
                        }
                    }
                    else
                    {
                        Debug.WriteLineIf(Logger.IsVerbose(), "received frame OK but not handled");
                    }
                }

                // remove response from buffer
                ClearResponseBuffer(fullResponseLength);
                if (m_currentResponse != null &&
                    m_currentResponse.Length != 0)
                {
                    checkNextResponse = true;
                }
            }

            if (signalResponseReceived)
            {
                if (null != atCommand)
                {
                    atCommand.SignalResponseReceive();
                }
                else if (null != zigBeeCommand)
                {
                    zigBeeCommand.SignalResponseReceive();
                }
            }

            return(checkNextResponse);
        }
        public override bool ParseResponse(byte[] buffer)
        {
            SOURCE_INFO sourceInfo = new SOURCE_INFO();

            // verify command Id
            int offset = GetZclCommandIdOffset(ref buffer);

            if (COMMAND_ID_REPORT_ATTRIBUTES != buffer[offset])
            {
                return(false);
            }

            if (OnReception == null)
            {
                // can't signal anything
                // however this is not an error => return true
                return(true);
            }

            // get Mac address, network address, endpoint Id and cluster Id of source
            offset = 0;
            sourceInfo.macAddress = AdapterHelper.UInt64FromXbeeFrame(buffer, offset);
            offset = AdapterHelper.MAC_ADDR_LENGTH;

            sourceInfo.networkAddress = AdapterHelper.UInt16FromXbeeFrame(buffer, offset);
            offset += AdapterHelper.NETWORK_ADDRESS_LENGTH;

            sourceInfo.endpointId = buffer[offset];
            offset++;

            // skip destination end point
            offset++;

            sourceInfo.clusterId = AdapterHelper.UInt16FromXbeeFrame(buffer, offset);

            string strBuffer = "";

            foreach (byte b in buffer)
            {
                strBuffer = strBuffer + b.ToString() + " ";
            }

            loggingServices.WriteLine <ZclReportAttributes>("strBuffer = [" + strBuffer + "]");
            loggingServices.WriteLine <ZclReportAttributes>("macAddress = [" + sourceInfo.macAddress + "]");
            loggingServices.WriteLine <ZclReportAttributes>("networkAddress = [" + sourceInfo.networkAddress + "]");
            loggingServices.WriteLine <ZclReportAttributes>("endpointId = [" + sourceInfo.endpointId + "]");
            loggingServices.WriteLine <ZclReportAttributes>("clusterId = [" + sourceInfo.clusterId + "]");

            // parse ZCL payload
            offset = GetZclPayloadOffset(ref buffer);
            loggingServices.WriteLine <ZclReportAttributes>("offset of addributeId = [" + offset + "]");
            while (offset < buffer.Length)
            {
                object value = null;

                // from ZCL report attribute payload
                // - 1st byte is the attribute Id
                // - 2nd byte indicates the type
                // - following byte(s) contain the value
                UInt16 attributeId = AdapterHelper.UInt16FromZigBeeFrame(buffer, offset);
                loggingServices.WriteLine <ZclReportAttributes>("attributeId = [" + attributeId + "]");
                offset += sizeof(UInt16);
                byte type = buffer[offset];
                offset += sizeof(byte);
                loggingServices.WriteLine <ZclReportAttributes>("offset of value = [" + offset + "]");
                if (!ZclHelper.GetValue(type, ref buffer, ref offset, out value))
                {
                    // give up if attribute can't be retrieved
                    break;
                }

                // execute notification callback asynchronously
                Task.Run(() => { OnReception(sourceInfo, attributeId, value); });
            }
            return(true);
        }
Example #5
0
        public override bool ParseResponse(byte[] buffer)
        {
            if (m_commandList.Count == 0)
            {
                // no server command registered
                return(false);
            }

            // get Mac address, endpoint Id, cluster Id and command Id of source
            int    offset     = 0;
            UInt64 macAddress = AdapterHelper.UInt64FromXbeeFrame(buffer, offset);

            offset = AdapterHelper.MAC_ADDR_LENGTH;

            // skip network address (mac address is enough)
            offset += AdapterHelper.NETWORK_ADDRESS_LENGTH;

            byte endpointId = buffer[offset];

            offset++;

            // skip destination end point
            offset++;

            UInt16 clusterId = AdapterHelper.UInt16FromXbeeFrame(buffer, offset);

            offset = GetZclCommandIdOffset(ref buffer);
            byte commandId = buffer[offset];

            // find element that matches Mac address, network address, endpoint Id and cluster Id
            var element = Find(macAddress, endpointId, clusterId, commandId);

            if (element == null)
            {
                // no corresponding element for that Zcl server command
                return(false);
            }

            if (element.OnReception == null)
            {
                // no notification hence nothing else to do
                return(true);
            }

            // get parameters
            offset = GetZclPayloadOffset(ref buffer);
            // fill in out parameters
            foreach (var parameter in element.ParamList)
            {
                object value;
                if (!ZclHelper.GetValue(parameter.ZigBeeType, ref buffer, ref offset, out value))
                {
                    // can't get one of the out parameters => nothing else to do
                    // note that return value is true because server command has been found but can't be parsed
                    return(true);
                }

                parameter.Data = value;
            }

            // execute notification callback asynchronously
            Task.Run(() => { element.OnReception(element); });

            return(true);
        }