IoT/透過oc_lwm2m/boudica150 源碼中的AT指令序列,分析NB-IoT接入華為云物聯網平臺IoTDA的工作機制

文章目錄

  • 概述
  • 指令調用順序
  • 具體接入指令分析
    • ATE0 關閉回顯
    • AT+QREGSWT 設置(平臺)注冊模式
    • AT+QLWSREGIND=0 手動注冊平臺
    • set_autoconnect / AT+NCONFIG
    • AT+NBAND=x,x
    • set_plmn / AT+COPS
    • _set_apn / AT+CGDCONT
    • (安全)接入參數 CDP+DTLS+PSK
    • AT+NNMI 設置新消息指示
    • _check_netattach 網絡附著狀態
    • AT+COPS=0 和 AT+CGATT=1
    • _check_observe網絡附著狀態
    • urc_qlwevtind
  • 總結和后記

概述

在一個不斷探索的過程中,我們已經可以真正的將NB-IoT設備以安全的方式接入打破IoTDA平臺,包括使用PC-AT指令、使用MCU-AT指令及其數據處理代碼,也已經了解了NB-IoT-AT的實現機制。本文我們將繼續深入,詳談 NB-IoT設備是如何通過不同的AT指令,先接入運營商網絡,再接入華為云物聯網平臺的。

@HISTORY
我們已經從<實驗5 基于NB-IoT的智慧農業實驗> 的烏龍坑里爬了出來。并有了以下知識點作為后文分析的支撐知識:
0、PC-AT指令的部分設置是存儲在模組內的,即使MCU-AT不執行這些操作,也會成功連接!
1、NB-IoT通信模組通過串口以AT指令形式與MCU通信。
1、注冊NB-IoT設備時,設備標識只能是IMEI國際移動設備識別碼?Yes
2、在當下連接到IoTDA,是否必須啟用DTLS?不再支持5683非安全接入?Yes
3、NB-IoT設備密鑰格式,在代碼中以數組字符串定義,和Wifi設備不一樣?Yes

@NOTE
轉載請標明出處,https://blog.csdn.net/quguanxin/category_12929470.html

指令調用順序

在 #<IoT/實現和分析 NB-IoT+DTLS+PSK 接入華為云物聯網平臺IoTDA過程,總結避坑攻略># 文中,我們已經實現了較完整和準確的設備安全(PSK+DTLS)接入IoTDA的程序,并詳細分析了 boudica150_boot 上層的調用關系,在 boudica150_boot 函數中被循環執行的指令序列如下。結合上文以及 #<IoT/基于NB28-A/BC28-CNV通信模組使用AT指令連接華為云IoTDA平臺># 中的表述,我們將展開更細致的NB-IoT設備AT指令接入運營商網絡和接入華為云物聯網平臺過程和原理的分析。

//如下過程的外層是while(1)//Do:執行命令 AT+NRB 重啟UE 即重啟我們的NB-IoT通信模組 并延時等待10sboudica150_reboot();
//Do:執行ATE0,等待返回OK /禁用模組對接收到的AT指令的回顯(Echo)/什么是回顯下文另談boudica150_set_echo (0);
//Do: 設置UE是自動還是手動觸發以注冊IoT平臺 /這就是一個本地設置操作,些模組內存或KV? 應該會立即返回Okboudica150_set_regmode(1);
//Do:使能 +CME ERROR: <err> 結果碼 https://blog.csdn.net/quguanxin/article/details/146547709boudica150_set_cmee(1);
//Do:關閉AUTOCONNECT自動連接,本質上是想關閉CFUN射頻
//cgatt and cfun must be called if autoconnect is falseboudica150_set_autoconnect(0);    
//Do:設置通信模組支持的頻帶(依據SIM卡運營商選擇,或默認選擇全部支持的頻段)/Band20并不被支持,需要修改掉boudica150_set_bands(bands);
//Do:AT+CFUN=1 使能射頻boudica150_set_fun(1);
//Do:AT+COPS=0 設置自動注冊網絡/源碼中實參plmn==NULLboudica150_set_plmn(plmn);
//Do:由于apn==NULL,呼應plmn==NULL;本質上該函數內部什么也沒干,直接返回trueboudica150_set_apn(apn);
//Do:參見PC-AT指令,設置CDP服務器boudica150_set_cdp(server,port);
//Do:開啟dtls /river.qu 202506boudica150_set_dtls(1);
//Do:設置 PSK ID 和 PSK /river.qu 202506boudica150_set_psk(s_boudica150_oc_cb.oc_param.app_server.psk_id, s_boudica150_oc_cb.oc_param.app_server.psk);
//Do:AT+CGATT=1boudica150_set_cgatt(1);
//Do:AT+NNMI=1 /使能新消息指示和數據,會返回當前所有緩存的消息boudica150_set_nnmi(1);
//Do:檢測網絡附著狀態/重復執行AT+CGATT?查詢指令if(false == boudica150_check_netattach(16)) {continue;}
//Do:等待模組程序成功創建所需要的lwm2m對象if(false == boudica150_check_observe(16)) {continue; //we should do the reboot for the nB}     

@NOTE 要意識到一個事情是,以上函數內部幾乎都有等待反饋返回的過程,器本質上是在等信號量(后續其他文會繼續講述這塊)。這些返回大多是瞬時完成的,因為它們不涉及到與基站或平臺的交互,是由模組固件程序本地直接處理并完成的。

具體接入指令分析

部分指令分析請參考 #<PC-AT實驗># 。

ATE0 關閉回顯

所謂的回顯,是在主機端顯示你發送出去的AT指令。
在這里插入圖片描述

AT+QREGSWT 設置(平臺)注冊模式

AT+QREGSWT=1 該命令用于在重啟模塊后設置注冊模式:
在這里插入圖片描述
如果不需要使用 LwM2M 物聯網平臺,必須使用命令 AT+QREGSWT=2 禁用注冊功能。該命令只有在使用 AT+NRB 重啟 UE 后才生效,若不禁用注冊功能會使 UE 從網絡中分離,造成相關服務(例如 TCP/UDP)失敗。

連接到網絡后自動觸發注冊,這里的網絡是指?這里的注冊是像誰發起?

這里的“網絡”指 蜂窩移動網絡,具體為NB-IoT無線接入網(RAN)和核心網(EPC/5GC),包括以下關鍵節點:
基站(eNodeB/gNB):提供無線信號覆蓋。
移動管理實體(MME/AMF):負責終端接入認證和位置管理。
數據網關(PGW/UPF):提供互聯網或專網連接。
連接過程: 模組通過PLMN(公共陸地移動網絡)搜索并附著到運營商網絡,完成空口同步、鑒權、默認承載建立等流程。

而注冊對象是,LwM2M物聯網平臺(如華為OceanConnect、移動OneNET)
無論是 =0(手動注冊)、當 =1(自動注冊),其注冊對象都是物聯網平臺。手動注冊時,要通過AT+QLWSREGIND命令顯式觸發。而自動觸發的時機在,模組重啟后成功連接蜂窩網絡(完成PSM激活或eDRX喚醒),此時,模組通過CoAP協議向LwM2M服務器(如coap://lwm2m.iot.platform.com)發送Register請求,攜帶Endpoint Client Name、Lifetime等參數,服務器返回2.01 Created響應,分配注冊ID并維護在線狀態。

AT+QLWSREGIND=0 手動注冊平臺

在這里插入圖片描述
在PC-AT指令的實驗中,我曾經有個疑問就是,我的NB-IoT是在什么時候注冊勾搭上的物聯網平臺,當時只知道這個過程自動完成了,并不知道所以然。現在大約明白了,在手動注冊模式(AT+QREGSWT=0)下,用戶要發送AT+QLWSREGIND=0 指令,然后模組的固件程序會解析此指令,將其轉換為LwM2M協議交互過程,這在固件實現內,其與自動注冊模式下的LwM2M客戶端和服務端建立連接的過程應該是同源的。這個大體過程可參考lwm2m_tiny源碼實現。

set_autoconnect / AT+NCONFIG

static bool_t boudica150_set_autoconnect(int enable) {if(enable)   mode = "AUTOCONNECT,TRUE";else //源碼中傳遞的是0mode = "AUTOCONNECT,FALSE";(void) memset(resp,0,64);ret = boudica150_atcmd_response("AT+NCONFIG?\r","+NCONFIG",resp,64);//which means we need to set it if((false == ret)||(NULL == strstr(resp,mode)))  {(void) memset(cmd,0,64);(void) snprintf(cmd,64,"AT+NCONFIG=%s\r",mode);ret = boudica150_atcmd(cmd,"OK");//上述設置后,需要再次軟重啟boudica150_reboot();}//如果檢測到已經設置過,則直接返回成功

在小熊派社區/或HCIP_Lab源碼中,這里的實參都是是0哈,不是1,即失能配置。此時,指令展開為:
AT+NCONFIG=AUTOCONNECT,FALSE
上述操作可能起到關閉CFUN的作用,這么猜想,主要是因為從后續代碼來看,還會有CFUN射頻開啟過程。另外猜測注釋 cgatt and cfun must be called if autoconnect is false 的含義可能是,若上述操作沒有關閉成功,則需要手動去關閉 cgatt和cfun,起初這只是猜測哈,下一小節中,這一猜測被驗證是正確的,NBAND操作時要求 CFUN 是關閉狀態。
在這里插入圖片描述
@OTHER
NCONFIG 指令的 參數有超級多的選項,這里就不列舉了,哈哈,感覺我一年內就只能折騰這第一個選項了。通過指令手冊,結合觀察實際實驗過程中的日志輸出,我們可以看到,NCONFIG 查詢指令,會輸出 類型的設置值,我們可以先只關注AUTOCONNECT 功能類型的設置值是否為true即可。

@NOTE
我們在PC-AT實驗中并沒有使用到該指令,但是我們手動執行了 CFUN 的關閉操作過程。

AT+NBAND=x,x

在 boudica150_oc.c 源碼中的 int oc_lwm2m_imp_init(void) 函數下,bands 已經被賦值,

//實測中,如下BAND配置是設置失敗的,因為20不被我的模組支持。合適的配置是3,5,8
#define CONFIG_BOUDICA150_BANDS  "5,8,20"
//from oc_lwm2m_imp_init
s_boudica150_oc_cb.bands = CONFIG_BOUDICA150_BANDS;

先看看,讓我高興的一句話,
在這里插入圖片描述
這個備注說明了,前邊boudica150_set_autoconnect傳0,進行失能操作,試圖關閉CFUN射頻功能的猜想是對的。

所謂頻段,是指3GPP標準定義的全球蜂窩網絡頻率范圍,直接影響模組與運營商基站的通信能力,每個頻段對應特定的上行(UL)和下行(DL)頻率,確保模組與運營商基站在同一頻段上收發信號,避免干擾。如,
Band 5:上行824-849MHz,下行869-894MHz
Band 8:上行880-915MHz,下行925-960MHz
不同國家/地區的運營商根據工信部或國際頻譜管理機構的授權使用特定頻段。以中國為例:
在這里插入圖片描述
要注意的是頻段由模組的射頻芯片(如高通MDM9205、海思Boudica 200)硬件支持,指令僅啟用/禁用特定頻段,這個事情或能力與SIM關系不大,SIM卡僅提供運營商身份認證(IMSI/Ki密鑰)和簽約數據,不參與物理頻段選擇。綜合上述分析,一個更合適的BAND配置應該是 3,5,8,而不是源碼中的那樣,但是有Band8就基本夠用了,所以早期實驗是成功的。我們通過NBAND測試指令,查詢指令等,也是可以確認我們SIM卡的頻段支持的,并確定源代碼示例中的設置過程是不生效的,
在這里插入圖片描述

set_plmn / AT+COPS

AT+COPS指令,用來選擇和注冊 EPS 網絡運營商。PLMN(Public Land Mobile Network,公共陸地移動網絡) 是由政府或運營商建立的移動通信網絡,用于為公眾提供無線通信服務。其核心標識由 MCC(移動國家碼) 和 MNC(移動網絡碼) 組成,例如中國移動的 PLMN 為 46000,中國聯通為 46001。我們在PC-AT實驗中也是用過的。這里首先看看,我的卡是哪個運營商的呢?
在這里插入圖片描述
AT+CIMI 請求國際移動用戶識別碼,其返回的是IMSI。
IMSI(國際移動用戶識別碼)和IMEI(國際移動設備識別碼)是兩種完全不同的標識符,分別用于識別SIM卡和物理設備。
在這里插入圖片描述
通過 CIMI號、COPS查詢結果,都可以斷定此SIM卡是中國移動運營商的。COPS/PLMN 選擇,在老文章中有講過,
在這里插入圖片描述
要注意的一點是,
當我們執行AT+CFUN=0關閉設備后,執行COPS查詢指令,結果為+COPS:2,即mode=2 注銷網絡。之后實驗中再執行AT+CFUN=1 打開射頻,COPS查詢結果不變,還是注銷狀態。只有執行AT+COPS=0后,才會注冊網絡,COPS才能查詢到有效信息,相關驗證過程,

AT+CFUN=0
OKAT+COPS?
+COPS:2
OKAT+CFUN=1
OK
AT+COPS?
+COPS:2
OKAT+COPS=0
OK
+QDTLSSTAT:0
+QLWEVTIND:0
+QLWEVTIND:3AT+COPS?
+COPS:0,2,"46000"
OK

接下來,我們回到boudica150源碼中,

static bool_t boudica120_set_plmn(const char *plmn) {if (NULL != plmn) {ret = boudica120_atcmd_response("AT+COPS?\r","+COPS",resp,64);...//which means we need to set itif((false == ret)||(NULL == strstr(resp,cmd))) {(void) snprintf(cmd,63,"AT+COPS=1,2,\"%s\"\r",plmn);}//HCIP-Lab源碼中,走的就是這個分支else {(void) snprintf(cmd,64,"AT+COPS=0\r");ret = boudica150_atcmd(cmd,"OK");}...
}//實際上該宏在代碼中并未被使用,//初始化函數中s_boudica150_oc_cb.plmn = NULL;
#define CONFIG_BOUDICA150_PLMN  "460001"

在源碼中,BOUDICA150_PLMN,被配置為46001,這是中國聯通,好在源碼中并沒有使用,否則就又多一個烏龍。前文我們已經談到過,我使用的SIM卡其是46008中國移動物聯網號段,COPS查詢到的國家代碼和運營商代碼是46000,中國移動。
一開始我沒有注意到 NULL != plmn 的判斷,還擔心了會,因為我知道,
C99/C11標準(§7.21.6.5)和C++標準均未明確定義%s接收NULL時的行為,屬于未定義行為,這是非常危險的。
好在虛驚一場,_set_plmn處理了plmn是空的情況,且boudica150初始化函數中,使用的就是NULL。在此場景下,上述函數就是執行了一次 AT+COPS=0,這與我們在PC-AT實驗中的方式是一致的。

我們也要看懂手動模式的PLMN選擇,其3個參數如下,
在這里插入圖片描述

_set_apn / AT+CGDCONT

該過程名為設置APN。APN 即 Access Point Name,接入點名稱。 APN是移動通信網絡中的一個關鍵參數,用于標識設備接入運營商數據網絡的方式。它決定了設備如何連接到互聯網、企業專網或其他數據服務,并影響IP地址分配、計費策略和網絡服務質量。
在這里插入圖片描述
源碼中出現的 _APN “cmnet” 是未被使用的,即使用了也不對。CMNET 是中國移動(China Mobile)的傳統移動互聯網APN,主要用于2G/3G/4G數據業務,而非專為NB-IoT設計,可能以前是能用的,現在不行了估計。
AT+CGDCONT,我們打開BC28的AT指令使用手冊,該指令看上去非常復雜,
在這里插入圖片描述
從設置指令格式上看,源碼中的格式似乎不咋對啊,在PC串口終端中進行嘗試,也確實總返回ERROR。好在我們的源碼中,apn字符串是被初始化為NULL的,與plmn被初始化為NULL交相呼應。在我們的源碼中,本質上_set_apn函數啥也沒干,太累不展開了。

(安全)接入參數 CDP+DTLS+PSK

參見 #<IoT/實現和分析 NB-IoT+DTLS+PSK 接入華為云物聯網平臺IoTDA過程,總結避坑攻略>#

AT+NNMI 設置新消息指示

在移遠通信的AT指令手冊中,這個指令的功能表述非常的爛,讓人不好理解,甚至是錯誤的。一個修正后的表述如下,
該命令用于配置模組在接收到LwM2M平臺下發的消息后,如何向主機(Host)發送新消息到達的指示。UE 從 LwM2M 物聯網平臺接收到一個下行消息后會發送新消息指示。這里,所謂的消息(可含數據),是指平臺到NB通信模組的消息數據,而消息指示是模組對MCU主機的一種異步通信機制。NNMI 默認值為 1,模塊重啟后 會還原到默認值。
在這里插入圖片描述
AT+NNMI=1 使能新消息指示和數據,會返回當前所有緩存的消息,格式為 +NNMI:,。
例如,+NNMI:5,48656C6C6F。
AT+NNMI=2 僅使能新消息指示,每次收到新的消息都會觸發指示 URC,響應結果格式為:+NNMI。
可以通過命令 AT+NMGR 接收緩存消息。

_check_netattach 網絡附著狀態

上述函數的本質是在循環執行 AT+CGATT? 查詢操作,
在這里插入圖片描述
我們在前文操作中執行了AT+CGATT=1,試圖將 MT 附著于 PS 域,這個附著過程是需要時間的,_check_netattach是在等待成功。這里重點關注上圖中紅色標注的部分,其表明在網絡附著一旦成功后,將自動執行 AT+COPS=0,即

AT+COPS=0 和 AT+CGATT=1

按照源碼中的接入流程,先被執行的是 AT+COPS=0 自動選擇和注冊 EPS 網絡運營商,之后又執行了一次 AT+CGATT=1 將 MT 附著于 PS 域,最后再循環執行AT+CGATT?查詢用戶設備網絡附著狀態。同時,我們在CGATT的指令備注中可以看到,AT+CGATT=1 的過程會自動選擇 AT+COPS=0。實際上,在NB-IoT模組的網絡注冊流程中,AT+CGATT=1 和 AT+COPS=0 的功能既有重疊又有分工。AT+CGATT=1 設置工作的第一步是檢查與COPS指令操作結果相關的EPS注冊狀態,若不符合,則會先執行 AT+COPS=0 指令。詳細過程如下:

AT+COPS=0 的獨立功能,僅完成EPS網絡注冊(無線接入網和核心網控制面),主要包含以下工作:
1、PLMN選擇:自動搜索并注冊優先級最高的運營商網絡(如中國移動46000)。
2、RRC/NAS層連接:與基站(eNodeB)和MME完成控制面信令交互(鑒權、安全模式激活)。
結果狀態對應如上兩個功能:
AT+COPS? 返回運營商名稱(如"CHINA MOBILE") AT+CEREG? 返回EPS注冊狀態(如+CEREG: 1,1表示已注冊)
在這里插入圖片描述

AT+CGATT=1 的本職功能,即 PS 域專屬功能(扣除AT+COPS=0后)
1、PDP上下文激活:向PGW申請IP地址(依賴APN配置,如cmnbiot)。核心網建立SGW→PGW的數據通道(默認承載QCI=9)。
2、IP地址分配:動態獲取IPv4/IPv6地址(可通過AT+CGPADDR查詢)。
3、數據就緒狀態:AT+CGACT?返回1,1(默認承載已激活)。模組可進行TCP/UDP通信(仍需APN正確)。

總結下來,設備接入運營商的主要的幾個步驟,PLMN選擇、EPS注冊、PS附著、IP地址分配,大約流程如下:
在這里插入圖片描述
其他補充:
PS域(Packet Switched Domain,分組交換域)是移動通信網絡中用于處理數據業務的邏輯域,其核心特點是通過分組交換技術實現高效的數據傳輸。PS域采用分組交換(Packet Switching)機制,將數據拆分為多個帶地址標識的“分組”(數據包),每個分組獨立傳輸并通過最優路徑到達目的地,接收端重新組裝為完整數據。PS域并非物理上的地理區域,而是邏輯上的業務承載劃分。其覆蓋范圍由核心網設備互聯構成,用戶通過無線接入網(如基站)接入PS域,實現數據業務的端到端傳輸。運營商需在核心網中部署PS域設備(如SGSN、GGSN、SGW/PGW等),并通過策略控制(如PCRF)實現流量管理、計費和服務質量(QoS)保障。用戶通過AT+CGATT命令附著PS域時,終端與核心網完成鑒權(AT+COPS的作用)、IP地址分配等流程,建立數據會話(PDP上下文),從而接入互聯網。

_check_observe網絡附著狀態

網絡附著成功后,也即 CGATT查詢到狀態1后,即數據會話(PDP上下文)已經被成功建立。接下來設備就要真正去和物聯網平臺握手交互了啦,我最初的問題是,psk、dtls等配置信息是在哪個指令環節中使用的呢?AT+QREGSWT指令只是設置了一種平臺注冊模式,并沒有真正啟動注冊過程。我們以自動觸發模式為例,結合我對lwm2m_tiny(wifi通信時使用的)的已有的部分理解,
當網絡附著CGATT成功后,NB模組內的固件程序就會,
通過CoAP協議向LwM2M服務器(如coap://lwm2m.iot.platform.com)發送Register請求,攜帶 Endpoint Client Name、Lifetime、dtls、psk 等參數。模組固件的實際代碼實現我們暫時看不到,但我猜測,其與lwm2m_tiny源碼的如下實現基本一致,

static int agent_add_objects(void *handle, atiny_param_t *lwm2m_params) {int ret = (int) ATINY_ERR;ret = agent_add_security_object(handle, lwm2m_params);  // 安全對象(ID=0) //psk秘鑰用在這里哦ret = agent_add_server_object(handle, lwm2m_params);    // 服務器對象(ID=1)ret = agent_add_acc_ctrl_object(handle);                // 訪問控制對象(ID=2)ret = agent_add_device_object(handle);                  // 設備對象(ID=3)ret = agent_add_conn_m_object(handle);                  // 連接監控對象(ID=4)ret = agent_add_firmware_object(handle);                // 固件對象(ID=5)ret = agent_add_location_object(handle);                // 位置對象(ID=6)// 二進制應用數據對象(ID=19)ret = agent_add_binary_app_data_object(handle, &(lwm2m_params->server_params.storing_cnt));     return ret;
}

上述操作,添加了7種標準對象和1種擴展標準對象,具體如下表,
在這里插入圖片描述
呢?在上述理解的基礎上,我們再回到NB源碼的 _check_observe 函數,就好理解多了,

//unit second
static bool_t boudica150_check_observe(int time)  {//wait for the server observedbool_t ret = false;  int times;for(times =0;times <time;times++ ) {if(s_boudica150_oc_cb.lwm2m_observe) {ret = true;break;}osal_task_sleep(1000);}return ret;
}

函數很簡單,就是在循環著檢查 s_boudica150_oc_cb.lwm2m_observe 標志字,該標記只在如下回調函數實現中賦值,

#define cn_urc_qlwevtind           "\r\n+QLWEVTIND:"//wait for the lwm2m observe
static int urc_qlwevtind(void *args,void *msg,size_t len) {   ...index_str = strlen(cn_urc_qlwevtind);if(len > index_str) {ind = data[index_str]-'0';LINK_LOG_DEBUG("GET THE LWM2M:ind:%d\n\r",ind);if(ind == 3) { //這是關鍵哦,s_boudica150_oc_cb.lwm2m_observe = true;}}return len;
}

urc_qlwevtind 函數是在 boudica150_boot 函數的一開始被注冊的,它是urc消息處理函數,與前邊我們進行NNMI設置密切相關。

urc_qlwevtind

在 #<IoT/基于NB28-A/BC28-CNV通信模組使用AT指令連接華為云IoTDA平臺># 中,我們已經知道,
若設備注冊平臺成功,就會看到兩條異步消息+QLWEVTIND:0和+QLWEVTIND:3,表明我們可以使用數據傳輸相關AT指令和平臺進行通訊啦,平臺設備也會變為在線。
在這里插入圖片描述
URC(Unsolicited Result Code,非請求結果碼)是AT指令通信中的一種異步通知機制,用于設備(如NB-IoT模組)主動向主機(MCU/處理器)推送狀態變化或事件,無需主機主動查詢。URC廣泛應用于網絡狀態、短信接收、數據到達等場景。
+QLWEVTIND:0
通知主機,平臺注冊流程已啟動,但尚未獲得平臺最終確認,主機應等待+QLWEVTIND:3(注冊成功)后再發送業務數據。此時的底層狀態大約是模組已附著PS域(AT+CGATT=1成功)、已解析平臺地址。
+QLWEVTIND:3
通知主機,平臺注冊完成,可安全使用數據傳輸指令。此時底層的狀態大約為,平臺已分配資源路徑(如/12345/0/1)、設備狀態在平臺顯示為在線。LwM2M平臺注冊成功,模組已收到平臺的最終確認(如2.01 Created響應)時,會觸發此URC消息。

如下 NB-IoT-AT 代碼實現,就是上述理論和工作機制的一種具體實踐,

//
static bool_t boudica150_boot(const char *plmn, const char *apn, const char *bands,const char *server,const char *port) {at_oobregister("qlwevind",cn_urc_qlwevtind,strlen(cn_urc_qlwevtind),urc_qlwevtind,NULL);...
}//
int at_oobregister(const char *name,const void *index,size_t len,fn_at_oob func,void *args) {...oob->func = func;oob->args = args;
}//check if any out of band method could deal the data
static int  __oob_match(void *data,size_t len) {int ret = -1;at_oob_item *oob;int i = 0;for(i =0;i<CONFIG_AT_OOBTABLEN;i++) {oob = &g_at_cb.oob[i];if((oob->func != NULL)&&(oob->index != NULL) && (0 == memcmp(oob->index,data,oob->len))) {ret = oob->func(oob->args,data,len);  //執行回調函數urc_qlwevtind break;}}return ret;
}
//任務入口函數
static int __rcv_task_entry(void *args) {while(NULL != g_at_cb.devhandle)   {if (1 == g_at_cb.streammode) {rcvlen += __resp_rcv(g_at_cb.rcvbuf+ rcvlen,CONFIG_AT_RECVMAXLEN,cn_osal_timeout_forever);...oobret = __oob_match(g_at_cb.rcvbuf,rcvlen);...

函數 __oob_match 實現在 \iot_link\at\at.c 文件中,而 _oob_match 函數在 __rcv_task_entry 接收任務入口函數中調用。上述接收任務器消息來源可能是串口數據接收任務或中斷服務,這個問題我們在后續新文章中繼續探討。

總結和后記

boudica150_boot 函數上層相關的源碼解析,請參考#<IoT/實現和分析 NB-IoT+DTLS+PSK 接入華為云物聯網平臺IoTDA過程,總結避坑攻略>#
boudica150_boot 函數下層相關的源碼解析,請參考#<…>#

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93100.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93100.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93100.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android UI(一)登錄注冊 - Compose

UI - 登錄注冊 - Compose一、聲明式UI1. **顛覆傳統開發模式**2. **技術優勢**3. **開發效率提升**4. **未來生態方向**5. **實際影響**二、創建項目1. Compose UI結構2. Scaffold3. 可組合函數三、創建組件頁面1. LoginPage2. RegisterPage3. MainPage四、導航1. 添加依賴2. 使…

分享10個ai生成ppt網站(附ai生成ppt入口)

實測對比&#xff1a;15頁PPT從3小時壓縮到3分鐘的秘密武器 當ChatGPT能寫方案、Midjourney能畫圖&#xff0c;做PPT還在手動排版就OUT了&#xff01;這些AI生成PPT網站已實現「輸入文案秒出設計稿」&#xff0c;無論職場匯報、畢業答辯還是路演融資&#xff0c;零設計基礎也能…

最強開源視頻模型通義萬相wan2.1在comfyui中的安裝應用詳解

摘要&#xff1a;阿里巴巴開源通義萬相Wan2.1模型&#xff0c;支持文生視頻、圖生視頻等多種功能&#xff0c;并整合關鍵環節簡化創作流程。官方和Kiji版本需配套使用各自工作流。低顯存顯卡可使用GGUF模型解決方案&#xff0c;最低適配4G顯存。ComfyUI已原生支持該模型&#x…

機器學習:基于OpenCV和Python的智能圖像處理 實戰

機器學習&#xff1a;基于OpenCV和Python的智能圖像處理實戰——待填坑圖像處理基礎圖像的基本表示方法圖像處理的基本操作圖像運算圖像的色彩空間轉換圖像幾何變換4.1 仿射變換4.2 重映射4.3 投影變換 4.4 極坐標變換5 圖像直方圖處理7 圖像閾值處理8 圖像形態學處理github地址…

proteus實現簡易DS18B20溫度計(stm32)

一、新建proteus工程 具體看前面文章 二、搭建電路 需要配置供電網絡以及尋找元器件&#xff0c;細節看前面文章&#xff0c;下面給出電路圖 電路包含了五個部分&#xff1a; 1、DS18B20&#xff1a;數據引腳記得上拉 2、stm32電路 3、串口電路&#xff08;右下角那個器件…

Autoppt-AI驅動的演示文稿生成工具

本文轉載自&#xff1a;Autoppt-AI驅動的演示文稿生成工具 - Hello123工具導航 ** 一、 Autoppt&#xff1a;AI 驅動的智能演示文稿生成工具 Autoppt 是一款基于人工智能的在線演示文稿生成平臺&#xff0c;通過輸入主題或上傳文檔&#xff08;Word/PDF/ 圖片等&#xff09;&…

Flink on YARN啟動全流程深度解析

Flink on YARN 模式啟動流程及核心組件協作詳解整個過程分為三個主要階段&#xff1a;??JobManager 啟動??&#xff08;作業提交與 AM 初始化&#xff09;??TaskManager 資源分配與啟動????任務部署與執行??第一階段&#xff1a;作業提交與 JobManager (AM) 啟動?…

安卓開發者自學鴻蒙開發1基礎入門

1.基礎 聲明式UI&#xff1a;?? ??核心&#xff1a;?? 你??聲明??你想要UI是什么樣子&#xff08;在build()方法里描述&#xff09;&#xff0c;而不是一步步命令式地創建和操作View對象&#xff08;findViewById, setText, setOnClickListener&#xff09;。 模塊化…

彈性擴展新范式:分布式LLM計算的FastMCP解決方案

本文較長&#xff0c;建議點贊收藏&#xff0c;以免遺失。更多AI大模型應用開發學習視頻及資料&#xff0c;盡在聚客AI學院。如果你想系統學習AI大模型應用開發&#xff0c;挑戰AI高薪崗位&#xff0c;可在文章底部聯系。在現代大語言模型&#xff08;LLM&#xff09;應用架構中…

springboot項目不同平臺項目通過http接口AES加密傳輸

前言&#xff1a; 在公司協作開發的過程中&#xff0c;自己的項目是公共調用平臺&#xff0c;也可以說是中轉平臺&#xff0c;供公司其他團隊的項目進行接口調用。因為是不同團隊項目之間的相互調用&#xff0c;所以不能通過openFeign遠程調用。只能通過http遠程調用&#xff…

推薦5個網頁模板資源網

1. 企業模板官方網站&#xff1a; http://www.qimoban.com介紹&#xff1a;企業模板(qimoban.com )是一個專注于提供豐富多樣的企業模板的優質平臺&#xff0c;致力于為企業和個人打造高效、專業、個性化的模板獲取渠道。該平臺提供海量的企業模板資源&#xff0c;涵蓋企業官網…

Redis持久化機制(RDB AOF)

1. RDB RDB 持久化是把當前進程數據生成快照保存到硬盤的過程&#xff0c;觸發 RDB 持久化過程分為手動觸發和 自動觸發&#xff0c;存儲的是二進制數據。 1.1 手動觸發 使用 save 和 bgsave 命令觸發&#xff1a; save&#xff1a;Redis服務主進程阻塞式執行持久化操作&…

【css】讓瀏覽器支持小于12px的文字

【css】讓瀏覽器支持小于12px的文字.demo {display: inline-block;/** 使用Webkit引擎的變換屬性&#xff08;主要針對舊版Safari/Chrome&#xff09; **/-webkit-transform: scale(0.8); }注意&#xff1a;display: inline-block; 一定要加上&#xff01;1.transform: scale(…

機器學習-基礎入門:從概念到核心方法論

在人工智能飛速發展的今天&#xff0c;機器學習作為其核心技術&#xff0c;正深刻改變著我們的生活與工作。從 AlphaGo 戰勝圍棋世界冠軍&#xff0c;到日常的智能推薦、人臉識別&#xff0c;機器學習的應用無處不在。本文將從基礎概念出發&#xff0c;帶你系統了解機器學習的核…

《Leetcode》-面試題-hot100-動態規劃

題目列表 70. 爬樓梯 簡單難度 leetcode鏈接 118. 楊輝三角 簡單難度 leetcode鏈接 198. 打家劫舍 中等難度 leetcode鏈接 279.完全平方數 中等難度 leetcode鏈接 322.零錢兌換 中等難度 leetcode鏈接 139.單詞拆分 中等難度 leetcode鏈接 300.最長遞增子序列 中等難度 l…

數巔中標中建科技AI知識庫項目,開啟建筑業數智化新篇章

AI正以前所未有的迅猛態勢滲透進建筑業的每一處脈絡。在這場數智化轉型浪潮中&#xff0c;AI技術如何與建筑業基因深度融合&#xff1f;如何充分釋放數據價值&#xff1f;近日&#xff0c;數巔成功中標中建科技集團有限公司“企業AI知識庫研發”項目&#xff0c;這一“大語言模…

想要PDF翻譯保留格式?用對工具是關鍵

嘿&#xff0c;朋友&#xff01;最近有沒有被PDF翻譯的事兒搞得焦頭爛額呀&#xff1f;尤其是碰到韓文PDF文件的時候&#xff0c;是不是更頭疼了&#xff1f;別擔心&#xff0c;我最近也遇到了類似的問題&#xff0c;試了不少軟件&#xff0c;發現有五款軟件在處理韓文PDF翻譯時…

【MySQL?】服務器安裝 MySQL 及配置相關操作

1. 安裝 MySQL 在安裝 MySQL 時&#xff0c;如果使用官方 RPM 源&#xff0c;會遇到 GPG 密鑰驗證失敗的錯誤&#xff0c;可以按照以下步驟解決&#xff1a; 解決 GPG 密鑰驗證失敗的問題下載 MySQL 官方 GPG 密鑰 使用以下命令下載并安裝 MySQL 的官方 GPG 密鑰&#xff1a; w…

大數據量返回方案(非分頁)

一、普通方式返回100萬條數據RestController RequestMapping("/bad") public class BadController {Autowiredprivate UserRepository userRepository;/*** 危險&#xff01;一次性加載 100 萬條到內存*/GetMapping("/all-users")public List<User> …

基于Casbin的微服務細粒度權限控制方案對比與實踐

基于Casbin的微服務細粒度權限控制方案對比與實踐 隨著微服務架構在互聯網和企業級應用中的廣泛應用&#xff0c;服務間的安全邊界愈發重要。傳統的集中式權限控制方式已難以滿足微服務的高并發、動態擴展和多語言支持等需求。本文將從主流的三種微服務權限控制方案入手&#x…