예제 #1
0
        // This function gets the CASHBOX PAYOUT OPERATION DATA from the validator and returns it as a string
        public void GetCashboxPayoutOpData(TextBox log = null)
        {
            // first send the command
            m_cmd.CommandData[0]    = CCommands.Hopper.SSP_CMD_CASHBOX_PAYOUT_OP_DATA;
            m_cmd.CommandDataLength = 1;

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

            // now deal with the response data
            if (CheckGenericResponses(log))
            {
                // number of different coins
                int    n             = m_cmd.ResponseData[1];
                string displayString = "Number of Total Coins: " + n.ToString() + "\r\n\r\n";
                int    i             = 0;
                for (i = 2; i < (9 * n); i += 9)
                {
                    displayString += "Moved " + CHelpers.ConvertBytesToInt16(m_cmd.ResponseData, i) +
                                     " x " + CHelpers.FormatToCurrency(CHelpers.ConvertBytesToInt32(m_cmd.ResponseData, i + 2)) +
                                     " " + (char)m_cmd.ResponseData[i + 6] + (char)m_cmd.ResponseData[i + 7] + (char)m_cmd.ResponseData[i + 8]
                                     + " to cashbox\r\n";
                }
                displayString += CHelpers.ConvertBytesToInt32(m_cmd.ResponseData, i) + " coins not recognised\r\n";

                if (log != null)
                {
                    log.AppendText(displayString);
                }
            }
        }
예제 #2
0
파일: CNV11.cs 프로젝트: kalkansa/stserver
 // The get note positions command instructs the validator to return in the second byte the number of
 // notes stored and then in the following bytes, the values/channel (see SetValueReportingType()) of the stored
 // notes. The length of the response will vary based on the number of stored notes.
 public void CheckForStoredNotes(TextBox log = null)
 {
     cmd.CommandData[0]    = CCommands.SSP_CMD_GET_NOTE_POSITIONS;
     cmd.CommandDataLength = 1;
     if (!SendCommand(log))
     {
         return;
     }
     if (CheckGenericResponses(log))
     {
         int counter = 0;
         Array.Clear(m_NotePositionValues, 0, m_NotePositionValues.Length);
         // Work backwards for a more accurate display (LIFO)
         for (int i = (cmd.ResponseData[1] * 4) + 1; i >= 2; i -= 4, counter++)
         {
             m_NotePositionValues[counter] = CHelpers.ConvertBytesToInt32(cmd.ResponseData, i - 3);
         }
     }
 }
예제 #3
0
        // This function is called repeatedly to poll the validator about what events are happening. It
        // can optionally output these events to a textbox.
        public bool DoPoll(TextBox log)
        {
            byte i;

            //send poll
            m_cmd.CommandData[0]    = CCommands.Generic.SSP_CMD_POLL;
            m_cmd.CommandDataLength = 1;

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

            // Check unit hasn't lost key (could be due to power loss or reset)
            if (m_cmd.ResponseData[0] == 0xFA)
            {
                return(false);
            }

            // isolate poll response to allow reuse of the SSP_COMMAND structure
            m_CurrentPollResponseLength = m_cmd.ResponseDataLength;
            m_cmd.ResponseData.CopyTo(m_CurrentPollResponse, 0);

            //parse poll response
            int    coin     = 0;
            string currency = "";

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

                // This response is given when the unit is disabled.
                case CCommands.Hopper.SSP_POLL_DISABLED:
                    log.AppendText("Unit disabled...\r\n");
                    break;

                // The unit is in the process of paying out a coin or series of coins, this will continue to poll
                // until the coins have been fully dispensed
                case CCommands.Hopper.SSP_POLL_DISPENSING:
                    log.AppendText("Dispensing coin(s)...\r\n");
                    // Now the index needs to be moved on to skip over the data provided by this response so it
                    // is not parsed as a normal poll response.
                    // In this response, the data includes the number of countries being dispensed (1 byte), then a 4 byte value
                    // and 3 byte currency code for each country.
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // This is polled when a unit has finished a dispense operation. The following 4 bytes give the
                // value of the coin(s) dispensed.
                case CCommands.Hopper.SSP_POLL_DISPENSED:
                    for (int j = 0; j < m_CurrentPollResponse[i + 1] * 7; j += 7)
                    {
                        coin = CHelpers.ConvertBytesToInt32(m_cmd.ResponseData, i + j + 2);     // get coin data from response
                        // get currency from response
                        currency  = "";
                        currency += (char)m_CurrentPollResponse[i + j + 6];
                        currency += (char)m_CurrentPollResponse[i + j + 7];
                        currency += (char)m_CurrentPollResponse[i + j + 8];
                        log.AppendText(CHelpers.FormatToCurrency(coin) + " " + currency + " coin(s) dispensed\r\n");
                    }

                    UpdateData();
                    EnableValidator();
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // The coins being recycled inside the unit are running low.
                case CCommands.Hopper.SSP_POLL_COINS_LOW:
                    log.AppendText("Coins low\r\n");
                    break;

                // There are no coins left in the unit.
                case CCommands.Hopper.SSP_POLL_EMPTY:
                    log.AppendText("Unit empty\r\n");
                    break;

                // The mechanism inside the unit is jammed.
                case CCommands.Hopper.SSP_POLL_JAMMED:
                    log.AppendText("Jammed\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // A dispense, SMART empty or float operation has been halted.
                case CCommands.Hopper.SSP_POLL_HALTED:
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // The device is 'floating' a specified amount of coins. It will transfer some to the cashbox and
                // leave the specified amount in the device.
                case CCommands.Hopper.SSP_POLL_FLOATING:
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // The float operation has completed.
                case CCommands.Hopper.SSP_POLL_FLOATED:
                    UpdateData();
                    EnableValidator();
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // This poll appears when the SMART Hopper has been searching for a coin but cannot find it within
                // the timeout period.
                case CCommands.Hopper.SSP_POLL_TIME_OUT:
                    log.AppendText("Search for suitable coins failed\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // A payout was interrupted in some way. The amount paid out does not match what was requested. The value
                // of the dispensed and requested amount is contained in the response.
                case CCommands.Hopper.SSP_POLL_INCOMPLETE_PAYOUT:
                    log.AppendText("Incomplete payout detected...\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 11) + 1);
                    break;

                // A float was interrupted in some way. The amount floated does not match what was requested. The value
                // of the dispensed and requested amount is contained in the response.
                case CCommands.Hopper.SSP_POLL_INCOMPLETE_FLOAT:
                    log.AppendText("Incomplete float detected...\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 11) + 1);
                    break;

                // This poll appears when coins have been dropped to the cashbox whilst making a payout. The value of
                // coins and the currency is reported in the response.
                case CCommands.Hopper.SSP_POLL_CASHBOX_PAID:
                    log.AppendText("Cashbox paid\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // A credit event has been detected, this is when the coin mech has accepted a coin as legal currency.
                case CCommands.Hopper.SSP_POLL_COIN_CREDIT:
                    coin      = CHelpers.ConvertBytesToInt16(m_cmd.ResponseData, i + 1);
                    currency  = "";
                    currency += (char)m_CurrentPollResponse[i + 5];
                    currency += (char)m_CurrentPollResponse[i + 6];
                    currency += (char)m_CurrentPollResponse[i + 7];
                    log.AppendText(CHelpers.FormatToCurrency(coin) + " " + currency + " credited\r\n");
                    UpdateData();
                    i += 7;
                    break;

                // The coin mech has become jammed.
                case CCommands.Hopper.SSP_POLL_COIN_MECH_JAMMED:
                    log.AppendText("Coin mech jammed\r\n");
                    break;

                // The return button on the coin mech has been pressed.
                case CCommands.Hopper.SSP_POLL_COIN_MECH_RETURN_PRESSED:
                    log.AppendText("Return button pressed\r\n");
                    break;

                // The unit is in the process of dumping all the coins stored inside it into the cashbox.
                case CCommands.Hopper.SSP_POLL_EMPTYING:
                    log.AppendText("Emptying...\r\n");
                    break;

                // The unit has finished dumping coins to the cashbox.
                case CCommands.Hopper.SSP_POLL_EMPTIED:
                    log.AppendText("Emptied\r\n");
                    UpdateData();
                    EnableValidator();
                    break;

                // A fraud attempt has been detected.
                case CCommands.Hopper.SSP_POLL_FRAUD_ATTEMPT:
                    log.AppendText("Fraud attempted\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // The unit is in the process of dumping all the coins stored inside it into the cashbox.
                // This poll means that the unit is keeping track of what it empties.
                case CCommands.Hopper.SSP_POLL_SMART_EMPTYING:
                    log.AppendText("SMART emptying...\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // The unit has finished SMART emptying. The info on what has been dumped can be obtained
                // by sending the CASHBOX PAYOUT OPERATION DATA command.
                case CCommands.Hopper.SSP_POLL_SMART_EMPTIED:
                    GetCashboxPayoutOpData(log);
                    UpdateData();
                    EnableValidator();
                    log.AppendText("SMART emptied\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // A coin has had its routing changed to either cashbox or recycling.
                case CCommands.Hopper.SSP_POLL_COIN_ROUTED:
                    log.AppendText("Routed coin\r\n");
                    UpdateData();
                    break;

                default:
                    log.AppendText("Unsupported poll response received: " + (int)m_CurrentPollResponse[i] + "\r\n");
                    break;
                }
            }
            return(true);
        }
예제 #4
0
        // This function uses the setup request command to get all the information about the validator.
        public void SetupRequest(TextBox log = null)
        {
            // send setup request
            cmd.CommandData[0]    = CCommands.Generic.SSP_CMD_SETUP_REQUEST;
            cmd.CommandDataLength = 1;

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

            // display setup request
            string displayString = "Validator Type: ";
            int    index         = 1;

            // unit type (table 0-1)
            m_UnitType = (char)cmd.ResponseData[index++];
            switch (m_UnitType)
            {
            case (char)0x00: displayString += "Validator"; break;

            case (char)0x03: displayString += "SMART Hopper"; break;

            case (char)0x06: displayString += "SMART Payout"; break;

            case (char)0x07: displayString += "NV11"; break;

            default: displayString += "Unknown Type"; break;
            }

            displayString += "\r\nFirmware: ";

            // firmware (table 2-5)
            while (index <= 5)
            {
                displayString += (char)cmd.ResponseData[index++];
                if (index == 4)
                {
                    displayString += ".";
                }
            }

            // country code (table 6-8)
            // this is legacy code, in protocol version 6+ each channel has a seperate currency
            index = 9; // to skip country code

            // value multiplier (table 9-11)
            // also legacy code, a real value multiplier appears later in the response
            index = 12; // to skip value multiplier

            displayString += "\r\nNumber of Channels: ";
            int numChannels = cmd.ResponseData[index++];

            m_NumberOfChannels = numChannels;

            displayString += numChannels + "\r\n";
            // channel values (table 13 to 13+n)
            // the channel values located here in the table are legacy, protocol 6+ provides a set of expanded
            // channel values.
            index = 13 + m_NumberOfChannels; // Skip channel values

            // channel security (table 13+n to 13+(n*2))
            // channel security values are also legacy code
            index = 13 + (m_NumberOfChannels * 2); // Skip channel security

            displayString += "Real Value Multiplier: ";

            // real value multiplier (table 13+(n*2) to 15+(n*2))
            // (big endian)
            m_ValueMultiplier  = cmd.ResponseData[index + 2];
            m_ValueMultiplier += cmd.ResponseData[index + 1] << 8;
            m_ValueMultiplier += cmd.ResponseData[index] << 16;
            displayString     += m_ValueMultiplier + "\r\nProtocol Version: ";
            index             += 3;

            // protocol version (table 16+(n*2))
            index = 16 + (m_NumberOfChannels * 2);
            int protocol = cmd.ResponseData[index++];

            displayString += protocol + "\r\n";

            // protocol 6+ only

            // channel currency country code (table 17+(n*2) to 17+(n*5))
            index = 17 + (m_NumberOfChannels * 2);
            int sectionEnd = 17 + (m_NumberOfChannels * 5);
            int count      = 0;

            byte[] channelCurrencyTemp = new byte[3 * m_NumberOfChannels];
            while (index < sectionEnd)
            {
                displayString += "Channel " + ((count / 3) + 1) + ", currency: ";
                channelCurrencyTemp[count] = cmd.ResponseData[index++];
                displayString += (char)channelCurrencyTemp[count++];
                channelCurrencyTemp[count] = cmd.ResponseData[index++];
                displayString += (char)channelCurrencyTemp[count++];
                channelCurrencyTemp[count] = cmd.ResponseData[index++];
                displayString += (char)channelCurrencyTemp[count++];
                displayString += "\r\n";
            }

            // expanded channel values (table 17+(n*5) to 17+(n*9))
            index          = sectionEnd;
            displayString += "Expanded channel values:\r\n";
            sectionEnd     = 17 + (m_NumberOfChannels * 9);
            int n = 0;

            count = 0;
            int[] channelValuesTemp = new int[m_NumberOfChannels];
            while (index < sectionEnd)
            {
                n = CHelpers.ConvertBytesToInt32(cmd.ResponseData, index);
                channelValuesTemp[count] = n;
                index         += 4;
                displayString += "Channel " + ++count + ", value = " + n + "\r\n";
            }

            // Create list entry for each channel
            m_UnitDataList.Clear(); // clear old table
            for (byte i = 0; i < m_NumberOfChannels; i++)
            {
                ChannelData d = new ChannelData();
                d.Channel = i;
                d.Channel++; // Offset from array index by 1
                d.Value       = channelValuesTemp[i] * Multiplier;
                d.Currency[0] = (char)channelCurrencyTemp[0 + (i * 3)];
                d.Currency[1] = (char)channelCurrencyTemp[1 + (i * 3)];
                d.Currency[2] = (char)channelCurrencyTemp[2 + (i * 3)];
                d.Level       = 0;     // Can't store notes
                d.Recycling   = false; // Can't recycle notes

                m_UnitDataList.Add(d);
            }

            // Sort the list of data by the value.
            m_UnitDataList.Sort(delegate(ChannelData d1, ChannelData d2) { return(d1.Value.CompareTo(d2.Value)); });

            if (log != null)
            {
                log.AppendText(displayString);
            }
        }
예제 #5
0
        // 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(TextBox log)
        {
            byte i;

            //send poll
            cmd.CommandData[0]    = CCommands.Generic.SSP_CMD_POLL;
            cmd.CommandDataLength = 1;

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

            // Check unit hasn't lost key (could be due to power loss or reset)
            if (cmd.ResponseData[0] == 0xFA)
            {
                return(false);
            }

            // Store poll response to avoid corruption if the cmd structure is accessed whilst polling
            cmd.ResponseData.CopyTo(m_CurrentPollResponse, 0);
            m_CurrentPollResponseLength = 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.NV11.SSP_POLL_RESET:
                    log.AppendText("Unit reset\r\n");
                    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.NV11.SSP_POLL_NOTE_READ:
                    if (m_CurrentPollResponse[i + 1] > 0)
                    {
                        noteVal = GetChannelValue(m_CurrentPollResponse[i + 1]);
                        log.AppendText("Note in escrow, amount: " + CHelpers.FormatToCurrency(noteVal) + "\r\n");
                    }
                    else
                    {
                        log.AppendText("Reading note\r\n");
                    }
                    i++;
                    break;

                // A credit event has been detected, this is when the validator has accepted a note as legal currency.
                case CCommands.NV11.SSP_POLL_CREDIT:
                    noteVal = GetChannelValue(m_CurrentPollResponse[i + 1]);
                    log.AppendText("Credit " + CHelpers.FormatToCurrency(noteVal) + "\r\n");
                    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.NV11.SSP_POLL_REJECTING:
                    break;

                // A note has been rejected from the validator. This response only appears once.
                case CCommands.NV11.SSP_POLL_REJECTED:
                    log.AppendText("Note rejected\r\n");
                    QueryRejection(log);
                    UpdateData();
                    break;

                // A note is in transit to the cashbox.
                case CCommands.NV11.SSP_POLL_STACKING:
                    log.AppendText("Stacking note\r\n");
                    break;

                // A note has reached the cashbox.
                case CCommands.NV11.SSP_POLL_STACKED:
                    log.AppendText("Note stacked\r\n");
                    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.NV11.SSP_POLL_SAFE_JAM:
                    log.AppendText("Safe jam\r\n");
                    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.NV11.SSP_POLL_UNSAFE_JAM:
                    log.AppendText("Unsafe jam\r\n");
                    break;

                // The validator is disabled, it will not execute any commands or do any actions until enabled.
                case CCommands.NV11.SSP_POLL_DISABLED:
                    log.AppendText("Unit disabled...\r\n");
                    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.NV11.SSP_POLL_FRAUD_ATTEMPT:
                    log.AppendText("Fraud attempt, note type: " + GetChannelValue(m_CurrentPollResponse[i + 1]) + "\r\n");
                    i++;
                    break;

                // The stacker (cashbox) is full.
                case CCommands.NV11.SSP_POLL_STACKER_FULL:
                    log.AppendText("Stacker full\r\n");
                    break;

                // A note was detected somewhere inside the validator on startup and was rejected from the front of the
                // unit.
                case CCommands.NV11.SSP_POLL_NOTE_CLEARED_FROM_FRONT:
                    log.AppendText(GetChannelValue(m_CurrentPollResponse[i + 1]) + " note cleared from front at reset." + "\r\n");
                    i++;
                    break;

                // A note was detected somewhere inside the validator on startup and was cleared into the cashbox.
                case CCommands.NV11.SSP_POLL_NOTE_CLEARED_TO_CASHBOX:
                    log.AppendText(GetChannelValue(m_CurrentPollResponse[i + 1]) + " note cleared to stacker at reset." + "\r\n");
                    i++;
                    break;

                // The cashbox has been removed from the unit. This will continue to poll until the cashbox is replaced.
                case CCommands.NV11.SSP_POLL_CASHBOX_REMOVED:
                    log.AppendText("Cashbox removed\r\n");
                    break;

                // The cashbox has been replaced, this will only display on a poll once.
                case CCommands.NV11.SSP_POLL_CASHBOX_REPLACED:
                    log.AppendText("Cashbox replaced\r\n");
                    break;

                // A note has been stored in the payout device to be paid out instead of going into the cashbox.
                case CCommands.NV11.SSP_POLL_NOTE_STORED:
                    log.AppendText("Note stored\r\n");
                    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.NV11.SSP_POLL_NOTE_DISPENSING:
                    log.AppendText("Dispensing note\r\n");
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                // The note has been dispensed and removed from the bezel by the user.
                case CCommands.NV11.SSP_POLL_NOTE_DISPENSED:
                    for (int j = 0; j < m_CurrentPollResponse[i + 1]; j += 7)
                    {
                        log.AppendText("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] + "\r\n");
                    }
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    NotesDispensed++;
                    UpdateData();
                    EnableValidator(log);
                    break;

                // A note has been transferred from the payout storage to the cashbox
                case CCommands.NV11.SSP_POLL_NOTE_TRANSFERRED_TO_STACKER:
                    log.AppendText("Note stacked\r\n");
                    UpdateData();
                    EnableValidator(log);
                    break;

                // This single poll response indicates that the payout device has finished emptying.
                case CCommands.NV11.SSP_POLL_EMPTIED:
                    log.AppendText("Device emptied\r\n");
                    UpdateData();
                    EnableValidator(log);
                    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.NV11.SSP_POLL_NOTE_HELD_IN_BEZEL:
                    for (int j = 0; j < m_CurrentPollResponse[i + 1]; j += 7)
                    {
                        log.AppendText((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...\r\n");
                    }
                    i += (byte)((m_CurrentPollResponse[i + 1] * 7) + 1);
                    break;

                default:
                    break;
                }
            }
            return(true);
        }