综合案例2.0-居家隔离监控系统
- 简介
- AJ-SR04M- T-X超声波测距模块
- 准备
- 硬件连接图
- 代码流程
- 功能实现
- 1、物联网平台开发
- 2、设备端开发
- 3、调试
- 4、创建钉钉机器人
- 5、IoT Studio配置业务逻辑
简介
新型冠状病毒持续危害着人类安全,阻击病毒传播的最简单有效方式就是切断病毒的传播路径,居家隔离应运而生。
本系统的核心在于如何确定居家隔离过程中入户门的开关状态,并及时通知给社区管理人员。
AJ-SR04M- T-X超声波测距模块
功能说明
工作原理
用IO口Trig触发测距,至少给10us的高电平。模块自动发送8个40KHZ的方波,自动检测是否有信号返回。当有信号返回时,通过IO口Echo输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。常温下测试距离=(高电平时间*声速(348M/S))/2。模块被触发测距后,如果接收不到回波(原因超过所测范围或是探头没有正对被测物),ECHO 口会在 40MS 后自动变为低电平,标志着此次测量结束,不论成功与否。LED 上电时末亮,只有在给了 TRIG 引脚触发信号后才亮,灯闪频率与触发周期同步,说明此时模块接收到正确的指令进入工作状态。建议测量周期为 50ms 以上,以防止发射信号对回响信号的影响。
简单来说就是主板通过IO口Trig给个不小于10us的高电平,触发测距。测距成功,模块通过IO口Echo输出一个高电平给主板;测距失败,ECHO 口会在 40MS 后自动结束本次测量。
- 其他模式可以查看模块手册
准备
本案例需要的硬件
器材 | 数量 |
HaaS506开发板 | 1 |
AJ-SR04M- T-X超声波测距模块 | 1 |
SIM卡 | 1 |
杜邦线 | 若干 |
硬件连接图
代码流程
1、连接阿里云平台。
2、重复检测超声波距离,当距离大于40cm设定开门状态为1,将开门的状态上传云端;当距离小与40cm设定开门状态为0,将开门状态上传云端。(每次状态改变时才上传一次)。
3、创建钉钉机器人,使用IoT Studio业务逻辑根据开门状态发送对应消息。
功能实现
1、物联网平台开发
第一次使用物联网平台的读者,需要开通实例后使用物联网平台功能。也可以使用免费的公共实例进行开发,在阿里云物联网平台中,左上角选择‘华东2-上海’,点击‘公共实例’,即可开通。
1、平台产品创建可参考haas506 2.0开发教程-aliyunIoT 2、创建产品属性(添加物模型)
选择产品功能定义–编辑草稿
1、添加自定义功能
2、添加标识符与数据类型(标识符要与代码一致)
3、点击发布上线
选择读写类型
- 发布上线,点击确定
2、设备端开发
- 第一次使用开发板的读者可以按照haas5062.0开发教程-导学篇搭建开发环境。
- 搭建完后复制以下代码到Visual Studio Code,复制产品证书到代码相应位置。
- 2.2版本获取IMEI号接口有更新,需要更改以下内容(Ctrl+F 查找modem)
# 获取设备的IMEI 作为deviceName 进行动态注册
deviceName = modem.info.getDevImei()
...
- 替换 productKey ,productSecret。(物联网平台开发添加设备时请使用IMEI号)
main.py
# coding=utf-8
from driver import GPIO
import network
import ujson
import utime as time
import modem
from aliyunIoT import Device
import kv
#当iot设备连接到物联网平台的时候触发'connect' 事件
def on_connect(data):
global module_name,default_ver,productKey,deviceName,deviceSecret,on_trigger,on_download,on_verify,on_upgrade
print('***** connect lp succeed****')
data_handle = {}
data_handle['device_handle'] = device.getDeviceHandle()
#当连接断开时,触发'disconnect'事件
def on_disconnect():
print('linkkit is disconnected')
#当iot云端下发属性设置时,触发'props'事件
def on_props(request):
print('clound req data is {}'.format(request))
#当iot云端调用设备service时,触发'service'事件
def on_service(id,request):
print('clound req id is {} , req is {}'.format(id,request))
#当设备跟iot平台通信过程中遇到错误时,触发'error'事件
def on_error(err):
print('err msg is {} '.format(err))
#网络连接的回调函数
def on_4g_cb(args):
global g_connect_status
pdp = args[0]
netwk_sta = args[1]
if netwk_sta == 1:
g_connect_status = True
else:
g_connect_status = False
#网络连接
def connect_network():
global net,on_4g_cb,g_connect_status
#NetWorkClient该类是一个单例类,实现网络管理相关的功能,包括初始化,联网,状态信息等.
net = network.NetWorkClient()
g_register_network = False
if net._stagecode is not None and net._stagecode == 3 and net._subcode == 1:
g_register_network = True
else:
g_register_network = False
if g_register_network:
#注册网络连接的回调函数on(self,id,func); 1代表连接,func 回调函数 ;return 0 成功
net.on(1,on_4g_cb)
net.connect(None)
else:
print('网络注册失败')
while True:
if g_connect_status:
print('网络连接成功')
break
time.sleep_ms(20)
#动态注册回调函数
def on_dynreg_cb(data):
global deviceSecret,device_dyn_resigter_succed
deviceSecret = data
device_dyn_resigter_succed = True
# 连接物联网平台
def dyn_register_device(productKey,productSecret,deviceName):
global on_dynreg_cb,device,deviceSecret,device_dyn_resigter_succed
key = '_amp_customer_devicesecret'
deviceSecretdict = kv.get(key)
print("deviceSecretdict:",deviceSecretdict)
if isinstance(deviceSecretdict,str):
deviceSecret = deviceSecretdict
if deviceSecretdict is None or deviceSecret is None:
key_info = {
'productKey': productKey ,
'productSecret': productSecret ,
'deviceName': deviceName
}
# 动态注册一个设备,获取设备的deviceSecret
#下面的if防止多次注册,当前若是注册过一次了,重启设备再次注册就会卡住,
if not device_dyn_resigter_succed:
device.register(key_info,on_dynreg_cb)
status_data = {}
def upload_status(n):
global status_data
status_data["open_door"]= n
status_data_str=ujson.dumps(status_data)
data={
'params':status_data_str
}
device.postProps(data)
#超声波测距
def getData():
TRIG.write(0)
#set period,above 50ms
time.sleep_ms(500)
TRIG.write(1) #Set TRIG as LOW
time.sleep_us(10) #Delay of 10us
TRIG.write(0) #Set TRIG as HIGH
while ECHO.read()==0: #Check if Echo is LOW
pass
pulse_start = time.ticks_us() #Time of the last LOW pulse
while ECHO.read()==1: #Check whether Echo is HIGH
pass
pulse_end = time.ticks_us() #Time of the last HIGH pulse
#print("pulse_duration",time.ticks_diff(pulse_end,pulse_start)) # us
pulse_duration = time.ticks_diff(pulse_end,pulse_start)/10000 #pulse duration: s
d=pulse_duration*340/2
return d
if __name__ == '__main__':
ICCID=None
g_connect_status = False
net = None
device = None
deviceSecret = None
deviceName = None
#替换下列产品信息
###################################
productKey = "a1laDtv9VrO"
productSecret = "bPbyllJ80mRX5PPy"
###################################
device_dyn_resigter_succed = False
# 连接网络
connect_network()
# 获取设备的IMEI 作为deviceName 进行动态注册
#2.2版本改为
#deviceName = modem.info.getDevImei()
deviceName = modem.getDevImei()
#获取设备的ICCID
ICCID=modem.sim.getIccid()
#初始化物联网平台Device类,获取device实例
device = Device()
if deviceName is not None and len(deviceName) > 0 :
#动态注册一个设备
dyn_register_device(productKey,productSecret,deviceName)
else:
print("获取设备IMEI失败,无法进行动态注册")
while deviceSecret is None:
time.sleep(0.2)
print('动态注册成功:' + deviceSecret)
key_info = {
'region' : 'cn-shanghai' ,
'productKey': productKey ,
'deviceName': deviceName ,
'deviceSecret': deviceSecret ,
'keepaliveSec': 60,
}
#打印设备信息
print(key_info)
#device.ON_CONNECT 是事件,on_connect是事件处理函数/回调函数
device.on(device.ON_CONNECT,on_connect)
device.on(device.ON_DISCONNECT,on_disconnect)
device.on(device.ON_PROPS,on_props)
device.on(device.ON_SERVICE,on_service)
device.on(device.ON_ERROR,on_error)
device.connect(key_info)
#主程序
time.sleep(2)
#creat instances
TRIG = GPIO()
ECHO = GPIO()
TRIG.open('trig') # Set pin as GPIO out
ECHO.open('echo') # Set pin as GPIO in
door_status = 0
turn = 0
try:
while True:
dis = getData()
if dis > 20 and dis < 600:
if dis < 40:
door_status = 0
if door_status != turn:
print ("distance:%0.2f cm" % dis)
print('door status changed:',door_status)
upload_status(door_status)
turn = door_status
else:
door_status = 1
if door_status != turn:
print ("distance:%0.2f cm" % dis)
print('door status changed:',door_status)
upload_status(door_status)
turn = door_status
else:
print ("Out Of Range")
except KeyboardInterrupt:
print("exit")
board.json
{
"name": "haas506",
"version": "2.0.0",
"io": {
"echo":{
"type":"GPIO",
"port": 20,
"dir": "input",
"pull":"pullup"
},
"trig":{
"type":"GPIO",
"port": 19,
"dir": "output",
"pull":"pullup"
}
},
"debugLevel": "ERROR",
"repl": "enable",
"replPort": 0
}
3、调试
1、串口调试工具log,网络连接成功–动态注册成功–门的状态改变后打印当前距离和门的状态。
2、阿里云平台,打开实时刷新,物模型数值会即时改变。
4、创建钉钉机器人
群设置中找到智能群助手。
添加机器人
点击添加
输入机器人名称及机器人想要添加的钉钉群组(如果没有可以自行创建),在安全设置一项添加"自定义关键词"。需要注意的是:自定义关键词用来过滤向钉钉群推送的信息,只有包括了该关键词的推送信息才会在群里显示,不包含该关键词的推送信息会被过滤掉。可以定义多个关键词,只要推送的信息中有一个词跟关键词匹配即可被群接收并显示。这里我们定义"入户门"关键词,也就是说后续的推送信息里面必须包含"入户门"这个词语。
提醒的两条消息“入户门关闭,疫情安全”,“入户门打开,危险”
创建完成后会弹出提示框,点击复制
按钮复制Webhook地址以备后用,使用该地址可以向钉钉群推送消息。点击“完成”。
5、IoT Studio配置业务逻辑
登录IoT Studio平台,在左侧的侧边栏点击项目管理,在项目管理页面点击新建项目按钮。
在新建项目页面点击创建空白项目。
弹出新建空白项目页面,输入项目名称及描述后点击确定按钮。
项目创建完成后会自动导航到新创建的项目,新项目需要关联产品,设备,并创建业务逻辑,以实现云端上报信息到钉钉的信息推送。点击关联设备
创建业务逻辑
业务服务创建完成后自动导航到业务逻辑开发页面。点击“节点”按钮显示所有原子功能,并以此拖住设备触发,条件判断 和 钉钉机器人到右侧的窗口。按住鼠标左键连接各个模块,注意条件判断两个逻辑输出要连接正确的钉钉机器人,以免逻辑混乱。
点击设备触发模块,在弹出的对话框中选择产品,设备及触发条件。
点击条件判断模块,在弹出的对话框中条件配置。
点击疫情安全模块,在弹出的对话框中设置Webhook,选择配置方式及消息类型。Webhook对话框输入之前创建“疫情安全”钉钉机器人时候拷贝的字符串。在“消息类型”的内容配置项里填写content内容。(内容需要包括钉钉机器人设置的"自定义关键词")
按照上述办法配置疫情危险模块(使用相同的Webhook信息)。
业务逻辑开发配置完成后,我们可以先使用软件调试的方式验证相关逻辑链路的正确性。点击保存按钮后点击部署调试按钮。
在弹出的对话框选择前往按钮:
在弹出的设备模拟器页面点击启动设备模拟器按钮:
选择属性上报选项并在开关状态栏输入0(门关闭)或者1(门打开),点击发送命令按钮:
发送命令后,我们便可以在钉钉群接收到相关的通知: