SMS connection with a C # phone and receiving a response

I wrote a code to send SMS using my GSM phone, which is connected to the computer via the COM port. The code is below.

The problem is that I see that it is in the Outbox, and in fact it was sent, but when I contact the recipient, they say that I did not receive the message.

I am testing a phone and I am creating and sending a message using only the phone and it works great. However, when I do this with my code, it APPEARS is sent, and I get all the correct AT COMMAND responses from the phone, but the message is NOT actually sent.

Here is the code:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.IO.Ports; namespace WindowsFormsApplication1 { public partial class Form1 : Form { SerialPort serialPort1; int m_iTxtMsgState = 0; const int NUM_MESSAGE_STATES = 4; const string RESERVED_COM_1 = "COM1"; const string RESERVED_COM_4 = "COM4"; public Form1() { InitializeComponent(); this.Closing += new CancelEventHandler(Form1_Closing); } private void Form1_Load(object sender, EventArgs e) { serialPort1 = new SerialPort(GetUSBComPort()); if (serialPort1.IsOpen) { serialPort1.Close(); } serialPort1.Open(); //ThreadStart myThreadDelegate = new ThreadStart(ReceiveAndOutput); //Thread myThread = new Thread(myThreadDelegate); //myThread.Start(); this.serialPort1.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived); } private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { serialPort1.Close(); } private void SendLine(string sLine) { serialPort1.Write(sLine); sLine = sLine.Replace("\u001A", ""); consoleOut.Text += sLine; } public void DoWork() { ProcessMessageState(); } public void ProcessMessageState() { switch (m_iTxtMsgState) { case 0: m_iTxtMsgState = 1; SendLine("AT\r\n"); //NOTE: SendLine must be the last thing called in all of these! break; case 1: m_iTxtMsgState = 2; SendLine("AT+CMGF=1\r\n"); break; case 2: m_iTxtMsgState = 3; SendLine("AT+CMGW=" + Convert.ToChar(34) + "+9737387467" + Convert.ToChar(34) + "\r\n"); break; case 3: m_iTxtMsgState = 4; SendLine("A simple demo of SMS text messaging." + Convert.ToChar(26)); break; case 4: m_iTxtMsgState = 5; break; case 5: m_iTxtMsgState = NUM_MESSAGE_STATES; break; } } private string GetStoredSMSID() { return null; } /* //I don't think this part does anything private void serialPort1_DataReceived_1(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { string response = serialPort1.ReadLine(); this.BeginInvoke(new MethodInvoker(() => textBox1.AppendText(response + "\r\n"))); } */ void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { try { Thread.Sleep(500); char[] msg; msg = new char[613]; int iNumToRead = serialPort1.BytesToRead; serialPort1.Read(msg, 0, iNumToRead); string response = new string(msg); this.BeginInvoke(new MethodInvoker(() => textBox1.AppendText(response + "\r\n"))); serialPort1.DiscardInBuffer(); if (m_iTxtMsgState == 4) { int pos_cmgw = response.IndexOf("+CMGW:"); string cmgw_num = response.Substring(pos_cmgw + 7, 4); SendLine("AT+CMSS=" + cmgw_num + "\r\n"); //stop listening to messages received } if (m_iTxtMsgState < NUM_MESSAGE_STATES) { ProcessMessageState(); } } catch { } } private void button1_Click(object sender, EventArgs e) { m_iTxtMsgState = 0; DoWork(); } private void button2_Click(object sender, EventArgs e) { string[] sPorts = SerialPort.GetPortNames(); foreach (string port in sPorts) { consoleOut.Text += port + "\r\n"; } } private string GetUSBComPort() { string[] sPorts = SerialPort.GetPortNames(); foreach (string port in sPorts) { if (port != RESERVED_COM_1 && port != RESERVED_COM_4) { return port; } } return null; } } 
+6
c # vba excel sms
source share
4 answers

This is my code that works (tested) with a Telia U9 cellular modem:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; using System.Configuration; using UsbEject.Library; using Utils; namespace Hardware { public class TeliaModem : IDisposable { public delegate void NewSmsHandler(InboundSMS sms); public event NewSmsHandler OnNewSMS; #region private data System.IO.Ports.SerialPort modemPort; Timeouter _lastModemKeepAlive; private delegate void DataReceivedDelegate(); private DataReceivedDelegate dataReceivedDelegate; Queue<OutboundSMS> _outSmses = new Queue<OutboundSMS>(); enum ModemState { Error = -1, NotInitialized, PowerUp, Initializing, Idle, SendingSMS, KeepAliveAwaitingResponse }; Timeouter ModemStateTimeouter = new Timeouter(timeout_s: 10, autoReset: false); ModemState _modemState = ModemState.NotInitialized; ModemState CurrentModemState { get { return _modemState; } set { _modemState = value; ModemStateTimeouter.Reset(); NihLog.Write(NihLog.Level.Debug, "State changed to: " + value.ToString()); } } private System.Windows.Forms.Control _mainThreadOwnder; #endregion public TeliaModem(System.Windows.Forms.Control mainThreadOwnder) { _mainThreadOwnder = mainThreadOwnder; dataReceivedDelegate = new DataReceivedDelegate(OnDataReceived); } public void SendSMS(string phone, string text) { _outSmses.Enqueue(new OutboundSMS(phone, text)); HeartBeat(); } private void SendSmsNow() { OutboundSMS sms = _outSmses.Peek(); sms.Attempt++; if (sms.Attempt > sms.MaxTries) { NihLog.Write(NihLog.Level.Error, "Failure to send after " + sms.MaxTries + " tries"); _outSmses.Dequeue(); return; } NihLog.Write(NihLog.Level.Info, "Sending SMS: " + sms.ToString()); WriteToModem("AT+CMGS=\"" + sms.Destination + "\"\r"); System.Threading.Thread.Sleep(500); WriteToModem(sms.Text); byte[] buffer = new byte[1]; buffer[0] = 26; // ^Z modemPort.Write(buffer, offset:0, count:1); CurrentModemState = ModemState.SendingSMS; } public void Dispose() { UninitModem(); } public void HeartBeat() { if (CurrentModemState == ModemState.NotInitialized) { TryInitModem(); return; } if (IsTransitionalState(CurrentModemState) && ModemStateTimeouter.IsTimedOut()) { NihLog.Write(NihLog.Level.Error, "Modem error. Timed out during " + CurrentModemState); CurrentModemState = ModemState.Error; return; } if (CurrentModemState == ModemState.Idle && _lastModemKeepAlive.IsTimedOut()) { // Send keepalive WriteToModem("AT\r"); CurrentModemState = ModemState.KeepAliveAwaitingResponse; return; } if (CurrentModemState == ModemState.Error) { NihLog.Write(NihLog.Level.Debug, "Reenumerating modem..."); UninitModem(); return; } if (_outSmses.Count != 0 && CurrentModemState == ModemState.Idle) { SendSmsNow(); return; } } private string pendingData; private void OnDataReceived() { // Called in the main thread string nowWhat = modemPort.ReadExisting(); pendingData += nowWhat; string[] lines = pendingData.Split(new string[] { "\r\n" }, StringSplitOptions.None); if (lines.Length == 0) { pendingData = string.Empty; return; } else { pendingData = lines[lines.Length - 1]; } // This happens in main thread. for (int i = 0; i < lines.Length - 1; i++) { string line = lines[i]; if (line.Length >= 5 && line.Substring(0, 5) == "+CMT:") { // s+= read one more line if (i == lines.Length - 1) // no next line { pendingData = line + "\r\n" + pendingData; // unread the line continue; } string line2 = lines[++i]; NihLog.Write(NihLog.Level.Debug, "RX " + line); NihLog.Write(NihLog.Level.Debug, "RX " + line2); InboundSMS sms = new InboundSMS(); sms.ParseCMT(line, line2); if(OnNewSMS != null) OnNewSMS(sms); } else // Not a composite NihLog.Write(NihLog.Level.Debug, "RX " + line); if (line == "OK") { OnModemResponse(true); } else if (line == "ERROR") { OnModemResponse(false); NihLog.Write(NihLog.Level.Error, "Modem error"); } } } private void ProcessSmsResult(bool ok) { if (!ok) { OutboundSMS sms = _outSmses.Peek(); if (sms.Attempt < sms.MaxTries) { NihLog.Write(NihLog.Level.Info, "Retrying sms..."); return; } NihLog.Write(NihLog.Level.Error, "Failed to send SMS: " + sms.ToString()); } _outSmses.Dequeue(); } private void OnModemResponse(bool ok) { if (CurrentModemState == ModemState.SendingSMS) ProcessSmsResult(ok); if (!ok) { NihLog.Write(NihLog.Level.Error, "Error during state " + CurrentModemState.ToString()); CurrentModemState = ModemState.Error; return; } switch (CurrentModemState) { case ModemState.NotInitialized: return; case ModemState.PowerUp: WriteToModem("ATE0;+CMGF=1;+CSCS=\"IRA\";+CNMI=1,2\r"); CurrentModemState = ModemState.Initializing; break; case ModemState.Initializing: case ModemState.SendingSMS: case ModemState.KeepAliveAwaitingResponse: CurrentModemState = ModemState.Idle; break; } } private void CloseU9TelitNativeApp() { bool doneSomething; do { doneSomething = false; Process[] processes = Process.GetProcessesByName("wirelesscard"); foreach (Process p in processes) { p.CloseMainWindow(); doneSomething = true; NihLog.Write(NihLog.Level.Info, "Killed native U9 app"); System.Threading.Thread.Sleep(1000); // Will not wait if no native app is started } } while (doneSomething); } void WriteToModem(string s) { modemPort.Write(s); NihLog.Write(NihLog.Level.Debug, "TX " + s); } void UninitModem() { if (modemPort != null) modemPort.Dispose(); modemPort = null; CurrentModemState = ModemState.NotInitialized; } private bool IsTransitionalState(ModemState ms) { return ms == ModemState.Initializing || ms == ModemState.SendingSMS || ms == ModemState.PowerUp || ms == ModemState.KeepAliveAwaitingResponse; } Timeouter _initFailureTimeout = new Timeouter(timeout_s: 10, autoReset:false, timedOut:true); void TryInitModem() { // Try pistoning the modem with higher frequency. This does no harm (such as redundant logging) PrepareU9Modem(); // Will do nothing if modem is okay if (!_initFailureTimeout.IsTimedOut()) return; // Don't try too frequently if (modemPort != null) return; const string modemPortName = "Basecom HS-USB NMEA 9000"; const int speed = 115200; string portName = Hardware.Misc.SerialPortFromFriendlyName(modemPortName); if (portName == null) { NihLog.Write(NihLog.Level.Error, "Modem not found (yet). "); _initFailureTimeout.Reset(); return; } NihLog.Write(NihLog.Level.Info, string.Format("Found modem port \"{0}\" at {1}", modemPortName, portName)); modemPort = new System.IO.Ports.SerialPort(portName, speed); modemPort.ReadTimeout = 3000; modemPort.NewLine = "\r\n"; modemPort.Open(); modemPort.DiscardInBuffer(); modemPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(delegate { _mainThreadOwnder.Invoke(dataReceivedDelegate); }); // called in different thread! _lastModemKeepAlive = new Timeouter(60, true); WriteToModem("AT+CFUN=1\r"); CurrentModemState = ModemState.PowerUp; } void CheatU9Telit() { // U9 telit appears as USB CDrom on the bus, until disk eject is sent. // Then, it reappears as normal stuff. VolumeDeviceClass volumeDeviceClass = new VolumeDeviceClass(); foreach (Volume device in volumeDeviceClass.Devices) { if (device.FriendlyName == "PCL HSUPA Modem USB Device") { NihLog.Write(NihLog.Level.Info, "Trying to initialize: " + device.FriendlyName); device.EjectCDRomNoUI(); } } } void PrepareU9Modem() { CloseU9TelitNativeApp(); // Closes the autorun native app CheatU9Telit(); } } public class OutboundSMS { public string Destination; public string Text; public int MaxTries; public int Attempt = 0; public OutboundSMS(string dest, string txt) { Destination = dest; Text = txt; MaxTries = 3; } override public string ToString() { if(Attempt > 1) return string.Format("\"{0}\" to {1}, attempt {2}", Text, Destination, Attempt); else return string.Format("\"{0}\" to {1}", Text, Destination); } } public class InboundSMS { public string SourcePhone; public DateTime ReceiveTime; public string Text; public void ParseCMT(string line1, string line2) { string[] fields = line1.Split(new char[] { ',', ' ', '/', ':', '"' }); if (fields.Length < 12) throw new ApplicationException("CMT message too short. Expected 2 fields"); SourcePhone = fields[3]; ReceiveTime = DateTime.Parse("20" + fields[7] + "-" + fields[8] + "-" + fields[9] + " " + fields[10] + ":" + fields[11] + ":" + fields[12].Substring(0, 2)); //test carefully Text = line2; } }; } 

Winforms application example:

 Hardware.TeliaModem _modem; public Form1() { InitializeComponent(); _modem = new Hardware.TeliaModem(this); _modem.OnNewSMS += new Hardware.TeliaModem.NewSmsHandler(ProcessNewSMS); _timer.Interval = 1000; // milliseconds _timer.Tick += new EventHandler(OnTimerTick); _timer.Start(); } 

To send SMS:

  _modem.SendSMS(sms.SourcePhone, "Aircon is now " + BoolToString.ON_OFF(_aircon.On)); 

By timer event, once per second:

 private void OnTimerTick(object o, EventArgs e) { _modem.HeartBeat(); } 

This is registered as a Winforms timer handler, so the modem will not have a stream.

Some utility classes are used:

 namespace Utils { public class StopWatch { protected DateTime _resetTime; public StopWatch() { Reset(); } public void Reset() { _resetTime = DateTime.Now; } public double TotalSeconds { get { return (DateTime.Now - _resetTime).TotalSeconds; } } public TimeSpan Time { get { return DateTime.Now - _resetTime; } } }; public class Timeouter : StopWatch { private bool _autoReset; private double _timeout_s; public Timeouter(double timeout_s, bool autoReset, bool timedOut = false) { _timeout_s = timeout_s; _autoReset = autoReset; if (timedOut) _resetTime -= TimeSpan.FromSeconds(_timeout_s + 1); // This is surely timed out, as requested } public bool IsTimedOut() { if (_timeout_s == double.PositiveInfinity) return false; bool timedout = this.TotalSeconds >= _timeout_s; if (timedout && _autoReset) Reset(); return timedout; } public void Reset(double timeout_s) { _timeout_s = timeout_s; Reset(); } public double TimeLeft { get { return _timeout_s - TotalSeconds; } } } } 

I implemented this to turn on the air conditioning with SMS (yes, I live in a hot country). It works. Please feel free to use any of these codes.

Enjoy.

+2
source share

Microsoft provides a pretty decent example of VB.Net in the Knowledge Base article, " How to Access Serial and Parallel Ports Using Visual Basic.NET ." I'm not sure if your phone is returning, however, if you change the buffer cycle in the example, you can at least print the answer:

 MSComm1.Output = "AT" & Chr(13) Console.WriteLine("Send the attention command to the modem.") Console.WriteLine("Wait for the data to come back to the serial port...") ' Make sure that the modem responds with "OK". ' Wait for the data to come back to the serial port. Do Buffer = Buffer & MSComm1.Input Console.WriteLine("Found: {0}", Buffer) Loop Until InStr(Buffer, "OK" & vbCrLf) 
0
source share

GSMComm is a C # library that allows you to easily interact with your GSM mobile phone in text or PDU mode. (The site also has a bunch of test utilities)

0
source share

Working with a GSM modem to send SMS has never been a good idea as such. Here is a checklist to make sure your SMS is sent correctly.

  • You send SMS in text mode. Try sending it in PDU mode.
  • Try this library http://phonemanager.codeplex.com/
  • Change SMSC number before sending SMS, if so, make sure SMSC is correct.
  • Also make sure that your SIM card has enough credits so that you can send outgoing SMS.
  • Check the status of the network , especially when you send SMS from your program. This can be a problem.

I recommend that you release the Lite version of the NowSMS gateway , which is free and allows you to work with a GSM modem very constantly. NowSMS will provide you an api abstraction over the GSM modem connection, so you just need to call Http Api from the NowSMS gateway, rest will depend on the NowSMS gateway.

First of all, if your end users will remain connected to the Internet while using your application or if your application is based on the Internet and hosted via the Internet, I highly recommend that you opt out of the GSM modem option and opt for reliable Http SMS gateway service providers .

-one
source share

All Articles