Cellular driver NOT stable

@ BigFoot - We’ll take a look and see what we can find. I believe you can only add an image. But you can post code snippets that get syntax highlighted using the code tags.

@ John - ok, thank you! I await a reply about the problem! :slight_smile:

@ John - In the last 25 days I made a 24/24h and 7/7d test on the cellular driver (using the latest source code from bitbucket and an external power supply with 1.2A) without any issue (I talk about manage calls and SMSs).
So the errors I had were related to a lack of power supply!

Thanks for support

Good stuff.

I wish there was an option to realize that the power was insufficient, and raise an event or something meaningful…

@ Sprigo, njbuch, and BigFoot - I’ve made some more improvements to the cellular radio driver: https://bitbucket.org/ghi_elect/gadgeteer/src/94b2d85725c5115c87f3806b77a0e20eb912046c/Modules/GHIElectronics/CellularRadio/CellularRadio_43/CellularRadio_43.cs?at=master#

-Added LineSent and LineReceived events for debugging and tracing
-Added an overload to customize the PPP initialization commands
-Added an overload to customize the module power up commands
-Added an overload to wait for an expected response to SendATCommands
-Fixed setting the module state to off in the constructor
-Fixed a null reference exception when using multiple network modules

5 Likes

@ John - Well done, I have reviewed the code. Looks really promising… :clap:

Do you have more detailed instructions, or test code, that we can play with?

@ John - Great news. I’ll try to have a play with it this weekend.

@ njbuch - I don’t have any specific test code to release, but here’s some more detailed explanations:

LineReceived will be raised every time a line (some text ending in \r\n) is received. That text is not swallowed so other events will still be raised too. LineSent will be raised every time the driver writes out a line, usually in response to a function you call, but sometimes due to internal things. Think of both like a logging mechanism or a way to handle responses we do not. The second parameter to both is the line in question.

PowerUp now has an overload PowerUp(params string[] commands). Power() calls that with the old built in commands. What you pass to it is really up to you, but a good starting point is what we pass in to it from PowerUp().

Same thing with UseThisNetworkInterface(…, string expectedResponse, params string[] commands). The old UseThisNetworkInterface calls just pass “CONNECT” for expectedResponse and AT+CGDCONT=1,“IP”,"[APN]" and ATDT99**1# for commands.

bool SendATCommand(string atCommand, string expectedResponse, int timeout) has been added. As you would expect, it blocks until expectedResponse is received or the timeout expires. It returns true if the response was received, false if it timed out. Quick example: SendATCommand(“AT”, “OK”, 1000). It also does not swallow the response, so other events will still be raised. It only works with single lines though, so commands like sending an SMS will not work too well with this.

The constructor was always meant to ensure the module was off. It did this by writing AT and seeing if a response was received. If it was, it turned it off. That way you can be sure of the module state in ProgramStarted() and can initialize it as you wish. Until now, I forgot to terminate the test command with a newline, so the module response was never received and it would remain on after the constructor.

The null reference exception was the one BigFoot reported, I believe, when he had an ENC28 and the CellularRadio in his project. Use of the ENC28 would cause a null reference exception in CellularRadio because it made incorrect assumptions about it being the only created network module.

3 Likes

@ John - What a great work!! thanks a lot, I’ll try the new driver in the weekend.

@ John - I’m working hard on Cellular Radio driver because I’m trying to get the most reliability possible.

Working with the “standard” driver (I mean the driver as you provide, without source code changes) when an SMS is received raises the “SmsReceived” event.
Sometimes happens that the SMS received doesn’t raise the SmsReceived event (I wasn’t able to understand why, I need to investigate more).

Apart from that, requesting the list of SMS I get an exception in the DoWork() method during the elaboration of AT+CMGL response.
These are the details that I have:
[ul]The exception is a System.Exception, the message says that it “can’t convert to int32 or int64”[/ul]
[ul]The response elaborated is “1,“REC READ”,"+393434343434","","1505/08,08:39:11+8"”[/ul]

What I see of strange? First the SMS is stored as “REC READ” … but the “SmsReceived” event wasn’t raised.
And second (what I think has thrown the exception) the date format… I think that a slash is missing (and I don’t refer at Guns’n’roses guitarrist!)… I read “1505/08,08:39:11+8” but I think it should be “15/05/08,08:39:11+8”.

So the Exception I receive I think is thrown by these rows of driver’s code:

.Length >= 7)
                                                sms.Timestamp = new DateTime(int.Parse(parts[4].Substring(1, 2)) + 2000, int.Parse(parts[4].Substring(4, 2)), int.Parse(parts[4].Substring(7, 2)), int.Parse(parts[5].Substring(0, 2)), int.Parse(parts[5].Substring(3, 2)), int.Parse(parts[5].Substring(6, 2)));

It can’t compose a DateTime instance without having that slash (/)…

The question is: why the cellular radio module replies without that slash?

Any help is appreciated!

Thanks guys.

EDIT: I’m working with the last source code of Cellular Radio downloaded from bitbucket, but I had this exception also on previous versions.

I made some change at the source code of cellular radio…

  1. Manage the date format with a missing slash “1505/08,08:39:11+8” in AT+CMGL and AT+CMGR (this explains why I didn’t get the SmsReceived event raised)
//CMGL
if (parts[4].Length >= 7 && parts[5].Length >= 7) {
     if (parts[4].Split('/').Length == 1)
          sms.Timestamp = new DateTime(int.Parse(parts[4].Substring(1, 2)) + 2000, int.Parse(parts[4].Substring(3, 2)), int.Parse(parts[4].Substring(6, 2)), int.Parse(parts[5].Substring(0, 2)), int.Parse(parts[5].Substring(3, 2)), int.Parse(parts[5].Substring(6, 2)));
     else
          sms.Timestamp = new DateTime(int.Parse(parts[4].Substring(1, 2)) + 2000, int.Parse(parts[4].Substring(4, 2)), int.Parse(parts[4].Substring(7, 2)), int.Parse(parts[5].Substring(0, 2)), int.Parse(parts[5].Substring(3, 2)), int.Parse(parts[5].Substring(6, 2)));
}
//CMGR
if (parts[3].Length >= 7 && parts[4].Length >= 7) {
     if (parts[3].Split('/').Length == 1)
          sms.Timestamp = new DateTime(int.Parse(parts[3].Substring(1, 2)) + 2000, int.Parse(parts[3].Substring(3, 2)), int.Parse(parts[3].Substring(6, 2)), int.Parse(parts[4].Substring(0, 2)), int.Parse(parts[4].Substring(3, 2)), int.Parse(parts[4].Substring(6, 2)));
     else
          sms.Timestamp = new DateTime(int.Parse(parts[3].Substring(1, 2)) + 2000, int.Parse(parts[3].Substring(4, 2)), int.Parse(parts[3].Substring(7, 2)), int.Parse(parts[4].Substring(0, 2)), int.Parse(parts[4].Substring(3, 2)), int.Parse(parts[4].Substring(6, 2)));
}
  1. Add an event named “DoWorkException” that allows me to retrieve all details of exception and avoid to get uncontrolled exceptions … Probably someone prefers to get an uncontrolled exception that breaks the program execution, not me!

Code snippet:

/// <summary>
/// Represents the delegate used for the DoWorkException event.
/// </summary>
/// <param name="sender">The object that raised the event.</param>
/// <param name="ex">The exception thrown.</param>
/// <param name="line">The line that was being analyzed.</param>
public delegate void DoWorkExceptionHandler(CellularRadio sender, Exception ex, string line);

I can’t post the entire source code of cellular radio (too long), if you’d like to try these changes I can upload the .cs file and provide a link.

@ BigFoot - I’m not too sure why the module would send without the slash in the date. Does it happen consistently?