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;
 

可以看到,我們使用端口20,多播地址爲0xfffffffa下發的數據 01 02 03 04 05 。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章