![]() |
![]() |
|
•
Продукты • Где купить • Пользователям • Для бизнеса • Мы на связи |
null null null
|
API для работы с устройствами IRLink серии VS Это первая версия описания программного интерфейса для работы с нашими устройствами. Если у вас возникнут вопросы, пожалуйста, свяжитесь с нами. Данное API предназначено для работы с устройствами IRLink серии VS: приёмникам и приёмниками-излучателями (тип корпуса при этом значения не имеет). Статья про кодировки пультов ДУ. После установки драйверов IRLink.VS в системе появляется виртуальный COM порт. Для работы с устройством надо открыть появившийся порт и протестировать наличие устройства на нём (т. к. виртуальные COM порты могут использоваться также Bluetooth адаптерами, GPRS навигаторами и пр.). Для опознания приёмника надо записать в порт байт 0x81, в ответ придёт такой же. Для опознания излучателя используется байт 0x82. Для приёмника-излучателя надо использовать оба байта последовательно. Обратите внимание, что опознание устройства происходит по тому же каналу, что и приём данных, то есть гипотеически возможно получить ответный байт не как реакцию устройства на запрос, а просто выловить ответный байт в поток данных, посылаемых устройствов в порт. При приёме сигналов приёмник записывает в порт последовательность импульсов и пауз в сигнале после принятия сигнала (то есть по истечении максимально возможной кодируемой паузы). Каждый байт в посылке обозначает импульс или паузу и данные о масштабе.
Например ИК импульс длительностью 8,9 мс будет обозначаться байтом 0xC1, а пауза длительностью 4,4 мс будет обозначаться байтом 0xA0. ИК импульс, длительностью 417 мкс будет обозначаться 0x0E. ИК импульс длительностью более 256/14400 обозначается 0xFF. ИК пауза длительностью более 256/14400 обозначается 0xFE. При работе с излучателем когда есть возможность представить один и тот же промежуток времени в обих масштабах, предпочтительнее масштаб 1/14400. Пример поиска устройства
char* findDevice(){
char* portName = NULL;
HKEY hKey;
LONG result;
// перечисление установленных в системе COM портов
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"HARDWARE\\DEVICEMAP\\SERIALCOMM",
0,
KEY_ALL_ACCESS,
&hKey);
if(result != ERROR_SUCCESS){
MessageBox(NULL, "error opening registry", "IRLink", MB_OK);
}
DWORD portCount = -1;
DWORD keyNameSize = 16, keyValueSize = 8;
char *keyName = (char *)malloc(keyNameSize);
char *portName2 = (char *)malloc(keyValueSize);
do{
portCount ++;
//
//after each reading (RegQueryValueEx) of a registry value buffersizeentry is changed to the size of last read number of bytes. So you should set again this value before using it in a new RegQueryValueEx
//
keyNameSize = 16;
keyValueSize = 8;
result = RegEnumValue(hKey, portCount, keyName, &keyNameSize, NULL, NULL, (LPBYTE)portName2, &keyValueSize);
//shouldnt check result for ERROR_SUCCESS, because sometime
//we get ERROR_UNSUFFICIENT_BUFFER_SIZE for keyName
//we ignore this error because we arent interested in keyName
if(result != ERROR_NO_MORE_ITEMS && checkDevice(portName2, keyName)){
portName = portName2;
}
SecureZeroMemory(keyName, keyNameSize);
}while(result != ERROR_NO_MORE_ITEMS && portName == NULL);
RegCloseKey(hKey);
return getJString(env, portName);
}
//метод для поиска устройства на заданном порту
BOOL checkDevice(const char* portName, char* portDescription){
// описание виртуального COM порта для IRLink.VS состоит из букв vcp
if(StrStrI(portDescription, "vcp") == NULL){
return FALSE;
}
HANDLE hComm;
char buff[128] = "\\\\.\\";
StrCat(buff, portName);
hComm = CreateFile( buff,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if(hComm == NULL){
return false;
}
DCB dcb;
GetCommState(hComm, &dcb);
dcb.BaudRate = CBR_115200;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.fParity = 0;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
SetCommState(hComm, &dcb);
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutConstant = 1;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 10;
timeouts.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(hComm, &timeouts);
Sleep(100);
//creating event
OVERLAPPED o;
o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// тестовый байт для проверки устройства
const BYTE TEST_BYTE[] = {0, 0x81};
DWORD bytesCount;
WriteFile(hComm, &TEST_BYTE[0], 2, &bytesCount, &o);
DWORD error = GetLastError();
if(error == ERROR_IO_PENDING){
DWORD result = WaitForSingleObject(o.hEvent, 50);
if(result == WAIT_TIMEOUT){
CloseHandle(hComm);
return FALSE;
}
}else{
CloseHandle(hComm);
return FALSE;
}
Sleep(50);
BYTE receivedByte[128] = {0};
ReadFile(hComm, &receivedByte[0], 128, &bytesCount, &o);
error = GetLastError();
if(error == ERROR_IO_PENDING){
DWORD result = WaitForSingleObject(o.hEvent, 200);
if(result == WAIT_TIMEOUT){
CloseHandle(hComm);
return FALSE;
}else{
BOOL replyFound = false;
for(int i=0; i<128 && !replyFound; i++){
replyFound = (receivedByte[i] == 0x81);
}
CloseHandle(hComm);
return replyFound;
}
}else{
CloseHandle(hComm);
return FALSE;
}
}
Пример чтения данных с приёмника
void run(char* port){
HANDLE hComm;
char buff[128] = "\\\\.\\";
StrCat(buff, port);
hComm = CreateFile( buff,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
NULL,
0);
if(hComm == INVALID_HANDLE_VALUE){
return;
}
DCB dcb;
GetCommState(hComm, &dcb);
dcb.BaudRate = CBR_115200;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
SetCommState(hComm, &dcb);
COMMTIMEOUTS timeouts;
GetCommTimeouts(hComm, &timeouts);
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutConstant = 1;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 10;
timeouts.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(hComm, &timeouts);
Sleep(20);
DWORD rawBuffer[256] = {0};
DWORD rawBufferSize = 0;
DWORD period;
BYTE byte;
double value;
DWORD bytesRead;
BOOL isPause;
while(true){
if(!ReadFile (hComm, &byte, 1, &bytesRead, NULL) || bytesRead != 1){
continue;
}
isPause = !(byte & 1);
// определение масштаба интервала времени
if((byte & 128) == 128){
byte = (byte & 126) >> 1;
value = byte/0.0000853/3600;
if(value - floor(value) >= 0.5){
period = ceil(value);
}else{
period = floor(value);
}
}else{
byte = (byte & 126) >> 1;
value = byte/0.0000853/14400;
if(value - floor(value) >= 0.5){
period = ceil(value);
}else{
period = floor(value);
}
}
if(period > 200 && isPause){
// если байт кодирует паузу больше максимально возможной длительнсти — значит это конец посылки
// теперь у нас в буфере rawBuffer[0] записано rawBufferSize данных об импульсах и паузах.
// тут делает дальнейшая обработка сигнала
// очишаем буфер для следующей посылки
rawBufferSize = 0;
SecureZeroMemory(&rawBuffer[0], 256*sizeof(DWORD));
}else{
if(rawBufferSize < 256){
rawBuffer[rawBufferSize] = period;
rawBufferSize++;
}
}
}
CloseHandle(hComm);
}
Дополнительно Надо обратить внимание на то, что сигнал у пульта неидеальный, обычно каждые импульс и пауза гуляет немного. Поэтому при сравнении принятого сигнала с образцом имеет смысл делать допуск на каждый импульс и паузу. При приёме сигнала иногда вместо одного импульса приходит серия более мелких импульсов, разделённых паразитными паузами. В плагине приёмнка IRLink.VS (см. пример ниже) введён дополнительный метод doFiltering(), который делает следующее: если встречается слишком маленькая пауза, то она не засчитывается за паузу, а считается как продолжение предыдущего импульса. Примеры
Пример тестиров для приёмника и излучателя | ||||||||||||||||||||||||||
| Главная l Продукты | Где купить | Пользователям | Предложения для бизнеса | Мы на связи | Мешки-сетки для хранения спальников |
| © 2003–2010 автор идеи Павел |