Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

Lumia Sensor Core SDK

From Wiki
Jump to: navigation, search
SignpostIcon XAML 40.png
WP Metro Icon WP8.png
Article Metadata
Compatibility
Platform(s):
Windows Phone 8
Article
Created: ()
Last edited: Xinx Gong (27 Jun 2014)

Contents

Lumia Sensor Core SDK是什么

SensorCore SDK是一组API,它可以访问手机上的多种传感器数据(加速度传感器/数字罗盘/陀螺仪)和位置信息。这些信息可以用来追踪用户的身体和运动状态。一般情况下,传感器以较低的功耗在后台运行,并保存最近10天内的数据。用户总是可以禁用SensorCore SDK传感器和清除任何收集的数据。

Lumia SensorCore SDK beta

Step Counter API 统计用户步行和跑步的步数

Step Counter API提供的数据包括步数和用户持续步行或跑步的时间。API不仅提供当前步数,同时以每5分钟间隔提供了10天的历史记录。

在Step Counter开始计数前会有6到7秒的延时。在初始化延时过后,Step Counter数值几乎是实时更新的。引入延时是为了避免误报,7秒是出于对应用程序 UI响应的考虑。要指出的是,一旦计数开始,Step Counter不会遗漏初始化前的步数。即如果用户在Step Counter初始化完成前已经走了10步,在API开始提供数据时这10步也会被计入总步数,但是如果在6-7秒的阈值之前就停止计步,那这几步将不会被记录。

Step Counter的准确性的一些变化是来自于用户,设备是怎么被握住以及设备放在什么地方。在一些场景下是出现错误的计步,例如用户在骑车时把设备放在裤兜里,或者用户正在乘坐一辆强烈颠簸的汽车。

Activity Monitor 确定用户和手机的运动类型

Activity Monitor API提供的信息是关于用户在身体活动时的变化。例如:当用户开始或停止步行,或是保持静止。为了保证准确性,在检测Activity的变化时通常有几秒的延时。延时长短是根据Delta(时间和传感器数据)活动时的变化来定的。延时一般大概是5到10秒。Activity信息最精确时是当用户把设备放在口袋或者包里,此时的设备能紧密的遵循着用户的活动行为。另外也有一些对于Activity Monitor非常有难度用例,比如用户乘坐一辆强烈颠簸的车或者是用户用手拿着设备在摇晃。 Activities被分为下面几类:

o Idle (设备平放着) 
o Stationary (用户拿着手机但是用户没有动) 
o Moving
    • Pedestrian and bicycle
         • Walking
         • Running 

为了观察Activities变化,应用程序可以指定一组感兴趣的Activities。当Activity发生改变时,应用程序会接收到与指定Activity最为匹配和接近的Activity的一个通知。例如,如果一个程序对idle和moving Activity感兴趣,此时不论是在walking还是running,都只会收到moving的认知通知。

Place monitor 识别用户的家、工作和去过的地点

Place monitor API提供了用户停留超过一定时间段的地理位置信息,它运行在后台,为了使得功耗尽量低,主要利用手机基站和WiFi接入点信息来定位。因此,它不会主动激活GPS进行地理位置追踪,除非其他应用已经在使用GPS(如导航类应用)。由于该类API是被动工作的,因此它提供的地理位置信息并非是实时的。除了提供相关的地理位置信息以外,它还会尝试推断用户的家和工作单位的地理位置。 用户携带设备在某一个地点停留10分钟以上,该地点才会被认为是一个Known Places,同时加入到Known Places列表。一般来讲,单个Known Place的半径范围是200米。两个Known Place之间的距离一般要求500米以上,因此,即使500米范围内有两个不同的地理位置,该API会将这些位置融合为一个Known Place,这一点也是开发者需要考虑的。

Place monitor 为尝试分类place为“home”和“work”。判断“home”和“work”的规则如下:

• 设备在一定时间间隔内处于一个给定的Known Place内。
• 设备的移动范围和用户的活跃度
• 设备被使用的活跃度 
• 设备如何连接到充电器

根据用户行为,分类通常需要2-3天。应用应该注意,只能为这两个place提供逻辑分类标签,它们可能会也可能不会反应这些place的真实意义。例如,如果对学校的访问符合判断“work”的规则,place monitor 很可能会把学校检测为“work”。分类是非常好的尝试,在所有的设备使用场景里应该不会完全准确。“home”和“work”随着时间推移是会变化的。例如,如果设备持有者搬家了或是换工作了,place monitor 会重新检测,但是这个时间可能需要超过10天。

Place monitor 随着时间推移会调整Known Place列表。如果一个Known Place不再被访问,那么这个Known Place最终会从Known Place列表里消失。

Place的排序也会根据用户行为来调整。经常去的Known Place会在列表的上面,不经常去的Known Place则会在列表的下面。所有的新Known Place都会加在列表的顶部。这些调整的频度是由用户行为来决定的。

所有Place都有下面的属性:

ID:给出的位置的唯一ID
• Kind: frequent, home or work
• Position:place的地理位置。Position的准确性取决于环境和用户的使用因素。
• Radius:place的圆形区域的半径,单位是米。Radius的准确性取决于环境和用户的使用因素。


需要注意的是,places的检测取决于消费者如何使用设备以及环境因素,如基站的使用人数和Wi-Fi热点。在一些有大量基站和Wi-Fi热点的区域,如市中心,places的识别会更加准确。如果用户在用一些需要使用GPS的应用,例如导航应用,place monitor会在这种情况下利用从GPS过来的数据。在这些情况下,places数据会有更高的精准度。

Route Tracker 记录用户路线的位置点

Route tracker API 提供了用户的运动信息。它与place monitor很接近,但是它跟踪的是路线点(geo-location with heading)而不是像home或work那样的place。和place monitor一样, route tracker 也是被动的使用基站和Wi-Fi热点指出设备位置来工作。GPS信息只在有其他应用用着GPS时才被使用。另外,应用需要了解的是应用提供的线路点可能不完全准确。它更多的应该被看作是city tracker(可以提供city blocks级别的位置),而不是fitness tracker(可以提供几米级别的位置)。

跟踪点的注册最多间隔5分钟(API实现每隔5分钟记录路线点),并且距离上一个记录的路线点最少500米。例如,如果用户在一个给定的500米的区域内停留了很长时间,route tracker只会在这个区域记录一个路线点。当用户在高速公路上开车时,后续的跟踪点根据车速和基站的频率可以与其他点间隔数公里。

跟踪点的准确度取决于位置数据的频率和质量,也就是基站和Wi-Fi热点的存有数。例如,在公园里慢跑,在没有活跃的GPS会话并且手机始终只连接到同一个信号塔时就可能只记录到一个点。

API提供了下面参数:

Heading:用户在旅游时线路点被记录时的方向。这只在使用GPS时可用。这意味着这个参数在大部分情况下不可用。 
• LenghtOfStay:设备在这个点待的时间 。
• Position:线路点的地理位置。
• Radius:环绕位置的圆形区域的半径,反映的是地区的不精准性。不精准性取决于各种因素,如设备是怎么被使用的,以及如基站使用人数和Wi-Fi热点等环境因素。 
• Timestamp:进入地点的时间点。以5分钟为精度。

目前支持Sensor Core的设备

Lumia 1520, Lumia Icon, Lumia 930, Lumia 630 and 635

Windows Phone 8.1 with Cyan firmware

Cyan.png

如何启用设备的SensorCore 功能

为了使用SensorCore提供的API,我们需要在手机的功能中做一些设置,具体来说,是将定位运动数据功能打开。 Sensor Core Location.pngSensor Core Motion Data.png

Start Coding

开发环境

利用SensorCore进行应用开发,需要的开发环境为:Visual Studio 2013 Update 2 with Windows Phone SDK。SensorCore SDK 支持模拟器调试,但是支持的功能很有限。所以,如果实际开发应用的话,建议在支持Sensor Core并且解锁的开发设备上进行调试。

新建项目

首先,在Visual Studio中新建项目,选择 Installed > Templates > Visual C# > Store Apps > Windows Phone Apps > Blank App (Windows Phone) ,同时,将项目名称命名为HelloSensorCore

在项目中添加SensorCore SDK

选择Tools > NuGet Package Manager > Manage NuGet Packages for Solution,在nuget.org下搜索关键字Sensor Core,找到Lumia SensorCore SDK以及Lumia SensorCore SDK Testing Tools,然后点击安装。

Sensor Core Nuget.png

自动添加的引用 和 清单文件(Package.appxmanifest)自动添加的能力

安装完SDK后,工程会自动添加Lumia.Sense, Lumia.Sense.TestingMicrosoft Visual C++ 2013 Runtime Package for Windows Phone 这三个引用。同时也会在Package.appxmanifest文件中添加下面的能力:

 <DeviceCapability Name="location" /> 
<m2:DeviceCapability Name="humaninterfacedevice">
<m2:Device Id="vidpid:0421 0716">
<m2:Function Type="usage:ffaa 0001" />
<m2:Function Type="usage:ffee 0001" />
<m2:Function Type="usage:ffee 0002" />
<m2:Function Type="usage:ffee 0003" />
<m2:Function Type="usage:ffee 0004" />
</m2:Device>
</m2:DeviceCapability>

另外,为了使得程序能够正确的运行,我们需要对Configuration Manager中的目标平台进行配置。如果我们在实际设备中进行测试,那么必须选择ARM;如果在模拟器中进行测试,那么必须选择x86。

Sensor Core Remove Any CPU.png

在代码中使用SensorCore API

在MainPage.xaml的Grid元素中添加一个ListBox,用于显示SensorCore返回的数据。

<Grid> 
<ListBox x:Name="SensorcoreList"/>
</Grid>

在MainPage.xaml.cs中,加入命名空间的引用:

using Windows.UI.Popups; 
using Lumia.Sense;
using Lumia.Sense.Testing;
using System.Threading.Tasks;

在MainPage类中添加以下私有变量:

private PlaceMonitor _placeMonitor; 
private RouteTracker _routeTracker;
private ActivityMonitor _activityMonitor;
private StepCounter _stepCounter;

在MainPage的构造函数中添加Loaded事件处理代码,并根据应用的visibility来处理SensorCore的Activation和Deactivation:

this.Loaded += async (oo, ee) => 
{
await ShowStepCounter();
await ShowActivityMonitor();
await ShowRouteTracker();
await ShowPlacesMonitor();
};
 
Window.Current.VisibilityChanged += async (oo, ee) =>
{
if (!ee.Visible)
{
if (_placeMonitor != null) await CallSenseApiAsync(async () => await _placeMonitor.DeactivateAsync());
if (_routeTracker != null) await CallSenseApiAsync(async () => await _routeTracker.DeactivateAsync());
if (_activityMonitor != null) await CallSenseApiAsync(async () => await _activityMonitor.DeactivateAsync());
if (_stepCounter != null) await CallSenseApiAsync(async () => await _stepCounter.DeactivateAsync());
}
else
{
if (_placeMonitor != null) await CallSenseApiAsync(async () => await _placeMonitor.ActivateAsync());
if (_routeTracker != null) await CallSenseApiAsync(async () => await _routeTracker.ActivateAsync());
if (_activityMonitor != null) await CallSenseApiAsync(async () => await _activityMonitor.ActivateAsync());
if (_stepCounter != null) await CallSenseApiAsync(async () => await _stepCounter.ActivateAsync());
}
};

定义两个方法来检查设备是否支持SensorCore SDK,并且检查Location和motion data是否已经打开。通常来讲,用户默认会关闭这两个选项,所以我们需要为用户提供快速设置的方法。

private async Task<bool> CallSenseApiAsync(Func<Task> action) 
{
Exception failure = null;
try
{
await action();
}
catch (Exception e)
{
failure = e;
}
if (failure != null)
{
switch (SenseHelper.GetSenseError(failure.HResult))
{
case SenseError.LocationDisabled:
await CreateMessageDialog("Location has been disabled. Do you want to open Location settings now?", "Information", "Yes", async cmd => await SenseHelper.LaunchLocationSettingsAsync(), true);
return false;
case SenseError.SenseDisabled:
await CreateMessageDialog("Motion data has been disabled. Do you want to open Motion data settings now?", "Information", "Yes", async cmd => await SenseHelper.LaunchSenseSettingsAsync(), true);
return false;
default:
await CreateMessageDialog(SenseHelper.GetSenseError(failure.HResult).ToString(), "Failure", "OK", null, false);
return false;
}
}
return true;
}
 
private static async Task CreateMessageDialog(string message, string title, string label, UICommandInvokedHandler command, bool no)
{
var dialog = new MessageDialog(message, title);
dialog.Commands.Add(new UICommand(label,command));
if (no) dialog.Commands.Add(new UICommand("No"));
await dialog.ShowAsync();
}

开始使用StepCounter。 CallSenseApiAsync封装了安全访问SensorCore SDK的方法。在这个方法里面,我们先实例化一个StepCounter对象,并且调用StepCounter.IsSupportedAsync()来确认当前设备是否支持StepCounter。然后就可以获取当前StepCounter相关的数据,并且显示在主页面的Listbox中。

 private async Task ShowStepCounter()
{
await CallSenseApiAsync(async () =>
{
if (_stepCounter == null)
{
_stepCounter = await StepCounter.GetDefaultAsync();
}
if (await StepCounter.IsSupportedAsync())
{
var reading = await _stepCounter.GetCurrentReadingAsync();
SensorcoreList.Items.Add("Current step counter reading");
if (reading != null)
{
SensorcoreList.Items.Add(reading.Timestamp.ToString());
SensorcoreList.Items.Add("Walk steps = " + reading.WalkingStepCount);
SensorcoreList.Items.Add("Walk time = " + reading.WalkTime.ToString());
SensorcoreList.Items.Add("Run steps = " + reading.RunningStepCount);
SensorcoreList.Items.Add("Run time = " + reading.RunTime.ToString());
}
else
{
SensorcoreList.Items.Add("data not available");
}
}
});
}

使用ActivityMonitor

 private async Task ShowActivityMonitor()
{
await CallSenseApiAsync(async () =>
{
if (_activityMonitor == null)
{
_activityMonitor = await ActivityMonitor.GetDefaultAsync();
}
if (await ActivityMonitor.IsSupportedAsync())
{
var reading = await _activityMonitor.GetCurrentReadingAsync();
SensorcoreList.Items.Add("Current activity");
 
if (reading != null)
{
SensorcoreList.Items.Add(reading.Timestamp.ToString() + ", activity = " + reading.Mode);
}
else
{
SensorcoreList.Items.Add("not available");
}
}
});
}

使用PlacesMonitor

 private async Task ShowPlacesMonitor()
{
await CallSenseApiAsync(async () =>
{
if (_placeMonitor == null)
{
_placeMonitor = await PlaceMonitor.GetDefaultAsync();
}
 
if (await PlaceMonitor.IsSupportedAsync())
{
Place reading = await _placeMonitor.GetCurrentPlaceAsync();
SensorcoreList.Items.Add("Current place");
 
if (reading != null)
{
SensorcoreList.Items.Add(“place kind = " + reading.Kind);
}
else
{
SensorcoreList.Items.Add("
not available");
}
}
});
}

使用RouteTracker

 private async Task ShowRouteTracker()
{
await CallSenseApiAsync(async () =>
{
if (_routeTracker == null)
{
_routeTracker = await RouteTracker.GetDefaultAsync();
}
 
if (await RouteTracker.IsSupportedAsync())
{
IList<RoutePoint> reading = await _routeTracker.GetRouteAsync(
DateTime.Now.AddDays(-2), TimeSpan.FromDays(2));
SensorcoreList.Items.Add("Route history");
 
if (reading != null)
{
SensorcoreList.Items.Add("count = " + reading.Count);
 
foreach (RoutePoint route in reading)
{
SensorcoreList.Items.Add(
route.Position.Latitude + ", " +
route.Position.Longitude);
}
}
else
{
SensorcoreList.Items.Add("not available");
}
}
});
}

编译并部署应用

Sensor Core Deploy.png

记录和模拟传感器

记录

 StepCounter stepCounter = await StepCounter.GetDefaultAsync();
SenseRecorder recorder = new SenseRecorder(stepCounter);
await recorder.StartAsync();
/// ... Record data ...
await recorder.StopAsync();
await recorder.GetRecording().SaveAsync();

模拟

 SenseRecording recording = await SenseRecording.LoadFromFileAsync("jsonData.txt");
StepCounterSimulator simulator = await StepCounterSimulator.GetDefaultAsync(recording);
 
StepCounterSimulator simulator = await StepCounterSimulator.GetDefaultAsync(
recording, DateTime.Now - TimeSpan.FromDays(2));

开发时的建议

• 用户可以很方便的启用/禁用定位服务和运动数据。
• 不是所有的设备都支持运动数据。
• 运动数据只有在启用系统设置的运动数据之后才开始收集。
• 运动数据可以被用户清空。
• 记住Place monitor 和 Route tracker是被动收集数据的。
• 注意数据收集的延迟。
• 注意Step Counter历史数据的间隔时间。
• 注意Step Counter数据是绝对的。
• 尽量减少后台线程的使用。
• 注意系统时钟的变化。
This page was last modified on 27 June 2014, at 07:57.
316 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×