1

I want to send two different type of messages from server to client. I have created two functions data_signal() and probe_signal() for each of these two different messages.

The data_signal() function will periodically send a defined message with an interval of CLOCK_SECOND * 1 to the client.

I use a timer for interval CLOCK_SECOND * 30 duration to periodically call probe_signal() to send a different message to the client.

Currently the data_signal() function is working as expected. However the probe_signal() function is not sending its message to the client.

I have verified this by simply printing message at the client end and the "probe_signal()" message is not received.

Moreover, if I comment uip_udp_packet_send(conn, buf, strlen(buf)); line of data_signal() then I am able to receive the message from probe_signal(). I think this issue is happening because I am using the same UDP connection

Code:


#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"

#define DEBUG DEBUG_FULL
#include "net/ip/uip-debug.h"
#include "net/ip/uiplib.h"
#include "net/ipv6/uip-icmp6.h"

#include <string.h>
#define SERVER_IP             "fe80::9a07:2dff:fe3c:8d01" //"::"

#define CLIENT_PORT           61617
#define SERVER_PORT           61616

#define PING_TIMEOUT              (CLOCK_SECOND / 4)
#define CLIENT_SEND_INTERVAL      (CLOCK_SECOND * 1)

#define UDP_LEN_MAX           255
/*---------------------------------------------------------------------------*/
static uip_ipaddr_t server_addr;
static struct uip_icmp6_echo_reply_notification icmp_notification;
static uint8_t echo_received;
static struct uip_udp_conn *conn;

static struct etimer timer;
static char buf[UDP_LEN_MAX];
static uint16_t packet_counter;
static uint16_t probe_packet_counter;
static uint16_t actualSent_packet_counter;
static int flag;

/*---------------------------------------------------------------------------*/
PROCESS(ipv6_ble_client_process, "IPv6 over BLE - client process");
AUTOSTART_PROCESSES(&ipv6_ble_client_process);
/*---------------------------------------------------------------------------*/
void icmp_reply_handler(uip_ipaddr_t *source, uint8_t ttl,
                   uint8_t *data, uint16_t datalen)
{
  PRINTF("echo response received\n");
  echo_received = 1;
}
/*---------------------------------------------------------------------------*/
static void tcpip_handler(void)
{


}
/*---------------------------------------------------------------------------*/
static void
data_signal(void)
{

    sprintf(buf, "Current packet count is: %04u!",packet_counter);
    PRINTF("send message: <%s>\n", buf); /*This printf is commented for understanding the low level code*/
    uip_udp_packet_send(conn, buf, strlen(buf));
    packet_counter++;
}


static void probe_signal(void)
{   
    sprintf(buf, "%04u", probe_packet_counter);
    uip_udp_packet_send(conn, buf, strlen(buf));
    printf("Probe signal is sent");
}

/*---------------------------------------------------------------------------*/


PROCESS_THREAD(ipv6_ble_client_process, ev, data)
{
    static struct timer t;  
    PROCESS_BEGIN();
    PRINTF("CC26XX-IPv6-over-BLE client started\n");

    conn = udp_new(&server_addr, UIP_HTONS(SERVER_PORT), NULL);
    udp_bind(conn, UIP_HTONS(CLIENT_PORT));
    timer_set(&t, CLOCK_SECOND * 30);

    etimer_set(&timer, CLIENT_SEND_INTERVAL);

    while(1) 
    {
        if(timer_expired(&t))
        {   
            flag =1;
            if(flag==1)
            {
                probe_signal();
                timer_reset(&t);
                printf("Timer is reset\n");
            }

        }
        PROCESS_YIELD();
        if((ev == PROCESS_EVENT_TIMER) && (data == &timer)) 
        {
            data_signal();    
            etimer_set(&timer, CLIENT_SEND_INTERVAL);
        } 
        else if(ev == tcpip_event) 
        {
            printf("TCPIP event occured\n");
            tcpip_handler();
        }
    }

  PROCESS_END();
}
/*---------------------------------------------------------------------------*/

Can someone guide how to resolve this, it would be a great help.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
  • I sincerely doubt that your problem is due to using the same UDP connection to send data from two different functions. However you are using the same buffer for both functions and I would change that to use two different buffers. – Richard Chambers Sep 23 '19 at 13:12
  • The logic in the `PROCESS_THREAD` function does not look right. I suggest you update your post describing what your code is supposed to be doing so that people can then read the code to see if it appears to be doing what you intend it to do. Tell us what the purpose of this code is and what you are trying to accomplish with this code. – Richard Chambers Sep 23 '19 at 13:21
  • @RichardChambers It's okay to use the variable `buffer` in both functions. The buffer content is set in the `xx_signal` functions and used immediately before the return. The other function can't be called between `sprintf` and `uip_udp_packet_send` of the one function. – harper Sep 23 '19 at 15:12
  • @RichardChambers Both xx_signal functions are called from **the** thread function `ipv6_ble_client_process`. This function is started once, at least the code doesn't show something else. While executing the function, the PC can only be at one location. – harper Sep 23 '19 at 15:45
  • @RichardChambers I admit that I don't know the contiki OS or the libraries used from the project. Probably it's documented that any (or some of) functions can YIELD to another thread. If `uip_udp_packet_send()` calls such a function, it will be hard to predict what happens here. The function itself doesn't call a YIELD. Your proposal to avoid sharing the buffer may help in that case. The OP should verify how many threads she starts. But you can have as many CPU cores as you like, if there is one thread it doesn't care. – harper Sep 23 '19 at 16:07
  • @RichardChambers, I tried with different buffers but it didn't help. – SUBHANSHU SAHU Sep 23 '19 at 18:12

1 Answers1

1

I am able to resolve this issue by changing the code:

  • Changed timer type to etimer
  • Waited for etimer event and then called probe_signal().

From Events and Scheduling from Documentation: Processes and events:

Contiki-NG is built on an event-based execution model, where processes typically perform chunks of work before telling the scheduler that they are waiting for an event, and thereby suspend execution. Such events can be the expiration of a timer, an incoming network packet, or a serial line message being delivered.

Processes are scheduled cooperatively, which means that each process is responsible for voluntarily yielding control back to the operating system without executing for too long. Hence, the application developer must make sure that long-running operations are split into multiple process schedulings, allowing such operations to resume at the point where they last stopped.

And from the section Pausing and yielding from the same document:

By contrast, PROCESS_YIELD() will yield control back to the scheduler without expecting to be scheduled again shortly thereafter. Instead, it will wait for an incoming event, similar to PROCESS_WAIT_EVENT_UNTIL(), but without a required condition argument.

A discussion of the Etimer library can be found at Timers in the contiki-os github repository:

The Contiki etimer library provides a timer mechanism that generate timed events. An event timer will post the event PROCESS_EVENT_TIMER to the process that set the timer when the event timer expires. The etimer library use clock_time() in the clock module to get the current system time.

Updated Code:


#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"

#define DEBUG DEBUG_FULL
#include "net/ip/uip-debug.h"
#include "net/ip/uiplib.h"
#include "net/ipv6/uip-icmp6.h"

#include <string.h>
#define SERVER_IP             "fe80::9a07:2dff:fe3c:8d01" //"::"

#define CLIENT_PORT           61617
#define SERVER_PORT           61616

#define PING_TIMEOUT              (CLOCK_SECOND / 4)
#define CLIENT_SEND_INTERVAL      (CLOCK_SECOND * 1)
#define PROBE_SIGNAL_INTERVAL      (CLOCK_SECOND * 30)

#define UDP_LEN_MAX           255
/*---------------------------------------------------------------------------*/
static uip_ipaddr_t server_addr;
static struct uip_icmp6_echo_reply_notification icmp_notification;
static uint8_t echo_received;
static struct uip_udp_conn *conn;

static struct etimer timer,probe_timer;
static char buf[UDP_LEN_MAX];
static uint16_t packet_counter;
static uint16_t probe_packet_counter;
static uint16_t actualSent_packet_counter;
static int flag;

/*---------------------------------------------------------------------------*/
PROCESS(ipv6_ble_client_process, "IPv6 over BLE - client process");
AUTOSTART_PROCESSES(&ipv6_ble_client_process);
/*---------------------------------------------------------------------------*/
void icmp_reply_handler(uip_ipaddr_t *source, uint8_t ttl,
                   uint8_t *data, uint16_t datalen)
{
  PRINTF("echo response received\n");
  echo_received = 1;
}
/*---------------------------------------------------------------------------*/
static void tcpip_handler(void)
{


}
/*---------------------------------------------------------------------------*/
static void
data_signal(void)
{

    sprintf(buf, "Current packet count is: %04u!",packet_counter);
    PRINTF("send message: <%s>\n", buf); /*This printf is commented for understanding the low level code*/
    uip_udp_packet_send(conn, buf, strlen(buf));
    packet_counter++;
}


static void probe_signal(void)
{   
    sprintf(buf, "%04u", probe_packet_counter);
    uip_udp_packet_send(conn, buf, strlen(buf));
    printf("Probe signal is sent");
}

/*---------------------------------------------------------------------------*/


PROCESS_THREAD(ipv6_ble_client_process, ev, data)
{
    PROCESS_BEGIN();
    PRINTF("CC26XX-IPv6-over-BLE client started\n");

    conn = udp_new(&server_addr, UIP_HTONS(SERVER_PORT), NULL);
    udp_bind(conn, UIP_HTONS(CLIENT_PORT));

    etimer_set(&probe_timer, PROBE_SIGNAL_INTERVAL);  // set up a timer event for calling probe_signal() function

    etimer_set(&timer, CLIENT_SEND_INTERVAL);  // set up a timer event for calling data_signal() function

    while(1) 
    {
        PROCESS_YIELD();     // yield waiting for an timer event or other event
        if((ev == PROCESS_EVENT_TIMER) && (data == &timer)) 
        {
            // timer event received so process it and then reschedule again.
            data_signal();    
            etimer_set(&timer, CLIENT_SEND_INTERVAL);
        }
        if((ev == PROCESS_EVENT_TIMER) && (data == &probe_timer)) 
        {
            // timer event received so process it and then reschedule again.
            probe_signal();    
            etimer_set(&timer, PROBE_SIGNAL_INTERVAL);
        } 
        else if(ev == tcpip_event) 
        {
            printf("TCPIP event occured\n");
            tcpip_handler();
        }
    }

  PROCESS_END();
}
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
  • If this solves your problem, please accept it as an answer so that other people with a similar problem will see this as an answered question. Also please add some additional information about the change in the process loop you made with the change to using `etimer` and why you made that change to help others with a similar problem. – Richard Chambers Sep 23 '19 at 20:22