项目3
监 测 谎 言
项目3
本项目通过鸿蒙App控制Hi3861开发板,监测用户的心率,基于心跳变化,判断用户是否说谎。
3.1总体设计
本部分包括系统架构和系统流程。
3.1.1系统架构
系统架构如图31所示,Hi3861开发板与外设引脚连线如表31所示。
图31系统架构
表31Hi3861开发板与外设引脚连线
Hi3861开发板OLEDMAX30102血氧模块
GNDGNDGND
3.3VVINVIN
GPIO13SDASDA
GPIO14SCLSCL
3.1.2系统流程
系统流程如图32所示。
图32系统流程
3.2模块介绍
本部分包括OLED显示、WiFi模块、血氧模块、OneNET云平台和前端模块。下面分别给出各模块的功能介绍及相关代码。
3.2.1OLED显示
本模块将问题呈现到OLED显示屏上,重点在于实现I2C通信,调用其常用API接口,如表32所示。
表32API接口与说明
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对象,如表33和图38所示。
表33返回参数
参 数 名 称格式说明
errnoint调用错误码, 0表示调用成功
errorstring错误描述,succ表示调用成功
datajson接口调用成功后返回的设备信息
idstring数据流ID
create_timestring数据流创建时间
update_atstring最新数据上传时间
current_valuestring/int/json最新数据点
图38获取数据的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调试工具执行请求,由图39可以看出,返回内容为“"errno": 10, "error": "device not online: 954036868"”,表示设备不在线。在此不需要关注返回内容,重点在于下达命令的数据类型。OneNET云平台可接收POST请求的body内容为: Json、string或二进制数据(小于64KB)。
图39下达命令的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的内容为获取的文本框信息
图310文本信息
弹框出现于按键下方,应正确显示输入的文本信息,如图310所示。
为防阻塞主线程启用新线程发起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开发板实时刷新的展示效果,如图311所示; 单击按键后的OLED显示相应数据,如图312所示。
图311开发板实时刷新结果
图312单击按键后的OLED
3.4元件清单
完成本项目所需的元件及数量如表34所示。
表34元件清单
元件/测试仪表数量元件/测试仪表数量
面包板1个OLED显示屏1个
Hi38611个MAX30102血氧模块1个
项目4
监测心率及血氧