/// <summary>
        /// Method for request the failure of tag that have been report failed tag
        /// </summary>
        /// <param name="failedTagIndex">Index of tag to retreive</param>
        /// <param name="tagID">>variable to store the uid retrieved</param>
        /// <param name="serialDigitsRead">Number of digit read before failure</param>
        /// <param name="failureReason">The reason of the failure in string format</param>
        /// <returns>true is succeed</returns>
        public bool getFailedTag(uint failedTagIndex, out UInt64 tagID, out uint serialDigitsRead, out string failureReason)
        {
            PbMsgRfidGetTagFailure message  = new PbMsgRfidGetTagFailure(failedTagIndex);
            PbRspRfidGetTagFailure response =
                (PbRspRfidGetTagFailure)marshalMessage(message, typeof(PbRspRfidGetTagFailure));

            if ((response == null) || (response.completionStatus != (byte)ResponseCodeType.PBRC_SUCCESS))
            {
                Debug.Fail("Unexpected response for PbMsgRfidGetNextTag: " +
                           ((response == null) ? "null" : ((ResponseCodeType)response.completionStatus).ToString()));
                tagID            = 0;
                serialDigitsRead = 0;
                failureReason    = "";
                return(false);
            }

            tagID            = SerialRFID.SerialNumber(response.digitSequence);
            serialDigitsRead = response.digitsRead;
            switch ((TagFailureEnumType)response.failureType)
            {
            case TagFailureEnumType.TFFT_MissingDigit: failureReason = "Digit Missing"; break;

            case TagFailureEnumType.TFFT_ChecksumFailure: failureReason = "Checksum"; break;

            default: Debug.Fail("Unexpected failure type."); failureReason = "** Unknown **"; break;
            }

            return(true);
        }
        private Tag findOrAddTag(UInt64 tagID, bool useSPCE2)
        {
            Tag tag = (Tag)tagList[tagID];

            if (tag == null)
            {
                int rowIndex;
                if (useSPCE2)
                {
                    string codeOct = SerialRFID.SerialNumberAsString(tagID);
                    if (codeOct.StartsWith("3"))
                    {
                        rowIndex = tagListDataGrid.Rows.Add(SerialRFID.SerialNumberAsAlphaString(tagID, TagType.TT_SPCE2_RO), 0, 0, 0, 0, Axis);
                    }
                    else
                    {
                        rowIndex = tagListDataGrid.Rows.Add(SerialRFID.SerialNumberAsAlphaString(tagID, TagType.TT_SPCE2_RW), 0, 0, 0, 0, Axis);
                    }
                }
                else
                {
                    rowIndex = tagListDataGrid.Rows.Add(SerialRFID.SerialNumberAsString(tagID), 0, 0, 0, 0, Axis);
                }
                tag = new Tag(tagID, tagListDataGrid.Rows[rowIndex]);
                tagListDataGrid.FirstDisplayedScrollingRowIndex = rowIndex;
                tagList.Add(tag.id, tag);
            }
            else
            {
                tagListDataGrid.Rows[tag.row.Index].Cells[5].Value = Axis;
            }

            return(tag);
        }
        /// <summary>
        /// Method to request next tag in list known tagin Stat Scan function
        /// </summary>
        /// <param name="bFirstTag">If set, the first tag is requested and put all the tag uin the list in no reported status</param>
        /// <param name="tagID">variable to store the uid retrieved</param>
        /// <param name="tagIndex">Index of the tag in the list</param>
        /// <param name="tagCount">number of tag in the list</param>
        /// <returns>true is succeed to request</returns>
        ///
        public bool getNextTag(bool bFirstTag, out UInt64 tagID, out uint tagIndex, out uint tagCount)
        {
            PbMsgRfidGetNextTag message = new PbMsgRfidGetNextTag();

            message.bGetFirst = bFirstTag;

            while (true)
            {
                PbRspRfidGetNextTag getNextTagResponse =
                    (PbRspRfidGetNextTag)marshalMessage(message, typeof(PbRspRfidGetNextTag));

                if ((getNextTagResponse == null) || (getNextTagResponse.completionStatus != (byte)ResponseCodeType.PBRC_SUCCESS))
                {
                    Debug.Fail("Unexpected response for PbMsgRfidGetNextTag: " +
                               ((getNextTagResponse == null) ? "null" : ((ResponseCodeType)getNextTagResponse.completionStatus).ToString()));
                    tagID    = 0;
                    tagIndex = 0;
                    tagCount = 0;
                    return(false);
                }

                tagID    = SerialRFID.SerialNumber(getNextTagResponse.serialNumber);
                tagIndex = getNextTagResponse.tagIndex;
                tagCount = getNextTagResponse.currentTagCount;

                // If another tag has responded, return it to the caller.
                if ((getNextTagResponse.tagInfo & (uint)TagInfoFlags.TIF_ReachedEndOfTagList) == 0)
                {
                    return(true);
                }

                // If the device is still scanning tags, loop to try again, else return false.
                if ((getNextTagResponse.scanStatus & (uint)ScanStatusFlags.SSF_ScanningTagsNow) == 0)
                {
                    return(false);
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="asyncEventMessage"></param>
        public void handleAsyncEvent(AsyncEventMessage asyncEventMessage)
        {
            switch (asyncEventMessage.asyncEventType)
            {
            //case AsyncEventType.PBET_TagAdded
            case AsyncEventType.PBET_TagAddedR8:
            {
                PBAE_RfidTagAdded tagAddedMessage = (PBAE_RfidTagAdded)Utilities.MarshalToStruct(
                    asyncEventMessage.serialMessage, typeof(PBAE_RfidTagAdded));
                Tag tag = findOrAddTag(SerialRFID.SerialNumber(tagAddedMessage.serialNumber), false);
                tag.inventorySequence = inventorySequence;
                tag.bTagAdded         = true;

                nbTagPerAxis[Axis]++;
                updateNbTagPerAxis();
                cptCount++;
                Invoke((MethodInvoker) delegate { labelCpt.Text = "Count: " + cptCount.ToString(); });
                checkKZout = 0;        // raz cpt  test sortie
                Invoke((MethodInvoker) delegate { labelKZ.Text = "KZ : " + checkKZout.ToString(); });
                break;
            }

            //case AsyncEventType.PBET_TagRemoved:
            case AsyncEventType.PBET_TagAddedSPCE2_RO:
            case AsyncEventType.PBET_TagAddedSPCE2_RW:
            {
                PBAE_RfidTagAdded tagAddedMessage = (PBAE_RfidTagAdded)Utilities.MarshalToStruct(
                    asyncEventMessage.serialMessage, typeof(PBAE_RfidTagAdded));
                Tag tag = findOrAddTag(SerialRFID.SerialNumber(tagAddedMessage.serialNumber), true);
                tag.inventorySequence = inventorySequence;
                tag.bTagAdded         = true;

                nbTagPerAxis[Axis]++;
                updateNbTagPerAxis();
                cptCount++;
                Invoke((MethodInvoker) delegate { labelCpt.Text = "Count: " + cptCount.ToString(); });
                checkKZout = 0;     // raz cpt  test sortie
                Invoke((MethodInvoker) delegate { labelKZ.Text = "KZ : " + checkKZout.ToString(); });
                break;
            }

            case AsyncEventType.PBET_BackDoorInfo:
            {
                PBAE_BackDoorInfo backDoorPacket = (PBAE_BackDoorInfo)Utilities.MarshalToStruct(
                    asyncEventMessage.serialMessage, typeof(PBAE_BackDoorInfo));
                if (backDoorPacket.backDoorEventType == (byte)BackDoorEventType.BDET_AxisChange)
                {
                    if ((backDoorPacket.value1 < 10) && (backDoorPacket.value2 > 20))
                    {
                        Axis = backDoorPacket.value1;
                        Invoke((MethodInvoker) delegate { labelaxis.Text = "Axis : " + backDoorPacket.value1.ToString(); });
                        Invoke((MethodInvoker) delegate { labelaxis.Refresh(); });
                        stopTime = DateTime.Now;
                        TimeSpan duration = stopTime - startTime;
                        string   time     = duration.ToString();
                        double   rate     = cptCount / duration.TotalSeconds;
                        if (time.Length > 12)
                        {
                            Invoke((MethodInvoker) delegate { labelTime.Text = "Time : " + time.Substring(0, 12) + " - Tags/s : " + String.Format("{0:0.00}", rate);; });
                        }
                    }
                }

                if ((backDoorPacket.value1 == 10) && (backDoorPacket.value2 == 1))
                {
                    checkKZout++;
                }
                Invoke((MethodInvoker) delegate { labelKZ.Text = "KZ : " + checkKZout.ToString(); });
                break;
            }

            case AsyncEventType.PBET_RfidScanStateChanged:
            {
                PBAE_RfidScanStateChanged scanStateChangedMessage = (PBAE_RfidScanStateChanged)Utilities.MarshalToStruct(
                    asyncEventMessage.serialMessage, typeof(PBAE_RfidScanStateChanged));

                // Switch on the new scan state.
                switch ((ScanStatusType)scanStateChangedMessage.scanStatus)
                {
                case ScanStatusType.SS_TagScanStarted:                                 // Cabinet scan has begun.
                {
                    //KB000: This could happen due to a Pyxibus bug where message with broken ACK is delivered twice.
                    // MyDebug.Assert(bScanActive);

                    nbTagPerAxis = new int[10];
                    updateNbTagPerAxis();
                    startTime  = DateTime.Now;
                    checkKZout = 1;
                    Invoke((MethodInvoker) delegate { labelKZ.Text = "KZ : " + checkKZout.ToString(); });
                    if (!bScanActive)
                    {
                        bScanRequested = false;
                        bScanActive    = true;

                        /* if(receiveTagsSynchronouslyDuringScanRadioButton.Checked)
                         * {
                         *       bool bFirstTag = true;
                         *       uint tagIndex;
                         *       uint tagCount;
                         *       UInt64 tagID;
                         *       while(device.getNextTag(bFirstTag, out tagID, out tagIndex, out tagCount))
                         *       {
                         *               bFirstTag = false;
                         *               Tag tag = findOrAddTag(tagID);
                         *       }
                         * }*/
                    }
                    break;
                }

                case ScanStatusType.SS_TagScanCanceledByHost:                                 // Cabinet scan canceled by host.
                    //KB000: This could happen due to a Pyxibus bug where message with broken ACK is delivered twice.
                    // MyDebug.Assert(bScanActive);
                    checkKZout = 255;
                    Invoke((MethodInvoker) delegate { labelKZ.Text = "KZ : " + checkKZout.ToString(); });
                    if (bScanActive)
                    {
                        bScanActive    = false;
                        bCancelLooping = true;
                        TagScanActive(false);
                    }
                    break;

                case ScanStatusType.SS_TagScanCanceledByDoorOpen:                                 // Cabinet scan canceled due to door opening.
                    //KB000: This could happen due to a Pyxibus bug where message with broken ACK is delivered twice.
                    // MyDebug.Assert(bScanActive);
                    if (bScanActive)
                    {
                        bScanActive    = false;
                        bCancelLooping = true;
                        MessageBox.Show("Tag scan canceled by opening door.");
                        TagScanActive(false);
                    }
                    break;

                case ScanStatusType.SS_TagScanFailedByUnrecoverableError:                                 // Cabinet scan failed due to unrecoverable error.
                    //KB000: This could happen due to a Pyxibus bug where message with broken ACK is delivered twice.
                    // MyDebug.Assert(bScanActive);
                    if (bScanActive)
                    {
                        bScanActive    = false;
                        bCancelLooping = true;
                        MessageBox.Show("Tag scan failed due to unrecoverable error: " +
                                        ((UnrecoverableErrorType)scanStateChangedMessage.info).ToString());
                        TagScanActive(false);
                    }
                    break;

                case ScanStatusType.SS_TagScanSendPourcent:
                    break;

                case ScanStatusType.SS_TagScanCompleted:                                 // Cabinet scan has completed
                {
                    //KB000: This could happen due to a Pyxibus bug where message with broken ACK is delivered twice.
                    // MyDebug.Assert(bScanActive);
                    stopTime = DateTime.Now;
                    TimeSpan duration = stopTime - startTime;
                    string   time     = duration.ToString();
                    double   rate     = cptCount / duration.TotalSeconds;
                    if (time.Length > 12)
                    {
                        Invoke((MethodInvoker) delegate { labelTime.Text = "Time : " + time.Substring(0, 12) + " - Tags/s : " + String.Format("{0:0.00}", rate);; });
                    }

                    if (bScanActive)
                    {
                        foreach (Tag tag in tagList.Values)
                        {
                            if (bKnownTagsCleared)
                            {
                                tag.bPresent = (tag.inventorySequence == inventorySequence);
                                Debug.Assert(!tag.bPresent || tag.bTagAdded);                                                         // When known tags are cleared, the only tag reports should be tag-added.
                            }
                            else if (tag.inventorySequence == inventorySequence)
                            {
                                // The tag reported a change in the presence state.
                                tag.bPresent = tag.bTagAdded;
                            }
                        }

                        uint presentTags = 0;
                        uint missingTags = 0;
                        foreach (Tag tag in tagList.Values)
                        {
                            if (tag.bPresent)
                            {
                                tag.missingCount = 0;
                                tag.presentCount++;
                                tag.presentTotal++;
                                presentTags++;
                            }
                            else
                            {
                                tag.missingCount++;
                                tag.missingTotal++;
                                tag.presentCount = 0;
                                missingTags++;
                            }

                            tag.row.Cells[1].Value = tag.presentCount.ToString();
                            tag.row.Cells[2].Value = tag.missingCount.ToString();
                            tag.row.Cells[3].Value = tag.presentTotal.ToString();
                            tag.row.Cells[4].Value = tag.missingTotal.ToString();

                            // Update the row color to give a visual indication of sequential present/missing state.
                            if (!tag.bPresent)
                            {
                                tag.row.DefaultCellStyle.BackColor = FadeColor(Color.Red, Color.Gray, tag.missingCount);
                            }
                            else if (tag.presentTotal == tag.presentCount)
                            {
                                tag.row.DefaultCellStyle.BackColor = Color.White;
                            }
                            else
                            {
                                tag.row.DefaultCellStyle.BackColor = FadeColor(Color.Green, Color.White, tag.presentCount);
                            }
                        }

                        Invoke((MethodInvoker) delegate { presentTagsLabel.Text = "Present: " + presentTags.ToString(); });
                        Invoke((MethodInvoker) delegate { missingTagsLabel.Text = "Missing: " + missingTags.ToString(); });



                        bScanActive = false;
                        // If too many tags were detected, show a warning.
                        if ((scanStateChangedMessage.info & (byte)TagScanCompleteInfoFlagsType.TSCF_TooManyTags) != 0)
                        {
                            bCancelLooping = true;
                            MessageBox.Show("Too many tags detected.");
                            TagScanActive(false);
                        }

                        // If looping, start again.
                        else if (loopCheckBox.Checked && !bCancelLooping)
                        {
                            if (bLoopTimerExpired)
                            {
                                doInventory();
                            }
                        }
                        else
                        {
                            TagScanActive(false);
                        }
                    }
                    break;
                }
                }

                break;
            }
            }
        }