Использование сенсоров в приложении: реализация в native-коде (ч.1)

Автор: Topol Четверг, Май 3rd, 2012 Нет комментариев

Рубрика: Операционные системы

После поверхностного обзора платформы Sensor and Location пришло время углубиться в API. Мы начнем с описания Win32 API для понимания потока данных, а затем рассмотрим управляемые API через [url=http://code.msdn.microsoft.com/WindowsAPICodePack]Windows API Code Pack для .NET  Framework[/url].

Платформа Sensor and Location состоит из двух компонентов: сенсорного и созданного поверх него компонента, отвечающего за местоположени. Для начала мы подробно рассмотрим сенсорную часть, чтобы к тому моменту, когда пойдет речь о местоположении, мы будем понимать, на базе чего она основана.

Sensor API (равно как и Location API) основан на COM. Все необходимые API и определения GUID можно найти в файлах Sensorsapi.h и Sensors.h из Windows 7  SDK. Файл Sensors.h содержит массу GUID, которые определяют различные аспекты категорий сенсоров, типов и данных. API и интерфейсы находятся в файле Sensorsapi.h. Более пристальный взгляд на файл Sensorsapi.h открывает три основных COM-интерфейса, о которых вам необходимо знать, работая с сенсорами:

  • ISensorManager является основным интерфейсом для всех сенсоров, подключенных к платформе. Менеджер сенсора позволяет вам получать список сенсоров, запрашивать разрешения для доступа к данным сенсора и получить уведомления о событиях при обнаружении нового сенсора.
  • ISensor представляет собой фактический объект сенсора, с которым вы собираетесь работать. Через этот интерфейс вы можете установить и получить свойства, получить отчеты и регистрировать события, которые произошли во время работы сенсора.
  • ISensorDataReport - единственный интерфейс, который вы будете любить и ненавидеть, поскольку это единственный способ получения актуальных данных от сенсора, однако это обобщенная форма обобщенного отчета данных, которые необходимо охватить.

Чтобы интегрировать сенсоры в ваше приложение, вам придется работать с этими тремя интерфейсами.

Интеграция сенсоров в приложение
Для интеграции сенсоров в приложение, вам необходимо выполнить следующие шаги:
1. Обнаружение сенсора- прежде, чем вы сможете обратиться к сенсору, вам необходимо обнаружить, какие сенсоры подключены к системе. Используйте интерфейс ISensorManager для получения списка сенсорных устройств, подключенных к платформе, и регистрации событий о подключении нового сенсора.
2. Получение сенсора и прав на него - как только вы обнаружили и выбрали сенсор, с которым вы желаете работать, вам необходимо убедиться, что вы имеете полномочия для доступа к нему. Если вы не имеете прав для доступа к данным сенсора (использовать его), вы должны получить права пользователя, чтобы приложение получило доступ к данным сенсора.
3. Взаимодействие с сенсором - теперь, когда вы получили доступ к данным сенсора, вы можете начать работу с ним, читая и устанавливая свойства, а также регистрируя события.

Обнаружение сенсоров
Первый шаг, который вам необходимо сделать для каждого приложения, в котором требуется использовать сенсоры, — это обнаружить, какие сенсоры подключены к платформе, а затем получить доступ к одному из них. Чтобы разрешить вашему приложению сделать это, вы должны использовать COM-интерфейс ISensorManager. Менеджер сенсора содержит список доступных датчиков. Так как это COM-интерфейс, вам необходимо его инициализировать с помощью CoCreateInstance. В принципе, этот интерфейс можно рассматривать как корневой интерфейс для API сенсора. Следующий фрагмент кода создает экземпляр менеджера сенсора:

Код:
// Объявляем указатель для получения указателя менеджера сенсора.
// Вообще данный указатель определяется в определении класса прототипов.
// CAmbientLightAwareSensorManagerEvents
CComPtr<ISensorManager> m_spISensorManager;
HRESULT hr;
// Создаем менеджер сенсора
hr = m_spISensorManager.CoCreateInstance(CLSID_SensorManager);

Интерфейс ISensorManager обеспечивает набор методов для обнаружения и получения доступных сенсоров. Он также выдает событие, используемое для получения уведомлений о доступности новых сенсоров. Вы можете спросить себя, как регистрировать событие, когда сенсор «покидает» систему. Ответ на этот вопрос можно отыскать в самом сенсоре. С указателем ISensorManager под рукой вы можете начать поиск сенсоров. У ISensorManager есть три метода, которые помогут вам найти подключенные датчики:

  • GetSensorsByID - первый метод возвращает определенный сенсор по его идентификатору (ID), который предсталяет собой обычный GUID. Это не самая используемая функция, поскольку GUID сенсора генерируется автоматически при первоначальном подключении к системе для обеспечения поддержки нескольких сенсоров одного и того же производителя и одинаковой модели.
  • GetSensorsByCategory - эта функция возвращает набор сенсоров, совместно использующих ту же самую категорию. Например, может быть несколько сенсоров местоположения, включая GPS и триангуляцию Wi-Fi, подключенных с платформой, и вы не хотите отказываться от их использования.
  • GetSensorsByType - эта функция возвращает набор сенсоров одного и того же типа.

Как вы могли заметить, имена функций показывают, что к компьютеру одновременно подключено множество сенсоров. Технически возможно, чтобы несколько сенсоров одной и той же категории были подключены к одному и тому же ПК. Например, на моем компьютере установлен один датчик освещения, установленный в корпус ПК, и еще один из состава Sensor Development Kit. Имеет смысл использовать световой датчик, встроенный в корпус, так как он обеспечивает самое точное чтение условий освещения. Для приложения наилучшим способом обнаружения сенсоров является использование типа интерфейса и категорий функции Sensor Manager с последующим выбором из списка нужного сенсора.

В этом цикле статей мы будем использовать очень простое приложение Microsoft Foundation Classes (MFC), являющееся частью Windows 7 SDK. Следующий код взят из метода Initialize класса CAmbientLightAwareSensorManagerEvents. В этом классе реализованы уведомления ISensorManagerEvents при обнаружении нового датчика.

Метод Initialize вызывают во время процесса инициализации главного диалога (у нас есть только один):

Код:
HRESULT CAmbientLightAwareSensorManagerEvents::Initialize()
{
HRESULT hr;
// Создаем менеджер сенсора
hr = m_spISensorManager.CoCreateInstance(CLSID_SensorManager);
if (SUCCEEDED(hr))
{
hr = m_spISensorManager->SetEventSink(this);
if (SUCCEEDED(hr))
{
// Ищем сенсоры внешнего освещения
CComPtr<ISensorCollection> spSensors;
hr = m_spISensorManager->GetSensorsByType
(SENSOR_TYPE_AMBIENT_LIGHT, &spSensors);
if (SUCCEEDED(hr) && NULL != spSensors)
{
ULONG ulCount = 0;
hr = spSensors->GetCount(&ulCount);
if (SUCCEEDED(hr))
{
for(ULONG i=0; i < ulCount; i++)
{
CComPtr<ISensor> spSensor;
hr = spSensors->GetAt(i, &spSensor);
if (SUCCEEDED(hr))
{
hr = AddSensor(spSensor);
if (SUCCEEDED(hr))
{
// Проверяем текущее состояние сенсора.
SensorState state = SENSOR_STATE_READY;
hr = spSensor->GetState(&state);
if(SUCCEEDED(hr))
{
if(state == SENSOR_STATE_READY)
{
// Читаем данные с сенсора и обновляем
// интерфейс приложения.
hr = m_pSensorEvents->GetSensorData
(spSensor);
}
}
}
}
}
}
}
}
return hr;
}

Как видите, после успешного получения интерфейса ISensorManager вы вызываете ISensorManager::GetSensorsByType, используя SENSOR_TYPE_AMBIENT_LIGHT и указатель на набор ISensorCollection, spSensors. SENSOR_TYPE_AMBIENT_LIGHT указывает, что мы хотим получить только сенсор внешнего освещения (ALS). В то же самое время можно опросить все сенсоры типа SENSOR_TYPE_VOLTAGE из электрической категории или SENSOR_TYPE_ACCELEROMETER_3D из категории акселлерометров.

В случае успешного выполнения функция GetSensorsByType заполняет ISensorCollection списком ALS-сенсоров. Затем вы повторяете это для всего набора и вызываете вспомогательную функцию AddSensor для каждого сенсора. Это устанавливает перехват события (делегат), регистрируя сенсор в m_pSensorEvents, являющийся классом реализации SensorEvents для перехвата событий, но об этом я расскажу позже. Наконец, вы вызываете другой вспомогательный метод, GetSensorData, чтобы считать данные с сенсора и обновить значение освещенности в интерфейсе приложения. Мы расскажем о фактическом чтении данных сенсора в следующих статьях.

В течение всего времени выполнения приложения к компьютеру могут быть подключены новые сенсоры, таким образом, требуется механизм уведомления приложения при подключении новых сенсоров. Интерфейс ISensorManager содержит метод SetEventSink для установки класса реализации перехвата события, то есть делегат, который обрабатывает события. Эта функция получает интерфейс обратного вызова ISensorManagerEvents, получающий уведомления о событии при подключении новое сенсора. Это событие выступает в качестве приемника, обрабатывающего OnSensorEnter — единственное событие, которое есть у интерфейса ISensorManagerEvents.

Если вы посмотрите на вышеприведенный пример, вы увидите, что вы вызываете SetEventSink после успешного создания интерфейса ISensorManager и передаете его в качестве входного параметра, а затем локальный класс CAmbientLightAwareSensorManagerEvents использует интерфейс ISensorManagerEvents.

Таким образом, в этом классе вы найдете реализацию для события ISensorManager:: OnSensorEnter, которая выглядит следующим образом:

Код:
HRESULT CAmbientLightAwareSensorManagerEvents::OnSensorEnter
(ISensor* pSensor, SensorState state)
{
HRESULT hr = S_OK;

if (NULL != pSensor)
{
SENSOR_TYPE_ID idType = GUID_NULL;
hr = pSensor->GetType(&idType);
if (SUCCEEDED(hr))
{
// Здесь нас интересуют лишь сенсоры освещения
if (IsEqualIID(idType, SENSOR_TYPE_AMBIENT_LIGHT))
{
hr = AddSensor(pSensor);
if (SUCCEEDED(hr))
{
if (SENSOR_STATE_READY == state)
{
hr = m_pSensorEvents->GetSensorData(pSensor);
}
}
}
}
}
else
{
hr = E_POINTER;
}

return hr;
}

В этом фрагменте кода метод OnSensorEnter получает указатель на недавно подключенный сенсор и состояние статуса сенсора. Если указатель сенсора верный (не пустой указатель), вы считываете тип сенсора, вызывая метод GetType интерфейса ISensor. Поскольку мы работаем со светочувствительным приложением и интересуемся только световыми сенсорами, мы проверим, является ли недавно подключенный сенсор световым, проверив его тип. Помните, что ISensorManager получает уведомление о любом типе сенсора, подключенного к ПК. Если сенсор является датчиком освещенности, тогда вы вызываете ту же вспомогательную функцию AddSensor, которую использовали в методе Initialize, устанавливая перехват для специфичных сенсоров. Не перепутайте с перехватом для ISensorManager. Последнее, что нужно сделать, — проверить, находится ли сенсор в состоянии готовности. Если да, вы просто читаете данные с сенсора и обновляете интерфейс приложения.

Но чтение данных с сенсора мы оставим для следующих статей.

Источник: thevista.ru

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты