1

我想从服务器向客户端发送两种不同类型的消息。我已经为这两个不同的消息data_signal()创建了两个函数。probe_signal()

data_signal()函数将定期向客户端发送一个间隔为 的定义消息CLOCK_SECOND * 1

我使用一个用于间隔CLOCK_SECOND * 30持续时间的计时器来定期调用probe_signal()以向客户端发送不同的消息。

目前该data_signal()功能正在按预期工作。但是,该probe_signal()功能不会将其消息发送给客户端。

我通过简单地在客户端打印消息验证了这一点,并且没有收到“probe_signal()”消息。

此外,如果我评论uip_udp_packet_send(conn, buf, strlen(buf));那一行,data_signal()我就能收到来自probe_signal(). 我认为这个问题正在发生,因为我使用的是相同的 UDP 连接

代码:


#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();
}
/*---------------------------------------------------------------------------*/

有人可以指导如何解决这个问题,这将是一个很大的帮助。

4

1 回答 1

1

我可以通过更改代码来解决此问题:

  • 将计时器类型更改为etimer
  • 等待etimer事件,然后调用probe_signal()

来自文档中的事件和调度:流程和事件

Contiki-NG 建立在基于事件的执行模型上,进程通常在告诉调度程序它们正在等待事件之前执行大量工作,从而暂停执行。此类事件可以是计时器到期、传入网络数据包或正在传递的串行线路消息。

进程是协作调度的,这意味着每个进程都有责任自愿将控制权交还给操作系统,而不会执行太长时间。因此,应用程序开发人员必须确保将长时间运行的操作拆分为多个进程调度,以允许此类操作在它们上次停止的位置恢复。

从同一文档的暂停和让步部分:

相比之下,PROCESS_YIELD() 将把控制权交还给调度程序,而不会期望在此后不久再次被调度。相反,它将等待传入事件,类似于 PROCESS_WAIT_EVENT_UNTIL(),但没有必需的条件参数。

可以在 contiki-os github 存储库的 Timers 中找到有关 Etimer 库的讨论:

Contiki etimer 库提供了一种生成定时事件的定时器机制。事件计时器将在事件计时器到期时将事件 PROCESS_EVENT_TIMER 发布到设置计时器的进程。etimer 库使用时钟模块中的clock_time() 来获取当前系统时间。

更新代码:


#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();
}
于 2019-09-23T19:00:06.103 回答