背景介绍
近年来涌现出很多AIoT产品,能够实现温湿度采集以及生理参数(心率脉搏血氧)的获取等功能,广泛应用于工业监测、智慧生活以及医疗电子等领域。移远通信模组作为智能硬件与物联网平台沟通的桥梁,能够将嵌入式设备采集的数据上传到云平台,最终利用人工智能算法提取数据背后的价值。过去一段时间里,企业一般采用传感器+mcu+DTU模组的方式,将设备接入物联网平台。随着技术的发展,模组的性能逐渐提升,能够直接驱动传感器工作,大大降低了设备的硬件成本,具体框架如图1所示:

近来,我们基于EC800M构建了一套数据采集设备,实现了污染物浓度检测、压力数据采集以及地理位置信息上报两部分功能,后续通过4G网络,将数据上传到物联网平台。能够实现燃油汽车尾气监测,户外可监测设备等领域,具体如图2所示:

程序框架
EC800M模组能够使用QuecPython进行二次开发,整体难度比较低。设备具有2个串口通道,能够支持HTTP、TCP、UDP、MQTT、阿里云、腾讯云以及私有云平台等;模块能够进行OTA远程升级,支持MQTT重连以及数据离线存储,大大增加了产品的容错能力,并且模组内置有IIC,SPI等协议的库文件;另外,模块支持低功耗模式,使用户做出的产品更容易满足市场需求。(附:python属于解释型语言,整体运行速度较慢,不建议应用于对实时性具有极高要求的场景)。
固件下载
我们通过串口工具,QPYcom和QFlash下载固件,具体所用的命令为:
ATI #显示产品标识信息 #采用串口工具连接Quectel USB AT port
AT+QDOWNLOAD=1 #进入下载模式,出现Quectel Download Port
点击stat,完成下载 #打开Qflash,通过Quectel Download Port,波特率等于9600;
最后打开“usb串行设备”端口,运行程序固件
MQTT通信
以往推文中介绍了如何利用MQTT协议将底层硬件连接到物联网平台,实现数据的通信。本次项目中数据上报的频率为2次/min,将时时的地理位置信息和电池状态,压力数据上传到云平台,具体结果如图所示:
1.设备连接密钥获取
productId='25RKSGsdAZi'
deviceId='EC800Mnew'
devicesecret='eXVhbmxpYW5nbWl5YW8='
connid = 'IT3J4';
CLIENT_ID = productId + deviceId;
now =str(utime.mktime(utime.localtime())+60*60*24*127);#将时间戳转换为str
USER = CLIENT_ID + ';' + '12010126' + ';' + connid + ';' + now;
token = hmac.new(base64.b64decode(devicesecret), msg=bytes(USER, "utf8"),digestmod=hashlib.sha256).hexdigest()
PASSWORD = "{};{}".format(token, "hmacsha256")
2.mqtt连接及消息上传
checknet = checkNet.CheckNetwork(PROJECT_NAME, VERSION)
checknet.poweron_print_once() #开机时打印一些信息,主要用于提示用户。
#打印内容如下:PROJECT_NAME : 用户项目名称 PROJECT_VERSION : 用户项目版本号 FIRMWARE_VERSION :
#固件版本号 POWERON_REASON : 开机原因 SIM_CARD_STATUS : SIM卡状态
try:
checknet.wait_network_connected()
except BaseException:
print('Not Net, Resatrting...')
utime.sleep_ms(200)
Power.powerRestart()
GetDevImei()
MQTT_Init(CLIENT_ID,SERVER,PORT,USER,PASSWORD,30)
#res = pm.wakelock_lock(lpm_fd)
_thread.start_new_thread(MQTT_PUB, ())
_thread.start_new_thread(wait_msg, ())
3.多种topic订阅
messageType=ujson.loads(msg.decode())['messageType']
Device_properties=ujson.loads(msg.decode())['properties'][0] #[0]将list类型转化为字符串类型
if messageType == "READ_PROPERTY":
if Device_properties == "tem":
...
temflag = 1
if Device_properties == "version":
messageId_version = ujson.loads(msg.decode())['messageId']
msg_read_reply_version['messageId']= messageId_version #重新赋值
msg_read_reply_version['properties']['version'] = VERSION
msg_read_reply_temp_v=ujson.dumps(msg_read_reply_version)
versionflag = 1
4.低功耗
import pm
import utime
# 创建wakelock锁
lpm_fd = pm.create_wakelock("test_lock", len("test_lock"))
# 设置自动休眠模式
pm.autosleep(1)
# 模拟测试,实际开发请根据业务场景选择使用
while 1:
utime.sleep(20) # 休眠
res = pm.wakelock_lock(lpm_fd)
print("ql_lpm_idlelock_lock, g_c1_axi_fd = %d" %lpm_fd)
print("unlock sleep")
print (a)
utime.sleep(20)
res = pm.wakelock_unlock(lpm_fd)
print(res)
print("ql_lpm_idlelock_unlock, g_c1_axi_fd = %d" % lpm_fd)
num = pm.get_wakelock_num() # 获取已创建锁的数量
print(num)
start frpc.exe -c frpc.ini > frp.log 2>&1