FXT009, adl_smssend and waiting for confirmation problem


#1

Hi All,

I currently have an FXT009 and I am monitoring the 2 GPIO’s (GPIO21 and GPIO25) for change of state. Upon change of state I am sending a text message to a list of recipients. This is working except when both GPIO states change together. When this happens the first one to initiate the sms works, the 2nd one stops, no errors, no sms sent, nothing.

Here are my code examples.

sms service subscription:

SMS_hndl = adl_smsSubscribe((adl_smsHdlr_f) SMS_hndlr, (adl_smsCtrlHdlr_f)  SMS_cntrl_hndlr, ADL_SMS_MODE_TEXT);

(ignore SMS_hndlr in this instance as this is used for received messages)

GPIO21;

adl_smsSend(SMS_hndl, phonenumber, "message", ADL_SMS_MODE_TEXT);

GPIO25;

adl_smsSend(SMS_hndl, phonenumber, "message", ADL_SMS_MODE_TEXT);

SMS_cntrl_hndlr ;

void SMS_cntrl_hndlr(u8 Event, u16 Nb)
{
	TRACE((5, "In SMS control handler"));
	switch (Event)
	{
	    case ADL_SMS_EVENT_SENDING_OK:
		       TRACE((5, "SMS sent ok"));
		break;
	    case ADL_SMS_EVENT_SENDING_ERROR:
		       TRACE((5, "SMS send failure, CMS error number, %d", Nb));
        break;
	    case ADL_SMS_EVENT_SENDING_MR:
		       TRACE((5, "SMS sent ok, message reference is, %d", Nb));
		break;
	}
}

Now, if GPIO21 and GPIO25 change state at the same time, they both do the adl_smsSend which goes to the hndl then the cntrl_hndlr which checks for the returned messages OK followed by ERROR or MR. The first adl_smssend works, the second one just stops, no errors, nothing (I assume because the first one is currently in process and therefore it can’t start it’s send process).

So, the question I have is how can I check that an adl_smsSend has already been started so that when another one wants to start it will wait for the cntrl_hndlr to receive the ERROR or MR messages BEFORE going to the hndl to send the message?

I think that I need to check the response in the cntrl_hndlr function from the GPIO21 and GPIO25 functions, is this even possible? (I have tried various ways to do this, including inline waits (while, timer wait, etc), setting global variables, etc, but in all cases the result is the same so far.

If the answer is that my code order is incorrect, that is fine, just please give me examples so that I can re-order the code appropriately.

thanks in advance


#2

Continuing on from https://forum.sierrawireless.com/t/error-sending-more-than-one-sms/3151/1

You aren’t checking the result returned by adl_smsSend - so how can you say, “no errors”?!

Correct.

Your system needs to keep a record of its State - hence the suggestion to implement this as a State Machine.


#3

I don’t think that’s correct; you get:

  • Either ERROR;
  • Or OK and MR

And it’s not documented whether OK follows MR, or vice-versa - hence the recommendation to wait until you have received both: https://forum.sierrawireless.com/t/error-sending-more-than-one-sms/3151/1


#4

i understand this. but please have a look at following code with state machine,

#include "adl_global.h"
#include "generated.h"
s32 QueueHandle;
s8 SMS_hndl;
ascii *smstel;
	char *result = NULL;
	int i = 0;
	ascii number [14];
	ascii text [100];

static bool flag = 0;

typedef enum { push2Q, read4mQ, sendtext, wait4rOK } estates;
estates state = push2Q;

bool SMS_hndlr(ascii * SmsTel, ascii * SmsTiSmeOrLength, ascii * SmsText)
{
	ascii *tel = NULL;
	 tel = (ascii*) adl_memGet((wm_strlen(SmsTel) + wm_strlen(SmsText) +2));
	 	wm_strRemoveCRLF(tel, SmsTel, wm_strlen(SmsTel));
	 	wm_strcat(tel, ",");
	 	wm_strcat(tel, SmsText);
	 	wm_strRemoveCRLF(tel, tel, wm_strlen(tel));
	 	 TRACE((1, SmsTel));
	 		 TRACE((1, tel));
while (1)
{
	 switch (state)
	 {
	 case push2Q:
		 TRACE((1, "in push2Q function"));
		 adl_queuePushItem ( QueueHandle, tel);
		 adl_queuePushItem ( QueueHandle, "+447412334056");
		  state = read4mQ;
		 break;
	 case read4mQ:
		 TRACE((1, "in read4mQ function"));
	        smstel = (ascii*) adl_queuePopItem ( QueueHandle );
	        TRACE((1, smstel));
	        result = strtok( smstel, "," );
	        		while( result != NULL ) //hsdkhg, ghsfdgdfsk, kjsdhslkdfg, sdhfsghlfdg
	        		{
	        			i++;
	        			if(i == 1)
	        			wm_strcpy(number, result);
	        			else if(i == 2)
	        			wm_strcpy(text, result);
	        			result = strtok( NULL, "," );
	        		}
	         if (result == NULL)
	        	 {
	        	   state = sendtext;
	        	 }
		 break;
	 case sendtext:
		 TRACE((1, "in sendtext function"));
		 if (wm_strlen(number) == 13)
		 {
			 adl_smsSend(SMS_hndl, number, text, ADL_SMS_MODE_TEXT);
			 state = wait4rOK;
		 }
		break;
	 case wait4rOK:
		 TRACE((1, "in wait4rOK function"));
		 if (flag == 1)
			 {
			 	 state = read4mQ;
			 }
		 else
			 {
			 state = wait4rOK;
			 }
		break;
	 }
}
//adl_memRelease(tel);
	return TRUE;
}

void SMS_cntrl_hndlr(u8 Event, u16 Nb)
		 {
		 	TRACE((5, "In SMS control handler"));
		 	switch (Event)
		 	{
		 	    case ADL_SMS_EVENT_SENDING_OK:
		 		       TRACE((5, "SMS sent ok"));
		 		       flag = 1;
		 		break;
		 	    case ADL_SMS_EVENT_SENDING_ERROR:
		 		       TRACE((5, "SMS send failure, CMS error number, %d", Nb));
		         break;
		 	    case ADL_SMS_EVENT_SENDING_MR:
		 		       TRACE((5, "SMS sent ok, message reference is, %d", Nb));
		 		break;
		 	}
		 }
void main_task(void)
{
	SMS_hndl  = adl_smsSubscribe((adl_smsHdlr_f) SMS_hndlr,	(adl_smsCtrlHdlr_f)  SMS_cntrl_hndlr, ADL_SMS_MODE_TEXT);
	QueueHandle = adl_queueSubscribe ( ADL_QUEUE_OPT_FIFO );
}

can you please tell me whats wrong in above state machine implementation?

Thanks


#5
while (1)

#6

with while(1):
it directly goes to

function and reboots the modem

without while(1):
it just goes to

and thts it.

case push2Q:
			 TRACE((1, "in push2Q function"));
			 adl_queuePushItem ( QueueHandle, tel);
			 adl_queuePushItem ( QueueHandle, "+447412334056");
			  state = read4mQ;
			 break;

as i am asking to go to read4mQ state but its not going into that state, why?


#7

You must not have an infinite loop in an Event Handler :exclamation:

An Event Handler is called by the system when an Event occurs; it must handle that event, and then return.

If a Handler doesn’t return, it hangs the system - until the Watchdog causes a reboot.


#8

ok I tried this, please have a look.
I am still confused why the state in case push2Q: is not changing to state = read4mQ; ?

void statemachine (ascii *tel)
{
	TRACE((1, tel));
	switch (state)
		 {
		 case push2Q:
			 TRACE((1, "in push2Q function"));
			 adl_queuePushItem ( QueueHandle, tel);
			 adl_queuePushItem ( QueueHandle, "+447412334056");
			  state = read4mQ;
			 break;
		 case read4mQ:
			 TRACE((1, "in read4mQ function"));
		        smstel = (ascii*) adl_queuePopItem ( QueueHandle );
		        TRACE((1, smstel));
		        result = strtok( smstel, "," );
		        		while( result != NULL ) //hsdkhg, ghsfdgdfsk, kjsdhslkdfg, sdhfsghlfdg
		        		{
		        			i++;
		        			if(i == 1)
		        			wm_strcpy(number, result);
		        			else if(i == 2)
		        			wm_strcpy(text, result);
		        			result = strtok( NULL, "," );
		        		}
		         if (result == NULL)
		        	 {
		        	   state = sendtext;
		        	 }
			 break;
		 case sendtext:
			 TRACE((1, "in sendtext function"));
			 if (wm_strlen(number) == 13)
			 {
				 adl_smsSend(SMS_hndl, number, text, ADL_SMS_MODE_TEXT);
				 state = wait4rOK;
			 }
			break;
		 case wait4rOK:
			 TRACE((1, "in wait4rOK function"));
			 if (flag == 1)
				 {
				 	 state = read4mQ;
				 }
			 else
				 {
				 state = wait4rOK;
				 }
			break;
		 }
}

bool SMS_hndlr(ascii * SmsTel, ascii * SmsTiSmeOrLength, ascii * SmsText)
{
	ascii *tel = NULL;
	 tel = (ascii*) adl_memGet((wm_strlen(SmsTel) + wm_strlen(SmsText) +2));
	 	wm_strRemoveCRLF(tel, SmsTel, wm_strlen(SmsTel));
	 	wm_strcat(tel, ",");
	 	wm_strcat(tel, SmsText);
	 	wm_strRemoveCRLF(tel, tel, wm_strlen(tel));
	 	 TRACE((1, SmsTel));
	 		 TRACE((1, tel));
 statemachine (tel);
adl_memRelease(tel);
	return TRUE;
}

Please note, in the above code, I have removed the while loop.

thanks