塞班传感器编程

 

塞班传感器编程

 

        塞班系统于v9.3开始支持传感器,从S60第五版SDK正式公布传感器接口(sensor API)。

        传感器接口(sensor API)提供给用户侦听和接收来至传感器数据的功能,它包括两个部分:通道接口(Channel API)和定义接口(Definitions API)。Channel API定义了传感器的基本功能和作用,Definitions API描述了各种传感器数据定义上的特征。

        通道也提供有条件的侦听数据,通道的属性也可以通过API配置,如数据频率。

 

通道种类(channels)

        加速器(accelerometer)、旋转(rotation)、方向(orientation)、双击(double-tap)、距离(proximity)、环境光(ambient light)、罗盘或指北针(magnetic north)、磁力(magnetometer XYZ)。

        1> 加速器(accelerometer)

        加速器通道测量设备在三维笛卡尔坐标系下的加速度。设备沿X轴正向移动的时候,加速度为正值;沿X轴反向移动的时候,加速度为负值。

 

        图:Z轴正向与屏幕朝向一致。

 

        2> 旋转(rotation)

        探测围绕三维笛卡尔坐标轴的旋转量。(值范围0-359度)

        图如上

 

        3> 方向(orientation)

        如下图相机有六个基本方向。

 

        图

 

        4> 双击(double-tap)

        双击通道当双击发生时发出事件,发送的事件数据用掩码(bitmask)表示双击发生的方向。

 

        5> 距离(proximity)

        距离传感器通道使用二进制位表示,设备是否接近人体。当该状态无法判断时,状态值为undefined。

 

        6> 环境光(ambient light)

        环境光传感器通道返回光线强度百分比。(0-100)

 

        7> 罗盘或指北针(magnetic north)

        罗盘传感器通道返回设备跟北极的顺时针夹角。(0-359)

 

        8> 磁力(magnetometer XYZ)

        返回磁场强度。

 

用例

        通道侦听用例

                查找、打开、关闭通道

                侦听数据

                侦听变化

 

        通道属性用例

                获取通道属性

                设置通道属性

                属性数组

                缩放通道数据

                侦听通道属性的变化

 

        条件侦听

                条件侦听

 

类结构

        一个物理传感器可以提供几种类型的数据,通道(channel)则是提供来至物理传感器的某种特定类型的数据。例如,磁力传感器就提供了磁力通道和罗盘通道。

 

        图:传感器类的简图

        上图显示一种物理传感器提供着几种通道(CSensrvChannel),通道通过MSensrvDataListener::DataReceived()回调接口提供了特定类型的数据(如 TSensrvXyzData),每个通道都对应着一个TSensrvChannelInfo结构来描述和查找,每个通道拥有多个属性(TSensrvProperty),每个属性可以通过ID和索引(index)来引用。

 

        CSensrvChannelFinder提供查找通道的方法。继承MSensrvChannelListener接口,可以侦听到可用通道的变换,例如新通道被安装到设备时。

        CSensrvChannel提供打开和控制通道的方法。

                1> CSensrvChannel开始和停止侦听,MSensrvDataListener接口接收数据。

                2> CSensrvChannel开始和停止有条件侦听,MSensrvChannelConditionListener接口接收数据。CSensrvChannelConditionSet 和 CSensrvChannelCondition 封装条件。

                3> get和set获取和设置通道属性,MSensrvPropertyListener接口属性的变化。

 

        图:类图

 

        客户端使用NewL创建C类的实例,继承并实现M类接口,并把M类的接口指针指派给相关函数用来接收数据。

 

使用传感器API

        要使用通道,客户端必须先查找并打开它。CSensrvChannelFinder提供了查找的方法,CSensrvChannel提供了打开的方法。

        不同的设置支持不同的通道。SDK定义了所有可能的通道,每个通道都有一个不变的唯一的ID和简述。例如下面的双击通道,它提供两种具体的通道,原数据通道(raw data channels)和事件通道(event channels)。原数据通道提供连续性数据,而事件通道提供事件提醒。

                /**

                  * - Name:          Double tapping event channel type

                  * - Type:          Event

                  * - Datatype:      TSensrvTappingData

                  * - Description:   Double tapping events 

                  */

                const TSensrvChannelTypeId KSensrvChannelTypeIdAccelerometerDoubleTappingData = 0x10205081;

        每个通道的数据类型都在各自的头文件里有定义,它描述了通道可以提供的数据的类型。如下是双击通道的。

                  class TSensrvTappingData 

                      {

                  public:

                      /**

                      * Channel data type Id number

                      */

                      static const TSensrvChannelDataTypeId KDataTypeId = 0x1020507F;

 

                      /**

                      * Channel data type enumerations

                      */

                      enum TSensrvAccelerometerAxisDataIndexes

                            {

                            iTimeStamp = 0,

                            iDirection

                            };

                          };

                  public:

                      /**

                      * - Item name:   Sampling time.

                      * - Item Index:  0

                      * - Conditions:  None

                      * - Description: Timestamp for a sample.

                      */   

                      TTime iTimeStamp;    

 

                      /**

                      * - Item name:   Tapping direction bitmask

                      * - Item Index:  1

                      * - Conditions:  Binary

                      * - Description: Direction bitmask of the tapping event.

                      *                See constant definitions above.

                      */

                      TUint32 iDirection;

                      };

        数据结构里的ID是不变的,每个通道唯一的。

        Index用来指定结构中各个属性的位置。例如,双击通道的数据的结构里iTimeStamp和iDirection分别是0和1。这在属性数组和条件数组里会用到。

        共用属性在sensrvgeneralproperties.h里声明,各通道独特属性在各自的头文件里声明。每种属性都有唯一的ID和描述,以及它们各自的数据成员,这些成员是TInt、TReal和TBuf类型。通道也可以定义属性的范围(scope)。

 

        如下例,定义中的Mandatory部分表示该属性是否是通道必须的属性,Capalibity部分表示所需的能力。

                /**

                  * - Name:         Accuracy of the channel data

                  * - Type:         TReal

                  * - Scope:        Channel item property

                  * - Mandatory:    No

                  * - Capability:   None

                  * - Description:  Returns the accuracy of this channel of the sensor as a

                  *                 percentage of reading (=data value).

                  */

                const TSensrvPropertyId KSensrvPropIdChannelAccuracy = 0x000000008;

 

        通道数据中可以设置一些列属性。如果是传感器或通道属性,item Index应为KSensrvItemIndexNone。

                  iPropertyId   = KSensrvPropIdChannelAccuracy

                  iItemIndex    = KSensrvItemIndexNone

                  iArrayIndex   = ESensrvSingleProperty

                  iRealValue    = 10.0

                  iReadOnly     = ETrue

                  iRealValueMax = n/a

                  iRealValueMin = n/a

                  iPropertyType = ESensrvRealProperty

                  iSecurityInfo = n/a

 

查找、打开、关闭通道

        使用CSensrvChannelFinder的实例来查找通道,查找返回RSensrvChannelInfoList结构的结果。例如,要查找双击通道,在TSensrvChannelInfo对象中把通道类型设置为 KSensrvChannelTypeIdAccelerometerDoubleTappingData,然后使用FindChannelsL()方法获得包含通道信息的结构channelInfoList,CSensrvChannel类使用这个结构就可以创建一个通道的实例。

                //Construct a channel finder.

                CSensrvChannelFinder* channelFinder;

                channelFinder = CSensrvChannelFinder::NewL();

                CleanupStack::PushL( channelFinder );

 

                //List of found channels.

                RSensrvChannelInfoList channelInfoList;

                CleanupClosePushL( channelInfoList );

                //Create and fill channel search criteria.

                //In this example double tapping channel is searched.

                TSensrvChannelInfo channelInfo;

                channelInfo.iChannelType = KSensrvChannelTypeIdAccelerometerDoubleTappingData;

                //Find the double tapping channel

                channelFinder->FindChannelsL( channelInfoList, channelInfo );

                if( channelInfoList.Count() != 1 )

                    {

                    //The device doesn't support double tapping channel or

                    //there are several double tapping channels.

                    }

                else

                    {

                    //double tapping channel found 

                    }

                //Open the double tapping channel.

                //When the channel object is created the channel info object 

                //must be an object returned by CSensrvChannelFinder::FindChannelsL().

                CSensrvChannel* sensorChannel;

                sensorChannel = CSensrvChannel::NewL( channelInfoList[ 0 ] );

                CleanupStack::PushL( sensorChannel ); 

                sensorChannel->OpenChannelL();

                //

                //Double tapping channel is now open.

                //

                //Close the double tapping channel.

                sensorChannel->CloseChannel();

                CleanupStack::PopAndDestroy( sensorChannel );

                CleanupStack::PopAndDestroy( &channelInfoList ); //Close() is being called on "channelInfoList"

                CleanupStack::PopAndDestroy( channelFinder );

 

侦听数据

        通道打开后,就可以侦听数据了。通道的数据保存在缓存中,可以通过GetData()方法获取。如果你要在新数据一到达时就接收,则要实现 MSensrvDataListener 接口的DataReceived()方法。

        例如,把双击通道的desired count 和 maximum count设置为1,则在每次双击发生时都会收到一个提醒。buffering period设置为0,表示消息不延时,立即通知。通道数据的缓存是客户端线程在堆上分配的,大小为其结构的大小乘以数据项的maximum number,可以通过GetData()访问。所以,如果决定缓存大小的maximum number太小,则会引发进程间通讯,从而影响效率。

        在这里,客户端实现了 MSensrvDataListener 接口,并把M类的指针赋给通道。

                iSensorChannel->StartDataListeningL( this, //this object is data listener for this channel

                        1, //aDesiredCount is one, i.e. each double tapping is notified separately

                        1, //aMaximumCount is one, i.e. object count in receiving data buffer is one

                        0 );//buffering period is not used

        侦听数据,需要实现 MSensrvDataListener 接口,需要重载它的 DataReceived() 方法。

                void CTestClass::DataReceived( CSensrvChannel& aChannel, 

                                           TInt aCount, 

                                           TInt aDataLost )

                {

                if ( aChannel.GetChannelInfo().iChannelType == KSensrvChannelTypeIdAccelerometerDoubleTappingData )

                    {

                    TSensrvTappingData tappingData;

                    TPckg<TSensrvTappingData> tappingPackage( tappingData );

                    aChannel.GetData( tappingPackage );

                    }

                }

        通道的 StopDataListening() 方法停止侦听。

 

侦听变化

获取通道属性

设置通道属性

属性数组

缩放通道数据

侦听通道属性的变化

条件侦听

        (暂略)

 

错误处理

        塞班系统的 leave 等错误机制依然有效。

 

内存开销

        传感器的内存开销基本集中在侦听数据的缓存。侦听频率和缓存大小如果不相匹配,则会引发进程间通讯,从而影响效率。

 

能力(capabilities)

        WriteDeviceData 修改channel属性时需要。

        ReadDeviceData 接收或读取channel数据时需要。

        (注:自签名和Express签名不能使用这两个能力,万恶啊)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值