使用传感器 API 事件
传感器 API 通过回调接口提供事件通知。
若要接收事件通知,程序必须实现所需的 COM 回调接口。 若要从传感器接收事件,必须实现 ISensorEvents。 若要从传感器管理器接收事件,必须实现 ISensorManagerEvents。
以下示例代码创建实现 ISensorEvents 的类。
class CMyEvents : public ISensorEvents
{
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(ISensorEvents))
{
*ppv = static_cast<ISensorEvents*>(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 OnEvent(
ISensor *pSensor,
REFGUID eventID,
IPortableDeviceValues *pEventData)
{
HRESULT hr = S_OK;
// Handle custom events here.
return hr;
}
STDMETHODIMP OnDataUpdated(
ISensor *pSensor,
ISensorDataReport *pNewData)
{
HRESULT hr = S_OK;
if(NULL == pNewData ||
NULL == pSensor)
{
return E_INVALIDARG;
}
ULONG ulHour = 0;
ULONG ulMinute = 0;
ULONG ulSecond = 0;
PROPVARIANT var = {};
hr = pNewData->GetSensorValue(SAMPLE_SENSOR_DATA_TYPE_HOUR, &var);
if(SUCCEEDED(hr))
{
if(var.vt == VT_UI4)
{
// Get the hour value.
ulHour = var.ulVal;
}
}
PropVariantClear(&var);
if(SUCCEEDED(hr))
{
hr = pNewData->GetSensorValue(SAMPLE_SENSOR_DATA_TYPE_MINUTE, &var);
}
if(SUCCEEDED(hr))
{
if(var.vt == VT_UI4)
{
// Get the hour value.
ulMinute = var.ulVal;
}
}
PropVariantClear(&var);
if(SUCCEEDED(hr))
{
hr = pNewData->GetSensorValue(SAMPLE_SENSOR_DATA_TYPE_SECOND, &var);
}
if(SUCCEEDED(hr))
{
if(var.vt == VT_UI4)
{
// Get the hour value.
ulSecond = var.ulVal;
}
}
PropVariantClear(&var);
if(SUCCEEDED(hr))
{
// Print
wprintf_s(L"Current local time is: \n");
wprintf_s(L"%02d:%02d:%02d (asynchronous)\n", ulHour, ulMinute, ulSecond);
}
return hr;
}
STDMETHODIMP OnLeave(
REFSENSOR_ID sensorID)
{
HRESULT hr = S_OK;
// Peform any housekeeping tasks for the sensor that is leaving.
// For example, if you have maintained a reference to the sensor,
// release it now and set the pointer to NULL.
return hr;
}
STDMETHODIMP OnStateChanged(
ISensor* pSensor,
SensorState state)
{
HRESULT hr = S_OK;
if(NULL == pSensor)
{
return E_INVALIDARG;
}
if(state == SENSOR_STATE_READY)
{
wprintf_s(L"\nTime sensor is now ready.");
}
else if(state == SENSOR_STATE_ACCESS_DENIED)
{
wprintf_s(L"\nNo permission for the time sensor.\n");
wprintf_s(L"Enable the sensor in the control panel.\n");
}
return hr;
}
private:
long m_cRef;
};
实现回调接口后,可以向特定传感器提供指向回调类实例的指针,以开始从传感器接收事件通知。
以下示例代码创建回调类的实例,然后从传感器请求事件通知。
CMyEvents* pEventClass = NULL;
ISensorEvents* pMyEvents = NULL;
if(SUCCEEDED(hr))
{
// Create an instance of the event class.
pEventClass = new(std::nothrow) CMyEvents();
}
if(SUCCEEDED(hr))
{
// Retrieve the pointer to the callback interface.
hr = pEventClass->QueryInterface(IID_PPV_ARGS(&pMyEvents));
}
if(SUCCEEDED(hr))
{
// Start receiving events.
hr = pSensor->SetEventSink(pMyEvents);
}
可以编写类似的代码来从传感器管理器接收事件。
以下示例代码演示如何停止接收事件通知。
if(SUCCEEDED(hr))
{
hr = pSensor->SetEventSink(NULL);
}
请求报告间隔
可以建议应用程序接收数据更新事件的频率值。 但是,传感器不需要以任何特定间隔提供事件。 应注意,建议的值可能与传感器用于引发事件的实际报告间隔不匹配。 若要了解实际报告间隔,请检索 SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL 属性的值,如检索和设置传感器属性中所述。
以下示例代码创建一个帮助程序函数,该函数请求 SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL 属性的新值。 该函数采用一个指向要为其设置属性的传感器的指针,以及一个指示要设置的新报告间隔的 ULONG 值。
HRESULT SetCurrentReportInterval(ISensor* pSensor, ULONG ulNewInterval)
{
assert(pSensor);
HRESULT hr = S_OK;
IPortableDeviceValues* pPropsToSet = NULL; // Input
IPortableDeviceValues* pPropsReturn = NULL; // Output
// Create the input object.
hr = CoCreateInstance(__uuidof(PortableDeviceValues),
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pPropsToSet));
if(SUCCEEDED(hr))
{
// Add the current report interval property.
hr = pPropsToSet->SetUnsignedIntegerValue(SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, ulNewInterval);
}
if(SUCCEEDED(hr))
{
// Only setting a single property, here.
hr = pSensor->SetProperties(pPropsToSet, &pPropsReturn);
}
// Test for failure.
if(hr == S_FALSE)
{
HRESULT hrError = S_OK;
// Check results for failure.
hr = pPropsReturn->GetErrorValue(SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, &hrError);
if(SUCCEEDED(hr))
{
// Print an error message.
wprintf_s(L"\nSetting current report interval failed with error 0x%X\n", hrError);
// Return the error code.
hr = hrError;
}
}
else if(hr == E_ACCESSDENIED)
{
// No permission. Take appropriate action.
}
SafeRelease(&pPropsToSet);
SafeRelease(&pPropsReturn);
return hr;
}
相关主题