// Turn off the reception mode of notes
        public CashCodeBillValidatorException Disable()
        {
            List <byte> byteResult;

            lock (_Locker)
            {
                // If the com port is not open
                if (!_isConnected)
                {
                    _lastError = _errorList.GetErrorByCode(100020);
                    throw _lastError;
                }

                _isEnableBills = false;

                // remove the ENABLE BILL TYPES command(in the test example, it sends 6 bytes(0 0 0 0 0 0)
                byteResult = SendCommand(BillValidatorCommands.ENABLE_BILL_TYPES, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }).ToList();
            }

            // If you did not receive an ACK signal from the bill acceptor
            if (byteResult[3] != 0x00)
            {
                _lastError = _errorList.GetErrorByCode(100050);
            }

            return(_lastError);
        }
        /// <summary>
        /// Opening a COM port for working with a bill acceptor
        /// handleBillStackingTimeout - how long to wait for making the decisiion to accept the bill or not until rejecting the bill, decision made in BillStacking delegate handlers
        /// </summary>
        /// <returns></returns>
        public CashCodeBillValidatorException Connect(string portName, IBillsDefinition billsDefinition, int handleBillStackingTimeout = 10000)
        {
            try
            {
                if (IsConnected)
                {
                    Dispose(true);
                }

                _handleBillStackingTimeout = handleBillStackingTimeout;
                _billsDefinition           = billsDefinition;

                _errorList = new CashCodeErroList();

                _disposed      = false;
                _isEnableBills = false;
                _comPortName   = "";
                _Locker        = new object();
                _isConnected   = _isPowerUp = _isListening = _returnBill = false;

                // From the specification:
                //      Baud Rate:	9600 bps/19200 bps (no negotiation, hardware selectable)
                //      Start bit:	1
                //      Data bit:	8 (bit 0 = LSB, bit 0 sent first)
                //      Parity:		Parity none
                //      Stop bit:	1

                _comPort = new SerialPort
                {
                    PortName = _comPortName = portName,
                    BaudRate = _baudRate,
                    DataBits = 8,
                    Parity   = Parity.None,
                    StopBits = StopBits.One
                };
                _comPort.DataReceived += _ComPort_DataReceived;

                _receivedBytes = new List <byte>();
                _synchCom      = new EventWaitHandle(false, EventResetMode.AutoReset);

                _listener = new Timer
                {
                    Interval = POLL_TIMEOUT,
                    Enabled  = false
                };
                _listener.Elapsed += _Listener_Elapsed;

                _comPort.Open();
                _isConnected = true;
            }
            catch
            {
                _isConnected = false;
                _lastError   = _lastError = _errorList.GetErrorByCode(100010);
            }

            return(_lastError);
        }
        // Enabling the mode of accepting bills
        public CashCodeBillValidatorException Enable()
        {
            // If the com port is not open
            if (!_isConnected)
            {
                _lastError = _errorList.GetErrorByCode(100020);
                throw _lastError;
            }

            try
            {
                if (!_isListening)
                {
                    throw new InvalidOperationException("Error in the method for enabling the receipt of notes.You must call the StartListening method.");
                }

                lock (_Locker)
                {
                    _isEnableBills = true;

                    //  remove the ENABLE BILL TYPES command(in the test case it sends 6 bytes(255 255 255 0 0 0) Hold function enabled(Escrow)
                    var byteResult = SendCommand(BillValidatorCommands.ENABLE_BILL_TYPES, ENABLE_BILL_TYPES_WITH_ESCROW).ToList();

                    // If you did not receive an ACK signal from the bill acceptor
                    if (byteResult[3] != 0x00)
                    {
                        _lastError = _errorList.GetErrorByCode(100050);
                        throw _lastError;
                    }

                    // Then we again question the bill acceptor
                    byteResult = SendCommand(BillValidatorCommands.POLL).ToList();

                    // Let's check the result
                    if (CheckPollOnError(byteResult.ToArray()))
                    {
                        SendCommand(BillValidatorCommands.NAK);
                        throw _lastError;
                    }

                    // Otherwise, send a confirmation tone
                    SendCommand(BillValidatorCommands.ACK);
                }
            }
            catch
            {
                _lastError = _errorList.GetErrorByCode(100030);
            }

            return(_lastError);
        }
        /// <summary>
        /// Begin listening to the receipt
        /// </summary>
        public void StartListening()
        {
            // If not connected
            if (!_isConnected)
            {
                _lastError = _errorList.GetErrorByCode(100020);
                throw _lastError;
            }

            // If there is no energy, then we turn on
            if (!_isPowerUp)
            {
                PowerUp();
            }

            _isListening = true;
            _listener.Start();
        }
        private bool CheckPollOnError(byte[] byteResult)
        {
            var isError = false;

            // If you did not receive from the bill acceptor a third byte equal to 30N(ILLEGAL COMMAND)
            if (byteResult[3] == 0x30)
            {
                _lastError = _errorList.GetErrorByCode(100040);
                isError    = true;
            }

            // If not received from the bill acceptor the third byte equal to 41N (Drop Cassette Full)
            else if (byteResult[3] == 0x41)
            {
                _lastError = _errorList.GetErrorByCode(100080);
                isError    = true;
            }

            // If not received from the bill acceptor the third byte equal to 42N (Drop Cassette out of position)
            else if (byteResult[3] == 0x42)
            {
                _lastError = _errorList.GetErrorByCode(100070);
                isError    = true;
            }

            // If not received from the bill acceptor the third byte equal to 43H (Validator Jammed)
            else if (byteResult[3] == 0x43)
            {
                _lastError = _errorList.GetErrorByCode(100090);
                isError    = true;
            }

            // If you did not receive a third byte equal to 44N from the bill acceptor (Drop Cassette Jammed)
            else if (byteResult[3] == 0x44)
            {
                _lastError = _errorList.GetErrorByCode(100100);
                isError    = true;
            }

            // If not received from the bill acceptor the third byte equal to 45N (Cheated)
            else if (byteResult[3] == 0x45)
            {
                _lastError = _errorList.GetErrorByCode(100110);
                isError    = true;
            }

            // If you did not get a third byte equal to 46N from the bill acceptor (Pause)
            else if (byteResult[3] == 0x46)
            {
                _lastError = _errorList.GetErrorByCode(100120);
                isError    = true;
            }

            // If you did not get a third byte equal to 47N (Generic Failure codes) from the bill acceptor,
            else if (byteResult[3] == 0x47)
            {
                if (byteResult[4] == 0x50)
                {
                    _lastError = _errorList.GetErrorByCode(100130);
                }                                                                                     // Stack Motor Failure
                else if (byteResult[4] == 0x51)
                {
                    _lastError = _errorList.GetErrorByCode(100140);
                }                                                                                     // Transport Motor Speed Failure
                else if (byteResult[4] == 0x52)
                {
                    _lastError = _errorList.GetErrorByCode(100150);
                }                                                                                     // Transport Motor Failure
                else if (byteResult[4] == 0x53)
                {
                    _lastError = _errorList.GetErrorByCode(100160);
                }                                                                                     // Aligning Motor Failure
                else if (byteResult[4] == 0x54)
                {
                    _lastError = _errorList.GetErrorByCode(100170);
                }                                                                                     // Initial Cassette Status Failure
                else if (byteResult[4] == 0x55)
                {
                    _lastError = _errorList.GetErrorByCode(100180);
                }                                                                                     // Optic Canal Failure
                else if (byteResult[4] == 0x56)
                {
                    _lastError = _errorList.GetErrorByCode(100190);
                }                                                                                     // Magnetic Canal Failure
                else if (byteResult[4] == 0x5F)
                {
                    _lastError = _errorList.GetErrorByCode(100200);
                }                                                                                     // Capacitance Canal Failure
                isError = true;
            }

            return(isError);
        }
        // Enable billing
        public CashCodeBillValidatorException PowerUp()
        {
            // If the com port is not open
            if (!_isConnected)
            {
                _lastError = _errorList.GetErrorByCode(100020);
                throw _lastError;
            }

            // POWER UP
            var byteResult = SendCommand(BillValidatorCommands.POLL).ToList();

            // Let's check the result
            if (CheckPollOnError(byteResult.ToArray()))
            {
                SendCommand(BillValidatorCommands.NAK);
                throw _lastError;
            }

            // Otherwise, send a confirmation tone
            SendCommand(BillValidatorCommands.ACK);

            // RESET
            byteResult = SendCommand(BillValidatorCommands.RESET).ToList();

            // If you did not receive an ACK signal from the bill acceptor
            if (byteResult[3] != 0x00)
            {
                _lastError = _errorList.GetErrorByCode(100050);
                return(_lastError);
            }

            // INITIALIZE
            // Then we again question the bill acceptor
            byteResult = SendCommand(BillValidatorCommands.POLL).ToList();

            if (CheckPollOnError(byteResult.ToArray()))
            {
                SendCommand(BillValidatorCommands.NAK);
                throw _lastError;
            }

            // Otherwise, send a confirmation tone
            SendCommand(BillValidatorCommands.ACK);

            // GET STATUS
            byteResult = SendCommand(BillValidatorCommands.GET_STATUS).ToList();

            // The GET STATUS command returns 6 bytes of the response. If all are equal to 0, then the status is ok and you can work further, otherwise the error
            if (byteResult[3] != 0x00 || byteResult[4] != 0x00 || byteResult[5] != 0x00 ||
                byteResult[6] != 0x00 || byteResult[7] != 0x00 || byteResult[8] != 0x00)
            {
                _lastError = _errorList.GetErrorByCode(100070);
                throw _lastError;
            }

            SendCommand(BillValidatorCommands.ACK);

            // SET_SECURITY (in the test case, it sends 3 bytes(0 0 0)
            byteResult = SendCommand(BillValidatorCommands.SET_SECURITY, new byte[] { 0x00, 0x00, 0x00 }).ToList();

            // If you did not receive an ACK signal from the bill acceptor
            if (byteResult[3] != 0x00)
            {
                _lastError = _errorList.GetErrorByCode(100050);
                return(_lastError);
            }

            // IDENTIFICATION
            byteResult = SendCommand(BillValidatorCommands.IDENTIFICATION).ToList();
            SendCommand(BillValidatorCommands.ACK);


            // POLL
            // Then we again question the bill acceptor.Should receive the INITIALIZE command
            byteResult = SendCommand(BillValidatorCommands.POLL).ToList();

            // Let's check the result
            if (CheckPollOnError(byteResult.ToArray()))
            {
                SendCommand(BillValidatorCommands.NAK);
                throw _lastError;
            }

            // Otherwise, send a confirmation tone
            SendCommand(BillValidatorCommands.ACK);

            // POLL
            // Then we again question the bill acceptor.Should get the UNIT DISABLE command
            byteResult = SendCommand(BillValidatorCommands.POLL).ToList();

            // Let's check the result
            if (CheckPollOnError(byteResult.ToArray()))
            {
                SendCommand(BillValidatorCommands.NAK);
                throw _lastError;
            }

            // Otherwise, send a confirmation tone
            SendCommand(BillValidatorCommands.ACK);

            _isPowerUp = true;

            return(_lastError);
        }