为了方便树莓派(Raspbery Pi)、工业型嵌入式计算机、嵌入式物联网开发板及各型个人计算机或工业计算机(IPC),可以直接利用USB连接LPWAN通讯模块,这里分享了一款以MTK MT2625设计的USB Dongle 可以让您快速利用树莓派Python 语言或x86 Base 的IPC以 .NET架构连接USB NB-IoT存取云端信息。
这款NB-IoT USB Dongle 采用Quectel BC26/BC66模块 (内建MTK MT2625 NB-IoT芯片),外观如下,可直接与树莓派、计算机连接或透过USB OTG 线与手机连接。
BC26/BC66内建国产MTK MT2625 NB-IoT芯片,完整功能规格如下:
1.支持全球NB-IoT频段:
完整支持B1/B2/B3/B4/B5/B8/B12/B13/B17/B18/B19/B20/B25/B26/B28/B66等频段。
2.通讯传输速率:
• Single-Tone :下行: 25.5kbps ;上行: 16.7kbps
• Multi-Tone :下行: 25.5kbps ;上行: 62.5kbps
3.支持讯协议:
UDP/TCP/CoAP/LwM2M/MQTT/*PPP/*SNTP/*TLS/*DTLS/*HTTP/*HTTPS/*FTP。
(注*: 陆续推出支持协议)
4.支持AT 指令集:3GPP Rel.13 /14以及 Quectel 增强型 AT 命令。
5.支持串行端口(UART)数:
3组(信讯电位为1.8V),串行端口传输速率均支持4800bps、9600bps、 115200bps、 230400bps、460800bps 和 921600bps(预设为115200bps)。
6.BC26/BC66可支持内置eSIM卡:可搭配设计eSIM芯片来取代传统SIM卡。
7.供电特性:低供电电压范围(2.1V~3.63V),适合锂锰、锂亚电池直接供电。
8.工作模式:
•Active:模块处于唤醒状态;所有功能正常可用,可以进行资料发送和接收,模块在此模式下可切换到 Idle 模式或 PSM 模式。
•Idle :模块处于轻休眠状态,网络处于 DRX/eDRX 状态,可接收寻呼消息,模块在此模式下可切换至 Active 或 PSM 模式。
•PSM:模块处于深睡眠状态,内部只有 RTC 工作,网络处于非连接状态,模块此模式下可切换至 Active 模式。
9.支持Firmware软件更新方式:UART、DFOTA。
10.BC26/BC66(MTK MT2625) USB Dongle方便快速开发创新应用:
•开发者可利用USB Dongle直接与工业计算机、一般PC、具USB插头的嵌入式单板计算机(如Raspbbery Pi)、各种手机(利用USB OTG接头连接)。
•可以以OpenCPU SDK开发应用,省下外接MCU之成本及所增加之电力,并独立运作。
•支援MS .Net 平台开发、VB、VC、JAVA、C++、Python…。
•功能界定:Maker、新创团队快速开发NB-IoT以USB为应用产品快速搭配原产品软件(APP)出货,如:智慧工业4.0、智慧医疗(IoT血糖计、血压计)。
为了让大家快速入门NB-IoT,在这边示范以树莓派 + NB-IoT USB Dongle 以Python 开发MQTT 应用,将数据以MQTT Publish Data 到MQTTBox subscribe。
MQTT Broker: broker.hivemq.com ,Port :1883
Publish LED Topic:”NB/BC26/USER99/LED”
Publish TEMP Topic:”NB/BC26/USER99/TEMP”
Publish HUMI Topic:”NB/BC26/USER99/HUMI”
BC26/BC66 MQTT AT command 使用及测试:
AT+QMTOPEN=0,”broker.hivemq.com”,1883
AT+QMTCONN=0,”BC26-Client1”
AT+QMTPUB=0,0,0,0,”NB/BC26/USER99/LED””,”1″
AT+QMTPUB=0,0,0,0,”NB/BC26/USER99/TEMP”,”23.10″
AT+QMTPUB=0,0,0,0,”NB/BC26/USER99/HUMI”,”61.10″
AT+QMTCLOSE=0
范例程序原始码:
import time
import serial
import sys
import serial.tools.list_ports
# global variables
TIMEOUT = 3 # seconds
####################################
# Main program
ser = serial.Serial()
port_list =list(serial.tools.list_ports.comports())
print(port_list)
if len(port_list) == 0:
print("NB-IoT Dongle 未安装!")
else:
for i in range(0,len(port_list)):
print(port_list[i])
nb= NBIoT() #define NBIoT Class
#Loop
try:
nb.sendATComm("ATE1","OK\r\n")
nb. getATI()
nb.getIMEI()
time.sleep(0.5)
nb.getFirmwareInfo()
time.sleep(0.5)
nb.getHardwareInfo()
time.sleep(0.5)
nb.getIPAddress()
time.sleep(0.5)
nb.getSignalQuality()
time.sleep(0.5)
nb.closeallMQTT()
nb.openMQTT("broker.hivemq.com",1883)
time.sleep(0.5)
nb.connectMQTT("MQTTclient1")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/LED","1")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/TEMP","21.20")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/HUMI","52.20")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/LED","0")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/TEMP","22.30")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/HUMI","53.40")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/LED","1")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/TEMP","23.40")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/HUMI","54.50")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/LED","0")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/TEMP","24.50")
time.sleep(0.5)
nb.publishMQTT("NB/BC26/USER99/HUMI","55.60")
time.sleep(0.5)
nb.closeMQTT()
except KeyboardInterrupt:
print('AT+QMTCLOSE=0')
nb.closeallMQTT() # 关闭MQTT 联机
sleep(3)
ser.close() # 清除序列通讯对象
print('结束 MQTT 测试!')
# function for printing debug message
def debug_print(message):
print(message)
# function for getting time as miliseconds
def millis():
return int(time.time())
# function for delay as miliseconds
def delay(ms):
time.sleep(float(ms/1000.0))
####################################
### NB IoT Shield Class ################
####################################
class NBIoT:
board = "" # Shield name
ip_address = "" # ip address
domain_name = "" # domain name
port_number = "" # port number
timeout = TIMEOUT # default timeout forfunction and methods on this library.
compose = ""
response = ""
# Default Initializer
def __init__(self,serial_port=“/dev/ttyAMA0”, serial_baudrate=115200, board="BC-26"):
self.board = board
ser.port = serial_port
ser.baudrate = serial_baudrate
ser.parity=serial.PARITY_NONE
ser.stopbits=serial.STOPBITS_ONE
ser.bytesize=serial.EIGHTBITS
debug_print(self.board + " Classinitialized!")
# Function for clearing compose variable
def clear_compose(self):
self.compose = ""
# Function for getting modem response
def getResponse(self, desired_response):
if (ser.isOpen() == False):
ser.open()
while 1:
self.response =""
while(ser.inWaiting()):
self.response +=ser.read(ser.inWaiting()).decode('utf-8', errors='ignore')
if(self.response.find(desired_response) !=-1):
debug_print(self.response)
break
# Function for sending at comamand tomodule
def sendATCommOnce(self, command):
if (ser.isOpen() == False):
ser.open()
self.compose = ""
self.compose = str(command) +"\r"
ser.reset_input_buffer()
ser.write(self.compose.encode())
debug_print(self.compose)
# Function for sending at command to BC26_AT.
def sendATComm(self, command,desired_response, timeout = None):
if timeout is None:
timeout = self.timeout
self.sendATCommOnce(command)
f_debug = False
timer = millis()
while 1:
if( millis() - timer > timeout):
self.sendATCommOnce(command)
timer = millis()
f_debug = False
self.response =""
while(ser.inWaiting()):
try:
self.response +=ser.read(ser.inWaiting()).decode('utf-8', errors='ignore')
delay(100)
except Exception as e:
debug_print(e.Message)
# debug_print(self.response)
if(self.response.find(desired_response) !=-1):
debug_print(self.response)
break
# Function for saving conf. and resetBC26_AT module
def resetModule(self):
self.saveConfigurations()
delay(200)
self.sendATComm("AT+QRST=1","")
# Function for save configurations tShieldbe done in current session.
def saveConfigurations(self):
self.sendATComm("AT&W","OK\r\n")
# Function for getting ATI
def getATI(self):
returnself.sendATComm("ATI","OK\r\n")
# Function for getting IMEI number
def getIMEI(self):
returnself.sendATComm("AT+CGSN=1","OK\r\n")
# Function for getting firmware info
def getFirmwareInfo(self):
returnself.sendATComm("AT+CGMR","OK\r\n")
# Function for getting hardware info
def getHardwareInfo(self):
returnself.sendATComm("AT+CGMM","OK\r\n")
# Function for getting self.ip_address
def getIPAddress(self):
returnself.sendATComm("AT+CGPADDR","OK\r\n")
#******************************************************************************************
#*** Network Service Functions************************************************************
#******************************************************************************************
# Function for getting signal quality
def getSignalQuality(self):
returnself.sendATComm("AT+CSQ","OK\r\n")
#Function for Query NBIoT Band
#def getBand(self):
#returnself.sendATComm("AT+QBAND?","OK\r\n")
#*************************************************************************************
#***MQTT Protocols Functions****BC-26/BC-66******************************
# Function for create MQTT broker serverconnection
#AT+QMTOPEN=0,"broker.hivemq.com",1883=> +QMTOPEN: 0,0
#*************************************************************************************
defopenMQTT(self,mqttserver="broker.hivemq.com",port_number=1883):
self.compose ="AT+QMTOPEN=0,\""
self.compose += str(mqttserver)
self.compose += "\","
self.compose += str(port_number)
self.sendATComm(self.compose,"+QMTOPEN:0,0")
self.clear_compose()
# Function fo connect MQTT broker serverconnection
#AT+QMTCONN=0,“LASSclient” => +QMTCONN:0,0,0
# *************************************************************************************
def connectMQTT(self,clientName):
self.compose ="AT+QMTCONN=0,\""
self.compose += str(clientName)
self.compose += "\""
self.sendATComm(self.compose,"+QMTCONN:0,0,0")
self.clear_compose()
# Function fo Punlish MQTT Topics payloaddata
#AT+QMTPUB=0,0,0,0,"NB/BC26/USER99/TEMP","23.10"=> +QMTPUB: 0,0,0
def publishMQTT(self,topic,payload):
self.compose ="AT+QMTPUB=0,0,0,0,\""
self.compose += str(topic)
self.compose += "\",\""
self.compose += str(payload)
self.compose += "\""
self.sendATComm(self.compose,"+QMTPUB:0,0,0")
self.clear_compose()
# Function for closing server connection
def closeMQTT(self):
self.sendATComm("AT+QMTCLOSE=0","+QMTCLOSE:0,0")
def closeallMQTT(self):
self.sendATComm("AT+QMTCLOSE=0","")
MQTTBox 接收结果如下图:
=====================