private static void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e, AGVInfoRequestPacket requestFrame)
        {
            AGVInfoRequestPacket resendFrame = requestFrame;

            if (ackReceived.AGVID == resendFrame.AGVID &&
                ackReceived.FunctionCode == (byte)FUNC_CODE.RESP_ACK_AGV_INFO &&
                ackReceived.ACK == (byte)'Y')
            {
                ackReceived = default(AckReceivePacket);
                ((System.Timers.Timer)sender).Dispose();
                return;
            }

            AGV agv = AGV.ListAGV.Find(a => a.ID == (int)resendFrame.AGVID);

            if (agv == null || !agv.IsInitialized)
            {
                return;
            }
            try { Communicator.SerialPort.Write(resendFrame.ToArray(), 0, resendFrame.ToArray().Length); }
            catch { return; }

            // Display ComStatus
            Display.UpdateComStatus("timeout", resendFrame.AGVID, "Request AGV info", System.Drawing.Color.Red);
            Display.UpdateComStatus("send", resendFrame.AGVID, "Request AGV info", System.Drawing.Color.Blue);
        }
        // Send AGV info request packet (InfoType = 'A' for all except line tracking error, 'L' for line tracking error)
        public static void SendAGVInfoRequest(uint agvID, char InfoType)
        {
            AGVInfoRequestPacket requestFrame = new AGVInfoRequestPacket();

            requestFrame.Header = new byte[2] {
                0xAA, 0xFF
            };
            requestFrame.FunctionCode    = (byte)FUNC_CODE.REQ_AGV_INFO;
            requestFrame.AGVID           = Convert.ToByte(agvID);
            requestFrame.InformationType = (byte)InfoType;
            // calculate check sum
            ushort crc = 0;

            crc += requestFrame.Header[0];
            crc += requestFrame.Header[1];
            crc += requestFrame.FunctionCode;
            crc += requestFrame.AGVID;
            crc += requestFrame.InformationType;
            requestFrame.CheckSum   = crc;
            requestFrame.EndOfFrame = new byte[2] {
                0x0A, 0x0D
            };

            // send data via serial port
            AGV agv = AGV.ListAGV.Find(a => a.ID == (int)agvID);

            if (!agv.IsInitialized)
            {
                return;
            }
            try { Communicator.SerialPort.Write(requestFrame.ToArray(), 0, requestFrame.ToArray().Length); }
            catch { };

            // Display ComStatus
            Display.UpdateComStatus("send", requestFrame.AGVID, "Request AGV info", System.Drawing.Color.Blue);

            // wait ack
            System.Timers.Timer timer1 = new System.Timers.Timer(timeout);
            timer1.Elapsed += (sender, e) => timer1_Elapsed(sender, e, requestFrame);
            timer1.Start();
        }