// 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); } } }
// This is a one off function that is called the first time the MainLoop() // function runs, it just sets up a few of the UI elements that only need // updating once. private void SetupFormLayout() { // need validator class instance if (Hopper == null) { MessageBox.Show("Validator class is null.", "ERROR"); return; } // Positioning int x = 555, y = 30; Label lbl = new Label(); lbl.Location = new Point(x, y); lbl.Size = new Size(70, 35); lbl.Name = "lbl"; lbl.Text = "Recycle\nChannels:"; Controls.Add(lbl); y += 20; for (int i = 1; i <= Hopper.NumberOfChannels; i++) { CheckBox c = new CheckBox(); c.Location = new Point(x, y + (i * 20)); c.Name = i.ToString(); c.Text = CHelpers.FormatToCurrency(Hopper.GetChannelValue(i)) + " " + new String(Hopper.GetChannelCurrency(i)); c.Checked = Hopper.IsChannelRecycling(i); c.CheckedChanged += new EventHandler(recycleBox_CheckedChange); Controls.Add(c); } }
// This is a one off function that is called the first time the MainLoop() // function runs, it just sets up a few of the UI elements that only need // updating once. private void SetupFormLayout() { // need validator class instance if (Payout == null) { MessageBox.Show("Validator class is null.", "ERROR"); return; } // Positioning int x = 600, y = 40; // Add label Label lbl = new Label(); lbl.Location = new Point(x, y - 10); lbl.Size = new Size(80, 30); lbl.Text = "Recycle\nChannels:"; Controls.Add(lbl); for (int i = 1; i <= Payout.NumberOfChannels; i++) { CheckBox c = new CheckBox(); c.Location = new Point(x, y + (i * 20)); c.Name = i.ToString(); ChannelData d = new ChannelData(); Payout.GetDataByChannel(i, ref d); c.Text = CHelpers.FormatToCurrency(d.Value) + " " + new String(d.Currency); c.Checked = d.Recycling; c.CheckedChanged += new EventHandler(recycleBox_CheckedChange); Controls.Add(c); } }
// This function calls the PAYOUT AMOUNT command to payout a specified value. This can be sent // with the option byte 0x19 to test whether the payout is possible or 0x58 to actually do the payout. public void PayoutAmount(int amount, char[] currency, bool test = false, TextBox log = null) { cmd.CommandData[0] = CCommands.SMARTPayout.SSP_CMD_PAYOUT_AMOUNT; byte[] b = CHelpers.ConvertInt32ToBytes(amount); cmd.CommandData[1] = b[0]; cmd.CommandData[2] = b[1]; cmd.CommandData[3] = b[2]; cmd.CommandData[4] = b[3]; cmd.CommandData[5] = (byte)currency[0]; cmd.CommandData[6] = (byte)currency[1]; cmd.CommandData[7] = (byte)currency[2]; if (!test) { cmd.CommandData[8] = 0x58; // real payout } else { cmd.CommandData[8] = 0x19; // test payout } cmd.CommandDataLength = 9; if (!SendCommand(log) || !CheckGenericResponses(log)) { return; } if (log != null) { log.AppendText("Paying out " + CHelpers.FormatToCurrency(amount) + " " + new string(currency) + "\r\n"); } }
// This is a one off function that is called the first time the MainLoop() // function runs, it just sets up a few of the UI elements that only need // updating once. private void SetupFormLayout() { // Basic Validator UI setup // Get channel levels in hopper tbCoinLevels.Text = Hopper.GetChannelLevelInfo(); // setup list of recyclable channel tick boxes based on OS type System.OperatingSystem osInfo = System.Environment.OSVersion; int x = 560, y = 47; Label l = new Label(); l.Location = new Point(x, y); l.Size = new Size(65, 38); l.Name = "lblRecycleCheckBoxes"; l.Text = "Recycle\nChannels:"; Controls.Add(l); for (int i = 1; i <= Hopper.NumberOfChannels; i++) { CheckBox c = new CheckBox(); c.Location = new Point(x, y + 15 + (i * 20)); c.Name = i.ToString(); c.Text = CHelpers.FormatToCurrency(Hopper.GetChannelValue(i)) + " " + new String(Hopper.GetChannelCurrency(i)); c.Checked = Hopper.IsChannelRecycling(i); c.CheckedChanged += new EventHandler(recycleBox_CheckedChange); Controls.Add(c); } }
// This uses the SET COIN AMOUNT command to increase a channel level by passing over the channel and the amount to increment by public void SetCoinLevelsByChannel(int channel, short amount, TextBox log = null) { m_cmd.CommandData[0] = CCommands.Hopper.SSP_CMD_SET_COIN_AMOUNT; // Level to set byte[] b = CHelpers.ConvertInt16ToBytes(amount); m_cmd.CommandData[1] = b[0]; m_cmd.CommandData[2] = b[1]; // Coin(channel) to set b = CHelpers.ConvertInt32ToBytes(GetChannelValue(channel)); m_cmd.CommandData[3] = b[0]; m_cmd.CommandData[4] = b[1]; m_cmd.CommandData[5] = b[2]; m_cmd.CommandData[6] = b[3]; // Add country code, locate from dataset foreach (ChannelData d in m_UnitDataList) { if (d.Channel == channel) { m_cmd.CommandData[7] = (byte)d.Currency[0]; m_cmd.CommandData[8] = (byte)d.Currency[1]; m_cmd.CommandData[9] = (byte)d.Currency[2]; break; } } m_cmd.CommandDataLength = 10; if (!SendCommand(log)) { return; } if (CheckGenericResponses(log)) { // Update the level foreach (ChannelData d in m_UnitDataList) { if (d.Channel == channel) { d.Level += amount; break; } } if (log != null) { log.AppendText("Changed coin value " + CHelpers.FormatToCurrency(GetChannelValue(channel)).ToString() + "'s level to " + amount.ToString() + "\r\n"); } } }
// 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. // 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, TextBox log = null) { cmd.CommandData[0] = CCommands.SMARTPayout.SSP_CMD_SET_ROUTING; // if this note is being changed to stack (cashbox) if (stack) { cmd.CommandData[1] = 0x01; } // note being stored (payout) else { cmd.CommandData[1] = 0x00; } // get the note as a byte array byte[] b = BitConverter.GetBytes(note); cmd.CommandData[2] = b[0]; cmd.CommandData[3] = b[1]; cmd.CommandData[4] = b[2]; cmd.CommandData[5] = b[3]; // send country code (protocol 6+) cmd.CommandData[6] = (byte)currency[0]; cmd.CommandData[7] = (byte)currency[1]; cmd.CommandData[8] = (byte)currency[2]; cmd.CommandDataLength = 9; if (!SendCommand(log) || !CheckGenericResponses(log)) { return; } if (log != null) { string s = new string(currency); if (stack) { s += " to cashbox)\r\n"; } else { s += " to storage)\r\n"; } log.AppendText("Note routing successful (" + CHelpers.FormatToCurrency(note) + " " + s); } }
// This function uses the GET ROUTING command to see if a specified coin is recycling. The // caller passes a bool across which is set by the function. public void IsCoinRecycling(int coinValue, char[] currency, ref bool response, TextBox log = null) { // First determine if the coin is currently being recycled m_cmd.CommandData[0] = CCommands.Hopper.SSP_CMD_GET_ROUTING; byte[] b = CHelpers.ConvertInt32ToBytes(coinValue); m_cmd.CommandData[1] = b[0]; m_cmd.CommandData[2] = b[1]; m_cmd.CommandData[3] = b[2]; m_cmd.CommandData[4] = b[3]; // Add currency m_cmd.CommandData[5] = (byte)currency[0]; m_cmd.CommandData[6] = (byte)currency[1]; m_cmd.CommandData[7] = (byte)currency[2]; m_cmd.CommandDataLength = 8; if (!SendCommand(log)) { return; } if (CheckGenericResponses(log)) { // True if it is currently being recycled if (m_cmd.ResponseData[1] == 0x00) { response = true; if (log != null) { log.AppendText(CHelpers.FormatToCurrency(coinValue) + " is recycling\r\n"); } } // False if not else if (m_cmd.ResponseData[1] == 0x01) { response = false; if (log != null) { log.AppendText(CHelpers.FormatToCurrency(coinValue) + " is not recycling\r\n"); } } } }
// This is a one off function that is called the first time the MainLoop() // function runs, it just sets up a few of the UI elements that only need // updating once. private void SetupFormLayout() { // Note float UI setup // Find number and value of channels in NV11 and update combo box cbRecycleChannelNV11.Items.Add("No recycling"); foreach (ChannelData d in NV11.UnitDataList) { cbRecycleChannelNV11.Items.Add(d.Value / 100 + " " + new String(d.Currency)); } cbRecycleChannelNV11.SelectedIndex = 0; // Get channel levels in hopper tbCoinLevels.Text = Hopper.GetChannelLevelInfo(); // setup list of recyclable channel tick boxes int x = 0, y = 0; x = 465; y = 30; Label lbl = new Label(); lbl.Location = new Point(x, y); lbl.Size = new Size(70, 35); lbl.Name = "lbl"; lbl.Text = "Recycle\nChannels:"; Controls.Add(lbl); y += 20; for (int i = 1; i <= Hopper.NumberOfChannels; i++) { CheckBox c = new CheckBox(); c.Location = new Point(x, y + (i * 20)); c.Name = i.ToString(); c.Text = CHelpers.FormatToCurrency(Hopper.GetChannelValue(i)) + " " + new String(Hopper.GetChannelCurrency(i)); c.Checked = Hopper.IsChannelRecycling(i); c.CheckedChanged += new EventHandler(recycleBox_CheckedChange); Controls.Add(c); } }
// This uses the SET COIN AMOUNT command to increase a channel level by passing over the coin value and the amount to increment by public void SetCoinLevelsByCoin(int coin, char[] currency, short amount, TextBox log = null) { m_cmd.CommandData[0] = CCommands.Hopper.SSP_CMD_SET_COIN_AMOUNT; byte[] b = CHelpers.ConvertInt16ToBytes(amount); m_cmd.CommandData[1] = b[0]; m_cmd.CommandData[2] = b[1]; b = CHelpers.ConvertInt32ToBytes(coin); m_cmd.CommandData[3] = b[0]; m_cmd.CommandData[4] = b[1]; m_cmd.CommandData[5] = b[2]; m_cmd.CommandData[6] = b[3]; m_cmd.CommandData[7] = (byte)currency[0]; m_cmd.CommandData[8] = (byte)currency[1]; m_cmd.CommandData[9] = (byte)currency[2]; m_cmd.CommandDataLength = 10; if (!SendCommand(log)) { return; } if (CheckGenericResponses(log)) { // Update the level foreach (ChannelData d in m_UnitDataList) { if (d.Value == coin) { d.Level += amount; break; } } if (log != null) { log.AppendText("Increased coin value " + CHelpers.FormatToCurrency(coin).ToString() + "'s level by " + amount.ToString() + "\r\n"); } } }
// 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); }
// 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); } // if 0xFA received the key has been lost, possibly by power down so return false if (cmd.ResponseData[0] == 0xFA) { return(false); } // Store poll response cmd.ResponseData.CopyTo(m_CurrentPollResponse, 0); m_CurrentPollResponseLength = cmd.ResponseDataLength; //parse poll response int noteVal = 0; 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.Validator.SSP_POLL_RESET: log.AppendText("Validator reset\r\n"); 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.Validator.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.Validator.SSP_POLL_CREDIT: noteVal = GetChannelValue(m_CurrentPollResponse[i + 1]); log.AppendText("Credit " + CHelpers.FormatToCurrency(noteVal) + "\r\n"); m_NumStackedNotes++; i++; break; // A note is being rejected from the validator. This will carry on polling while the note is in transit. case CCommands.Validator.SSP_POLL_REJECTING: log.AppendText("Rejecting note...\r\n"); break; // A note has been rejected from the validator, the note will be resting in the bezel. This response only // appears once. case CCommands.Validator.SSP_POLL_REJECTED: log.AppendText("Note rejected\r\n"); QueryRejection(log); break; // A note is in transit to the cashbox. case CCommands.Validator.SSP_POLL_STACKING: log.AppendText("Stacking note...\r\n"); break; // A note has reached the cashbox. case CCommands.Validator.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.Validator.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.Validator.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.Validator.SSP_POLL_DISABLED: 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.Validator.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.Validator.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.Validator.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.Validator.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.Validator.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.Validator.SSP_POLL_CASHBOX_REPLACED: log.AppendText("Cashbox replaced\r\n"); break; default: break; } } return(true); }
// 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); } if (cmd.ResponseData[0] == 0xFA) { return(false); } // store response locally so data can't get corrupted by other use of the cmd variable byte[] response = new byte[255]; cmd.ResponseData.CopyTo(response, 0); byte responseLength = cmd.ResponseDataLength; //parse poll response ChannelData data = new ChannelData(); for (i = 1; i < responseLength; ++i) { switch (response[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.SMARTPayout.SSP_POLL_RESET: log.AppendText("Unit reset\r\n"); UpdateData(); break; // This response indicates the unit is disabled. case CCommands.SMARTPayout.SSP_POLL_DISABLED: log.AppendText("Unit disabled...\r\n"); 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.SMARTPayout.SSP_POLL_NOTE_READ: if (cmd.ResponseData[i + 1] > 0) { GetDataByChannel(response[i + 1], ref data); log.AppendText("Note in escrow, amount: " + CHelpers.FormatToCurrency(data.Value) + "\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.SMARTPayout.SSP_POLL_CREDIT: GetDataByChannel(response[i + 1], ref data); log.AppendText("Credit " + CHelpers.FormatToCurrency(data.Value) + "\r\n"); UpdateData(); i++; break; // A note is being rejected from the validator. This will carry on polling while the note is in transit. case CCommands.SMARTPayout.SSP_POLL_REJECTING: log.AppendText("Rejecting note\r\n"); break; // A note has been rejected from the validator, the note will be resting in the bezel. This response only // appears once. case CCommands.SMARTPayout.SSP_POLL_REJECTED: log.AppendText("Note rejected\r\n"); QueryRejection(log); break; // A note is in transit to the cashbox. case CCommands.SMARTPayout.SSP_POLL_STACKING: log.AppendText("Stacking note\r\n"); break; // The payout device is 'floating' a specified amount of notes. It will transfer some to the cashbox and // leave the specified amount in the payout device. case CCommands.SMARTPayout.SSP_POLL_FLOATING: log.AppendText("Floating notes\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 floated (1 byte), then a 4 byte value // and 3 byte currency code for each country. i += (byte)((response[i + 1] * 7) + 1); break; // A note has reached the cashbox. case CCommands.SMARTPayout.SSP_POLL_STACKED: log.AppendText("Note stacked\r\n"); break; // The float operation has been completed. case CCommands.SMARTPayout.SSP_POLL_FLOATED: log.AppendText("Completed floating\r\n"); UpdateData(); EnableValidator(); i += (byte)((response[i + 1] * 7) + 1); break; // A note has been stored in the payout device to be paid out instead of going into the cashbox. case CCommands.SMARTPayout.SSP_POLL_NOTE_STORED: log.AppendText("Note stored\r\n"); UpdateData(); 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.SMARTPayout.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.SMARTPayout.SSP_POLL_UNSAFE_JAM: log.AppendText("Unsafe jam\r\n"); break; // An error has been detected by the payout unit. case CCommands.SMARTPayout.SSP_POLL_PAYOUT_ERROR: // Note: Will be reported only when Protocol version >= 7 log.AppendText("Detected error with payout device\r\n"); i += (byte)((response[i + 1] * 7) + 2); break; // A fraud attempt has been detected. case CCommands.SMARTPayout.SSP_POLL_FRAUD_ATTEMPT: log.AppendText("Fraud attempt\r\n"); i += (byte)((response[i + 1] * 7) + 1); break; // The stacker (cashbox) is full. case CCommands.SMARTPayout.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.SMARTPayout.SSP_POLL_NOTE_CLEARED_FROM_FRONT: log.AppendText("Note cleared from front of validator\r\n"); i++; break; // A note was detected somewhere inside the validator on startup and was cleared into the cashbox. case CCommands.SMARTPayout.SSP_POLL_NOTE_CLEARED_TO_CASHBOX: log.AppendText("Note cleared to cashbox\r\n"); i++; break; // A note has been detected in the validator on startup and moved to the payout device case CCommands.SMARTPayout.SSP_POLL_NOTE_PAID_INTO_STORE_ON_POWERUP: log.AppendText("Note paid into payout device on startup\r\n"); i += 7; break; // A note has been detected in the validator on startup and moved to the cashbox case CCommands.SMARTPayout.SSP_POLL_NOTE_PAID_INTO_STACKER_ON_POWERUP: log.AppendText("Note paid into cashbox on startup\r\n"); i += 7; break; // The cashbox has been removed from the unit. This will continue to poll until the cashbox is replaced. case CCommands.SMARTPayout.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.SMARTPayout.SSP_POLL_CASHBOX_REPLACED: log.AppendText("Cashbox replaced\r\n"); 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.SMARTPayout.SSP_POLL_NOTE_DISPENSING: log.AppendText("Dispensing note(s)\r\n"); i += (byte)((response[i + 1] * 7) + 1); break; // The note has been dispensed and removed from the bezel by the user. case CCommands.SMARTPayout.SSP_POLL_NOTE_DISPENSED: log.AppendText("Dispensed note(s)\r\n"); UpdateData(); EnableValidator(); i += (byte)((response[i + 1] * 7) + 1); break; // The payout device is in the process of emptying all its stored notes to the cashbox. This // will continue to poll until the device is empty. case CCommands.SMARTPayout.SSP_POLL_EMPTYING: log.AppendText("Emptying\r\n"); break; // This single poll response indicates that the payout device has finished emptying. case CCommands.SMARTPayout.SSP_POLL_EMPTIED: log.AppendText("Emptied\r\n"); UpdateData(); EnableValidator(); break; // The payout device is in the process of SMART emptying all its stored notes to the cashbox, keeping // a count of the notes emptied. This will continue to poll until the device is empty. case CCommands.SMARTPayout.SSP_POLL_SMART_EMPTYING: log.AppendText("SMART Emptying...\r\n"); i += (byte)((response[i + 1] * 7) + 1); break; // The payout device has finished SMART emptying, the information of what was emptied can now be displayed // using the CASHBOX PAYOUT OPERATION DATA command. case CCommands.SMARTPayout.SSP_POLL_SMART_EMPTIED: log.AppendText("SMART Emptied, getting info...\r\n"); UpdateData(); GetCashboxPayoutOpData(log); EnableValidator(); i += (byte)((response[i + 1] * 7) + 1); break; // The payout device has encountered a jam. This will not clear until the jam has been removed and the unit // reset. case CCommands.SMARTPayout.SSP_POLL_JAMMED: log.AppendText("Unit jammed...\r\n"); i += (byte)((response[i + 1] * 7) + 1); break; // This is reported when the payout has been halted by a host command. This will report the value of // currency dispensed upto the point it was halted. case CCommands.SMARTPayout.SSP_POLL_HALTED: log.AppendText("Halted...\r\n"); i += (byte)((response[i + 1] * 7) + 1); break; // This is reported when the payout was powered down during a payout operation. It reports the original amount // requested and the amount paid out up to this point for each currency. case CCommands.SMARTPayout.SSP_POLL_INCOMPLETE_PAYOUT: log.AppendText("Incomplete payout\r\n"); i += (byte)((response[i + 1] * 11) + 1); break; // This is reported when the payout was powered down during a float operation. It reports the original amount // requested and the amount paid out up to this point for each currency. case CCommands.SMARTPayout.SSP_POLL_INCOMPLETE_FLOAT: log.AppendText("Incomplete float\r\n"); i += (byte)((response[i + 1] * 11) + 1); break; // A note has been transferred from the payout unit to the stacker. case CCommands.SMARTPayout.SSP_POLL_NOTE_TRANSFERRED_TO_STACKER: log.AppendText("Note transferred to stacker\r\n"); i += 7; break; // A note is resting in the bezel waiting to be removed by the user. case CCommands.SMARTPayout.SSP_POLL_NOTE_HELD_IN_BEZEL: log.AppendText("Note in bezel...\r\n"); i += 7; break; // The payout has gone out of service, the host can attempt to re-enable the payout by sending the enable payout // command. case CCommands.SMARTPayout.SSP_POLL_PAYOUT_OUT_OF_SERVICE: log.AppendText("Payout out of service...\r\n"); break; // The unit has timed out while searching for a note to payout. It reports the value dispensed before the timeout // event. case CCommands.SMARTPayout.SSP_POLL_TIMEOUT: log.AppendText("Timed out searching for a note\r\n"); i += (byte)((response[i + 1] * 7) + 1); break; default: log.AppendText("Unsupported poll response received: " + (int)cmd.ResponseData[i] + "\r\n"); break; } } return(true); }
// 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.SSP_CMD_POLL; cmd.CommandDataLength = 1; if (!SendCommand(log)) { return(false); } //parse poll response int noteVal = 0; for (i = 1; i < cmd.ResponseDataLength; i++) { switch (cmd.ResponseData[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.SSP_POLL_RESET: log.AppendText("Unit reset\r\n"); 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_NOTE_READ: if (cmd.ResponseData[i + 1] > 0) { noteVal = GetChannelValue(cmd.ResponseData[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.SSP_POLL_CREDIT: noteVal = GetChannelValue(cmd.ResponseData[i + 1]); log.AppendText("Credit " + CHelpers.FormatToCurrency(noteVal) + "\r\n"); m_NumStackedNotes++; 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_REJECTING: log.AppendText("Rejecting note...\r\n"); break; // A note has been rejected from the validator, the note will be resting in the bezel. This response only // appears once. case CCommands.SSP_POLL_REJECTED: log.AppendText("Note rejected\r\n"); QueryRejection(log); break; // A note is in transit to the cashbox. case CCommands.SSP_POLL_STACKING: log.AppendText("Stacking note...\r\n"); break; // A note has reached the cashbox. case CCommands.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.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.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.SSP_POLL_DISABLED: 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.AppendText("Fraud attempt, note type: " + GetChannelValue(cmd.ResponseData[i + 1]) + "\r\n"); i++; break; // The stacker (cashbox) is full. case CCommands.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.SSP_POLL_NOTE_CLEARED_FROM_FRONT: log.AppendText(GetChannelValue(cmd.ResponseData[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.SSP_POLL_NOTE_CLEARED_TO_CASHBOX: log.AppendText(GetChannelValue(cmd.ResponseData[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.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.SSP_POLL_CASHBOX_REPLACED: log.AppendText("Cashbox replaced\r\n"); break; // A bar code ticket has been detected and validated. The ticket is in escrow, continuing to poll will accept // the ticket, sending a reject command will reject the ticket. case CCommands.SSP_POLL_BAR_CODE_VALIDATED: log.AppendText("Bar code ticket validated\r\n"); break; // A bar code ticket has been accepted (equivalent to note credit). case CCommands.SSP_POLL_BAR_CODE_ACK: log.AppendText("Bar code ticket accepted\r\n"); break; // The validator has detected its note path is open. The unit is disabled while the note path is open. // Only available in protocol versions 6 and above. case CCommands.SSP_POLL_NOTE_PATH_OPEN: log.AppendText("Note path open\r\n"); break; // All channels on the validator have been inhibited so the validator is disabled. Only available on protocol // versions 7 and above. case CCommands.SSP_POLL_CHANNEL_DISABLE: log.AppendText("All channels inhibited, unit disabled\r\n"); break; default: log.AppendText("Unrecognised poll response detected " + (int)cmd.ResponseData[i] + "\r\n"); break; } } return(true); }
// 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); }
// This is a one off function that is called the first time the MainLoop() // function runs, it just sets up a few of the UI elements that only need // updating once. private void SetupFormLayout() { // Get channel levels in hopper tbCoinLevels.Text = Hopper.GetChannelLevelInfo(); // setup list of recyclable channel tick boxes based on OS type System.OperatingSystem osInfo = System.Environment.OSVersion; int x1 = 0, y1 = 0, x2 = 0, y2 = 0; // XP, 2000, Server 2003 if (osInfo.Platform == PlatformID.Win32NT && osInfo.Version.Major == 5) { x1 = this.Location.X + 455; y1 = this.Location.Y + 10; x2 = this.Location.X + 780; y2 = this.Location.Y + 10; } // Vista, 7 else if (osInfo.Platform == PlatformID.Win32NT && osInfo.Version.Major == 6) { x1 = this.Location.X + 458; y1 = this.Location.Y + 12; x2 = this.Location.X + 780; y2 = this.Location.Y + 12; } GroupBox g1 = new GroupBox(); g1.Size = new Size(100, 380); g1.Location = new Point(x1, y1); g1.Text = "Hopper Recycling"; GroupBox g2 = new GroupBox(); g2.Size = new Size(100, 380); g2.Location = new Point(x2, y2); g2.Text = "Payout Recycling"; // Hopper checkboxes for (int i = 1; i <= Hopper.NumberOfChannels; i++) { CheckBox c = new CheckBox(); c.Location = new Point(5, 20 + (i * 20)); c.Name = i.ToString(); c.Text = CHelpers.FormatToCurrency(Hopper.GetChannelValue(i)) + " " + new String(Hopper.GetChannelCurrency(i)); c.Checked = Hopper.IsChannelRecycling(i); c.CheckedChanged += new EventHandler(recycleBoxHopper_CheckedChange); g1.Controls.Add(c); } // Payout checkboxes for (int i = 1; i <= Payout.NumberOfChannels; i++) { CheckBox c = new CheckBox(); c.Location = new Point(5, 20 + (i * 20)); c.Name = i.ToString(); ChannelData d = new ChannelData(); Payout.GetDataByChannel(i, ref d); c.Text = CHelpers.FormatToCurrency(d.Value) + " " + new String(d.Currency); c.Checked = d.Recycling; c.CheckedChanged += new EventHandler(recycleBoxPayout_CheckedChange); g2.Controls.Add(c); } Controls.Add(g1); Controls.Add(g2); }