Hello.

You need to make your own "bicycle" by receiving / sending SMS messages. The snag is: I execute an AT command (sending an SMS in PDU format), but I don’t know how much the response will come. The algorithm is approximately as follows:

var sp = new SerialPort(); //производим настройку: устанавливаем скорость, биты данных, четность и т.п. sp.Open(); if(sp.IsOpen) { sp.Write("AT+CMGF=1\r"); sp.Write("AT+CMGS=118\r"); sp.Write("07919772099090F031000B811032547698F000080B68041C0435043D044F00200437043E0432044304420020042104350431043E04410442044C044F043D0020041F04350440043504390440043E002D0442043E04400433043E0432043504460020044704350440043D044B043C002004340435044004350432043E043C\x1A"); } 

should come back: " + CMGS: 158 " or + " CMS ERROR: error text " where 158 is in the range 0..255 (message index) how do I get into the mode of waiting for a response to the sent command.

Thank you in advance

PS if there is an example I will be very grateful.

Update

while it turns out something like this:

 public class SMS { public string Phone {get;set;} public string Message {get;set;} public DateTime Sent {get;set;} public DateTime? Delivery {get;set;} } public class GSMModem { //Строка куда будем записывать полученные данные private string response = string.Empty; private SerialPort sp = new SerialPort(); private Queue<SMS> outgoingMessages = new Queue<SMS>(); private Queue<SMS> sentMesssages = new Queue<SMS>(); public IsOpen { get { return sp.IsOpen; } } void Open() { sp.Open() if(IsOpen) { sp.DataReceived+=ReceivingData; } } void Close() { sp.DataReceived-=ReceivingData; } void ReceivingData(object sender, EventArgs e) { try { response = sp.ReadExisting(); if(response.Contains("+CMGS:")) { //в случае успешной отправки убираем сообщение //из очереди на отправку в отправленные сообщения var message = outgoingMessages.Dequeue() sentMesssages.Enqueue(message); } else if(response.Contains("+CMTI:")) { //Входящее сообщение } else if(response.Contains("+CUSSD:")) { //USSD запрос } } catch(Exception) {} finally {} } bool ExecuteATCommand(string atCommand) { bool result = false; if(IsOpen) { try { sp.DiscardInBuffer(); sp.DiscardOutBuffer(); sp.Write(atCommand + "\r"); result = true; } catch(Exception) {} finally {} } return result; } void SendMessage(string phone, string message) { var message = outgoingMessages.Peek() var pduMessage = new PDU.Encoding(message.Phone, message.Message); ExecuteATCommand("AT+CMGF=1") ExecuteATCommand("AT+CMGS="+pduMessage.Length.ToString()); ExecuteATCommand(pduMessage.ToString()); } } 

really I don’t know how to handle the situation when the modem didn’t respond to the command sent at all, i.e. "stuck". can someone tell me how to handle this situation

    1 answer 1

    Option 1

    Use the DataReceived event, which is called when the number of bytes specified in the ReceivedBytesThreshold property is ReceivedBytesThreshold .

     public void Communicate() { var sp = new SerialPort(); sp.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); //далее Ваш код настройки и отправки данных } private static void DataReceivedHandler( object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; string indata = sp.ReadExisting(); Console.WriteLine("Data Received:"); Console.Write(indata); } 

    It is important that the flow was not killed before the end of the communications you need. In particular, this option will be useful in a GUI application. Although the general recommendation for all options is to exchange with I / O devices in a separate thread, if you have a graphical interface. This will help eliminate the "hang" of the application.

    Option 2

    Make a blocking call to Read :

     sp.Read(buffer, 0, 4); // читаем 4 байта для примера 

    Minus - blocking call due to which the application will "hang" if it is executed in the main thread. This will cause a TimeoutException if the SerialPort ReadTimeout property is different from SerialPort.InfiniteTimeout and that time has passed.

    Option 3

    Check the value of the BytesToRead property in a loop:

     while (sp.BytesToRead == 0) { // ничего нет } // что-то пришло, делаем sp.Read(...) 

    In fact, an analogue of the previous version, only without the built-in implementation of the timeout.

    • It has already been outlined to use the standard DataReceived event, but a small question has arisen. In this global event, I will receive data and in accordance with the fact that it has come to trigger other events and accordingly process them (receive sms / delivery report, etc.) and how to process that nothing happened in ODA. time interval. for example, the piece of iron just hung ?! - Bald
    • Record somewhere the time of the last command and set the timer. If the answer came - turn off the timer. Otherwise, you can conclude that the piece of hardware is not responding. See the Timer class for an example. If you need more, then create a separate question. - Alexander Soloshenko September