Oct
15

Работаем с LED-индикаторами устройства под управлением Windows Mobile

Для того чтобы управлять LED-индикаторами устройства, в Windows Mobile предусмотрено специальное API:

BOOL WINAPI NLedSetDevice(UINT nDeviceId, void* pInput);

Первый параметр, nDeviceID указывает на то, какие данные передаются в параметре pInput. Для того чтобы установить состояние LED-индикатора, параметр nDeviceID должен иметь значение NLED_SETTINGS_INFO_ID, а в качестве параметра pInput необходимо передать указатель на структуру NLED_SETTINGS_INFO, содержащую информацию о новом состоянии LED-индикатора.

struct NLED_SETTINGS_INFO {
UINT LedNum;
INT OffOnBlink;
LONG TotalCycleTime;
LONG OnTime;
LONG OffTime;
INT MetaCycleOn;
INT MetaCycleOff;
};
  • LedNum – содержит индекс LED-индикатора (zero-based).
  • OffOnBlink – содержит новое состояние индикатора (0 – выключен, 1 – включен, 2 – мигающий
  • TotalCycleTime – длительность цикла мерцания в миллисекундах
  • OnTime – длительность включенного состояния индикатора при мерцании
  • OffTime – длительность выключенного состояния индикатора при мерцании
  • MetaCycleOn – количество ON-циклов
  • MetaCycleOff – количество OFF-циклов

Вобще описание назначения последних двух полей структуры вводит меня в недоумение. В MSDN по этому поводу всего две скупые фразы “Number of on blink cycles.” и “Number of off blink cycles.” без какого-либо дальнейшего пояснения.

Для того чтобы получить количество LED-индикаторов в системе можно воспользоваться функцией NLedGetDeviceInfo:

BOOL WINAPI NLedGetDeviceInfo(UINT nInfoId, void* pOutput);

В качестве первого параметра необходимо передать значение NLED_COUNT_INFO_ID, в качестве второго параметра – указатель на структуру NLED_COUNT_INFO, которая, в случае успешного завершения работы функции, будет содержать количество индикаторов.

Ну вот, с теоретической частью закончили, теперь перейдем к рассмотрению простенького примера. А в качестве примера у нас будет небольшая библиотека-обертка над описанным выше API.

wxMobileLED.h

#ifndef _WX_MOBILE_LED_H
#define _WX_MOBILE_LED_H

class wxMobileLEDImpl;

class wxMobileLED
{
	wxMobileLEDImpl * m_Impl;
public:
	wxMobileLED();
	~wxMobileLED();
	size_t GetCount();
	bool SetLED(size_t index, bool value, bool blink = false);
};

#endif

wxMobileLED.cpp

#include "wxMobileLED.h"
#if defined(__WXWINCE__)
#include "wxMobileLEDImplWinCE.h"
#else
#endif

wxMobileLED::wxMobileLED()
{
	m_Impl = 
#if defined(__WXWINCE__)
		new wxMobileLEDImplWinCE;
#else
		NULL;
#endif
}

wxMobileLED::~wxMobileLED()
{
	if(m_Impl) delete m_Impl;
}

size_t wxMobileLED::GetCount()
{
	if(m_Impl)
	{
		return m_Impl->GetCount();
	}
	return 0;
}

bool wxMobileLED::SetLED(size_t index, bool value, bool blink)
{
	if(m_Impl)
	{
		return m_Impl->SetLED(index, value, blink);
	}
	return false;
}

wxMobileLEDImpl.h

#ifndef _WX_MOBILE_LED_IMPL_H
#define _WX_MOBILE_LED_IMPL_H

class wxMobileLEDImpl
{
public:
	virtual size_t GetCount() = 0;
	virtual bool SetLED(size_t index, bool value, bool blink = false) = 0;
};

#endif

wxMobileLEDImplWinCE.h

#ifndef _WX_MOBILE_LED_IMPL_WINCE_H
#define _WX_MOBILE_LED_IMPL_WINCE_H

#include "wxMobileLEDImpl.h"

class wxMobileLEDImplWinCE : public wxMobileLEDImpl
{
public:
	virtual size_t GetCount();
	virtual bool SetLED(size_t index, bool value, bool blink = 0);
};

#endif

wxMobileLEDImplWinCE.cpp

#include "wxMobileLEDImplWinCE.h"
#include <windows.h>
#include <NLed.h>

size_t wxMobileLEDImplWinCE::GetCount()
{
#if defined(__WXWINCE__) && (UNDER_CE >= 0x500)
	NLED_COUNT_INFO count = {0};
	NLedGetDeviceInfo(NLED_COUNT_INFO_ID,&count); 
	return count.cLeds;
#else
	return 0;
#endif
}

bool wxMobileLEDImplWinCE::SetLED(size_t index, bool value, bool blink)
{
#if defined(__WXWINCE__) && (UNDER_CE >= 0x500)
	do
	{
		if(index >= GetCount()) break;
		NLED_SETTINGS_INFO info;
		ZeroMemory(&info, sizeof(NLED_SETTINGS_INFO));
		info.LedNum = index;
		info.OffOnBlink = value ? (blink ? 2 : 1) : 0;
		return (NLedSetDevice(NLED_SETTINGS_INFO_ID, &info) == TRUE);
	}
	while(false);
#endif
	return false;
}

Пример использования библиотеки:


wxMobileLED m_MobileLED;

...
void wxMobileLEDTestMainFrame::FillLEDList()
{
	size_t ledCount = m_MobileLED.GetCount();
	for(size_t i = 0; i < ledCount; i++)
	{
		int item = m_LEDList->Append(wxString::Format(wxT("LED %i"), i+1));
	}
}

void wxMobileLEDTestMainFrame::UpdateLEDs()
{
	for(size_t i = 0; i < m_LEDList->GetCount(); i++)
	{
		bool value = m_LEDList->IsChecked(i);
		if(!m_MobileLED.SetLED(i, value, m_BlinkCheckBox->GetValue()))
		{
			wxLogTrace(wxTraceMask(), _("Unable to turn LED #%i %s"), i, 
				value ? _("ON") : _("OFF"));
		}
	}
}

Исходный код примера для wxWinCE, а также исполняемый файл для Windows Mobile 6 можно взять здесь.

PS: Хотя описанное выше API предназначено для управления состоянием LED-индикаторов и на эмуляторе действительно управляет ими, но на реальном устройстве (ETEN Glofiish X800 под управлением Windows Mobile 6) включение/віключение индикатора с индексом 1 приводит к включению/віключению вибро. Мая шоке %).

Еще интересные посты о программировании для мобильных устройств:

2 Comments

Make A Comment
  • dr.cod Said:

    Так и есть, ведь вибро – это индикатор с состоянием вкл/выкл.

    На счет моста – несовсем, случай вырожденный, для других платформ он не определен. Достаточно было бы простого наследования.

  • T-Rex Said:

    Так же ж по поводу моста, планировалось же “на вырост”, чтобы еще под Linux дописать аналог.

Comments RSS Feed   TrackBack URL

Leave a comment

Please leave these two fields as-is:

top