none
Using Sensor API events to understand when a sensor is connected, in windows8/windows8.1? RRS feed

  • Question

  • Hi, 

    I am trying to build an application that can identify when the sensors are connected. I have an USB interfaced sensor hub. but i have not been successful in building such an application, but SDT (Sensor Diagnostic tool) is able to detect the sensors and even display the values.I am new to COM interfaces and the callback functions,etc.

    So please advice if my understanding is correct from the implementation i have shown below(this code is not able to detect when sensors are connected):



    #include "stdafx.h"
    #include <initguid.h>
    #include "Sensorsapi.h"
    #include "Sensors.h"


    #include <iostream>
    using namespace std;


    ISensorManager* pSensorManager; 
    ISensorCollection* pSensorColl;
    ISensor* pSensor;
    ISensorDataReport* pReport;
    SensorState* pState;


    VARIANT_BOOL pIsSupported;
    int flag;

    class CMyManagerEvents : public ISensorManagerEvents
    {
    public:

        STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
        {
            if (ppv == NULL)
            {
                return E_POINTER;
            }
            if (iid == __uuidof(IUnknown))
            {
                *ppv = static_cast<IUnknown*>(this);
            }
            else if (iid == __uuidof(ISensorManagerEvents))
            {
                *ppv = static_cast<ISensorManagerEvents*>(this);
            }
            else
            {
                *ppv = NULL;
                return E_NOINTERFACE;
            }
            AddRef();
            return S_OK;
        }

        STDMETHODIMP_(ULONG) AddRef()
        {
            return InterlockedIncrement(&m_cRef); 
        }

        STDMETHODIMP_(ULONG) Release()
        {
            ULONG count = InterlockedDecrement(&m_cRef);
            if (count == 0)
            {
                delete this;
                return 0;
            }
            return count;
        }

        //
        // ISensorEvents methods.
        //

        STDMETHODIMP OnSensorEnter(
                ISensor* pSensor,
                SensorState state)
        {
            HRESULT hr = S_OK;

            flag=500; 
    cout<<"Sensor is connected"<<endl;
            return hr;
        }


        private:
            long m_cRef;

    };

    CMyManagerEvents* pManagerEventClass = NULL;
    ISensorManagerEvents* pMyManagerEvents = NULL;

    int _tmain(int argc, _TCHAR* argv[])
    {

    cout<<"asynchronous events for sensor manager"<<endl;
    CoInitialize(NULL);
    HRESULT hr = CoCreateInstance(CLSID_SensorManager, 
    NULL, CLSCTX_INPROC_SERVER,
    IID_PPV_ARGS(&pSensorManager));

    if(SUCCEEDED(hr))
    {
    cout<<"Sensor Manager created"<<endl;
    // Create an instance of the event class.
    pManagerEventClass = new(std::nothrow) CMyManagerEvents();        
    }

    if(SUCCEEDED(hr))
    {
    cout<<"Event class generated"<<endl;
    // Retrieve the pointer to the callback interface.
    hr = pManagerEventClass->QueryInterface(IID_PPV_ARGS(&pMyManagerEvents));


    }


    if(SUCCEEDED(hr))
    {
    // Start receiving events.
    hr = pSensorManager->SetEventSink(pMyManagerEvents);

    }

    while(flag!=500)
    {
    for(int i=0;i<100;i++);
    cout<<flag;
    if(flag==500)
    {
    cout<<"sensor detected";
    getchar();
    }

    }
    CoUninitialize();
    return 0;
    }

    I referred to the following microsoft page for this:

    http://msdn.microsoft.com/en-us/library/windows/desktop/dd319014(v=vs.85).aspx




    • Edited by ArMD Tuesday, December 31, 2013 8:24 AM
    Tuesday, December 31, 2013 6:43 AM

Answers

  • CoInitialize(NULL) instantiates the COM apartment as a single-threaded apartment (STA).  What this basically means is that all the COM objects you created (SensorManager and CMyManagerEvents) are expected to be called on that thread.  The reason why you aren't receiving the events is that your while wait loop is effectively blocking incoming COM calls to the CMyManagerEvents.

    Two ways to fix this:

    1. If you don't care about the COM apartment, the simplest fix is to switch to a multi-threaded apartment (MTA).  To do this, you replace CoInitialize(NULL) with CoInitializeEx(NULL, COINIT_MULTITHREADED).  The effect of this is tell COM that CMyManagerEvents does not need to be invoked on the same thread as your main program.

    2. If you need to use an STA (for example, if your program needs to update some UI controls based on the detected sensors), then you would need to replace that while wait loop with a message pump and a wait on an event handle.  One way to do this is to create an event (using CreateEvent), make it part of the CMyManagerEvents class, and then SetEvent during OnSensorEnter.  In the main program, you would use CoWaitForMultipleHandles with the COWAIT_DISPATCH_CALLS | COWAIT_DISPATCH_WINDOW_MESSAGES flags for that same event handle.  This allows the STA to process incoming COM calls, and allows CMyManagerEvents to be called when a sensor is detected.

    Tuesday, December 31, 2013 7:09 PM