// The set routing command changes the way the validator deals with a note, either it can send the note straight to the cashbox
        // or it can store the note for payout. This is specified in the second byte (0x00 to store for payout, 0x01 for cashbox). The
        // bytes after this represent the 4 bit value of the note, or the channel (see SetValueReportingType()).
        // This function allows the note to be specified as an int in the param note, the stack bool is true for cashbox, false for storage.
        public void ChangeNoteRoute(int note, char[] currency, bool stack)
        {
            m_cmd.CommandData[0] = CCommands.SSP_CMD_SET_DENOMINATION_ROUTE;

            // if this note is being changed to stack (cashbox)
            if (stack)
            {
                m_cmd.CommandData[1] = 0x01;
            }
            // note being stored (payout)
            else
            {
                m_cmd.CommandData[1] = 0x00;
            }

            // get the note as a byte array
            byte[] b = BitConverter.GetBytes(note);
            m_cmd.CommandData[2] = b[0];
            m_cmd.CommandData[3] = b[1];
            m_cmd.CommandData[4] = b[2];
            m_cmd.CommandData[5] = b[3];

            // send country code
            m_cmd.CommandData[6] = (byte)currency[0];
            m_cmd.CommandData[7] = (byte)currency[1];
            m_cmd.CommandData[8] = (byte)currency[2];

            m_cmd.CommandDataLength = 9;

            if (!SendCommand())
            {
                return;
            }
            if (CheckGenericResponses())
            {
                string s;
                string cs = new string(currency);
                if (stack)
                {
                    s = " to cashbox) ";
                }
                else
                {
                    s = " to storage) ";
                }
                Log.WriteLog("Note routing successful (" + CHelpers.FormatToCurrency(note) + cs + s, "CashAcceptor");
            }
        }
        public void ShowAllRouting()
        {
            UpdateData();
            string Route;

            m_StoredCurrency = "";
            foreach (ChannelData d in m_UnitDataList)
            {
                if (d.Recycling)
                {
                    Route            = " storage";
                    m_StoredCurrency = GetChannelCurrency(d.Channel);
                }
                else
                {
                    Route = " cashbox";
                }

                Log.WriteLog(CHelpers.FormatToCurrency(d.Value) + " " + GetChannelCurrency(d.Channel) + Route + " ", "CashAcceptor");
            }
        }
        // The poll function is called repeatedly to poll to validator for information, it returns as
        // a response in the command structure what events are currently happening.
        public bool DoPoll()
        {
            byte i;

            m_cmd.CommandData[0]    = CCommands.SSP_CMD_POLL;
            m_cmd.CommandDataLength = 10;

            if (!SendCommand())
            {
                return(false);
            }

            // Store poll response to avoid corruption if the cmd structure is accessed whilst polling
            m_cmd.ResponseData.CopyTo(m_CurrentPollResponse, 0);
            m_CurrentPollResponseLength = m_cmd.ResponseDataLength;

            //parse poll m_CurrentPollResponse
            int noteVal = 0;

            for (i = 1; i < m_CurrentPollResponseLength; i++)
            {
                switch (m_CurrentPollResponse[i])
                {
                // This m_CurrentPollResponse indicates that the unit was reset and this is the first time a poll
                // has been called since the reset.
                case CCommands.SSP_POLL_SLAVE_RESET:
                    Log.WriteLog("Unit reset ");
                    UpdateData();
                    break;

                // A note is currently being read by the validator sensors. The second byte of this response
                // is zero until the note's type has been determined, it then changes to the channel of the
                // scanned note.
                case CCommands.SSP_POLL_READ_NOTE:
                    if (m_CurrentPollResponse[i + 1] > 0)
                    {
                        noteVal = GetChannelValue(m_CurrentPollResponse[i + 1]);
                        Log.WriteLog("Note in escrow, amount: " + CHelpers.FormatToCurrency(noteVal) + " " + GetChannelCurrency(m_CurrentPollResponse[i + 1]) + " ", "CashAcceptor");
                        noteVal = noteVal / 100;
                        if (Global.iTotalAmount < noteVal)
                        {
                            Log.WriteLog("Rs " + noteVal + " Return Fire", "CashAcceptor");
                            ReturnNote();
                        }

                        m_HoldCount = m_HoldNumber;
                    }
                    else
                    {
                        Log.WriteLog("Reading note ", "CashAcceptor");
                    }
                    i++;
                    break;

                // A credit event has been detected, this is when the validator has accepted a note as legal currency.
                case CCommands.SSP_POLL_CREDIT_NOTE:
                    noteVal = GetChannelValue(m_CurrentPollResponse[i + 1]);
                    Log.WriteLog("Credit " + CHelpers.FormatToCurrency(noteVal) + " " + GetChannelCurrency(m_CurrentPollResponse[i + 1]) + " ", "CashAcceptor");
                    Global.iTotalAmount = Global.iTotalAmount - (noteVal / 100);
                    NotesAccepted++;
                    UpdateData();
                    i++;
                    break;

                // A note is being rejected from the validator. This will carry on polling while the note is in transit.
                case CCommands.SSP_POLL_NOTE_REJECTING:
                    break;

                // A note has been rejected from the validator. This response only appears once.
                case CCommands.SSP_POLL_NOTE_REJECTED:
                    Log.WriteLog("Note rejected ", "CashAcceptor");
                    QueryRejection();
                    UpdateData();
                    EnableValidator();
                    break;

                // A note is in transit to the cashbox.
                case CCommands.SSP_POLL_NOTE_STACKING:
                    Log.WriteLog("Stacking note ", "CashAcceptor");
                    break;

                // A note has reached the cashbox.
                case CCommands.SSP_POLL_NOTE_STACKED:
                    Log.WriteLog("Note stacked ", "CashAcceptor");
                    break;

                // A safe jam has been detected. This is where the user has inserted a note and the note
                // is jammed somewhere that the user cannot reach.
                case CCommands.SSP_POLL_SAFE_NOTE_JAM:
                    Log.WriteLog("Safe jam ", "CashAcceptor");
                    break;

                // An unsafe jam has been detected. This is where a user has inserted a note and the note
                // is jammed somewhere that the user can potentially recover the note from.
                case CCommands.SSP_POLL_UNSAFE_NOTE_JAM:
                    Log.WriteLog("Unsafe jam ", "CashAcceptor");
                    break;

                // The validator is disabled, it will not execute any commands or do any actions until enabled.
                case CCommands.SSP_POLL_DISABLED:
                    Log.WriteLog("Unit disabled... ", "CashAcceptor");
                    break;

                // A fraud attempt has been detected. The second byte indicates the channel of the note that a fraud
                // has been attempted on.
                case CCommands.SSP_POLL_FRAUD_ATTEMPT:
                    Log.WriteLog("Fraud attempt, note type: " + GetChannelValue(m_CurrentPollResponse[i + 1]) + " ", "CashAcceptor");
                    i++;
                    break;

                // The stacker (cashbox) is full.
                case CCommands.SSP_POLL_STACKER_FULL:
                    Log.WriteLog("Stacker full ", "CashAcceptor");
                    break;

                // A note was detected somewhere inside the validator on startup and was rejected from the front of the
                // unit.
                case CCommands.SSP_POLL_NOTE_CLEARED_FROM_FRONT:
                    Log.WriteLog(GetChannelValue(m_CurrentPollResponse[i + 1]) + " " + GetChannelCurrency(m_CurrentPollResponse[i + 1]) + " note cleared from front at reset." + " ", "CashAcceptor");
                    i++;
                    break;

                // A note was detected somewhere inside the validator on startup and was cleared into the cashbox.
                case CCommands.SSP_POLL_NOTE_CLEARED_TO_CASHBOX:
                    Log.WriteLog(GetChannelValue(m_CurrentPollResponse[i + 1]) + " " + GetChannelCurrency(m_CurrentPollResponse[i + 1]) + " note cleared to stacker at reset." + " ", "CashAcceptor");
                    i++;
                    break;

                // The cashbox has been removed from the unit. This will continue to poll until the cashbox is replaced.
                case CCommands.SSP_POLL_CASHBOX_REMOVED:
                    Log.WriteLog("Cashbox removed ", "CashAcceptor");
                    break;

                // The cashbox has been replaced, this will only display on a poll once.
                case CCommands.SSP_POLL_CASHBOX_REPLACED:
                    Log.WriteLog("Cashbox replaced ", "CashAcceptor");
                    break;

                // A note has been stored in the payout device to be paid out instead of going into the cashbox.
                case CCommands.SSP_POLL_NOTE_STORED_IN_PAYOUT:
                    Log.WriteLog("Note stored ", "CashAcceptor");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    UpdateData();
                    break;

                // The validator is in the process of paying out a note, this will continue to poll until the note has
                // been fully dispensed and removed from the front of the validator by the user.
                case CCommands.SSP_POLL_DISPENSING:
                    Log.WriteLog("Dispensing note ", "CashAcceptor");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // The note has been dispensed and removed from the bezel by the user.
                case CCommands.SSP_POLL_DISPENSED:
                    for (int j = 0; j < m_CurrentPollResponse[i + 1]; j += 7)
                    {
                        Log.WriteLog("Dispensed " + (CHelpers.ConvertBytesToInt32(m_CurrentPollResponse, j + i + 2) / 100).ToString() +
                                     " " + (char)m_CurrentPollResponse[j + i + 6] + (char)m_CurrentPollResponse[j + i + 7] +
                                     (char)m_CurrentPollResponse[j + i + 8] + " ", "CashAcceptor");
                    }
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    NotesDispensed++;
                    UpdateData();
                    EnableValidator();
                    break;

                // A note has been transferred from the payout storage to the cashbox
                case CCommands.SSP_POLL_NOTE_TRANSFERED_TO_STACKER:
                    Log.WriteLog("Note stacked ", "CashAcceptor");
                    UpdateData();
                    EnableValidator();
                    break;

                // This single poll response indicates that the payout device has finished emptying.
                case CCommands.SSP_POLL_EMPTIED:
                    Log.WriteLog("Device emptied ", "CashAcceptor");
                    UpdateData();
                    EnableValidator();
                    break;

                // This response indicates a note is being dispensed and is resting in the bezel waiting to be removed
                // before the validator can continue
                case CCommands.SSP_POLL_NOTE_HELD_IN_BEZEL:
                    for (int j = 0; j < m_CurrentPollResponse[i + 1]; j += 7)
                    {
                        Log.WriteLog((CHelpers.ConvertBytesToInt32(m_CurrentPollResponse, j + i + 2) / 100).ToString() +
                                     " " + (char)m_CurrentPollResponse[j + i + 6] + (char)m_CurrentPollResponse[j + i + 7] +
                                     (char)m_CurrentPollResponse[j + i + 8] + " held in bezel... ", "CashAcceptor");
                    }
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                case CCommands.SSP_POLL_SMART_EMPTYING:
                    Log.WriteLog((CHelpers.ConvertBytesToInt32(m_CurrentPollResponse, i + 2) / 100).ToString() +
                                 " " + (char)m_CurrentPollResponse[i + 6] + (char)m_CurrentPollResponse[i + 7] +
                                 (char)m_CurrentPollResponse[i + 8] + " emptied so far... ", "CashAcceptor");
                    i += 9;
                    break;

                case CCommands.SSP_POLL_SMART_EMPTIED:
                    Log.WriteLog((CHelpers.ConvertBytesToInt32(m_CurrentPollResponse, i + 2) / 100).ToString() +
                                 " " + (char)m_CurrentPollResponse[i + 6] + (char)m_CurrentPollResponse[i + 7] +
                                 (char)m_CurrentPollResponse[i + 8] + " emptied in total. ", "CashAcceptor");
                    i += 9;
                    EnableValidator();
                    break;

                //Default condition: do nothing
                default:
                    break;
                }
            }

            return(true);
        }