FCM DataHnadler again


#1

Dear OAT forum members,

After a month of reading PDF manuals(adl, WIP, Using FCM flow …), I started designing my own OpenAT app. It should do next:
-MicroCPU send at command on serial port(UART1), OAT app parse command and
-Create TCP/IP connection to server( this is working part( GPRS and etc is OK)).
-Send and recive data from server.

Flow in my app:
-Open and connect to GPRS. It’s working.
-Connect to server as TCP client, ok working.
-When recive WIP_CEV_OPEN event subscribe to FCM Flow.
-When FCM subscribed switch to data mode.( This is point where my app is in trouble)
–app switches to data mode and I enter some data to terminal, and nothing hapends until I send +++,
then app sends data from DataHandler on FCM, data that I have entered.( and after that app is in at mode). There is no my traces that indicate that my app reaches DataHandler and on the other hand after +++ it prints what i entered. I don’t get the picture from theese manuals what could be wrong.

-My question is how to handle * Data in DataHandler. How to use recive buffers(Credits). What am I doing wrong. Please help.

Best regards, Nik


#2

Why do you say “again”?
If you have a previous thread in mind, then provide a link to it!

It’s impossible to say, as you haven’t actually shown what you are doing!

it’s simply a pointer to the data that’s been received!

Credits are to do with sending - not receiving!

If you’re happy that your GPRS is OK, then I suggest that you set that aside for now, and just do a really simple app that just uses FCM; eg, to receive data from a UART, and echo it back to the same UART


#3

Dear Awneil,

In case of receiving data from FCM flow, ‘credits’ indicates the number of data blocks recived and threated by the embedded app. Please note that whenever data is erecieved on FCM flow, the FCM Data Handler is inwoked . . . From Using FCM flow in an OpenAT application(WM_ASW_OAT_APN_022-001). Adl has 5 buffers for storing data. How to reach them?

That I understand, but I saw that you posted what is Block. I’ll post code of my App just to make it cleaner (now is Spaghetti) :smiley:.

At this point what I recive in DataHandler(* Data, DataLen) should get on same uart with adl_fcmSendData(Handle, Data, DataLen).
Is that correct?


#4

You don’t “reach” them - they are purely internal to FCM.
FCM delivers the data to your app by calling your Data Handler, and giving you a pointer to the data.

So where’s the problem?

You’ll need to provide a link to the actual post - that makes no sense without the context!

That alone could be the cause of your problems!

Again, start from scratch with a simple app that simply receives and sends data using FCM.

Only if that’s the way that your application has configured it!
(in the FCM subscruiption).


#5

Here are my Control and Data handler:

bool CTRLHdlr( adl_fcmEvent_e Ev) {
	switch (Ev) {
		case ADL_FCM_EVENT_FLOW_OPENNED:{
			TRACE((1,"FCM opened"));
			adl_fcmSwitchV24State(FCMHindl, ADL_FCM_V24_STATE_DATA);
			break;}
		case ADL_FCM_EVENT_V24_DATA_MODE:{
			TRACE((1,"Data mode"));
			break;
		}
		case ADL_FCM_EVENT_V24_AT_MODE:{
			TRACE((1,"At mode"));
			adl_fcmSwitchV24State(FCMHindl, ADL_FCM_V24_STATE_AT);
			break;
		}
		case ADL_FCM_EVENT_MEM_RELEASE:
			TRACE((1,"Mem release"));
			break;

	}



	return TRUE;
}

ascii * tempbuff;
u16 templen=0;
s8 fcmsendstate, ssret;
ascii result;


bool DATAHdlr(u16 DataLen, u8 * Data){
	{
	   adl_atSendResponse(ADL_AT_RSP,"IN TO DATA MODE:");
	   ascii NewText[20],txt[20];
	   u16 i;
	   result=*Data;

	   for ( i = 0; i < DataLen; i++ ){
	      if ( Data [ i ] == '~' ){
	         adl_fcmUnsubscribe(FCMHindl);
	      } else {
	         txt[i]=Data[i];
	         wm_sprintf ( NewText, "%c", txt[i] );

	         adl_atSendResponse(ADL_AT_UNS, NewText);//to send received data and display using uart1.
	         //adl_fcmSendData ( FCM_Handler, NewText, DataLen );
	      }
	   }
	   return TRUE;
	}
}

Why only when I enter +++ in Hyperterminal only then get out like this(I enter ana )

IN TO DATA MODE:IN TO DATA MODE:IN TO DATA MODE:IN TO DATA MODE:IN TO DATA MODE:                                                                                
IN TO DATA MODE:                
OK  
ana

I get feeling like my app don’t reach data handler until is switched to at mode.

Sorry to bodder you.
Nik


#6

But your data handler contains calls to adl_atSendResponse - doesn’t it?

As should be obvious from the name - adl_atSendResponse - this is for sending stuff in AT mode - isn’t it?!


#7

Awneil,

Thank’s again. Now it is.


#8

https://forum.sierrawireless.com/t/fcm-newby/4115/2


#9

Awneal,

As, You said i managed to write only FCM that sends data back to same uart and code is(‘A’ is terminator):

bool DataHandler(u16 DataLen, u8 * Data){
	int i = 0;
	u16 var;
	dataduzina = DataLen;

	for (var = 0; var < dataduzina+1; var++) {
		if((*(Data+var))!='A'){
		dataniz[var] = *(Data + var);
		i = 0;
		}
	}
	rezultatslanja = adl_fcmSendData(FCMHandle, dataniz, dataduzina);
	i = 1;
	return TRUE;
}

And it works.
Now I have WIP plugin app witch should send data from uart to TCP socket, and I can’t manage that.
App works like this:
First i connect to gprs. Then create socket, when i get WIP_CEV_OPEN subscribe to FCM. ADL_FCM_EVENT_FLOW_OPENED switch to data mode.
and then cannot send data with wip_write to socket from data handler.

Please some guides how to manage this problem. Again thanks
code:

static void tcpevh( wip_event_t *ev, void *ctx) {

  switch( ev->kind) {
  chnl = ev->channel;
  case WIP_CEV_OPEN: {
    wip_debug ("[SAMPLE] Connection established successfully\n");
    adl_atSendResponse(ADL_AT_RSP,"\r\nOtvorena\r\n");
    if ((adl_fcmIsAvailable(ADL_FCM_FLOW_V24_UART1))){
    	wip_debug("availabale uart1\n");
        adl_atSendResponse(ADL_AT_RSP,"\r\nUart1 free\r\n");
		FCM_Handle = adl_fcmSubscribe(ADL_FCM_FLOW_V24_UART1, DTM_FCM_Ctrl_Handler, DTM_FCM_Data_Handler);
        wip_debug("FCM: %i\n", FCM_Handle);
    }
    break;
  }
  case WIP_CEV_READ: {
	  wip_debug("wip cev read\n");
	  bprimljeno = wip_read(socket, rcv_buffer, RCV_BUFFER_SIZE);
	  wip_debug("Bajtova primljeno: %d", bprimljeno);

	  adl_fcmSendData(FCM_Handle, rcv_buffer, 100);
	  break;
  }
  case WIP_CEV_WRITE: {
	  wip_debug("wip cev write\n");
    break;
  }
  case WIP_CEV_ERROR: {
    wip_debug( "[SAMPLE] Error %i on socket. Closing.\n", 
               ev->content.error.errnum);
    wip_close( ev->channel);
    break;
  }
  case WIP_CEV_PEER_CLOSE: {
    wip_debug( "[SAMPLE] Connection closed by peer\n");
    wip_close( ev->channel);
    break;
  }
  default:
	  break;
  }
}

bool DTM_FCM_Ctrl_Handler(u8 fcmev){

TRACE((1,"Event koji je primljen: %d", fcmev));
	switch (fcmev) {

		case ADL_FCM_EVENT_FLOW_OPENNED:{
			// switching to data mode ...
			TRACE((1,"switch to data mode."));
			wip_debug("FCMCTRLHDLR: switching to data mode\n");
			adl_fcmSwitchV24State(FCM_Handle, ADL_FCM_V24_STATE_DATA);
		    adl_atSendResponse(ADL_AT_RSP,"\r\nOtvoren FCM \r\n");
			wip_debug("datamode\r\n");
			break;
		}
		case ADL_FCM_EVENT_V24_DATA_MODE:{
			TRACE((1,"FCMEV: Data mode\r\n"));
			wip_debug("FCMCTRLHDLR: switched to datamode, trying to write\r\n");
			//bposlato = wip_write(socket, snd_buffer, sizeof(snd_buffer));
			//niz = adl_memGet(sizeof(snd_buffer));
			//wm_memcpy(niz, snd_buffer, sizeof(niz));
			//resp =  adl_fcmSendData(FCM_Handle, niz, sizeof(niz));
			wip_debug("poslato bajtova: %d\n", bposlato);
			//adl_memRelease(niz);
			 //adl_atSendResponse(ADL_AT_RSP,"\r\nData mode\r\n");
			 //adl_fcmReleaseCredits(FCM_Handle,5);
			break;
		}
		case ADL_FCM_EVENT_FLOW_CLOSED:{
			wip_debug("FCM flow closed\n");
			break;
		}

		case ADL_FCM_EVENT_RESUME:{
			wip_debug("FCM event resume\n");
			break;
		}

		case ADL_FCM_EVENT_V24_AT_MODE_EXT: {
			wip_debug("Switching to AT mode");
		    adl_atSendResponse(ADL_AT_RSP,"\r\nSwitching to AT mode\r\n");
			adl_fcmSwitchV24State(FCM_Handle, ADL_FCM_V24_STATE_AT);
			adl_fcmUnsubscribe(FCM_Handle);

			break;
		}

		case ADL_FCM_EVENT_MEM_RELEASE: {
			wip_debug("adl fcm memrealease\n");
			adl_atSendResponse(ADL_AT_RSP, "Release\n");

			break;
		}
	}
return TRUE;
}


bool DTM_FCM_Data_Handler(u16 DataLen, u8 * Data){
	int i = 0;
	u16 var;
	dataduzina = DataLen;

	for (var = 0; var < dataduzina+1; var++) {
		if((*(Data+var))!='A'){
		dataniz[var] = *(Data + var);
		i = 0;
		}
	}
	//rezultatslanja = adl_fcmSendData(FCMHandle, dataniz, dataduzina);
	bposlato = wip_write(socket, dataniz, dataduzina);
	i = 1;
	return TRUE;
}

#10

Have you looked at the WIP samples?


#11

Yes I have, and i made it work when I dont mess with FCM(data handler). Is it necessary to write a outer function from witch I call wip_write? Or how to handle Data handler?
P.S.
And another, when running tcp client example(modified for my needs), in Traces there are two FCM handlers. First one, for witch I think is from GPRS, and i the second witch is from my FCM subscribe?


#12

It’s best to keep things separate:

  • FCM need not know or care where the received data goes to;
  • WIP need not know or care where the data to transmit comes from

In computer science talk, this is known as “coupling” - and it is generally best to have the separate parts of your system as loosely “coupled” as possible.

One way to do this is to have FCM just write its received data to a buffer, and WIP read its data for transmission from the same buffer.

A common approach is to use a Circular Buffer; this is a standard computing technique - google it.


#13

Ok, if i make separate FCM and WIP, then I need some kind of semaphore or state diagram.
So as appeal, is there some example that ilistrate it.

I have working ring buffer, but googling for openat bring us back here, on this forum.


#14

You are now talking about general design techniques - these things are not specific to Open-AT!

The operating principles of a ring buffer (or “circular buffer”) are the same whether implemented on an 8-bit microcontroller, a PC, or Open-AT

Similarly for state machines and semaphores.


#15

I think you should declare a periodic timer in which you run the FCM in the main function like a simple task, declare a global variable in which you save what you need then you trigger the WIP_CEV_READ case in which you declare wip_write(send the global variable).


#16

What do you mean by, “run the FCM” :question:

FCM is already event-driven, and generates its own events - there is no need to add a timer!

No.
You don’t trigger the event; the event is triggered by WIP - you repsond to the event!


#17

Yes you are right awneil, he doesn’t have to add a timer, i thought that paunik had to interrogate a device and that s why i brought up with the timer idea.

And I don’t agree you response regarding case WIP_CEV_READ. This case is triggered by some data received form GPRS. If no data comes from GPRS then WIP_CEV_READ is not triggered. WIP handles these events but i can trigger the WIP_CEV_READ if i run a server and then i send some data to the modem.


#18

OK, yes.

What I should have said, then, was: “You don’t trigger the event in your Open-AT application; the event is triggered by WIP - your application repsond to the event!”

Sorry if that wasn’t clear.