LoRaWAN 节点多播(广播)处理过程

1、实现方法

关于LoRaWAN标准的所有东西,基本在LoRaWAN规范里面都可以查到,截取关于Class C多播部分如下:

多播地址及相关网络会话密钥和应用程序会话密钥必须来自应用程序层。

上面描述的意思就是说这些参数都需要我们自己定义。 

2、限制

  • 它们不允许携带MAC命令,无论是在FOpt字段中,还是在端口0上的有效负载中都不允许,因为多播下行链路不具有与单播帧相同的身份验证健壮性。
  • ACK和ADRACKReq位必须为零。MType字段必须保留未确认数据的值。
  • FPending位表示需要发送更多的多播数据。假定C类设备在大多数时间内保持其接收器处于活动状态,那么FPending位不会触发终端设备的任何特定行为。

3、节点实现过程

节点协议栈中关于多播的处理过程截取static void OnRadioTxDone( void ) 函数中的部分代码如下:

static void OnRadioTxDone( void )
{
    ……  //没有截取的代码部分
	
    log_info(loglevel,"\r\nRecv data:%d byte,rssi:%d,snr:%d,data[",size,rssi,snr);
    for(uint8_t i=0;i<size;i++)
    {
        log_info(loglevel," %02x",payload[i]);
    }
    log_info(loglevel,"]\r\n");
    //以上代码是将射频收到的数据、rssi、snr打印出来
	
    …… //没有截取的代码部分
	
    if( address != LoRaMacDevAddr ) //多播判断
    {
        curMulticastParams = MulticastChannels;  //MulticastChannels是一个多播参数指针
	while( curMulticastParams != NULL ) //遍历多播参数
	{
            if( address == curMulticastParams->Address )
	    //判断当前收到的短地址是否与多播的地址相等,若相等,则使用当前的多播参数,解密数据
	    {
		log_info(loglevel,"\r\nmulticast address:0x%x\r\n",address);
		//添加的调试信息,打印收到的多播的短地址
		multicast = 1;
		nwkSKey = curMulticastParams->NwkSKey;
		appSKey = curMulticastParams->AppSKey;
		downLinkCounter = curMulticastParams->DownLinkCounter;

		break;
	    }
	    curMulticastParams = curMulticastParams->Next;
        }
	if( multicast == 0 )
	{
	    //We are not the destination of this frame.
	    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
	    PrepareRxDoneAbort( );
	    return;
	}
    }
    else
    {
	multicast = 0;
	nwkSKey = LoRaMacNwkSKey;
	appSKey = LoRaMacAppSKey;
	downLinkCounter = DownLinkCounter;
    }

    ……  //没有截取的代码部分
	
    if( multicast == 1 )
    {
	McpsIndication.McpsIndication = MCPS_MULTICAST;
	//标记当前数据为多播数据

	if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) &&
			( curMulticastParams->DownLinkCounter != 0 ) )
	//判断当前的数据帧号,接收到的数据帧号要大于记录的数据帧号,否则,抛弃当前数据
	{
	    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
	    McpsIndication.DownLinkCounter = downLinkCounter;
	    PrepareRxDoneAbort( );
			
	    return;
	}
	curMulticastParams->DownLinkCounter = downLinkCounter;
    }

    …… //没有截取的代码部分
}

以上都是协议栈中的代码,在我们需要使用多播的时候,还需要我们定义多播参数,我们使用静态创建的方法简单定义如下:

MulticastParams_t MulticastChannels1,MulticastChannels2; //定义多播参数变量MulticastChannels1和MulticastChannels2

static uint8_t appskey_1[]={0x2d,0xc5,0x8c,0x7f,0xc6,0xcb,0xc3,0x4d,0x08,0x09,0xfb,0x56,0x50,0x06,0xff,0xea};
static uint8_t newskey_1[]={0x2d,0xc5,0x8c,0x7f,0xc6,0xcb,0xc3,0x4d,0x08,0x09,0xfb,0x56,0x50,0x06,0xff,0xeb};

static uint8_t appskey_2[]={0x2d,0xc5,0x8c,0x7f,0xc6,0xcb,0xc3,0x4d,0x08,0x09,0xfb,0x56,0x50,0x06,0xff,0xec};
static uint8_t newskey_2[]={0x2d,0xc5,0x8c,0x7f,0xc6,0xcb,0xc3,0x4d,0x08,0x09,0xfb,0x56,0x50,0x06,0xff,0xed};  
     
void MultcastParamInit(void)
{
	MulticastChannels=&MulticastChannels1;      //多播参数头指针指向多播参数1,
		
	MulticastChannels1.Next=&MulticastChannels2;//多播参数2指向
	
	MulticastChannels2.Next=NULL;

	MulticastChannels1.Address=0xfffffffa;     //多播参数1的短地址设置为0xfffffffa
	memcpy(MulticastChannels1.AppSKey, appskey_1, 16);  //多播参数1的应用会话密钥
	memcpy(MulticastChannels1.NwkSKey, newskey_1, 16);  //多播参数1的网络会话密钥
	
        MulticastChannels2.Address=0xfffffffb;     //多播参数1的短地址设置为0xfffffffb
	memcpy(MulticastChannels2.AppSKey, appskey_2, 16);  //多播参数2的应用会话密钥
	memcpy(MulticastChannels2.NwkSKey, newskey_2, 16);  //多播参数2的网络会话密钥
	
	//以上几个参数和server约定好就行
}

void MultcastParamInit(void) 这个函数就是我们在初始化多播参数,这里我初始化了两个多播参数,我们在初始化协议栈函数LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks, LoRaMacRegion_t region )里面调用一下就行。

4、下发数据

需要平台支持多播下发,测试使用的是内部开发的平台是支持的,我们这里不做过多展开。

5、节点接收数据测试

节点处理应用数据的回调函数如下:

static void McpsIndication( McpsIndication_t *mcpsIndication )
{
    if( mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
    {
        return;
    }
    switch( mcpsIndication->McpsIndication )
    {
        case MCPS_UNCONFIRMED:
        {
	    log_info(loglevel,"unconfirmed\r\n"); // log打印
            break;
        }
        case MCPS_CONFIRMED:
        {
	    log_info(loglevel,"confirmed\r\n");  // log打印  
            break;
        }
        case MCPS_PROPRIETARY:
        {
	    log_info(loglevel,"proprietary\r\n");  // log打印 
            break;
        }
        case MCPS_MULTICAST:
        {
	    log_info(loglevel,"multicast\r\n");  // log打印
            break;
        }
        default:
            break;
    }
    if(mcpsIndication->BufferSize!=0)
    {		
	log_info(loglevel,"user data:");
	for(uint8_t i=0;i<mcpsIndication->BufferSize;i++)
	{
            log_info(loglevel," %02x",mcpsIndication->Buffer[i]);
	}		
        log_info(loglevel,",port:%d\r\n",mcpsIndication->Port);
    }
	
	…… //没有截取的代码部分
}

可以看到,我们使用端口2,多播地址为0xfffffffb下发的数据05 04 03 02 01;
 

扫描二维码关注公众号,回复: 9290179 查看本文章

可以看到,我们使用端口20,多播地址为0xfffffffa下发的数据 01 02 03 04 05 。

发布了35 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/freemote/article/details/101364217