first submission
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : lwns_mesh_example.c
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2021/06/28
|
||||
* Description : mesh传输程序例子
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#include "lwns_mesh_example.h"
|
||||
|
||||
//每个文件单独debug打印的开关,置0可以禁止本文件内部打印
|
||||
#define DEBUG_PRINT_IN_THIS_FILE 1
|
||||
#if DEBUG_PRINT_IN_THIS_FILE
|
||||
#define PRINTF(...) PRINT(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...) \
|
||||
do \
|
||||
{ \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#define MESH_TEST_ROUTE_AUTO 1 //设置是否自动管理路由表
|
||||
#define MESH_TEST_SELF_ADDR_IDX 2 //当前测试中节点地址,在device_addr数组中
|
||||
#define MESH_TEST_ADDR_MAX_IDX 2 //当前测试中,有多少个节点
|
||||
|
||||
static uint8_t mesh_test_send_dst = 0;
|
||||
|
||||
static lwns_mesh_controller lwns_mesh_test;
|
||||
|
||||
static uint8_t lwns_mesh_test_taskID;
|
||||
static uint16_t lwns_mesh_test_ProcessEvent(uint8_t task_id, uint16_t events);
|
||||
static uint8_t TX_DATA[10] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39};
|
||||
static const lwns_addr_t device_addr[] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, //根节点地址
|
||||
{0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, //组1路由节点1
|
||||
{0x00, 0x00, 0x00, 0x00, 0x01, 0x02}, //组1节点2
|
||||
{0x00, 0x00, 0x00, 0x00, 0x01, 0x03}, //组1节点3
|
||||
{0x00, 0x00, 0x00, 0x00, 0x01, 0x04}, //组1节点4
|
||||
{0x00, 0x00, 0x00, 0x00, 0x02, 0x01}, //组2路由节点1
|
||||
{0x00, 0x00, 0x00, 0x00, 0x02, 0x02}, //组2节点2
|
||||
{0x00, 0x00, 0x00, 0x00, 0x02, 0x03}, //组2节点3
|
||||
{0x00, 0x00, 0x00, 0x00, 0x02, 0x04}, //组2节点4
|
||||
{0x00, 0x00, 0x00, 0x00, 0x03, 0x01}, //组3路由节点1
|
||||
{0x00, 0x00, 0x00, 0x00, 0x03, 0x02}, //组3节点2
|
||||
{0x00, 0x00, 0x00, 0x00, 0x03, 0x03}, //组3节点3
|
||||
{0x00, 0x00, 0x00, 0x00, 0x03, 0x04}, //组3节点4
|
||||
};
|
||||
|
||||
static void lwns_mesh_recv(lwns_controller_ptr ptr,
|
||||
const lwns_addr_t *sender, uint8_t hops);
|
||||
static void lwns_mesh_sent(lwns_controller_ptr ptr);
|
||||
static void lwns_mesh_timedout(lwns_controller_ptr ptr);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn lwns_mesh_recv
|
||||
*
|
||||
* @brief lwns mesh接收回调函数
|
||||
*
|
||||
* @param ptr - 本次接收到的数据所属的mesh控制结构体指针.
|
||||
* @param sender - 本次接收到的数据的发送者地址指针.
|
||||
* @param hops - 本次接收到的数据的从发送方到本节点经历的跳数.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static void lwns_mesh_recv(lwns_controller_ptr ptr,
|
||||
const lwns_addr_t *sender, uint8_t hops)
|
||||
{
|
||||
PRINTF("mesh %d received from %02x.%02x.%02x.%02x.%02x.%02x: %s (%d)\n",
|
||||
get_lwns_object_port(ptr), sender->v8[0], sender->v8[1],
|
||||
sender->v8[2], sender->v8[3], sender->v8[4], sender->v8[5],
|
||||
(char *)lwns_buffer_dataptr(), lwns_buffer_datalen());
|
||||
if(MESH_TEST_SELF_ADDR_IDX != 0)
|
||||
{
|
||||
//不为0,证明是从机,收到后回复主机
|
||||
lwns_buffer_save_data(TX_DATA);
|
||||
tmos_set_event(lwns_mesh_test_taskID, MESH_EXAMPLE_TX_NODE_EVT);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn lwns_mesh_sent
|
||||
*
|
||||
* @brief lwns mesh发送完成回调函数
|
||||
*
|
||||
* @param ptr - 本次发送完成的mesh控制结构体指针.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static void lwns_mesh_sent(lwns_controller_ptr ptr)
|
||||
{
|
||||
PRINTF("mesh %d packet sent\n", get_lwns_object_port(ptr));
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn lwns_mesh_timedout
|
||||
*
|
||||
* @brief lwns mesh发送超时回调函数
|
||||
*
|
||||
* @param ptr - 本次发送完成的mesh控制结构体指针.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static void lwns_mesh_timedout(lwns_controller_ptr ptr)
|
||||
{
|
||||
//寻找路由超时才会进入该回调,如果已经有路由,但是下一跳节点掉线,不会进入该回调。由lwns_route_init(TRUE, 60, HTIMER_SECOND_NUM);来管理掉线时间。
|
||||
PRINTF("mesh %d packet timedout\n", get_lwns_object_port(ptr));
|
||||
}
|
||||
|
||||
/**
|
||||
* lwns mesh回调函数结构体,注册回调函数
|
||||
*/
|
||||
static const struct lwns_mesh_callbacks callbacks = {lwns_mesh_recv,
|
||||
lwns_mesh_sent, lwns_mesh_timedout};
|
||||
|
||||
/*
|
||||
* mesh采用netflood模块进行寻找路由,所以初始化参数中包括了netflood所需要的参数
|
||||
* mesh为利用路由进行多跳转发的基础结构
|
||||
* mesh模块使用前必须初始化路由,包括库初始化时给路由表提供的内存空间。
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn lwns_mesh_process_init
|
||||
*
|
||||
* @brief lwns mesh例程初始化.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void lwns_mesh_process_init(void)
|
||||
{
|
||||
uint8_t route_enable = FALSE;
|
||||
lwns_addr_set(
|
||||
(lwns_addr_t *)(&device_addr[MESH_TEST_SELF_ADDR_IDX])); //改变lwns内部addr
|
||||
if(device_addr[MESH_TEST_SELF_ADDR_IDX].v8[5] == 1)
|
||||
{
|
||||
//每一组第一个节点打开路由功能,其他节点不打开路由功能
|
||||
route_enable = TRUE;
|
||||
}
|
||||
lwns_mesh_test_taskID = TMOS_ProcessEventRegister(lwns_mesh_test_ProcessEvent);
|
||||
#if MESH_TEST_ROUTE_AUTO
|
||||
lwns_route_init(TRUE, 60, HTIMER_SECOND_NUM);
|
||||
#else
|
||||
lwns_route_init(TRUE, 0, HTIMER_SECOND_NUM); //disable auto clean route entry
|
||||
#endif /*MESH_TEST_ROUTE_AUTO*/
|
||||
lwns_mesh_init(&lwns_mesh_test, 132, //打开一个端口号132的mesh网络,同时占用后其他的两个端口用作寻找路由,即133,134也同时打开了。
|
||||
HTIMER_SECOND_NUM / 2, //netflood的QUEUETIME功能
|
||||
1, //netflood的dups功能
|
||||
2, //最大跳跃次数层级为5级,即数据包最多可以经过5次转发,超出就丢弃数据包
|
||||
FALSE, //在路由请求的转发过程中,收到了新的需要转发的数据包,旧数据包是立刻发送出去还是丢弃,FALSE为立刻发送,TRUE为丢弃。
|
||||
50, //网络恢复参数,该值定义了一个差距,如果包序号比内存内保存的数据包序号小的值大于此值,则会认为网络故障恢复,继续接收该数据包。
|
||||
//同时,该值也决定了判定为新数据包的差值,即来自同一个节点的新数据包的序号不可以比内存中的大过多,即比此值还大。
|
||||
//例如,内存中保存的为10,新数据包序号为60,差值为50,大于等于此时设置的50,所以将不会被认为为新的数据包,被丢弃。
|
||||
//只有序号为59,差值为49,小于该值,才会被接收。
|
||||
route_enable, //是否使能本机的路由功能,如果为false,不会响应其他节点的路由请求。
|
||||
TRUE, //决定是否添加路由回路,比如收到了一个来自a节点的mesh数据包,本机是否需要存储前往a节点的路由表。FALSE不存,TRUE存。
|
||||
HTIMER_SECOND_NUM * 2, //路由超时时间,超过时间,停止寻找路由,进入timeout回调,该值应大于 route_discovery_hoptime * (hops+1) * 2
|
||||
&callbacks); //没有初始化路由表的话,会返回0,代表打开失败。返回1打开成功。
|
||||
if(MESH_TEST_SELF_ADDR_IDX == 0)
|
||||
{ //如果是主机,则开始周期性轮训其他节点。
|
||||
mesh_test_send_dst = 1;
|
||||
tmos_start_task(lwns_mesh_test_taskID, MESH_EXAMPLE_TX_PERIOD_EVT,
|
||||
MS1_TO_SYSTEM_TIME(200));
|
||||
#if MESH_TEST_ROUTE_AUTO
|
||||
PRINTF("Auto route\n");
|
||||
#else
|
||||
uint8_t i;
|
||||
for(i = 1; i < 5; i++)
|
||||
{
|
||||
lwns_route_add(&device_addr[i], &device_addr[1], 2); //手动管理,添加路由条目
|
||||
}
|
||||
for(i = 5; i < 9; i++)
|
||||
{
|
||||
lwns_route_add(&device_addr[i], &device_addr[5], 2); //手动管理,添加路由条目
|
||||
}
|
||||
for(i = 9; i < 13; i++)
|
||||
{
|
||||
lwns_route_add(&device_addr[i], &device_addr[9], 2); //手动管理,添加路由条目
|
||||
}
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 1)
|
||||
{
|
||||
lwns_route_add(&device_addr[4], &device_addr[4], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[3], &device_addr[3], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[2], &device_addr[2], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[0], &device_addr[0], 1); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 2)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[1], 2); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 3)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[1], 2); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 4)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[1], 2); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 5)
|
||||
{
|
||||
lwns_route_add(&device_addr[6], &device_addr[6], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[7], &device_addr[7], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[8], &device_addr[8], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[0], &device_addr[0], 1); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 6)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[5], 2); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 7)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[5], 2); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 8)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[5], 2); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 9)
|
||||
{
|
||||
lwns_route_add(&device_addr[10], &device_addr[10], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[11], &device_addr[11], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[12], &device_addr[12], 1); //手动管理,添加路由条目
|
||||
lwns_route_add(&device_addr[0], &device_addr[0], 1); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 10)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[9], 2); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 11)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[9], 2); //手动管理,添加路由条目
|
||||
}
|
||||
else if(MESH_TEST_SELF_ADDR_IDX == 12)
|
||||
{
|
||||
lwns_route_add(&device_addr[0], &device_addr[9], 2); //手动管理,添加路由条目
|
||||
#endif /*MESH_TEST_ROUTE_AUTO*/
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn lwns_mesh_test_ProcessEvent
|
||||
*
|
||||
* @brief lwns mesh Task event processor. This function
|
||||
* is called to process all events for the task. Events
|
||||
* include timers, messages and any other user defined events.
|
||||
*
|
||||
* @param task_id - The TMOS assigned task ID.
|
||||
* @param events - events to process. This is a bit map and can
|
||||
* contain more than one event.
|
||||
*
|
||||
* @return events not processed.
|
||||
*/
|
||||
static uint16_t lwns_mesh_test_ProcessEvent(uint8_t task_id, uint16_t events)
|
||||
{
|
||||
if(events & MESH_EXAMPLE_TX_PERIOD_EVT)
|
||||
{ //主机周期性轮询从机任务
|
||||
uint8_t temp;
|
||||
struct lwns_route_entry *rt;
|
||||
temp = TX_DATA[0];
|
||||
for(uint8_t i = 0; i < 9; i++)
|
||||
{
|
||||
TX_DATA[i] = TX_DATA[i + 1]; //移位发送数据,以便观察效果
|
||||
}
|
||||
TX_DATA[9] = temp;
|
||||
lwns_buffer_load_data(TX_DATA, sizeof(TX_DATA)); //载入需要发送的数据到缓冲区
|
||||
rt = lwns_route_lookup(&device_addr[mesh_test_send_dst]); //在路由表中寻找下一跳路由
|
||||
if(rt != NULL)
|
||||
{
|
||||
//打印下一跳路由信息
|
||||
PRINTF("dst:%d,forwarding to %02x.%02x.%02x.%02x.%02x.%02x\n",
|
||||
mesh_test_send_dst, rt->nexthop.v8[0], rt->nexthop.v8[1],
|
||||
rt->nexthop.v8[2], rt->nexthop.v8[3], rt->nexthop.v8[4],
|
||||
rt->nexthop.v8[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINTF("no route to dst:%d\n", mesh_test_send_dst);
|
||||
}
|
||||
lwns_mesh_send(&lwns_mesh_test, &device_addr[mesh_test_send_dst]); //发送mesh消息
|
||||
mesh_test_send_dst++; //轮询目标节点改为下一个
|
||||
if(mesh_test_send_dst > MESH_TEST_ADDR_MAX_IDX)
|
||||
{ //循环往复轮询
|
||||
mesh_test_send_dst = 1;
|
||||
}
|
||||
tmos_start_task(lwns_mesh_test_taskID, MESH_EXAMPLE_TX_PERIOD_EVT,
|
||||
MS1_TO_SYSTEM_TIME(2500)); //周期性轮询
|
||||
return (events ^ MESH_EXAMPLE_TX_PERIOD_EVT);
|
||||
}
|
||||
if(events & MESH_EXAMPLE_TX_NODE_EVT)
|
||||
{ //节点给主机发送数据的任务
|
||||
struct lwns_route_entry *rt;
|
||||
lwns_buffer_load_data(TX_DATA, sizeof(TX_DATA)); //载入需要发送的数据到缓冲区
|
||||
rt = lwns_route_lookup(&device_addr[0]); //在路由表中寻找下一跳路由
|
||||
if(rt != NULL)
|
||||
{
|
||||
//打印出下一跳路由信息
|
||||
PRINTF("src:%d,forwarding to %02x.%02x.%02x.%02x.%02x.%02x\n",
|
||||
MESH_TEST_SELF_ADDR_IDX, rt->nexthop.v8[0],
|
||||
rt->nexthop.v8[1], rt->nexthop.v8[2], rt->nexthop.v8[3],
|
||||
rt->nexthop.v8[4], rt->nexthop.v8[5]);
|
||||
}
|
||||
lwns_mesh_send(&lwns_mesh_test, &device_addr[0]); //调用mesh发送函数,进行数据的发送
|
||||
return (events ^ MESH_EXAMPLE_TX_NODE_EVT);
|
||||
}
|
||||
if(events & SYS_EVENT_MSG)
|
||||
{
|
||||
uint8_t *pMsg;
|
||||
if((pMsg = tmos_msg_receive(task_id)) != NULL)
|
||||
{
|
||||
// Release the TMOS message
|
||||
tmos_msg_deallocate(pMsg);
|
||||
}
|
||||
// return unprocessed events
|
||||
return (events ^ SYS_EVENT_MSG);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user