public Task <DispenseResult> DispenseAsync(DispenseMessage amount)
 {
     return(Task.Run(() =>
     {
         return Dispense(amount);
     }));
 }
        /// <summary>
        /// Send DISP message to dispenser.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public DispenseResult Dispense(DispenseMessage amount)
        {
            DispenseResult result = new DispenseResult();
            List <byte>    buffer = new List <byte>();
            List <byte>    MSG    = new List <byte>();

            if (internalSerialPort.IsOpen == false)
            {
                return(result);
            }
            internalSerialPort.ReadExisting();
            byte timeout1 = amount.timeOut == 0 ? (byte)0x20 : (byte)0x1C;
            byte timeout2 = amount.timeOut == 0 ? (byte)0x20 : (byte)(0x30 + amount.timeOut);

            byte[] msg = { EOT, 0x30, STX, DISPENSE, (byte)(0x20 + amount.cassette1Bills), (byte)(0x20 + amount.cassette2Bills), (byte)(0x20 + amount.cassette3Bills), (byte)(0x20 + amount.cassette4Bills), timeout1, timeout2, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, ETX };
            RequestLog(amount.cassette1Bills, amount.cassette2Bills, amount.cassette3Bills, amount.cassette4Bills);
            WriteBytes(new byte[] { EOT, 0x30, STX, DISPENSE, (byte)(0x20 + amount.cassette1Bills), (byte)(0x20 + amount.cassette2Bills), (byte)(0x20 + amount.cassette3Bills), (byte)(0x20 + amount.cassette4Bills), timeout1, timeout2, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, ETX }.ToList());

            Thread.Sleep(50);

            byte[] buf = new byte[1];
            internalSerialPort.Read(buf, 0, 1);
            ByteLog(buf[0]);
            if (buf[0] == NAK)
            {
                return(result);
            }

            Thread.Sleep(500);

            while (internalSerialPort.BytesToRead == 0)
            {
                Thread.Sleep(100);
            }

            while (internalSerialPort.BytesToRead > 0)
            {
                byte[] rawdata = new byte[internalSerialPort.BytesToRead];
                internalSerialPort.Read(rawdata, 0, rawdata.Length);
                buffer.AddRange(rawdata);
                Thread.Sleep(500);
            }
            WriteByte(ACK);
            Queue <int> SOHs = new Queue <int>();

            for (int i = 0; i < buffer.Count; i++)
            {
                if (buffer[i] == SOH)
                {
                    SOHs.Enqueue(i);
                }
            }

            while (SOHs.Count > 0)
            {
                Queue <int> ETXs = new Queue <int>();
                int         SOH  = SOHs.Dequeue();
                for (int i = 0; i < buffer.Count; i++)
                {
                    if (buffer[i] == ETX)
                    {
                        ETXs.Enqueue(i);
                    }
                }
                while (ETXs.Count > 0)
                {
                    try
                    {
                        int         ETX      = ETXs.Dequeue();
                        byte        lastitem = buffer[ETX + 1];
                        List <byte> cropped  = buffer.GetRange(SOH, ETX + 1);
                        if (lastitem == GetBCC(cropped.ToArray()))
                        {
                            MSG = cropped;
                            ETXs.Clear();
                            SOHs.Clear();
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Error("DISPENSE - CANNOT PARSE MESSAGE: " + e);
                        break;
                    }
                    buffer.RemoveRange(0, SOH);
                }
            }

            try
            {
                result.status.mainError         = (ERR_CODE_DISPENSER)MSG[4];
                result.status.isCassette1Exists = MSG[8] == 0x30 ? false : true;
                result.status.isCassette1Exists = MSG[11] == 0x30 ? false : true;
                result.status.isCassette1Exists = MSG[14] == 0x30 ? false : true;
                result.status.isCassette1Exists = MSG[17] == 0x30 ? false : true;
                result.cassette1Dispensed       = MSG[6] - 0x20;
                result.cassette2Dispensed       = MSG[9] - 0x20;
                result.cassette3Dispensed       = MSG[12] - 0x20;
                result.cassette4Dispensed       = MSG[15] - 0x20;
                result.cassette1Rejected        = MSG[7] - 0x20;
                result.cassette2Rejected        = MSG[10] - 0x20;
                result.cassette3Rejected        = MSG[13] - 0x20;
                result.cassette4Rejected        = MSG[16] - 0x20;
                result.status.success           = true;
                if (MSG.Count <= 0)
                {
                    result.status.success = false;
                    Logger.Warn("No Response from Dispenser");
                }
                BytesLog(MSG);
                DispensedLog(result.cassette1Dispensed, result.cassette2Dispensed, result.cassette3Dispensed, result.cassette4Dispensed, result.cassette1Rejected, result.cassette2Rejected, result.cassette3Rejected, result.cassette4Rejected);
            }
            catch (Exception e)
            {
                Logger.Error("DISPENSE - CANNOT PROCESS MESSAGE: " + e);
                result.status.success = false;
            }
            internalSerialPort.Read(buf, 0, 1);
            ByteLog(buf[0]);
            while (internalSerialPort.BytesToRead > 0)
            {
                internalSerialPort.ReadExisting();
            }
            return(result);
        }