private static void timer3_Elapsed(object sender, System.Timers.ElapsedEventArgs e, InformWaitingSendPacket sendFrame)
        {
            InformWaitingSendPacket resendFrame = sendFrame;

            if (ackReceived.AGVID == resendFrame.AGVID &&
                ackReceived.FunctionCode == (byte)FUNC_CODE.RESP_ACK_WAITING &&
                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.IsInitialized)
            {
                return;
            }
            try { Communicator.SerialPort.Write(resendFrame.ToArray(), 0, resendFrame.ToArray().Length); }
            catch { return; }

            // Display ComStatus
            Display.UpdateComStatus("timeout", resendFrame.AGVID, "Inform Waiting", System.Drawing.Color.Red);
            Display.UpdateComStatus("send", resendFrame.AGVID, "Inform Waiting", System.Drawing.Color.Blue);
        }
        public static void SendInformWaiting(uint agvID, ushort waitingTime)
        {
            InformWaitingSendPacket sendFrame = new InformWaitingSendPacket();

            sendFrame.Header = new byte[2] {
                0xAA, 0xFF
            };
            sendFrame.FunctionCode = (byte)FUNC_CODE.WR_WAITING;
            sendFrame.AGVID        = Convert.ToByte(agvID);
            sendFrame.WaitingTime  = waitingTime;
            // calculate check sum
            ushort crc = 0;

            crc += sendFrame.Header[0];
            crc += sendFrame.Header[1];
            crc += sendFrame.FunctionCode;
            crc += sendFrame.AGVID;
            crc += BitConverter.GetBytes(sendFrame.WaitingTime)[0];
            crc += BitConverter.GetBytes(sendFrame.WaitingTime)[1];
            sendFrame.CheckSum   = crc;
            sendFrame.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(sendFrame.ToArray(), 0, sendFrame.ToArray().Length); }
            catch { };

            // Display ComStatus
            Display.UpdateComStatus("send", sendFrame.AGVID, "Inform Waiting", System.Drawing.Color.Blue);

            // wait ack
            System.Timers.Timer timer3 = new System.Timers.Timer(timeout);
            timer3.Elapsed += (sender, e) => timer3_Elapsed(sender, e, sendFrame);
            timer3.Start();
        }