CoAP server/client
Antwort
04.01.17 15:01

Hello all,

I have a problem to setup a CoAP-server/client application. I hope that you can help me to solve this issue.

Later on I'll need a CoAP-server. Due to problems I started with a simple client request, but also got problems.

Short overview about the source code for the server:

  • WlanConnect_WEP_Open
  • PAL_initialize
  • PAL_socketMonitorInit
  • CoapServer_initialize
  • CoapServer_startInstance

Problem: do not get any client request... callback function is never called

For the client I just want to send an empty GET message.

  • WlanConnect_WEP_Open
  • PAL_initialize
  • PAL_socketMonitorInit
  • CoapServer_initialize
  • CoapServer_startInstance
  • CoapClient_initReqMsg
  • CoapSerializer_setup
  • CoapSerializer_setConfirmable
  • CoapSerializer_setCode
  • CoapClient_request

Problem: when calling CoapSerializer_setCode(&serializer_ptr, msg_ptr, code)  I got the return code RC_COAP_SERIALIZE_ERROR.

Without this function call a UDP message is sent (captured with wireshark) -> the CoAP-server does not answer.

Kind regards,

Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
05.01.17 16:29 als Antwort auf Manuel Bock.

Hello Manuel,

I will try to help you making some progress with your CoAP implementation.
Unfortunately you are dealing with different linked issues that I would recommend to handle separately.

CoAP-server implementation:

I would recommend to test your server for debugging purposes with the Firefox plugin Copper to make sure the CoAP request reaches the XDK.

CoAP-client:

You need to call the code serializer like this:
 

CoapSerializer_setCode(serializer_ptr, msg_ptr, Coap_Codes[COAP_GET]);


Please tell me if this is helpful.

Kind regards,
Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
06.01.17 09:25 als Antwort auf Manuel Cerny.

Hey Manuel,

thank you for your fast reply.

I have running a CoAP-server on an ubuntu machine and for testing I use wireshark and Copper. I checked the functionality of this CoAP-server(ubuntu) by using Copper.

CoAP-server:

The receive callback is still not called.

CoAP-client:

For the client I was able to set the code and to send a message. But it is still an UDP message... Have I forgotten something when creating the message? 

Maybe it is helpful for you if I post the code.

Start of my application:

  • initialization
  • task for server
  • timer for client
void appInitSystem(xTimerHandle xTimer)
{
    (void) (xTimer);

    init();

    // task for the CoAP-server
	if (xTaskCreate(startCoapServer, (const char * const ) "startCoapServer",TASK_STACK_SIZE,NULL, TASK_PRIORITY, &startCoapServerTask) != pdPASS)
	{
		assert(false);
	}

	// timer for the CoAP-client
	uint32_t Ticks = CONNECT_TIME_INTERVAL; // UINT32_C(10000)
	connectTimerHandle = xTimerCreate(
			(const char * const ) "connectServer", Ticks,
			TIMER_AUTORELOAD_ON, NULL, connectServer);

	if (connectTimerHandle != NULL)
	{
		if (xTimerStart(connectTimerHandle, TIMERBLOCKTIME) != pdTRUE)
		{
			assert(false);
		}
	}
}

The init() function:

  • wlanConnect() is similar to Lwm2mExampleClient but using WlanConnect_WEP_Open
void init(void)
{
	retcode_t rc = RC_OK;

	rc = wlanConnect();
	if (RC_OK != rc)
	{
		printf("Network init/connection failed %i \r\n", rc);
		return;
	}

	rc = PAL_initialize();
	if (RC_OK != rc)
	{
		printf("PAL init failed %i \r\n", rc);
		return;
	}

	PAL_socketMonitorInit();

	rc = CoapServer_initialize();
	if (RC_OK != rc)
	{
		printf("CoapServer init failed %i \r\n", rc);
		return;
	}
}

Task for starting the CoAP-server and callback function:

void startCoapServer(void * pvParameters)
{
    BCDS_UNUSED(pvParameters);

    retcode_t rc = RC_OK;

    rc = CoapServer_startInstance((uint16_t)5683, &coapReceiveCallback);
	if (RC_OK != rc)
	{
		printf("CoapServer start failed %i \r\n", rc);
		return;
	}
	printf("CoapServer start done %i \r\n", rc);
}
static retcode_t coapReceiveCallback(Msg_T *msg_ptr, retcode_t status)
{
	BCDS_UNUSED(msg_ptr);

	retcode_t rc = RC_OK;
	
	printf("CoapReceiveCallback with status %i \r\n", status);
	
	return rc;
}

CoAP-client and callback functions:

static void connectServer(xTimerHandle xTimer)
{
    BCDS_UNUSED(xTimer);

    retcode_t rc = RC_OK;

    // set destination address and port
	Ip_Address_T addr;
	Ip_convertOctetsToAddr(10, 42, 0, 1, &addr);
	Ip_Port_T port = Ip_convertIntToPort(5683);
	Msg_T* msg_ptr;

	// initialize request message
	rc = CoapClient_initReqMsg(&addr, port, &msg_ptr);
	if (RC_OK != rc || msg_ptr == NULL)
	{
		printf("CoapClient_initReqMsg failed %i \r\n", rc);
		return;
	}

	// setup serializer
	CoapSerializer_T serializer_ptr;
	CoapSerializeType_T type;
	type = REQUEST;
	rc = CoapSerializer_setup(&serializer_ptr, msg_ptr, type);
	if (RC_OK != rc)
	{
		printf("CoapSerializer_setup failed %i \r\n", rc);
		Msg_close(msg_ptr);
		return;
	}

	// set message code
	rc = CoapSerializer_setCode(&serializer_ptr, msg_ptr, Coap_Codes[COAP_GET]);
	if(rc != RC_OK)
	{
		printf("CoapSerializer_setCode failed %i \r\n", rc);
		return;
	}

	CoapSerializer_setConfirmable(msg_ptr, true);

	static Callable_T SentCallable;
	Callable_T * Callable_pointer;
	Callable_pointer = Callable_assign(&SentCallable, coapClientSentCallback);
	if (Callable_pointer == NULL)
	{
		printf("Failed Callable_assign\r\n ");
		return;
	}

	// send request
	rc = CoapClient_request(msg_ptr, &SentCallable, coapClientRespCallback);
	if (RC_OK != rc)
		{
			printf("CoapClient_request failed %i \r\n", rc);
			return;
		}
	printf("CoapClient_request done \r\n");
}

static retcode_t coapClientSentCallback(Callable_T *callable_ptr, retcode_t status)
{
	retcode_t rc = RC_OK;

	printf("coapClientSentCallback with status %i \r\n", status);

	return rc;
}

static retcode_t coapClientRespCallback(CoapSession_T *coapSession, Msg_T *msg_ptr, retcode_t status)
{
	retcode_t rc = RC_OK;

	printf("coapClientRespCallback with status %i \r\n", status);

	return rc;
}

Kind regards,

Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
10.01.17 17:17 als Antwort auf Manuel Bock.

Hello Manuel,

Your code looks quite good. I only would recommend one short change. We have often faced issues with stack sizes in operating tasks, because you really need to care about the correct stack size. Thus I would start the server instance with a timer task. Please note, with xTaskCreate() you can set the stack depth, witch is not equal to the stack size. But this should not matter if the server is running or not. I will further analyse your code and get back to you during the next days.

Meanwhile, are you in possession of a Jlink adapter to step through your code? I really recommend a Jlink to make sure that the ReceiveCallback is not called at all. Printfs can be deceptive sometimes in embedded development.

That you receive an UDP message of the client is completely correct because CoAP is operating on the application layer and is based on the transmission protocol UDP.

Kind regards,
Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
12.01.17 07:30 als Antwort auf Manuel Cerny.

Hello Manuel,

thanks for your reply.
Starting the server instance in a timer task does not help. Nothing changed. Additionally I implemented an "echo" in the receive callback of the server. But I still get no response. An example for a server application would be nice.

I ordered a debug probe.

I know that CoAP is based on UDP but wireshark distinguishes between UDP and CoAP. The client is working! The message was not correct. I thought that it is possible to send an empty message like the "ping" function in the firefox copper plugin. Do you know solution to send an empty message?

Best regards,

Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
13.01.17 16:51 als Antwort auf Manuel Bock.

Hello Manuel,

I have further analysed your CoAP server code.
I was able to send a CoAP message to a XDK CoAP server with copper and your code. Thus your implementation is completely correct.

I guess the issue is not caused by the CoAP implementation. Did you make sure that are connected to the same network as the XDK with your laptop/computer, when you send the CoAP messages? In other words, is the XDK reachable?

To check if the XDK is reachable i would suggest to use the command line of your operating system and ping it.

I recommend to include NetworkConfig_SetIpDhcp(0) before the connection Wi-Fi connection function. This will ensure that DHCP is activated. 

Additionally I would ask you to print out the assigned IP of the XDK and compare it with the IP of your computer.

Please tell me, if this is helpful.

Kind regards,
Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
14.01.17 17:28 als Antwort auf Manuel Cerny.

Hello Manuel,

I don't understand why it is working for you...

DHCP is/was always activated. The IP address is printed out and I successfully pinged the XDK. Also the CoAP-client is working.

I tried two scenarios: First a WEP secured hotspot on my laptop. Second a WPA2 secured network. In both cases the CoAP-server does not respond. Also the server does not respond if the client is switched off/commented out.

Again the code:

void appInitSystem(xTimerHandle xTimer)
{
    (void) (xTimer);

    init();

    // TIMERBLOCKTIME                  UINT32_C(0xffff)
    // TIMER_AUTORELOAD_ON     UINT32_C(1)
    // timer for the CoAP-server
    uint32_t Ticks = UINT32_C(1000);
    startServerTimerHandle = xTimerCreate(
			(const char * const ) "startServer", Ticks,
			TIMER_AUTORELOAD_ON, NULL, startServer);

	if (startServerTimerHandle != NULL)
	{
		if (xTimerStart(startServerTimerHandle, TIMERBLOCKTIME) != pdTRUE)
		{
			assert(false);
		}
	}
}

I put the start of the server in a timer task and in the following code snippet the task itself:

static void startServer(xTimerHandle xTimer)
{
	BCDS_UNUSED(xTimer);

	if(serverStarted == 0)
	{
		// start server
		retcode_t rc = RC_OK;

		rc = CoapServer_startInstance((uint16_t)5683, &coapReceiveCallback);
		if (RC_OK != rc)
		{
			printf("CoapServer start failed %i \r\n", rc);
			return;
		}
		printf("CoapServer start done %i \r\n", rc);

		serverStarted = 1;
	}
	else
	{
		printf("CoapServer running \r\n");
	}

}

And the receive callback function:

static retcode_t coapReceiveCallback(Msg_T *msg_ptr, retcode_t status)
{
	retcode_t rc = RC_OK;
	
	printf("CoapReceiveCallback with status %i \r\n", status);

	static Callable_T SentCallable;
	Callable_T * Callable_pointer;
	Callable_pointer = Callable_assign(&SentCallable, coapClientSentCallback);
	if (Callable_pointer == NULL)
	{
		printf("Failed Callable_assign\r\n ");
	}
	rc = CoapServer_respond(msg_ptr, &SentCallable);
	if (rc != RC_OK)
	{
		assert(false);
	}

	return rc;
}

The printout after the XDK is booted is always:

 INFO | XDK DEVICE 1:   Ip address of the device 192.168.2.115 
 INFO | XDK DEVICE 1:  CoapServer start done 0 

I hope you have another idea...

Best regards,

Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
16.01.17 23:28 als Antwort auf Manuel Bock.

Hello Manuel,

I am using your code in the exactly same manner as you did. I only added the following code lines to coapReceiveCallback() to display the received payload into the workbench console. 
 

CoapParser_T parser;
uint8_t* payload;
uint8_t payloadlen;

CoapParser_setup(&parser, msg_ptr);
CoapParser_getPayload(&parser,&payload,payloadlen);

printf("Incoming Coap request: %s \n\r",payload);


I would recommend to focus on the code you provided in the second post, because I can ensure that it is working correctly.

As I mentioned in the last post, I assume this issue is related to something else in your setup. Therefore I would like to get more into detail about the whole configuration. Especially the IP range of your networks, subnetmasks and the IP of your notebook.

Just to make sure, the IP of your XDK always gets assigned to 192.168.2.115? I guess it would be more likely to get different IPs depending on if you connect the XDK to the hotspot on your laptop or to the secure accesspoint.

Kind regards,
Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
17.01.17 09:46 als Antwort auf Manuel Cerny.

Hello Manuel,

I added the code lines from your last post in the receive callback. Nothing changed...

You are right! The XDK doesn't get always get the same IP address. In the following my network setup for the local hotspot on my laptop and the WLAN:

Hotspot
subnetmask: 255.255.255.0
IP address laptop: 10.42.0.1
IP address XDK: always 10.42.0.117 (always)

WLAN
subnetmask: 255.255.255.0
IP address laptop: 192.168.2.110
IP address XDK: 192.168.2.115 (always)

Regardless of the network, I can ping the XDK and the CoAP-client communication always works.

Best regards,
Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
17.01.17 15:54 als Antwort auf Manuel Bock.

Hello Manuel,

Manuel is on a business trip this afternoon, thats why I reply to your issue.

Your configuration looks good. It confirms that your issue is not related to DHCP. I tested your code  with all possibilities of execution (timer, operating task etc.). My conclusion is that startCoapServer() works fine if it is called as function directly into appInitSystem(). Just as if it is called as a timer task that runs only one time.

In contrast if it is called with an periodic timer task or operating task it always fails with an assertion.

Therefore I would ask you to set up the CoapServer implementation once again in a new clean XdkApplicationTemplate project. Please use the code you provided in your second post and only call startCoapServer() to start the server as normal function without any timer task in appInitSystem().

If it is still not working, I would ask you to post your email address in here that I can contact to analyse your complete application setup and compare it to mine.

Kind regards,
Franjo

0 (0 Stimmen)
RE: CoAP server/client
Antwort
18.01.17 09:22 als Antwort auf Franjo Stjepandic.

Hello Franjo,

I set up a new clean project with the XdkApplicationTemplate. I implemented only the CoAP-server with a single function call. Additionally I added the parser from Manuel's last post. But I still get no response.

My email address is bock.manuel AT gmail . com.

I hope that we will find a solution.

Kind regards,
Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
20.01.17 09:32 als Antwort auf Manuel Bock.

Hello Manuel and dear XDK community members,

Manuel send his CoapServer application to me and I was able to find the issue which causes the mentioned issues.

The issue is mainly caused by the following code line:

rc = CoapServer_startInstance( (uint16_t) 5683, &coapReceiveCallback);

The used port has to be converted via Ip_convertIntToPort() before it can be passed to CoapServer_startInstance(). Otherwise the implemented CoapServer will listen to a wrong port.

A correct implementation would look like:

rc = CoapServer_startInstance(Ip_convertIntToPort(5683), &coapReceiveCallback);

The CoapServer can receive data which is send via Copper. Please note that Copper sends confirmable CoAP messages. The current CoapServer implementation implements no response to the confirmable CoAP messages and therefore serval exception messages will appear into the XDK Workbench console.

Please do not hesitate to ask if you have further questions.

Kind regards,
Franjo

0 (0 Stimmen)
RE: CoAP server/client
Antwort
20.01.17 13:20 als Antwort auf Franjo Stjepandic.

Hello Franjo,

thank you very much for solving this issue.

I did this conversion before but at this time there was probably another issue. Because it has not changed anything, I corrected it back....

Now it is time to fill the receive callback with content.

Thanks again!

Kind regards,

Manuel

0 (0 Stimmen)
RE: CoAP server/client
Antwort
23.01.17 09:35 als Antwort auf Manuel Bock.

Hello Manuel,

I am glad that I could help you.

Please do not hesitate to ask if you have further questions.

Kind regards,
Franjo

0 (0 Stimmen)