nRF9151蜂窝模组简介与定位例程解析
1. 简介
产品
nRF9151是支持NB-IoT和CAT-M的低功耗蜂窝LTE模组。支持OpenMCU开发,和Nordic其他产品线统一SDK。支持GPS定位。
nRF Cloud是部署在AWS上的物联网云。支持MQTT和HTTPS(REST)API。提供设备注册、设备管理、OTA、定位(基站定位、Wi-Fi定位、AGPS、PGPS)等服务。
nRF7002是一个2.4G/5G低功耗双频Wi-Fi6收发器,可以用来模拟nRF7000。nRF7000是一个只能scan,不能connect的wifi6双频收发器,主要用于做Wi-Fi定位。
本文内容
介绍如何搭建环境、编译nrf_cloud_multi_service工程。这是一个支持多个nRF Cloud服务的设备端工程。让nRF9151连接到nRF Cloud云端,并进行GPS定位、基站定位、Wi-Fi定位。
介绍如何进行Modem Trace抓包分析基站内容。
分析代码框架思路。
2. 硬件准备
- nRF9151开发板(或其他91系列开发板)
- NB-IoT物联网卡,这里是中国移动的。左边是开发板送的2张卡,在国内不好用。
- (可选)nRF7002EK。
关于SIM卡:
- 9151DK赠送的两张卡(Onomondo和Wireless Logic)都是预先激活好的,不需要再次激活,并且带有一定的流量和使用期限。如果扫描二维码进行注册,可以获得更多的免费流量。
- Onomondo和Wireless Logic是虚拟运营商。他们会和全球的运营商合作,让自己的卡能够漫游到全球大部分地区,支持CAT-M和NB-IoT。具体覆盖范围可以去他们官网查询。国内在上海我试过Onomondo的NB IoT是可用的,Wireless Logic没有漫游成功。
- 使用国内的物联网卡,如中国移动的物联网卡时,注意是要支持NB-IoT的,并且注意国内的卡都会锁设备。也就是说新卡一但在一台设备上使用了,就不能换到其他设备上了。
3. 软件准备
安装开发环境与烧录工具
首先按照《nRF Connect SDK安装与入门》装好开发环境NCS v2.9.0,相关工具(nRF Connect for Desktop, nrfutil, Jlink驱动等)。
烧录Modem Firmware
在9151官网页面下载最新版Modem Firmware (MFW)。
MFW是Modem专门的固件,是不开源的,以zip包的形式提供。Modem有独立的CPU和存储空间,不占用App Core的Flash和RAM。
可以用nRF Connect for Desktop里面的Programmer烧录。
也可以用nrfutil命令行操作:
nrfutil self-upgrade |
配置模拟开关
nRF9160无需此步骤。
目前比较新的开发板都使用Interface MCU来控制板子上的模拟开关,而非物理开关。通过nRF Connect for Desktop上的Board Configurator控制。
nRF9151DK上有两种方式可以连接LEDs和Buttons。一种是GPIO直连,一种是通过I2C接口的IO扩展器连接。
如果你要使用7002EK扩展Wi-Fi功能,那么默认的LED就会占用7002要用的GPIO。因此,7002EK的DeviceTree文件会使能I2C接口的IO扩展器。
见zephyr/boards/nordic/nrf9151dk/dts/nrf9151dk_leds_on_io_expander.dtsi
。
对应地就需要在开发板上把模拟开关切换到IO扩展器。使用nRF Connect for Desktop的Board Configurator来配置:
配置完毕后点击左边写入。这里写入是把配置写入到板子上的Interface MCU(即Jlink DEBUGGER)中。
4. 修改、编译并烧录例程
通过copy a sample的形式复制并创建例程nRF Could Multi Service(v2.9.0/nrf/samples/cellular/nrf_cloud_multi_service
)。
修改prj.conf
,增加以下内容
移动物联网卡需要单独配置PDN |
创建编译目标。如果有7002ek,就增加以下参数。如果没有就不加:
也可以用命令行编译:
west build -p \ |
- 这个CMake参数等价于在CMakeLists.txt的开头写
set(SHIELD nrf7002ek_nrf7000)
,也就是会把7002ek这个扩展板的Kconfig配置和设备树overlay附加到当前工程的nrf9151板子上。- 7002ek有很多变体(
nrf7002ek
,nrf7002ek_7001
,nrf7002ek_7000
)。硬件上是2.4G/5GHz双频的nRF7002,通过这种变体配置来模拟7001(只有2.4GHz)和7000(只能scan不能连接)
[447/447] Linking C executable zephyr/zephyr.elf |
编译完成后可以看到应用和bootloader的占用。
然后烧录,使用nRF Connect for Desktop中的Serial Monitor查看串口:
能观察到:
- nRF Cloud的客户端ID是UUID,不是IMEI
- 设备可以附着基站,可以连网。但是无法连接到nRF Cloud MQTT
5. nRF Cloud设备注册简介
设备注册
nRF Cloud是Nordic的物联网云服务器,设置在AWS上,有设备托管、OTA、位置定位等服务。开放MQTT和HTTP(REST)的接口。
此例程需要把设备注册(Provision)到nRF Cloud上。
所谓的设备注册,就是让云端把这台设备的ID等信息注册在在你的个人账户下。除此之外,设备端和云端还需要各自持有对方的TLS证书(公钥),这样才能进行双向的认证和加密。
这里,云端的证书就是AWS的根证书,而设备端的证书是X.509格式的设备证书。
证书文件
要阅读这部分,首先你需要了解非对称加密和TLS证书。
设备内部需要三个证书文件(credentials):
- 服务器根证书(Root CA):这里是AWS根证书,用于确保自己连接的云服务器不是冒充的
- 设备证书(Client certificate):预先给云服务器上传此证书。后续进行访问时,云服务器通过证书来验证设备是否真正是注册的设备。
- 设备私钥(Client private key):通过密钥加密的数据,可以用设备证书携带的公钥解密。因此持有密钥的设备就是证书代表的设备。
这三个文件都是存储在Modem里面的,不占用Application Core的flash空间。
要管理modem里的证书,需要通过AT%CMNG
命令来操作。可以写入云服务器的证书、自动生成证书和私钥等。
%CMNG=<opcode>[,<sec_tag>[,<type>[,<content>[,<passwd>]]]] |
这里<opcode>
代表写、读等操作。
<sec_tag>
很重要,代表的是一组证书的句柄标签,范围是0–2147483647。例如,nRF Cloud的句柄就是16842753。当代码中通过网络访问nRF Cloud时,就通过16842753这个sec tag来获取到对应的证书,进行TLS通讯。
<type>
代表这个密钥文件的类型:
- 0 – Root CA certificate (ASCII text).
- 1 – Client certificate (ASCII text).
- 2 – Client private key (ASCII text).
- ……
同一个sec_tag之下,可以存一组证书文件。这里指的就是不同的<type>
。这里我们连接nRF Cloud,就需要0, 1, 2这三种整数文件。
某些云平台会直接把这三个证书文件都生成好,让你把服务器根证书、设备证书和设备私钥直接烧录到设备中。这种方式有暴露设备私钥的风险(毕竟经历了云端,下载到PC,再烧录到设备)。
nRF91系列可以直接在设备上生成私钥,使用AT%KEYGEN
命令生成。私钥生成后无法读出,可以调用API使用这个私钥来进行加密、解密,但是绝对无法读取到私钥本身。而设备证书是可以读取的。
更多参数详见:https://docs.nordicsemi.com/bundle/ref_at_commands_nrf91x1/page/REF/at_commands/security/cmng.html
所有证书文件操作时都必须先关闭网络(
AT+CFUN=4
)
nRF Cloud注册方式
通过前面的介绍,我们知道配网需要完成2件事:
- 把服务器的根证书存储到设备上
- 把设备的证书上传到服务器,并且确保设备中有该证书对应的私钥
nRF Cloud提供3种注册方式:
1. 连接前注册(Preconnect onboarding)
设备在生产完成后,还没有连网,就注册到云端。
可以用电脑手动给云端上传一个csv表格,里面包含设备的ID和证书公钥等信息。适合设备在生产时阶段就批量注册到云端的情况。
其中,证书的来源又有2种:
- 用
AT%KEYGEN
让设备自动生成证书与私钥,再把证书记录到表格中(安全) - 先用电脑生成好设备证书和私钥,然后烧录到设备中(可能不安全)
前者对应文档:Onboarding a device without the nRF Cloud Provisioning Service;
后者对应文档:Onboarding with hard-coded device credentials
2. 部署时注册(Auto-onboarding)
设备在生产完成后不注册到云端。而是等到现场部署时,再通过现场的人员操作进行证书生成、云端注册。
这需要在编译时,就在代码中开启Provisionning Service相关的配置。
本文不介绍这种方式,可以参考官方文档:https://docs.nordicsemi.com/bundle/ncs-2.9.0/page/nrf/samples/cellular/nrf_cloud_multi_service/README.html#provisioning_with_the_nrf_cloud_provisioning_service
3. JITP(Just-in-Time provisioning)
用于开发板评估的快速注册。由于开发板生产时都烧录好了证书,nRF Cloud也已经存储了这些证书。只需要扫描二维码就能把这个开发板对应的证书绑定到你的nRF Cloud账号里。
但是如果你已经重新烧了modem firmware,或者是量产的产品,则不能使用这种方式。
https://docs.nordicsemi.com/bundle/nrf-cloud/page/Devices/Associations/Onboarding.html#jitp
6. 将设备注册到nRF Cloud
注册nRF Cloud账号并获取API Key
- 免费注册一个 nRF Cloud 账号
注册登录后,右上角进入User Account界面
记录自己的API Key。
注意:API Key非常重要,可以通过API Key控制你账号下的所有设备、所有权限、调用付费API等。千万不能泄露!!!
如果你怀疑API Key泄露,可以点击右边的Regenerate API Key重新生成。
安装nRF Cloud Utils
需要python3环境。
可以直接用pip安装:
pip3 install nrfcloud-utils |
也可以直接clone仓库:https://github.com/nRFCloud/utils/
如果是pip安装,则直接执行命令,如
create_ca_cert
。如果是clone方式安装,则进入
src /nrfcloud_utils/
,然后执行脚本,如create_ca_cert.py
推荐以pip安装的方式进行。
设置临时环境变量
在命令行中设置临时环境变量,方便后面执行脚本
# Linux |
# Windows Powershell |
生成自签CA证书
生成一个你自己签名的根证书,私钥由你持有。后续所有的设备证书都由这个CA证书来签发。
create_ca_cert \ |
参数解释可查看
create_ca_cert --help
。证书会生成到-p
参数指定的目录下,这里是/my_ca
文件分别为:证书、私钥、公钥。
其中证书内包含公钥。
给设备签发设备证书
让设备生成公私钥,利用自签CA给设备签发设备证书,并把设备证书保存到csv表格中。
device_credentials_installer \ |
-d
:安装前先从Modem中删除sectag-t
:用于设备分组管理的标签,是一个字符串-T
:设置自定义的子类型,如温湿度传感器等,是一个字符串。此处未设置--ca
:CA证书文件的路径--ca-key
:CA证书私钥的路径(prv)-a
或--append
:保存设备注册信息到csv表格文件时,向末尾增加新的条目,而不是覆盖csv文件(这个选项是确保你可以重复执行脚本,搜集全部设备信息的基础)--devinfo-append
:保存设备信息到csv表格文件时,向末尾增加新的条目,而不是覆盖csv文件(这个选项是确保你可以重复执行脚本,搜集全部设备信息的基础)--csv
:用于存储设备注册信息的CSV表格的文件名,若文件不存在则创建。若文件存在,则根据-a
选项,向文件中添加新条目。(存储UUID、前缀、固件等信息)--devinfo
:用于存储设备信息的CSV表格的文件名,若文件不存在则创建。若文件存在,则根据-a
选项,向文件中添加新条目。(存储UUID、Modem固件版本、芯片IMEI等信息)--term
:AT指令的结束符(NULL
,CRLF
,CR
或LF
)--port
:指定AT指令串口(windows上是COM口,Linux上是/dev/tty*)
公私钥生成后,脚本自动读取了设备信息并将其保存到了csv表格中。
由于添加了-a
和--devinfo-append
,如果你有多个设备要注册,这些信息会追加添加到表格中。
注册时,最大支持一次性注册3000台设备。
这种方式是用
AT%KEYGEN
自动生成私钥的,比较安全。如果你想用前面提到的“先用电脑生成设备私钥,再烧录进去”的方式。可以参考:
create_device_credentials
命令来进行生成。然后用AT%CMNG
命令烧录三个证书文件(服务器CA证书、设备证书、设备私钥)。烧录前记得AT+CFUN=4关闭网络。AWS IoT CA证书在这里下载(https://www.amazontrust.com/repository/AmazonRootCA1.pem)
把注册信息上传到云端
可以继续使用命令
nrf_cloud_onboard --api-key $API_KEY --csv jayant_provision.csv |
利用前面获得的API_KEY来上传csv表格,注册设备。
也可以直接在网页端操作:
选择批量注册:
然后把jayant_provision.csv
表格拖进去就可以注册了。
检查连网情况
由于安装证书时,设备被设置为飞行模式。这里打开串口,再reset一下。
可以看到设备成功连网并访问到nRF Cloud.
7. 查看定位
我们进入nRF Cloud会发现设备已经上线:
点击ID进入设备详情页:
可以看到,设备通过MQTT已经上传了经纬度。同时,网页通过谷歌地图渲染了这个经纬度的地点(需要翻墙代理才能看到)。
并且根据颜色不同,有单基站、多基站、Wi-Fi和GPS定位:
我这里在室内,所以GPS定位失败。但是Wi-Fi定位还是很准的。
8. Modem Trace抓包
本节介绍如何进行Modem Trace抓包。Modem Trace就是让nRF9151和基站之间交互的数据包以二进制格式通过串口等方式输出,方便进行抓包调试。
要使能Modem Trace,需要打开一些config和进行一些设备树配置。Zephyr中支持通过snippets的形式提供一组config和设备树配置,这样就不用一个一个手动添加了。
在Build Configuration中添加nrf91-modem-trace-uart
即可。
如果是命令行编译的方法,就添加-D<image_name>_SNIPPET="nrf91-modem-trace-uart"
参数,如:
west build -p \ |
如果你想查看snippets具体添加了哪些配置,可以查看Build信息:
可以看到使用的是串口1,波特率1M:
编译完毕后重新烧录固件。
把9151DK通过USB连接到电脑。在nRF Connect for Desktop中打开Cellular Monitor:
nRF9151的UART0和UART1,在板子上直接连到Jink USB的,因此无需再接串口。
这里一个串口是日志输出和AT Commands通道,另一个是Modem Trace,注意不要选错。Modem Trace database选择你下载的Modem Firmware的版本。
nRF Connect下的所有软件可以共享串口,所以你可以同时打开“Open Serial Terminal”,查看日志和AT Commands.
之后点击Start就可以开始抓包:
左下角为抓包文件存储位置。
你也可以在Start之前,打开“Open in Wireshark”: