2

I developed a C# application for reading calls from GSM Modem. I used a timer to read the port regularly and notify me when there is a incoming call.

Now i am trying to use another timer which will write AT+CSQ -To know the signal quality, on the port and read the port for the quality value. In both the timers i used regular expressions to match and separate the data i need. Now the problem is that only my timer2 which is reading the signal quality is only working but not timer reading for incoming calls.

Timer reading signal strength:

private void tmr_sig_quality_Tick(object sender, EventArgs e)
    {
        if (port.IsOpen)
        {
            port.WriteLine("AT+CSQ");
            string s= port.ReadExisting();
            var match= Regex.Match(s,@"\+CSQ: (\d+),(\d+)");
            if (match.Success)
            {
                progressBar1.Value = int.Parse(match.Groups[1].Value);
            }

        }
    }

Timer reading incoming calls:

      private void timer1_Tick(object sender, EventArgs e)
       {
                s = port.ReadExisting();

                var match = Regex.Match(s, "RING[^\\+]*\\+CLIP:\\s*\"(?<phone>[^\"]*)\",(\\d+),\"([^\"]*)\",(\\w*),\"(\\w*)\",(\\w*)");

                if (match.Success && s.Contains("RING"))
                {
                    incall_status.Text = "Incoming Call...." + match.Groups["phone"].Value;
                    incall_status.Visible = true;
                }
        }

Why is this happening and solution please?

Shiridish
  • 4,942
  • 5
  • 33
  • 64
  • 1
    Why don't you have both in one single timer call? – Gavin Jul 30 '12 at 12:27
  • I have a typical problem here. I did that way but my progress bar does not show any thing. I used break points to see what my string has read and to my surprise it was reading correctly and my progress bar shows the status. But when i directly run my application, progress bar does not show anything. – Shiridish Jul 30 '12 at 12:43
  • You'll find that you cannot change the UI via a thread. If I recall correctly, timers use threads, so you need to use Invoke, i.e. http://stackoverflow.com/questions/661561/how-to-update-gui-from-another-thread-in-c – Gavin Jul 30 '12 at 12:52
  • Correct, the regular System.Timer cannot update the UI A DispachedTimer (if using WPF) (http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer.aspx) can update the UI, but it will also cause the UI to become sluggish if running a long task, such as polling a serial port. – Per Jul 30 '12 at 12:59

2 Answers2

2

Two major problems. First is ReadExisting(), that will always return an empty string. Except when you are debugging and stepping through the code line by line. That gives the modem enough time to send the response. But this won't work when you run at full speed, you'll need to make a blocking call that ensures your program waits long enough to get all the returned characters. Use ReadLine() instead.

Second killer problem is that you are mixing commands. Your tmr_sig_quality_Tick() method is likely to read whatever timer1_Tick() was supposed to read. You'll need to re-think this approach. Something like a queue of commands that doesn't advance until the response to a command is received.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • The first problem as you said with ReadExisting(), may be first time it would be empty, but atleast after 2 or 3 intervals of tick event execution there would be some response to read right? – Shiridish Jul 31 '12 at 08:46
  • No, you use WriteLine() before that and hope to get the response to that command. ReadExisting() will not give you that response, it returns an empty string. As I said, you need to re-think your approach. – Hans Passant Jul 31 '12 at 08:51
1

Not an actual answer to your question, but a general advice for communicating with a GSM modem:

Keep in mind that you have only one serial port, thus only one communication channel. A GSM modem can send spontaneous events, such as the RING, FAX, VOICE events, so there is no guarantee that when you write AT+CSQ the first reply is what you expect, i.e. the signal quality.

Having two timers like you're intending is not a good idea since you'll eventually end up with the response of one command in timer A when it was expected in B, because A read one of the spontaneous events...etc.

A much better and robust way is to have a worker thread that reads and interprets the incoming data and then distributes that in you application as needed. It can also handle the outgoing data. Use concurrent queues and some signaling mechanism (i.e. AutoResetEvent) for exchanging data with this thread, that way you get a cleaner interface to your hardware device and don't need to worry about timing and such in your application.

Per
  • 1,074
  • 6
  • 19