Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Sensor API: Make your Win32 applications environment-aware in Windows 7

4.89/5 (11 votes)
28 Sep 2009CPOL2 min read 75.9K   1.3K  
A Sensor Explorer demonstration of the Sensor API in Windows 7.

Image 1

Image 2

Introduction

The Sensor API is a simple Windows 7 ActiveX interface that allows you to communicate with sensors. Sensors can detect light, temperature, electricity, location (GPS), motion and so on. (The supported list of categories is available in MSDN).

You need

Where to Find Sensors?

In the SDK, there is a Virtual Light Sensor that can simulate a light sensor. As Windows 7 is released, more and more devices will support the Sensors abstraction API.

In my site, I've also created a GPS Sensor Driver that reads actual GPS data from a COM port. Read more here.

Overview

The sample here provides code for both full (explorer) sensor capabilities and also a simple SENSOR namespace that implements sensors in a library you can use. The steps for the full explorer are:

  • Call CoCreateInstance() to instantiate an ISensorManager.
  • Call ISensorManager::GetSensorsByCategory using the requested category (all categories in MSDN).
  • From the returned ISensorCollection, call GetCount() to get the number of sensors in that category, then call GetAt() to retrieve an ISensor.
  • Use ISensor methods to learn about the sensor properties, type, ID etc.
  • To get the supported data fields, call ISensor::GetSupportedDataFields().
  • Use GetCount() and GetAt() from the returned IPortableDeviceCollection to get the data fields.
  • Use ISensor::GetData() to retrieve the current data in a ISensorDataReport.
  • Use ISensorDataReport::GetSensorValue to get a specific value, use ISensorDataReport::GetTimestamp to return the time at which the data was collected.

Sensors are disabled by default, so you may have to call ISensorManager::RequestPermissions if you get an access denied error when retrieving the sensor state.

All this stuff is used in main.cpp.

Sensor Manager Events

The Sensor Manager can notify you when something occurs. Implement an ISensorManagerEvents, then pass it to ISensorManager::SetEventSink. Currently, this interface implements the OnSensorEnter() function which is called when a sensor is available.

Sensor Events

The Sensor can notify you when something occurs. Implement an ISensorEvents, then pass it to ISensor::SetEventSink, then call ISensor::SetEventInterest to indicate the types of notifications you want to receive. Currently, ISensorEvents implements four member functions which notify you when an event occurs, when data is changed, when state is changed, and when the sensor is disabled.

Using an Actual Sensor

The Virtual Light sensor is OK for testing purposes, but we need real data. I've created a small sample driver project, GPSDirect, which can read and parse actual GPS information from a COM port (Bluetooth, USB etc.). This driver currently supports parsing GGA and RMC sentences to provide position information.

SensorLib

In case you just want a simple interface, you can use my senslib* project and the SENSOR namespace. This currently implements a SENSOR and a LIGHTSENSOR class to be used as follows:

C++
INT_PTR CALLBACK D_DP(HWND hh,UINT mm,WPARAM ww,LPARAM ll)
{
    HWND hT = GetDlgItem(hh,701);
    HWND hL2 = GetDlgItem(hh,902);
    static SENSOR::LIGHTSENSOR* ls = 0;
    switch(mm)
    {
        case WM_INITDIALOG:
        {
            SetClassLongPtr(hh,GCLP_HICONSM,(LONG_PTR)hIcon1);
            SetClassLongPtr(hh,GCLP_HICON,(LONG_PTR)hIcon1);
            if (!SENSOR::InitializeSensorManager())
            // Make sure we are running under Windows 7
            {
                EndDialog(hh,-1);
                break;
            }
            // Install the light sensor, giving it our HWND and a custom message
            ls = new SENSOR::LIGHTSENSOR(hh,WM_USER);
            break;
        }
        case WM_USER:
        {
            // Sent by LIGHTSENSOR.
            // ww == 0 -> ll == address of a SENSOR_DATA containing the sensor data
            // ww == 1 -> Sensor is disabled
            // ww == 2 -> State changed, ll = the new SensorState
            if (ww == 0)
            {
                SENSOR::SENSOR_DATA* data = (SENSOR::SENSOR_DATA*)ll;
                if (data)
                {
                    for(unsigned int i = 0 ; i < data->Num ; i++)
                    {
                        if (data->keys[i] == SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX)
                        {
                            TCHAR x[100];
                            _stprintf(x,_T("Lux: %f"),data->data[i].fltVal);
                            SetDlgItemText(hh,701,x);
                        }
                    }
                }
            }
            return 0;
        }
        case WM_CLOSE:
        {
            delete ls;
            SENSOR::FreeSensorManager();
            EndDialog(hh,0);
            return 0;
        }
    }
    return 0;
}

To-do...

  • Add the Location API.

History

  • 28 - 9 - 2009: Library update and GPS Sensor.
  • 2 - 5 - 2009: First release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)