场景介绍
阿尔茨海默病, 是导致中老年人认知功能障碍的最常见疾病之一, 是发生在老年期及老年前期的一种原发性退行性脑病. 据估计, 全世界痴呆症患者数量为 4700 万, 到 2030 年将达到 7500 万人. 痴呆症患者数量到 2050 年预计将是现在的近三倍. 疾病的高昂费用给卫生系统应对未来预计不断增加的病例构成挑战. 据估计, 目前每年的支出为 8180 亿美元, 而支出的增长速度预计会比疾病流行率上升还要快. 照料痴呆症患者给照护者带来巨大压力, 包括身体上, 情感上和经济上的压力.(by 世界卫生组织)
用技术解决阿尔茨海默病护理的问题, 让老人和其护理者有更好的生活质量, 是我们可以解决的方法. 基于物联网技术, 已经有一些设备实现了阿尔茨海默病老人走失定位. 但是我们要做更高一层, 除了单独分发的硬件之外, 我们要使用开发工具 IoT Studio 帮助医疗机构做一个硬件 SaaS 管理系统, 让他们可以随时监控旗下所有阿尔兹海默护理设备的数据以及定位, 对老人的情况实现实时监控. 同时也有能力对掌控的设备进行增删改查, 方便他们自己管理设备. 通过 IoT Studio 赋能开发者, 让他们帮助包括医疗在内的各个行业用上物联网技术, 惠及百姓.
我们首先构建一个可以拍照, 检测心跳的手环设备, 然后基于这个设备帮助护理机构开发一个集合管理监控告警的 SaaS 系统. 设备由一个可以检测心跳的光学模块, 一个可以检测老人所在地场景的摄像头, 一个 GPS 定位模块, 一个物联网通讯模块(一般为 GPRS),MCU 和电源组成. 云端由物联网平台为基础建立设备与云端通讯, 配合 RDS 存储心跳 & GPS 数据, OSS 存储图片数据, 最后用 IoT Studio 的服务开发与 web 可视化开发功能完成功能页面搭建. 整个云端开发过程只需要 2 小时以内即可.
最终效果如图.
硬件部分
在 demo 阶段, 我们采用树莓派 3B + 摄像头 + 心跳模块 + GPS + 电池的方法, 验证不同数据的上报方法以及数据存储链路. 考虑简单化, 联网暂时采用 Wi-Fi 方法. 如果觉得使用电路比较麻烦, 也可以使用服务开发 + 虚拟设备上报的方式, 具体查看这篇文档.
虽然带手环的老人不一样, 但是每个手环上报的属性类别是一样的, 我们可以类似编程开发里把它们归结为同一个类(class). 我们首先需要在物联网平台上为我们的 demo 手环建立一个设备类(即产品), 这样我们才能在以后不断的往这个产品下实例化新的设备.
进入阿里云物联网平台, 在产品页面新建一个产品, 选择自定义品类即可, 命名为 "阿尔茨海默氏症老人监控手环".
进入产品的功能定义页, 定义 5 个自定义功能 -- 剩余电量, 地理位置, 心跳, 图片地址(存放摄像机上传图片的 URL).
地理位置只需要在 "添加功能" 里用标准的功能即可, 如图, 其他全部配置项默认即可.
心跳为一个整型数据, 剩余电量为浮点型数据, 图片地址为字符型数据, 如图.
在设备面板点击 "添加设备", 选择刚才创建的手环产品, 然后输入随意的设备名称即可.
IoT Studio 为交付型业务做了项目维度的隔离, 因此需要将用到的设备导入到对应的项目中.
首先打开物联网平台的 "开发服务" 选项进入 IoT Studio. 点击某个项目名称的 "查看" 进入项目详情页. 然后点击右上角的 "导入产品". 选择刚才的手环产品, 然后导入, 可以在设备管理页看到产品以及下属的设备已经导入项目里.
这样就完成了产品的定义, 实例化与项目维度的隔离了.
上云部分
- ## 注意, 本 demo 代码忽略了电池电量检测模块
- import aliyunsdkiotclient.AliyunIotMqttClient as iot ## 导入阿里云的设备 MQTT 库, 如果 import 失败需要先 pip3 install 一下
- import JSON
- import multiprocessing
- import time
- import random
- import oss2 ## 导入阿里云的 OSS 库, 如果 import 失败需要先 pip3 install oss2
- from picamera import PiCamera ## 树莓派的摄像头, 系统自带
- import RPi.GPIO as GPIO ##GPIO 口, 接红外 PIR 用
- import serial
- import pynmea2
- from pulsesensor import Pulsesensor ## 导入树莓派的 pulsesensor 库, https://github.com/tutRPi/Raspberry-Pi-Heartbeat-Pulse-Sensor/blob/master/example.py
- auth = oss2.Auth('**AccessId*****','**AccessSecret*****') ##OSS 的授权需要阿里云账号 AccessId 和 AccessSecret, 具体查看 https://usercenter.console.aliyun.com/#/manage/ak
- bucket = oss2.Bucket(auth,'http://oss-cn-beijing.aliyuncs.com','*** 你的 bucket 名称 ***') ## 需要根据服务器区域修改节点路径, 见文档
- global picURLtoIoT
- camera = PiCamera()
- camera.resolution = (800,600) ## 拍照分辨率, 越高越容易分析, 但是上次越慢
- GlobalBpm = 0 ## 记录心跳数据
- Latitude = 0 ## 记录 GPS 数据
- Longtitude = 0
- ## 初始化树莓派
- def init():
- GPIO.setwarnings(False)
- GPIO.setmode(GPIO.BOARD)
- GPIO.setup(3, GPIO.IN)
- pass
- def take_photo():
- ticks = int(time.time())
- fileName = 'test%s.jpg' % ticks ## 在文件名加入了时间戳作为简易加密手段
- filePath = '/home/pi/Pictures/%s' % fileName
- camera.capture(filePath)
- bucket.put_object_from_file('bucket_file_name/%s', fileName) ## 在这里改 bucket 名字
- global picURLtoIoT
- picURLtoIoT = 'http://*** 你的 bucket 名称 **.oss-cn-beijing.aliyuncs.com/bucket_file_name/%s' % fileName
- ## 在这里改 bucket 名字和 bucket 内文件夹的名字
- print(str(picURLtoIoT))
- def detect_Heartbeat():
- p = Pulsesensor()
- p.startAsyncBPM()
- try:
- while True:
- bpm = p.BPM
- if bpm> 0:
- print("BPM: %d" % bpm)
- GlobalBpm = bpm;
- else:
- print("No Heartbeat found")
- time.sleep(1)
- except:
- p.stopAsyncBPM()
- def get_GPS():
- ser = serial.Serial("/dev/ttyAMA0",9600)
- while True:
- line = ser.readline()
- if line.startswith('$GNRMC'):
- rmc = pynmea2.parse(line)
- print "Latitude:", float(rmc.lat)/100
- print "Longitude:", float(rmc.lon)/100
- Latitude = float(rmc.lat)/100
- Longtitude = float(rmc.lon)/100
- break
- options = {
- 'productKey':'** 你的 ProductKey**',
- 'deviceName':'** 你的 deviceName**',
- 'deviceSecret':'** 你的 deviceSecret**',
- 'port':1883,
- 'host':'iot-as-mqtt.cn-shanghai.aliyuncs.com' ## 注意阿里云 IoT 国内都是华东 2, 不一定跟 OSS 的节点一致
- }
- host = options['productKey'] + '.' + options['host']
- def on_message(client, userdata, msg):
- topic = '/' + productKey + '/' + deviceName + '/update'
- print(msg.payload)
- def on_connect(client, userdata, flags_dict, rc):
- print("Connected with result code" + str(rc))
- def on_disconnect(client, userdata, flags_dict, rc):
- print("Disconnected.")
- ## 设备上报的定义
- def upload_device(client):
- topic = '/sys/'+options['productKey']+'/'+options['deviceName']+'/thing/event/property/post'
- while True:
- payload_json = {
- 'id': int(time.time()),
- 'params': {
- 'BPM': GlobalBpm,
- 'picURL': picURLtoIoT,
- 'Geo':
- {
- 'CoordinateSystem":1,
- 'Latitude':Latitdue,
- 'Longitude':Longtitude,
- 'Altitude':0
- },
- },
- 'method': "thing.event.property.post"
- }
- print('send data to iot server:' + str(payload_json))
- client.publish(topic, payload=str(payload_json))
- if __name__ == '__main__':
- client = iot.getAliyunIotMqttClient(options['productKey'], options['deviceName'], options['deviceSecret'], secure_mode=3)
- client.on_connect = on_connect
- client.connect(host=host, port=options['port'], keepalive=60)
- p = multiprocessing.Process(target=upload_device, args=(client,))
- p.start()
- get_GPS()
- detect_Heartbeat()
- take_photo()
- GPIO.cleanup()
- client.loop_forever()
- {
- "table": "test",![_rds5](https://yqfile.alicdn.com/d0979c17aa88ac03cd75ae1752c0b85e6b47fc23.png)
- "rows": [
- {
- "BPM": "{{query.props.BPM.value}}",
- "Latitude": "{{query.GeoLocation.value.Latitude}}",
- "Longtitude": "{{query.GeoLocation.value.Longtitude}}",
- "time": "{{query.deviceContext.gmtCreate}}"
- }
- ]
- }
- {
- "deviceContext": {
- "productKey": "a1OhdcX0B8B",
- "deviceName": "Wrist003",
- "gmtCreate": 1560497545957
- },
- "props": {
- "GeoLocation": {
- "time": 1560497545957,
- "value": {
- "CoordinateSystem": 1,
- "Latitude": 25.26,
- "Longitude": 111.45,
- "Altitude": 0
- }
- },
- "BPM": {
- "time": 1560497545957,
- "value": 21
- }
- }
- }
- {
- "msgtype": "text",
- "text": {
- "content": "使用手环 {{query.deviceContext.deviceName}} 的老人心跳过低, 数字为{{query.props.BPM.value}}, 大家快去看看吧!"
- },
- "at": {
- "isAtAll": true
- }
- }
来源: https://yq.aliyun.com/articles/706042