#星光计划1.0# OpenHarmony 源码解析之Sensor子系统(上) 原创 精华
作者:李祥志
1 简介
人类获取外界信息必须借助于感觉器官,而在研究自然现象和规律以及生产活动仅靠感官已经远远不够了,为了适应这种情况,出现了传感器。随着物联网,移动互联网的快速发展,在数字时代,传感器在智能交通,智能工业,智能穿戴等领域有着广阔的应用空间。
1.1 OpenHarmony架构图
2 基础知识
2.1 传感器概述
传感器是检测到被测量信息,将非电量信息转换成电信号的检测装置。就像眼睛是人类心灵的窗户,传感器则是计算机感知世界万物的眼睛。
传感器用于侦测环境中所发生事件或变化,并将此消息发送至其他电子设备(如中央处理器)的设备,通常由敏感组件和转换组件组成。
根据用途可分为以下六大类:
-
运动类:加速度、陀螺仪、重力、线性加速度传感器等;
-
姿态类:旋转矢量、方向传感器等;
-
环境类:磁力计、气压、湿度传感器等;
-
光线类:环境光、接近光、色温传感器等;
-
健康类:心率、心跳传感器等;
-
其它:霍尔传感器、手握传感器等;
2.2 传感器架构图
应用层 :各种需要sensor
的应用,例如运动健康,计步器,指南针等等。
框架层 :
-
SDK :给应用提供标准接口,包括
JS接口
和C++接口
。 -
Framework:向应用层提供稳定的基础能力,包括
Sensor
列表查询、Sensor
启停、Sensor
订阅及去订阅,Sensor
参数配置,创建数据传递通道,sensor数据上传等功能。 -
Service:提供
Sensor
设备管理,Sensor
通用配置能力,Sensor
通用数据解析能力,权限管理能力。
HDF层 :HDF驱动框架
,Sensor设备驱动
的开发是基于该框架的基础上,结合操作系统适配层(OSAL
)和平台驱动接口(比如I2C/SPI/UART总线
等平台资源)能力,屏蔽不同操作系统和平台总线资源差异,实现Sensor驱动
“一次开发,多系统部署”的目标。
Hardware层 :各种传感器器件,例如加速度计,陀螺仪,温度,湿度等等。
2.3 Sensor子系统代码目录
3 源码分析
本文先讲解框架层的代码,HDF
的部分放在下一篇文章讲解。
框架层主要包含两部分:
-
JS
应用订阅、启动sensor
。 -
JS
应用收到订阅sensor
的数据信息。
3.1 JS应用订阅、启动Sensor
我们从JS API
开放的能力开始看源码,绿色部分看作client
,黄色部分看作service
。
JS API的主要接口:
接口名 | 描述 |
---|---|
on(type: SensorType, callback: AsyncCallback<Response>, options?: Options) | 监听传感器数据变化。SensorType为支持订阅的传感器类型,callback表示订阅传感器的回调函数,options为设置传感器数据上报的时间间隔。 |
once(type: SensorType, callback: AsyncCallback<Response>) | 监听传感器数据变化一次。SensorType为支持订阅的传感器类型,callback表示订阅传感器的回调函数。 |
off(type: SensorType, callback: AsyncCallback<void>) | 取消订阅传感器数据。SensorType为支持的取消订阅的传感器类型,callback表示取消订阅传感器是否成功。 |
给JS应用提供接口的实现文件是sensor_js.cpp
,我们从init
开始看接口的实现:
注一:SubscribeSensor
,订阅sensor
,建立sensor
数据传递频道。
先看注1,创建sensor
数据传递频道,sendFd
和receiveFd
,由调用关系找到,调用SensorDataChannel::InnerSensorDataChannel()
,我们来看下这个函数。
再看注2,如何将sendFd_
转移给service
,作为sensor
数据的发送端?
由SendRequest
,指定ISensorService::TRANSFER_DATA_CHANNEL
会调用到CreateDataChannelInner
,这个函数主要的作用是CreateSensorBasicChannel
,service
端获取到sendFd_
。
至此client
和service
跨进程传递Sensor
数据的通道建立完成了。
注二: 启用已订阅的传感器。
最终会调用到SensorServiceImpl::EnableSensor
,这里主要是调用HDF
提供的标准接口,打开sensor
,下一篇文章会讲述HDF
的内容。
3.2 JS应用接收订阅的sensor数据
Sensor打开之后,就会有sensor数据按照上报频率上报给应用。我们下面看下,数据是如何上报的?
前面看到传递的数据通道在订阅时已经创建好了,SensorService::EnableSensor
时,在其内部还调用了SaveSubscriber
。
SaveSubscriber 做了两件事情:
1、调用SensorManager::SaveSubscriber
管理sensor
订阅信息。
2、开启sensor
数据上报的线程。
看到这里,我们发现SaveSubscriber
创建了sensor
数据处理的线程,并使用SensorServiceImpl::dataCondition_.wait(lk)
进入阻塞状态,我们看下何时使用notify_one()
来激活该线程上报数据的?
系统开机启动时,hsensors
进程启动,也就是SensorService
启动。
SensorService
启动后,会将ZReportDataCallback
注册到HDF
,看下面的代码:
当JS应用订阅了传感器,并且启用了传感器,传感器数据就从SensorServiceImpl::SensorDataCallback
向上传递,我们看下这函数的实现,主要做了两件事情:
1、调用ReportDataCallback::ZreportDataCallback
将sensor
数据写入cb->eventsBuf\_
。
2、调用dataCondition_.notify_one()
激活数据上报的线程。
至此,回过头来再看SensorDataProcesser::ProcessEvents
,lock
锁激活后,获取到eventsBuf\_
。
EventFilter
最终会调用SendRawData
,通过该函数的channel-\>SendData
,调用Socket send
函数发送sensor
数据。这里的sendFd_
就是前面创建的。(中间的调用过程请看前面的时序图)
通过DataCallbackImpl
将数据上报给JS
应用。以加速度计为例,会出现下面的log
打印。
总结
本文主要和大家分享传感器应用到框架层的实现,重点分析了传感器订阅、启动以及接收订阅传感器数据,做了较为详细的代码说明,希望通过本文您能初步掌握JS应用开发到框架层开发的步骤与流程。关于传感器HDF框架和驱动的分析,请关注后续文章。
更多原创内容请关注:开鸿 HarmonyOS 学院
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,共建鸿蒙生态,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
OpenHarmony源码解析系列更新啦,后续还有一大波更新
膜拜大佬~学习了~
原来对sensor完全小白的我,看完这篇文章之后豁然开朗。
太棒了,让我对sensor有了全新的认识