关于LoRaWAN标准的所有东西,基本在LoRaWAN规范里面都可以查到,截取关于Class C多播部分如下:
多播地址及相关网络会话密钥和应用程序会话密钥必须来自应用程序层。
上面描述的意思就是说这些参数都需要我们自己定义。
节点协议栈中关于多播的处理过程截取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;iAddress )
//判断当前收到的短地址是否与多播的地址相等,若相等,则使用当前的多播参数,解密数据
{
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 )里面调用一下就行。
需要平台支持多播下发,测试使用的是内部开发的平台是支持的,我们这里不做过多展开。
节点处理应用数据的回调函数如下:
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;iBufferSize;i++)
{
log_info(loglevel," %02x",mcpsIndication->Buffer[i]);
}
log_info(loglevel,",port:%d\r\n",mcpsIndication->Port);
}
…… //没有截取的代码部分
}
可以看到,我们使用端口2,多播地址为0xfffffffb下发的数据05 04 03 02 01;
可以看到,我们使用端口20,多播地址为0xfffffffa下发的数据 01 02 03 04 05 。