/// <summary> /// Create new GM862GPS instance /// </summary> /// <param name="Port">Serial Port to use</param> public GM862GPS(String Port) { // We begin in IDLE state _CurrentState = GM862GPSStates.Idle; _SerialFIFO_CommandMode = ""; _SerialFIFI_IdleMode = ""; try { // Create new SerialPort Object _ComPort = new SerialPort(Port, 19200, Parity.None, 8, StopBits.One); _ComPort.Handshake = Handshake.None; _ComPort.Open(); } catch { // If failed throw error throw new GM862GPSException(GM862GPSException.FAILED_TO_CREATE); } // DataRecieved Handler _ComPort.DataReceived += new SerialDataReceivedEventHandler(_ComPort_DataReceived); // Create thread that handles Unsolicited Responses _ParseUnsolicitatedResponses = new Thread(new ThreadStart(ParseUnsolicitedResponse)); _ParseUnsolicitatedResponses.Priority = ThreadPriority.AboveNormal; _ParseUnsolicitatedResponses.Start(); // Add onUnsolicitedResponse Handler to check for incomming SMS and Call OnUnsolicitedResponse += new UnsolicitedResponseEvent(CheckForNewSMS); OnUnsolicitedResponse += new UnsolicitedResponseEvent(CheckForCall); }
/// <summary> /// Send Escape Sequence '+++' /// </summary> /// <returns>Return code</returns> public ResponseCodes Escape() { // Check if disposed // if (_Disposed) throw new ObjectDisposedException(); ResponseCodes RecievedResponse; int ResponseStart; int ResponseLength; // Set Command state lock (_CurrentStateLock) { // Now where in command state _CurrentState = GM862GPSStates.Command; } Thread.Sleep(2500); // Send Command to Serial Port byte[] OutBuffer = System.Text.Encoding.UTF8.GetBytes("+++"); lock (_ComPort) { _ComPort.Write(OutBuffer, 0, OutBuffer.Length); } Thread.Sleep(2500); // Now we wait for a response to come in RecievedResponse = WaitForResponse(out ResponseStart, out ResponseLength, 5000); // Delete response from FIFO lock (_SerialFIFO_CommandMode) { _SerialFIFO_CommandMode = _SerialFIFO_CommandMode.Substring(ResponseStart + ResponseLength); } // Return recieved response return(RecievedResponse); }
/// <summary> /// Request HTML page from Server /// !!! UNFINISHED !!! /// </summary> /// <param name="SocketID">Socket ID to use</param> /// <param name="Host">Host of server</param> /// <param name="Path">Path to fetch data from</param> /// <returns>Recieved HTTP Response</returns> public String RequestHTML(int SocketID, String Host, String Path) { // Check if disposed //if (_Disposed) throw new ObjectDisposedException(); // Say we want to connect to Socket if (ExecuteCommand("AT#SD=" + SocketID.ToString() + ", 0,80,\"" + Host + "\",0,0,0", 50000) != ResponseCodes.CONNECT) { throw new GM862GPSException("Did not recieve CONNECT response"); } // Object used for recieving HTML String RecievedData = ""; // Build request String Request = "GET " + Path + " HTTP/1.1\r\n"; Request += "Host: " + Host + "\r\n"; Request += "Connection: Close\r\n"; Request += "\r\n"; // Send request byte[] OutBuffer = System.Text.Encoding.UTF8.GetBytes(Request); lock (_ComPort) { _ComPort.Write(OutBuffer, 0, OutBuffer.Length); } // Recieve data while (true) { // Wait for .5 sec for data to arrive if (!WaitForDataToArrive.WaitOne(500, true)) { // When exit recieved exit now if (RecievedData.IndexOf("\r\nNO CARRIER\r\n") != -1) { RecievedData = RecievedData.Substring(0, RecievedData.LastIndexOf("\r\nNO CARRIER\r\n")); lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } break; } // No exit? Give some more time to get data if (!WaitForDataToArrive.WaitOne(10000, true)) { // If still no data Escape data mode try { Escape(); } catch { lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } } // Close socket ExecuteCommand("AT#SH=" + SocketID.ToString(), 1000); break; } } // Add data to recieve buffer lock (_SerialFIFO_CommandMode) { RecievedData += _SerialFIFO_CommandMode; _SerialFIFO_CommandMode = ""; } } // Return HTTP response return RecievedData; }
/// <summary> /// Execute AT Command. Wait until response is recieved. /// </summary> /// <param name="Command">Command to execute</param> /// <param name="Timeout">Timeout for response in miliseconds</param> /// <param name="ResponseBody">Returns the Response body</param> /// <returns>Recieved response code</returns> public ResponseCodes ExecuteCommand(String Command, int Timeout, out String ResponseBody) { /* * Send Command * Wait until command is send * Wait for last unsolicited response text is recieved * Go to command mode * Send \r\n to execute command * Wait until \r\n is send * Wait for response * Save command response body * Return response */ // Check if disposed // if (_Disposed) throw new ObjectDisposedException(); // Recieved response code ResponseCodes RecievedResponse; // Check if we are ready for Command lock (_CurrentStateLock) { if (_CurrentState != GM862GPSStates.Idle) throw new GM862GPSException(GM862GPSException.NOT_IN_IDLE_STATE); } // Send AT to Serial Port byte[] OutBuffer = System.Text.Encoding.UTF8.GetBytes(Command); lock (_ComPort) { _ComPort.Write(OutBuffer, 0, OutBuffer.Length); // Wait until command is send while (_ComPort.BytesToWrite > 0) { WaitForDataToArrive.WaitOne(10, false); } } // Check if in Idle State and set Command state lock (_CurrentStateLock) { if (_CurrentState != GM862GPSStates.Idle) throw new GM862GPSException(GM862GPSException.NOT_IN_IDLE_STATE); // Now where in command state _CurrentState = GM862GPSStates.Command; } // Wait for last data to arrive // WaitOne returns true when no data recieved in given time // So this loop exits when for the last 10 mSec no data has arrived while (WaitForDataToArrive.WaitOne(10, false)) { } // Clear input buffer lock (_SerialFIFO_CommandMode) { _SerialFIFO_CommandMode = ""; } // Send \r\n OutBuffer = System.Text.Encoding.UTF8.GetBytes("\r\n"); lock (_ComPort) { _ComPort.Write(OutBuffer, 0, OutBuffer.Length); // Wait until send while (_ComPort.BytesToWrite > 0) { WaitForDataToArrive.WaitOne(10, false); } } // Now we wait for a response to come in int ResponseStart=0; int ResponseLength; RecievedResponse = WaitForResponse(out ResponseStart, out ResponseLength, Timeout); // Now get response body and delete response from FIFO lock (_SerialFIFO_CommandMode) { ResponseBody = _SerialFIFO_CommandMode.Substring(0, ResponseStart); _SerialFIFO_CommandMode = _SerialFIFO_CommandMode.Substring(ResponseStart + ResponseLength); } // Return recieved response return RecievedResponse; }
/// <summary> /// Send Escape Sequence '+++' /// </summary> /// <returns>Return code</returns> public ResponseCodes Escape() { // Check if disposed // if (_Disposed) throw new ObjectDisposedException(); ResponseCodes RecievedResponse; int ResponseStart; int ResponseLength; // Set Command state lock (_CurrentStateLock) { // Now where in command state _CurrentState = GM862GPSStates.Command; } Thread.Sleep(2500); // Send Command to Serial Port byte[] OutBuffer = System.Text.Encoding.UTF8.GetBytes("+++"); lock (_ComPort) { _ComPort.Write(OutBuffer, 0, OutBuffer.Length); } Thread.Sleep(2500); // Now we wait for a response to come in RecievedResponse = WaitForResponse(out ResponseStart, out ResponseLength, 5000); // Delete response from FIFO lock (_SerialFIFO_CommandMode) { _SerialFIFO_CommandMode = _SerialFIFO_CommandMode.Substring(ResponseStart + ResponseLength); } // Return recieved response return RecievedResponse; }
/// <summary> /// Waits until it recieves a valid response code. /// This command automaticly sets the state to IDLE or DATA /// Throws exception when no response is recieved within timeout time. /// </summary> /// <param name="ResponseStart">Returns the position in the FIFO of response</param> /// <param name="ResponseLength">Returns the length of the response</param> /// <param name="Timeout">Timeout in miliseconds</param> /// <returns>Received response code</returns> private ResponseCodes WaitForResponse(out int ResponseStart, out int ResponseLength, int Timeout) { // Check if disposed // if (_Disposed) throw new ObjectDisposedException(); // Set TimeOut DateTime TimeOutAt = DateTime.Now.AddMilliseconds(Timeout); // Check if in Command or Data State lock (_CurrentStateLock) { if ((_CurrentState != GM862GPSStates.Command) && (_CurrentState != GM862GPSStates.Data)) throw new GM862GPSException(GM862GPSException.NOT_IN_COMMAND_OR_DATA_STATE); } // Search for response until timeout while (DateTime.Now < TimeOutAt) { // TODO: // Check if it's better to release/aquire lock for each response check lock (_SerialFIFO_CommandMode) { //DebugMessage("Check"); // OK response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nOK\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nOK\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return ResponseCodes.OK; } // ERROR response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nERROR\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nERROR\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return ResponseCodes.ERROR; } // ERROR response ResponseStart = _SerialFIFO_CommandMode.IndexOf("+CMS ERROR: 321"); if (ResponseStart != -1) { ResponseLength = "+CMS ERROR: 321".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return ResponseCodes.ERROR; } // RING response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nRING\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nRING\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return ResponseCodes.RING; } // BUSY response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nBUSY\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nBUSY\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return ResponseCodes.BUSY; } // NO CARRIER response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nNO CARRIER\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nNO CARRIER\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return ResponseCodes.NO_CARRIER; } // NO DIALTONE response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nNO DIALTONE\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nNO DIALTONE\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return ResponseCodes.NO_DIALTONE; } // NO ANSWER response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nNO ANSWER\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nNO ANSWER\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return ResponseCodes.NO_ANSWER; } // CONNECT response ResponseStart = _SerialFIFO_CommandMode.IndexOf("CONNECT"); if (ResponseStart != -1) { ResponseLength = _SerialFIFO_CommandMode.IndexOf("\r\n", ResponseStart + 2); if (ResponseLength != -1) { ResponseLength = (ResponseLength - ResponseStart) + 2; WaitForDataToArrive.Reset(); lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Data; } return ResponseCodes.CONNECT; } } // SEND_SMS_DATA (>) response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\n>"); if (ResponseStart != -1) { ResponseLength = "\r\n>".Length; WaitForDataToArrive.Reset(); lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Data; } return ResponseCodes.SEND_SMS_DATA; } } WaitForDataToArrive.WaitOne(50, false); } // Response Timeout lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } ResponseStart = -1; ResponseLength = 0; return ResponseCodes.ERROR; }
/// <summary> /// Execute AT Command. Wait until response is recieved. /// </summary> /// <param name="Command">Command to execute</param> /// <param name="Timeout">Timeout for response in miliseconds</param> /// <param name="ResponseBody">Returns the Response body</param> /// <returns>Recieved response code</returns> public ResponseCodes ExecuteCommand(String Command, int Timeout, out String ResponseBody) { /* * Send Command * Wait until command is send * Wait for last unsolicited response text is recieved * Go to command mode * Send \r\n to execute command * Wait until \r\n is send * Wait for response * Save command response body * Return response */ // Check if disposed // if (_Disposed) throw new ObjectDisposedException(); // Recieved response code ResponseCodes RecievedResponse; // Check if we are ready for Command lock (_CurrentStateLock) { if (_CurrentState != GM862GPSStates.Idle) { throw new GM862GPSException(GM862GPSException.NOT_IN_IDLE_STATE); } } // Send AT to Serial Port byte[] OutBuffer = System.Text.Encoding.UTF8.GetBytes(Command); lock (_ComPort) { _ComPort.Write(OutBuffer, 0, OutBuffer.Length); // Wait until command is send while (_ComPort.BytesToWrite > 0) { WaitForDataToArrive.WaitOne(10, false); } } // Check if in Idle State and set Command state lock (_CurrentStateLock) { if (_CurrentState != GM862GPSStates.Idle) { throw new GM862GPSException(GM862GPSException.NOT_IN_IDLE_STATE); } // Now where in command state _CurrentState = GM862GPSStates.Command; } // Wait for last data to arrive // WaitOne returns true when no data recieved in given time // So this loop exits when for the last 10 mSec no data has arrived while (WaitForDataToArrive.WaitOne(10, false)) { } // Clear input buffer lock (_SerialFIFO_CommandMode) { _SerialFIFO_CommandMode = ""; } // Send \r\n OutBuffer = System.Text.Encoding.UTF8.GetBytes("\r\n"); lock (_ComPort) { _ComPort.Write(OutBuffer, 0, OutBuffer.Length); // Wait until send while (_ComPort.BytesToWrite > 0) { WaitForDataToArrive.WaitOne(10, false); } } // Now we wait for a response to come in int ResponseStart = 0; int ResponseLength; RecievedResponse = WaitForResponse(out ResponseStart, out ResponseLength, Timeout); // Now get response body and delete response from FIFO lock (_SerialFIFO_CommandMode) { ResponseBody = _SerialFIFO_CommandMode.Substring(0, ResponseStart); _SerialFIFO_CommandMode = _SerialFIFO_CommandMode.Substring(ResponseStart + ResponseLength); } // Return recieved response return(RecievedResponse); }
/// <summary> /// Request HTML page from Server /// !!! UNFINISHED !!! /// </summary> /// <param name="SocketID">Socket ID to use</param> /// <param name="Host">Host of server</param> /// <param name="Path">Path to fetch data from</param> /// <returns>Recieved HTTP Response</returns> public String RequestHTML(int SocketID, String Host, String Path) { // Check if disposed //if (_Disposed) throw new ObjectDisposedException(); // Say we want to connect to Socket if (ExecuteCommand("AT#SD=" + SocketID.ToString() + ", 0,80,\"" + Host + "\",0,0,0", 50000) != ResponseCodes.CONNECT) { throw new GM862GPSException("Did not recieve CONNECT response"); } // Object used for recieving HTML String RecievedData = ""; // Build request String Request = "GET " + Path + " HTTP/1.1\r\n"; Request += "Host: " + Host + "\r\n"; Request += "Connection: Close\r\n"; Request += "\r\n"; // Send request byte[] OutBuffer = System.Text.Encoding.UTF8.GetBytes(Request); lock (_ComPort) { _ComPort.Write(OutBuffer, 0, OutBuffer.Length); } // Recieve data while (true) { // Wait for .5 sec for data to arrive if (!WaitForDataToArrive.WaitOne(500, true)) { // When exit recieved exit now if (RecievedData.IndexOf("\r\nNO CARRIER\r\n") != -1) { RecievedData = RecievedData.Substring(0, RecievedData.LastIndexOf("\r\nNO CARRIER\r\n")); lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } break; } // No exit? Give some more time to get data if (!WaitForDataToArrive.WaitOne(10000, true)) { // If still no data Escape data mode try { Escape(); } catch { lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } } // Close socket ExecuteCommand("AT#SH=" + SocketID.ToString(), 1000); break; } } // Add data to recieve buffer lock (_SerialFIFO_CommandMode) { RecievedData += _SerialFIFO_CommandMode; _SerialFIFO_CommandMode = ""; } } // Return HTTP response return(RecievedData); }
/// <summary> /// Waits until it recieves a valid response code. /// This command automaticly sets the state to IDLE or DATA /// Throws exception when no response is recieved within timeout time. /// </summary> /// <param name="ResponseStart">Returns the position in the FIFO of response</param> /// <param name="ResponseLength">Returns the length of the response</param> /// <param name="Timeout">Timeout in miliseconds</param> /// <returns>Received response code</returns> private ResponseCodes WaitForResponse(out int ResponseStart, out int ResponseLength, int Timeout) { // Check if disposed // if (_Disposed) throw new ObjectDisposedException(); // Set TimeOut DateTime TimeOutAt = DateTime.Now.AddMilliseconds(Timeout); // Check if in Command or Data State lock (_CurrentStateLock) { if ((_CurrentState != GM862GPSStates.Command) && (_CurrentState != GM862GPSStates.Data)) { throw new GM862GPSException(GM862GPSException.NOT_IN_COMMAND_OR_DATA_STATE); } } // Search for response until timeout while (DateTime.Now < TimeOutAt) { // TODO: // Check if it's better to release/aquire lock for each response check lock (_SerialFIFO_CommandMode) { //DebugMessage("Check"); // OK response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nOK\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nOK\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return(ResponseCodes.OK); } // ERROR response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nERROR\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nERROR\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return(ResponseCodes.ERROR); } // ERROR response ResponseStart = _SerialFIFO_CommandMode.IndexOf("+CMS ERROR: 321"); if (ResponseStart != -1) { ResponseLength = "+CMS ERROR: 321".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return(ResponseCodes.ERROR); } // RING response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nRING\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nRING\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return(ResponseCodes.RING); } // BUSY response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nBUSY\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nBUSY\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return(ResponseCodes.BUSY); } // NO CARRIER response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nNO CARRIER\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nNO CARRIER\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return(ResponseCodes.NO_CARRIER); } // NO DIALTONE response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nNO DIALTONE\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nNO DIALTONE\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return(ResponseCodes.NO_DIALTONE); } // NO ANSWER response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\nNO ANSWER\r\n"); if (ResponseStart != -1) { ResponseLength = "\r\nNO ANSWER\r\n".Length; lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } return(ResponseCodes.NO_ANSWER); } // CONNECT response ResponseStart = _SerialFIFO_CommandMode.IndexOf("CONNECT"); if (ResponseStart != -1) { ResponseLength = _SerialFIFO_CommandMode.IndexOf("\r\n", ResponseStart + 2); if (ResponseLength != -1) { ResponseLength = (ResponseLength - ResponseStart) + 2; WaitForDataToArrive.Reset(); lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Data; } return(ResponseCodes.CONNECT); } } // SEND_SMS_DATA (>) response ResponseStart = _SerialFIFO_CommandMode.IndexOf("\r\n>"); if (ResponseStart != -1) { ResponseLength = "\r\n>".Length; WaitForDataToArrive.Reset(); lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Data; } return(ResponseCodes.SEND_SMS_DATA); } } WaitForDataToArrive.WaitOne(50, false); } // Response Timeout lock (_CurrentStateLock) { _CurrentState = GM862GPSStates.Idle; } ResponseStart = -1; ResponseLength = 0; return(ResponseCodes.ERROR); }