Пример #1
0
        public void TriggerReadEventLogs(ISerial serial, DateTime start, DateTime end, int timeout)
        {
            List <byte> list = new List <byte>(17);

            list.Add(37);
            list.Add(254);
            list.Add(19);
            list.Add(10);
            list.Add(GetChecksum(list));
            list.Add(1);
            list.Add(1);
            if (start.CompareTo(new DateTime(1970, 1, 1, 0, 0, 0)) < 0)
            {
                start = new DateTime(1970, 1, 1, 0, 0, 0);
            }
            byte[] timeSinceEventEpoch = GetTimeSinceEventEpoch(start);
            list.AddRange(timeSinceEventEpoch.Take(4));
            byte[] timeSinceEventEpoch2 = GetTimeSinceEventEpoch(end);
            list.AddRange(timeSinceEventEpoch2.Take(4));
            list.AddRange(CalcCrcNew(list.Skip(5).Take(10).ToArray()));

            byte[] stream = list.ToArray();

            serial.Write(stream, 0, stream.Length);


            byte[] rawBuffer       = new byte[2];
            int    response_offest = 0;

            if (serial.isEcho())
            {
                response_offest = stream.Length;
            }
            Array.Resize(ref rawBuffer, (int)(response_offest + 2));

            long timeout_limit = DateTimeOffset.Now.ToUnixTimeMilliseconds() + (timeout);

            while (serial.BytesToRead() < rawBuffer.Length - 1)
            {
                if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit)
                {
                    //if even no data response no puck error..

                    if (serial.BytesToRead() <= response_offest)
                    {
                        throw new IOException();
                    }
                    else
                    {
                        throw new TimeoutException();
                    }
                }
                Thread.Sleep(10);
            }

            serial.Read(rawBuffer, 0, (int)(rawBuffer.Length));

            byte[] response = new byte[2];
            Array.Copy(rawBuffer, response_offest, response, 0, response.Length);

            if (response[0] != 0x06)
            {
                throw new LexiWriteException(response);
            }
        }
Пример #2
0
        public byte[] GetNextLogQueryResult(ISerial serial, int timeout)
        {
            List <byte> list = new List <byte>(5);

            list.Add(37);
            list.Add(254);
            list.Add(20);
            list.Add(0);
            list.Add(GetChecksum(list));

            byte[] stream = list.ToArray();

            serial.Write(stream, 0, stream.Length);

            byte[] rawBuffer       = new byte[10];
            int    response_offest = 0;

            if (serial.isEcho())
            {
                response_offest = stream.Length;
            }
            Array.Resize(ref rawBuffer, (int)(response_offest + 5));

            long timeout_limit = DateTimeOffset.Now.ToUnixTimeMilliseconds() + (timeout);

            while (serial.BytesToRead() < rawBuffer.Length)
            {
                if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit)
                {
                    //if even no data response no puck error..

                    if (serial.BytesToRead() <= response_offest)
                    {
                        throw new IOException();
                    }
                    else
                    {
                        throw new TimeoutException();
                    }
                }
                Thread.Sleep(10);
            }

            serial.Read(rawBuffer, 0, rawBuffer.Length);
            byte[] response = new byte[5];
            if (rawBuffer[0] != 37)
            {
                response_offest++;
            }
            Array.Copy(rawBuffer, response_offest, response, 0, rawBuffer.Length - response_offest);

            if (response[0] != 0x06)
            {
                throw new LexiWriteException(response);
            }

            if (response[1] == 1)
            {
                return(response);
            }
            else
            {
                byte[] full_response = new byte[25];
                Array.Copy(rawBuffer, response_offest, full_response, 0, rawBuffer.Length - response_offest);
                int moredata_to_read = 25 - (rawBuffer.Length - response_offest);
                Array.Resize(ref rawBuffer, moredata_to_read);
                while (serial.BytesToRead() < moredata_to_read)
                {
                    if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit)
                    {
                        //if even no data response no puck error..

                        if (serial.BytesToRead() <= response_offest)
                        {
                            throw new IOException();
                        }
                        else
                        {
                            throw new TimeoutException();
                        }
                    }
                    Thread.Sleep(10);
                }
                serial.Read(rawBuffer, 0, rawBuffer.Length);
                Array.Copy(rawBuffer, 0, full_response, 25 - moredata_to_read, moredata_to_read);

                return(full_response);
            }
        }
Пример #3
0
        public async Task Write(ISerial serial, UInt32 addres, byte[] data, int timeout)
        {
            int TEST = new Random().Next(0, 999);

            Utils.PrintDeep(Environment.NewLine + "-------LEXI_WRITE--------| " + TEST + " |--");
            Utils.PrintDeep("Lexi.Write = Write + UpdateBuffer + ReadBuffer");

            /*
             * +------------+----------+----------------------------------------------------------+
             * | Byte Index |  Field   |                          Notes                           |
             * +------------+----------+----------------------------------------------------------+
             * | 0          | Header   | This field is always 0x25                                |
             * | 1          | Command  | 0x81, 0x83, 0x85, 0x87 as detailed in section 4.2 above  |
             * | 2          | Address  | Address of first byte to write                           |
             * | 3          | Size     | Number of bytes to write                                 |
             * | 4          | Checksum | 2’s complement of sum: header + command + address + data |
             * | 5..4+N     | Data     | N = number of bytes specified in Data/Size field above   |
             * | 6+N..7+N   | CRC      | See section 7.2                                          |
             * +------------+----------+----------------------------------------------------------+
             *
             * Command
             * -------
             * block 0 addres >= 0 & < 256 = 0x81 => 129
             * block 1: addres >= 256 & < 512 = 0x83 => 131
             * block 2:addres >= 512 & < 768 = 0x85 => 133
             * block 3:addres >= 768 = 0x87 => 135
             */

            try
            {
                uint write_comand = (uint)(129 + ((addres / 256) * 2));

                /* Address
                 * -------
                 * addres then become offset from 256 block
                 * Example: Addres 600 --> block 2 --> offset 600 - 512 = 88;
                 */
                uint start_addres = (uint)(addres - ((addres / 256) * 256));

                // Data frame { 25 | WriteCmd | Address | BytesToWrite | Checksum }.Length = 5
                byte[] payload = new byte[] {
                    0x25, // header
                    (byte)write_comand,
                    (byte)start_addres,
                    (byte)data.Length
                };

                // Adds checksum to payload
                byte[] header = checkSum(payload);

                byte[] crc = BitConverter.GetBytes(calcCRC(data, data.Length));

                // Concatenate header, data to write and calculated CRC
                byte[] stream = new byte[0];
                Array.Resize(ref stream, header.Length + data.Length + 2 /*CRC*/);
                Array.Copy(header, 0, stream, 0, header.Length);
                Array.Copy(data, 0, stream, header.Length, data.Length);
                stream[stream.Length - 1] = crc[1];
                stream[stream.Length - 2] = crc[0];

                Utils.PrintDeep("Lexi.Write.. " +
                                "Stream = Header [ " +
                                "0x25 + " +
                                "WriteCmd 0x" + ( byte )write_comand + " ( " + write_comand + " ) + " +
                                "Address 0x" + ( byte )start_addres + " ( " + start_addres + " ) + " +
                                "NumBytesToWrite 0x" + ( byte )data.Length + " ( " + data.Length + " ) + " +
                                "Checksum 0x" + ( byte )header [header.Length - 1] + " ( " + header [header.Length - 1] + " ) + " +
                                "Data [ " + Utils.ByteArrayToString(data) + " ] + " +
                                "CRC [ " + Utils.ByteArrayToString(crc.Take(2).ToArray()) + " ]");

                Utils.PrintDeep("Lexi.Write.. " + Utils.ByteArrayToString(stream).Trim() + " [ Length " + stream.Length + " ]");

                // Send Lexi Write command
                // Stream length is always "5" = 25 + WriteCmd + Address + BytesToWrite + Checksum
                await serial.Write(stream, 0, stream.Length);

                Utils.PrintDeep("------BUFFER_START-------");

                //define response buffer size
                byte[] rawBuffer      = new byte[0];
                int    responseOffset = (serial.isEcho()) ? stream.Length : 0;
                Array.Resize(ref rawBuffer, responseOffset + 2);    // CRC that will be recovered

                Utils.PrintDeep("Lexi.Write.. " +
                                "Echo " + serial.isEcho().ToString().ToUpper() +
                                " | StreamFromMTU = Header x" + header.Length + " + Data x" + data.Length + " + CRC x2 + MTU.CRC x2 = " + rawBuffer.Length + " bytes");

                // Whait untill the response buffer data is available or timeout limit is reached
                int  bytesToRead   = 0;
                long timeout_limit = DateTimeOffset.Now.ToUnixTimeMilliseconds() + timeout;
                await Task.Run(() =>
                {
                    while ((bytesToRead = serial.BytesToRead()) < rawBuffer.Length - 1)
                    {
                        Utils.PrintDeep("Lexi.Write.. BytesToRead: " + bytesToRead + "/" + rawBuffer.Length + " [ " + DateTimeOffset.Now.ToUnixTimeMilliseconds() + " > " + timeout_limit + " ]");

                        if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit)
                        {
                            int num = serial.BytesToRead();

                            if (num <= responseOffset)
                            {
                                Utils.PrintDeep("Lexi.Write -> CheckResponseOk IOException");

                                throw new IOException();
                            }
                            else
                            {
                                Utils.PrintDeep("Lexi.Write -> CheckResponseOk TimeoutException");

                                throw new TimeoutException();
                            }
                        }
                        Thread.Sleep(10);
                    }
                });

                Utils.PrintDeep("Lexi.Read.. BytesRead: " + bytesToRead + " / " + (rawBuffer.Length - 1));

                Utils.PrintDeep("------BUFFER_FINISH------");

                serial.Read(rawBuffer, 0, rawBuffer.Length);

                byte[] response = new byte[2];
                Array.Copy(rawBuffer, responseOffset, response, 0, response.Length);

                Utils.PrintDeep("Lexi.Write.." +
                                " RawBuffer " + Utils.ByteArrayToString(rawBuffer) +
                                " | ACK " + Utils.ByteArrayToString(response));

                // If first byte of the recovered CRC is 6, everything has gone OK
                if (response[0] != 0x06)
                {
                    //throw new LexiWriteException(response);
                }
            }
            catch (Exception e)
            {
                throw new LexiWritingException();
            }
            finally
            {
                Utils.PrintDeep("----LEXI_WRITE_FINISH----| " + TEST + " |--" + Environment.NewLine);
            }
        }
Пример #4
0
        /// <summary>
        /// Request to read bytes from memory map
        /// </summary>
        /// <param name="serial">A double precision number.</param>
        /// <param name="addres">A double precision number.</param>
        /// <param name="bytesToRead">A double precision number.</param>
        /// <param name="timeut">A double precision number.</param>
        /// <returns>
        /// Memory Map values from read address request
        /// </returns>
        /// <example>
        /// <code>
        /// lx.Read(new USBSerial("COM5"), 0, 1, 400)
        /// </code>
        /// </example>
        /// <exception cref="System.TimeoutException">Thrown response Timeout is reached </exception>
        /// <exception cref="System.IO.InvalidDataException">Thrown when response data or CRC is not valid </exception>
        /// See <see cref="Read(UInt32 addres, uint data)"/> to add doubles.
        /// <seealso cref="Write(byte addres, byte[] data)"/>
        /// <seealso cref="Write(ISerial serial, UInt32 addres, byte[] data, int timeout)"/>
        public async Task <byte[]> Read(ISerial serial, UInt32 addres, uint bytesToRead, int timeout)
        {
            int TEST = new Random().Next(0, 999);

            Utils.PrintDeep(Environment.NewLine + "--------LEXI_READ-------| " + TEST + " |--");
            Utils.PrintDeep("Lexi.Read = Write + UpdateBuffer + Read");

            /* +------------+----------+----------------------------------------------------------+
             * | Byte Index |  Field   |                          Notes                           |
             * +------------+----------+----------------------------------------------------------+
             * |          0 | Header   | This field is always 0x25                                |
             * |          1 | Command  | 0x80, 0x82, 0x84, 0x86 as detailed in section 4.2 above  |
             * |          2 | Address  | Address of first byte to read                            |
             * |          3 | Size     | Number of bytes to read                                  |
             * |          4 | Checksum | 2’s complement of sum: header + command + address + data |
             * +------------+----------+----------------------------------------------------------+
             *
             * Command
             * -------
             * block 0 addres >= 0 & < 256 = 0x80 => 128
             * block 1: addres >= 256 & < 512 = 0x82 => 130
             * block 2:addres >= 512 & < 768 = 0x84 => 132
             * block 3:addres >= 768 = 0x86 => 134
             */

            try
            {
                uint read_comand = (uint)(128 + ((addres / 256) * 2));

                /* Address
                 * -------
                 * addres then become offset from 256 block
                 * Example: Addres 600 --> block 2 --> offset 600 - 512 = 88;
                 */
                uint start_addres = (uint)(addres - ((addres / 256) * 256));

                // Data frame { 25 | ReadCmd | Address | BytesToRead | CheckSum }.Length = 5
                byte[] payload = new byte[] {
                    0x25,
                    (byte)read_comand,
                    (byte)start_addres,
                    (byte)bytesToRead
                };

                // Adds checksum to payload
                byte[] stream = checkSum(payload);

                Utils.PrintDeep("Lexi.Read -> Write.." +
                                " Address " + start_addres +
                                " | ReadCmd " + read_comand +
                                " | BytesToRead " + bytesToRead +
                                " | TimeOut " + timeout +
                                " | Stream " + Utils.ByteArrayToString(stream) +
                                " [ " + stream.Length + " ]");

                // Send Lexi Read command
                // Stream length is always "5" = 25 + ReadCmd + Address + BytesToRead + Checksum
                await serial.Write(stream, 0, stream.Length);

                Utils.PrintDeep("------BUFFER_START-------");

                //define response buffer size
                byte[] rawBuffer    = new byte[0];
                int    headerOffset = (serial.isEcho()) ? stream.Length : 0;
                Array.Resize(ref rawBuffer, headerOffset + ( int )bytesToRead + 2);    // Header + Data + CRC

                Utils.PrintDeep("Lexi.Read -> Array.Resize.." +
                                " Echo " + serial.isEcho() +
                                " [ " + rawBuffer.Length + " = " + bytesToRead + " + Header " + headerOffset + " + CRC 2 ]");

                // Whait untill the response buffer data is available or timeout limit is reached
                long timeout_limit = DateTimeOffset.Now.ToUnixTimeMilliseconds() + (timeout);
                await Task.Run(() =>
                {
                    while (checkResponseOk(serial, rawBuffer))
                    {
                        if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit)
                        {
                            int num = serial.BytesToRead();

                            Utils.PrintDeep("Lexi.Read -> BytesToRead: " + num);

                            if (num <= headerOffset)
                            {
                                Utils.PrintDeep("Lexi.Read -> CheckResponseOk IOException");

                                throw new IOException();
                            }
                            else
                            {
                                Utils.PrintDeep("Lexi.Read -> CheckResponseOk TimeoutException");

                                throw new TimeoutException();
                            }
                        }
                        Thread.Sleep(10);
                    }
                });

                Utils.PrintDeep("------BUFFER_FINISH------");

                //read the response buffer
                serial.Read(rawBuffer, 0, rawBuffer.Length);

                /*
                 * +------------+-------+---------------+--------------------------------------------------------+
                 * | Byte Index | Field |   Value(s)    |                         Notes                          |
                 * +------------+-------+---------------+--------------------------------------------------------+
                 * | 0..N-1     | Data  | Read from RAM | N = number of bytes specified in Data field of Request |
                 * | N..N+1     | CRC   | Calculated    | CRC over all data bytes.  See section 7.2              |
                 * +------------+-------+---------------+--------------------------------------------------------+
                 *
                 */

                // Removes header
                byte[] response = new byte[2];
                Array.Resize(ref response, response.Length + ( int )bytesToRead);
                Array.Copy(rawBuffer, headerOffset, response, 0, response.Length);

                Utils.PrintDeep("Lexi.Read ->" +
                                " CheckCRC " + Utils.ByteArrayToString(response) +
                                " [ " + response.Length + " = BytesToRead " + bytesToRead + " + CRC 2 ]");

                // Validates CRC and if everything is ok, returns recovered data
                return(validateReadResponse(response, bytesToRead));
            }
            catch (Exception e)
            {
                throw new LexiReadingException();
            }
            finally
            {
                Utils.PrintDeep("----LEXI_READ_FINISH----| " + TEST + " |--" + Environment.NewLine);
            }
        }
Пример #5
0
        public void Write(ISerial serial, UInt32 addres, byte[] data, int timeout)
        {
            /*
             * +------------+----------+----------------------------------------------------------+
             * | Byte Index |  Field   |                          Notes                           |
             * +------------+----------+----------------------------------------------------------+
             * | 0          | Header   | This field is always 0x25                                |
             * | 1          | Command  | 0x81, 0x83, 0x85, 0x87 as detailed in section 4.2 above  |
             * | 2          | Address  | Address of first byte to write                           |
             * | 3          | Size     | Number of bytes to write                                 |
             * | 4          | Checksum | 2’s complement of sum: header + command + address + data |
             * | 5..4+N     | Data     | N = number of bytes specified in Data/Size field above   |
             * | 6+N..7+N   | CRC      | See section 7.2                                          |
             * +------------+----------+----------------------------------------------------------+
             *
             * Command
             * -------
             * block 0 addres >= 0 & < 256 = 0x81 => 129
             * block 1: addres >= 256 & < 512 = 0x83 => 131
             * block 2:addres >= 512 & < 768 = 0x85 => 133
             * block 3:addres >= 768 = 0x87 => 135
             */

            uint write_comand = (uint)(129 + ((addres / 256) * 2));

            /* Address
             * -------
             * addres then become offset from 256 block
             * Example: Addres 600 --> block 2 --> offset 600 - 512 = 88;
             */
            uint start_addres = (uint)(addres - ((addres / 256) * 256));

            byte[] payload = new byte[] {
                0x25, // header
                (byte)write_comand,
                (byte)start_addres,
                (byte)data.Length
            };

            //Addes checksum to payload
            byte[] header = checkSum(payload);

            byte[] stream = new byte[0];
            Array.Resize(ref stream, (int)(header.Length + data.Length));

            Array.Copy(header, 0, stream, 0, header.Length);
            Array.Copy(data, 0, stream, header.Length, data.Length);


            byte[] crc_bytes = BitConverter.GetBytes(calcCRC(data, data.Length));

            Array.Resize(ref stream, (int)(header.Length + data.Length + 2));
            stream[stream.Length - 1] = crc_bytes[1];
            stream[stream.Length - 2] = crc_bytes[0];

            serial.Write(stream, 0, stream.Length);

            byte[] rawBuffer       = new byte[2];
            int    response_offest = 0;

            if (serial.isEcho())
            {
                response_offest = stream.Length;
            }
            Array.Resize(ref rawBuffer, (int)(response_offest + 2));

            long timeout_limit = DateTimeOffset.Now.ToUnixTimeMilliseconds() + (timeout);

            while (serial.BytesToRead() < rawBuffer.Length - 1)
            {
                if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit)
                {
                    throw new TimeoutException();
                }
                Thread.Sleep(10);
            }

            serial.Read(rawBuffer, 0, (int)(rawBuffer.Length));

            byte[] response = new byte[2];
            Array.Copy(rawBuffer, response_offest, response, 0, response.Length);

            if (response[0] != 0x06)
            {
                throw new LexiWriteException(response);
            }
        }
Пример #6
0
        /// <summary>
        /// Request to read bytes from memory map
        /// </summary>
        /// <param name="serial">A double precision number.</param>
        /// <param name="addres">A double precision number.</param>
        /// <param name="data">A double precision number.</param>
        /// <param name="timeut">A double precision number.</param>
        /// <returns>
        /// Memory Map values from read address request
        /// </returns>
        /// <example>
        /// <code>
        /// lx.Read(new USBSerial("COM5"), 0, 1, 400)
        /// </code>
        /// </example>
        /// <exception cref="System.TimeoutException">Thrown response Timeout is reached </exception>
        /// <exception cref="System.IO.InvalidDataException">Thrown when response data or CRC is not valid </exception>
        /// See <see cref="Read(UInt32 addres, uint data)"/> to add doubles.
        /// <seealso cref="Write(byte addres, byte[] data)"/>
        /// <seealso cref="Write(ISerial serial, UInt32 addres, byte[] data, int timeout)"/>
        public byte[] Read(ISerial serial, UInt32 addres, uint data, int timeout)
        {
            /* +------------+----------+----------------------------------------------------------+
             * | Byte Index |  Field   |                          Notes                           |
             * +------------+----------+----------------------------------------------------------+
             * |          0 | Header   | This field is always 0x25                                |
             * |          1 | Command  | 0x80, 0x82, 0x84, 0x86 as detailed in section 4.2 above  |
             * |          2 | Address  | Address of first byte to read                            |
             * |          3 | Size     | Number of bytes to read                                  |
             * |          4 | Checksum | 2’s complement of sum: header + command + address + data |
             * +------------+----------+----------------------------------------------------------+
             *
             * Command
             * -------
             * block 0 addres >= 0 & < 256 = 0x80 => 128
             * block 1: addres >= 256 & < 512 = 0x82 => 130
             * block 2:addres >= 512 & < 768 = 0x84 => 132
             * block 3:addres >= 768 = 0x86 => 134
             */
            uint read_comand = (uint)(128 + ((addres / 256) * 2));

            /* Address
             * -------
             * addres then become offset from 256 block
             * Example: Addres 600 --> block 2 --> offset 600 - 512 = 88;
             */
            uint start_addres = (uint)(addres - ((addres / 256) * 256));

            //generate payload woth header, command, addres and data
            byte[] payload = new byte[] {
                0x25, // header
                (byte)read_comand,
                (byte)start_addres,
                (byte)data
            };

            //Addes checksum to payload
            byte[] stream = checkSum(payload);

            //Send Lexi Read command thought "serial port"
            serial.Write(stream, 0, stream.Length);


            //define response buffer size
            byte[] rawBuffer       = new byte[2];
            int    response_offest = 0;

            if (serial.isEcho())
            {
                response_offest = stream.Length;
            }
            Array.Resize(ref rawBuffer, (int)(rawBuffer.Length + data + response_offest));


            // whait till the response buffer data is available or timeout limit is reached
            long timeout_limit = DateTimeOffset.Now.ToUnixTimeMilliseconds() + (timeout);

            while (serial.BytesToRead() < rawBuffer.Length)
            {
                if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit)
                {
                    throw new TimeoutException();
                }
                Thread.Sleep(10);
            }

            //read the response buffer
            serial.Read(rawBuffer, 0, (int)(rawBuffer.Length));

            /*
             * +------------+-------+---------------+--------------------------------------------------------+
             * | Byte Index | Field |   Value(s)    |                         Notes                          |
             * +------------+-------+---------------+--------------------------------------------------------+
             * | 0..N-1     | Data  | Read from RAM | N = number of bytes specified in Data field of Request |
             * | N..N+1     | CRC   | Calculated    | CRC over all data bytes.  See section 7.2              |
             * +------------+-------+---------------+--------------------------------------------------------+
             *
             */

            //Get response body from RAW response (clean echo response)
            byte[] response = new byte[2];
            Array.Resize(ref response, (int)(response.Length + data));
            Array.Copy(rawBuffer, response_offest, response, 0, response.Length);

            //Validare CRC ane get Response BUDY
            return(validateReadResponse(response, data));
        }
Пример #7
0
        /// <summary>
        /// Request to read bytes from memory map
        /// </summary>
        /// <param name="serial">A double precision number.</param>
        /// <param name="addres">A double precision number.</param>
        /// <param name="bytesToRead">A double precision number.</param>
        /// <param name="timeut">A double precision number.</param>
        /// <returns>
        /// Memory Map values from read address request
        /// </returns>
        /// <example>
        /// <code>
        /// lx.Read(new USBSerial("COM5"), 0, 1, 400)
        /// </code>
        /// </example>
        /// <exception cref="System.TimeoutException">Thrown response Timeout is reached </exception>
        /// <exception cref="System.IO.InvalidDataException">Thrown when response data or CRC is not valid </exception>
        /// See <see cref="Read(UInt32 addres, uint data)"/> to add doubles.
        /// <seealso cref="Write(byte addres, byte[] data)"/>
        /// <seealso cref="Write(ISerial serial, UInt32 addres, byte[] data, int timeout)"/>
        private async Task <byte[]> Read(ISerial serial, UInt32 address, uint bytesToRead, int timeout)
        {
            int TEST = new Random().Next(0, 999);

            Utils.PrintDeep(Environment.NewLine + "--------LEXI_READ-------| " + TEST + " |--");
            Utils.PrintDeep("Lexi.Read = Write + UpdateBuffer + Read");

            try
            {
                byte[] stream;
                var    info = GeneratePackage(LexiAction.Read, out stream, address, null, bytesToRead);

                Utils.PrintDeep("Lexi.Read.. " +
                                "Stream = " +
                                "0x" + info.header + " ( " + Convert.ToInt32(info.header, 16) + " ) + " +
                                "WriteCmd 0x" + info.cmd + " ( " + Convert.ToInt32(info.cmd, 16) + " ) + " +
                                "Address 0x" + info.startAddress + " ( " + Convert.ToInt32(info.startAddress, 16) + " ) + " +
                                "Checksum 0x" + info.checksum + " ( " + Convert.ToInt32(info.checksum, 16) + " )");

                Utils.PrintDeep("Lexi.Read.. " + Utils.ByteArrayToString(stream).Trim() + " [ Length " + stream.Length + " ]");

                // Send Lexi Read command
                await serial.Write(stream, 0, stream.Length);

                Utils.PrintDeep("------BUFFER_START-------");

                //define response buffer size
                byte[] rawBuffer    = new byte[0];
                int    headerOffset = (serial.isEcho()) ? stream.Length : 0;
                Array.Resize(ref rawBuffer, headerOffset + ( int )bytesToRead + 2);    // Package + Data + ACK

                Utils.PrintDeep("Lexi.Read -> Array.Resize.." +
                                " Echo " + serial.isEcho() +
                                " [ " + rawBuffer.Length + " = " + bytesToRead + " + Header " + headerOffset + " + CRC 2 ]");

                // Whait untill the response buffer data is available or timeout limit is reached
                long timeout_limit = DateTimeOffset.Now.ToUnixTimeMilliseconds() + (timeout);
                await Task.Run(() =>
                {
                    while (checkResponseOk(serial, rawBuffer))
                    {
                        if (DateTimeOffset.Now.ToUnixTimeMilliseconds() > timeout_limit)
                        {
                            int num = serial.BytesReadCount();

                            Utils.PrintDeep("Lexi.Read -> BytesToRead: " + num);

                            if (num <= headerOffset)
                            {
                                Utils.PrintDeep("Lexi.Read -> CheckResponseOk IOException");

                                throw new IOException();
                            }
                            else
                            {
                                Utils.PrintDeep("Lexi.Read -> CheckResponseOk TimeoutException");

                                throw new TimeoutException();
                            }
                        }
                        Thread.Sleep(10);
                    }
                });

                Utils.PrintDeep("------BUFFER_FINISH------");

                //read the response buffer
                serial.Read(rawBuffer, 0, rawBuffer.Length);

                /*
                 * +------------+-------+---------------+--------------------------------------------------------+
                 * | Byte Index | Field |   Value(s)    |                         Notes                          |
                 * +------------+-------+---------------+--------------------------------------------------------+
                 * | 0..N-1     | Data  | Read from RAM | N = number of bytes specified in Data field of Request |
                 * | N..N+1     | CRC   | Calculated    | CRC over all data bytes.  See section 7.2              |
                 * +------------+-------+---------------+--------------------------------------------------------+
                 */

                // Removes header and get only the ACK
                byte[] response = new byte[2];
                Array.Resize(ref response, response.Length + ( int )bytesToRead);
                Array.Copy(rawBuffer, headerOffset, response, 0, response.Length);

                Utils.PrintDeep("Lexi.Read ->" +
                                " CheckCRC " + Utils.ByteArrayToString(response) +
                                " [ " + response.Length + " = BytesToRead " + bytesToRead + " + ACK 2 ]");

                // Validates CRC and if everything is ok, returns recovered data
                return(validateReadResponse(response, bytesToRead));
            }
            catch (Exception e)
            {
                throw new LexiReadingException();
            }
            finally
            {
                Utils.PrintDeep("----LEXI_READ_FINISH----| " + TEST + " |--" + Environment.NewLine);
            }
        }