Channels ▼
RSS

Design

Windows 7 Sensor API


Gaston Hillar is an IT consultant and author of more than 40 books. He can be contacted at gastonhillar@hotmail.com.


Most developers aren't keen on working with accelerometers, temperature sensors, and other complex hardware involving unique protocols and proprietary low-level APIs. Luckily, the Windows 7 Sensor API makes it relatively straightforward to build context-aware applications that interact with this sort of hardware.

Sensor-based, context-aware apps do things like adjust screen brightness according to ambient light sensor readings and control a cooling fan's speed based on temperature. Writing software to interact with several devices, each with a different API, can be a nightmare. Sensor API's common API and vendor-specific extensions let developers leave compatibility worries to sensor vendors.

The COM-based Sensor API works with drivers via extensions to a sensor class and consists of three main interfaces:

  • ISensorManager provides methods for identifying and retrieving available sensors, requesting permissions, and controlling what happens when the user connects a sensor to a computer.
  • ISensor lets sensors get and set properties, obtain reports, and control sensor-related events.
  • ISensorDataReport reports sensor data and provides time stamps.

ISensorManager classifies sensors by category (GetSensorByCategory) based on what's being sensed, like location, motion, and environmentals and by type (GetSensorByType) -- like voltage, GPS, and accelerometer -- based on how the corresponding category is sensed.

The Windows API Code Pack for Microsoft's .NET Framework has wrapper classes to handle unmanaged Sensor APIs. It replicates the main interfaces with three classes of wrapping properties and events: SensorManager; Sensor, an abstract base class; and SensorDataReport, also an abstract base class.

The API Code Pack also provides a subclass of sensor for each of the following types: AmbientLightSensor, BooleanSwitchArray, Accelerometer3D, and UnknownSensor. Each sensor subclass uses the corresponding subclass of SensorDataReport.

A common application of the Sensor API involves measuring and possibly changing lighting conditions. Such ambient light-sensing applications include ones that automatically adjust the brightness of a computer screen or illuminate a keyboard. To build a light-sensing program like this in C#, start by adding the Microsoft.WindowsAPICodePack.Sensors assembly as a reference to an existing project and include using Microsoft.WindowsAPICodePack.Sensors. This lets you access the classes and types that the Sensor API wrapper provides. An option is to include the Windows API Code Pack Library Sensors project instead of adding a reference to the assembly. You can use the SensorManager class to get a list of all the ambient light sensors. In this case, the type ID is a mix of category and type:


SensorList<AmbientLightSensor>lightSensorList;
lightSensorList = SensorManager.GetSensorsByTypeId<AmbientLightSensor>();


SensorList is a list of Microsoft.WindowsAPICodePack.Sensors.Sensor; lightSensorList holds a list of the available ambient light sensors. If there are no instances of the required type of sensor, GetSensorsByTypeId returns a null value.

Once you get the list of sensors of a specific type, request permission to use them. The following code does that for the previously generated list of sensors:


if (lightSensorList != null)
{
    var permissionSensorList = new SensorList<Sensor>();
    foreach (var sensor in lightSensorList)
    {
        permissionSensorList.Add(sensor);
    }
    SensorManager.RequestPermission(IntPtr.Zero, true, permissionSensorList);
}

The API wrapper class maps each sensor type to the sensor type GUID expected by the underlying COM API. The RequestPermission method receives three parameters:

  • The parent window handle; in this case, IntPtr.Zero.
  • A bool value indicating whether the dialog that appears should be modal (synchronous call).
  • SensorList of Sensor with all the sensors needed to request permission to access. Because this parameter is a SensorList of Sensor and lightSensorList is a SensorList of AmbientLightSensor, it's necessary to add the elements of this list to a new SensorList of Sensor.

Check whether the SensorList is null before creating the new list and calling the RequestPermission method. To keep things simple, I don't include code to catch exceptions.

Now, it's time to get data from the sensors. For simplicity, I use a single instance instead of the whole list, assuming the following code works with the first ambient light sensor on the list:


lightSensor = lightSensorList[0];

First, I create OnDataReportChanged, a DataReportChangeHandler method. This method receives the AmbientLightSensor instance and can react according to the changes in the value read from the ambient light sensor:


private void OnDataChanged(Sensor sender, EventArgs e)
{
    var intensity = ((AmbientLightSensor)sender).CurrentLuminousIntensity.Intensity;
    // Check the SensorId.Value
    // Do something with the intensity value that has been read
}

The sensor's GUID can be obtained in lightSensor.SensorId.Value. Since the event handler can be attached to many sensors, it's necessary to add code to check which sensor is bringing new data. In this case, I'm assuming there are several ambient light sensors. The sender must be typecasted to AmbientLightSensor because the definition for the event handler uses the generic Sensor class. CurrentLuminousIntensity.Intensity offers the light intensity value. You can fire the necessary actions according to the new value that's been read.

Now add code to force the sensor to generate a new data report by subscribing to the sensor's DataReportChanged event:


lightSensor.TryUpdateData();
lightSensor.DataReportChanged += OnDataReportChanged;

This code calls the TryUpdateData method to generate the new data report, so there's an initial value. Then, the DataReportChanged event fires periodically (or once the measured value changes beyond a certain threshold).

With a common API, the Windows 7 Sensor API provides a simple way to create context-aware applications without the need to learn multiple proprietary APIs. Furthermore, the common API lets you ensure that your code is going to be able to interact with sensors devices developed by different manufacturers. All the vendors have to do is make sure that they offer compatible Windows 7 drivers to support this new platform.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video