项目3 监 测 谎 言 项目3 本项目通过鸿蒙App控制Hi3861开发板,监测用户的心率,基于心跳变化,判断用户是否说谎。 3.1总体设计 本部分包括系统架构和系统流程。 3.1.1系统架构 系统架构如图31所示,Hi3861开发板与外设引脚连线如表31所示。 图31系统架构 表31Hi3861开发板与外设引脚连线 Hi3861开发板OLEDMAX30102血氧模块 GNDGNDGND 3.3VVINVIN GPIO13SDASDA GPIO14SCLSCL 3.1.2系统流程 系统流程如图32所示。 图32系统流程 3.2模块介绍 本部分包括OLED显示、WiFi模块、血氧模块、OneNET云平台和前端模块。下面分别给出各模块的功能介绍及相关代码。 3.2.1OLED显示 本模块将问题呈现到OLED显示屏上,重点在于实现I2C通信,调用其常用API接口,如表32所示。 表32API接口与说明 API接口说明 I2cInit(WifiIotI2cIdx id, unsigned int baudrate)用指定的波特速率初始化I2C设备 I2cDeinit (WifiIotI2cIdx id)取消初始化I2C设备 I2cWrite(WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData*i2cData)将数据写入I2C设备 I2cRead(WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData*i2cData)从I2C设备中读取数据 I2cWriteread(WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData*i2cData)向I2C设备发送数据并接收数据响应 I2cRegisterResetBusFunc(WifiIotI2cIdx id, WifiIotI2cFunc pfn)注册I2C设备回调 I2cSetBaudrate(WifiIotI2cIdx id, unsigned int baudrate)设置I2C设备的波特率 OLED显示的相关代码如下: //显示字符串 //x,y:起点坐标 //size1:字体大小 //chr:字符串起始地址 void OLED_ShowString(u8 x,u8 y,char *chr,u8 size1) { while((*chr>=' ')&&(*chr<='~'))//判断是否为非法字符! { OLED_ShowChar(x,y,*chr,size1); x+=size1/2; if(x>128-size1)//换行 { x=0; y+=2; } chr++; } } //在指定位置显示一个字符,包括部分字符 //x:0~127 //y:0~63 //size:选择字体 12/16/24 //取模方式:逐列式 void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1) { u8 i,m,temp,size2,chr1; u8 y0=y; size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数 chr1=chr-' ';//计算偏移后的值 for(i=0;i (3) 文本输入框。使用TextField组件实现文本输入框,TextField组件与Text组件属性类似,独有属性为basement(输入框基线)以及Bubble(文本气泡),TextField组件相关代码如下: (4) 使用Button组件实现一个按键功能,表示文本已输入完毕。后续逻辑设计需要通过该按键的单击事件获取文本输入框中的内容,并设置其ID、长、宽、按键背景颜色、上边距、对齐方式、文本大小等信息。 2. 程序逻辑 鸿蒙App软件部分的核心是与OneNET云平台进行交互,分为查询数据流和获取数据流两部分。 (1) 查询数据流详情。 请求方式: GET。 URL构成: http://api.heclouds.com/devices/device_id/datastreams/datastream_id。 其中,device_id需要替换为设备ID,datastream_id需要替换为数据流ID,利用OneNET云平台提供的API调试工具执行请求,观察返回内容,发现其为一个Json对象,如表33和图38所示。 表33返回参数 参 数 名 称格式说明 errnoint调用错误码, 0表示调用成功 errorstring错误描述,succ表示调用成功 datajson接口调用成功后返回的设备信息 idstring数据流ID create_timestring数据流创建时间 update_atstring最新数据上传时间 current_valuestring/int/json最新数据点 图38获取数据的API调试及返回内容 由查询到的数据流可知,返回内容为Json对象,根据其结构,定义一个JsonBean类,类的成员为参数errno、data、error与Json结构对应。 public static class JsonBean{ public int errno; public Data data; public String error; ... 定义一个内部类Data进行解析。 static class Data{ public String update_at; public String id; public String create_time; public float current_value; ... 对每个对象定义GET方法,用于在外部获取JsonBean内部对象的值。 public int getErrno() { return errno;} public Data getData() { return data;} public String getError() { return error;} ... JsonBean类定义完成后,通过Json库对其进行解析,在鸿蒙操作系统中实现这个操作需要用到外部库,本项目使用Google开发的Gson库。使用前,需要在build.gradle文件中导入依赖,输入命令“implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.0'”按钮后单击“立即同步”按钮。 在发起GET请求获取数据的函数中,利用JsonBean类和Gson获取键值对,从而取得心率等关键信息。 JsonBean jsonBean = new Gson().fromJson(result, JsonBean.class); 在App界面中,实时呈现检测者的心率数据。实现方法是定义线程类myEventHandler,并通过sendEvent方法将数据投递到新线程。 myEventHandler.sendEvent(InnerEvent.get(1002, jsonBean)); if(event.eventId==1002){ JsonBean jsonBean = (JsonBean) event.object; float tem = jsonBean.getData().getCurrent_value(); //获取最新数据点值 String temText = Float.toString(tem); //将其呈现在界面的temText位置 textTem.setText(temText);} 定义timer类,重复执行任务,使心率数据自动更新。 timer.schedule(new TimerTask() { @Override public void run() { doGet(getUrl);} },delay:0,period:500); //每0.5s执行一次任务后更新界面 (2) 获取数据流。 请求方式: POST。 URL: http://api.heclouds.com/cmds?device_id=/device_id。 利用OneNET云平台提供的API调试工具执行请求,由图39可以看出,返回内容为“"errno": 10, "error": "device not online: 954036868"”,表示设备不在线。在此不需要关注返回内容,重点在于下达命令的数据类型。OneNET云平台可接收POST请求的body内容为: Json、string或二进制数据(小于64KB)。 图39下达命令的API调试及返回内容 通过单击事件获取文本内容。在进行界面设计时,应实现按钮组件的实体,对按钮绑定单击事件,使用当前类作为接口的实现类: but.setClickedListener(this)。 事件绑定完毕后,通过onClick函数实现单击按钮并获取文本框中内容的操作: “String message=tf.getText();”。其中,message为获取的文本框内容,后续下达命令可以直接调用它。 为了验证文本框内容是否成功获取,使用Toast弹框将信息显示在按键下方,此部分起验证作用,成功后可以删除。 ToastDialog td=new ToastDialog(context:this); //补充上下文信息,为当前页面 td.setTransparent(true); //设置Toast的背景 td.setAlignment(LayoutAlignment.BOTTOM); //位置(默认居中) td.setOffset(0,200); //设置一个偏移 td.setText(message);//设置Toast的内容为获取的文本框信息 图310文本信息 弹框出现于按键下方,应正确显示输入的文本信息,如图310所示。 为防阻塞主线程启用新线程发起POST请求,实时呈现OLED界面。在dopost函数中,将string类型的命令放入POST请求的body中访问API。 postConnection.setRequestProperty("Content-Type","application/octet-stream"); postConnection.setRequestProperty("api-key", api_key); new Thread(new Runnable() { @Override public void run() { doPost(postUrl, message, 1102);} }).start(); 首先,单击“输入完毕”按钮后,下达发送message的命令,提问者所输入的问题将显示在OLED屏幕上; 然后,借助MyEventHandler类更新界面,将当前的屏幕显示同步到页面中。 3.3成果展示 计算机屏幕左侧为OneNET云平台的数据波动,右侧为App端的界面,下方为Hi3861开发板实时刷新的展示效果,如图311所示; 单击按键后的OLED显示相应数据,如图312所示。 图311开发板实时刷新结果 图312单击按键后的OLED 3.4元件清单 完成本项目所需的元件及数量如表34所示。 表34元件清单 元件/测试仪表数量元件/测试仪表数量 面包板1个OLED显示屏1个 Hi38611个MAX30102血氧模块1个 项目4 监测心率及血氧