SDK Readers 1.0.1
SDK для связи со считывателями Iron logic
auto_read_card/main.cpp

Демонстрирует автоматическое чтение данных карты при поднесении карты к считывателю.

#include <stdio.h>
#include <chrono>
#include <iomanip> // для std::put_time
#include <iostream>
#include "ilreaders.h"
// #define ILR_LOG // Раскомментируйте, чтобы включить отладочные сообщения
#define ILR_LOG_FILE // Писать лог в файл
using namespace ilr;
// Пароль для доступа к Temic, =-1 нет пароля
const int64_t g_TemicPassword = -1;
// Ключ аутентификации Mifare
const CMifareClassicKey g_McKey;
// Ключ аутентификации Mifare Plus
const CMifarePlusKey g_MpKey;
// True, открытая передача, иначе - зашифрованная
const bool g_fOpenText = true;
// Текущая команда чтения карты
ilr::CAsyncCommand g_oReadCmd;
// Время старта чтения карты
std::chrono::steady_clock::time_point g_StartTime;
// Тип карты, который читаем
// Размер данных карты
uint32_t g_nCardMemSize;
#ifdef ILR_LOG
const char kLogLevelChars[] = {'-', 'E', 'W', 'I', 'D'};
const char kLogFileName[] = "ilreaders.log"; // Путь к лог файлу
void ILR_CALL LogCallback(ilr_log_level level, const char* pContext, const char* pMessage, void*) {
#ifdef ILR_LOG_FILE // Запись в файл
std::ofstream file(kLogFileName, std::ios_base::out | std::ios_base::app);
auto& out = file;
#else // иначе в консоль
auto& out = std::cout;
#endif
auto t = std::time(nullptr);
auto tmb = std::localtime(&t);
out << std::put_time(tmb, "%d-%m-%Y %H:%M:%S") << " [" << kLogLevelChars[level] << ' '
<< pContext << "] " << pMessage << std::endl;
}
#endif
void ILR_CALL MessageCallback(ilr_reader_msg nMsg, const void* pMsgData, void* pUserData) {
try {
switch (nMsg) {
case ILR_READER_MSG_CARD_FOUND: // Карта найдена
{
auto pInfo = static_cast<const ilr_card_info*>(pMsgData);
std::stringstream ss;
if (pInfo->nMpType != ILR_MF_PLUS_UNKNOWN)
ss << " " << kMpTypeNames[pInfo->nMpType];
if (pInfo->nSL != ILR_MF_PLUS_SL_UNKNOWN)
ss << " SL" << static_cast<int>(pInfo->nSL);
std::cout << "{!} Карта найдена " << kCardTypeNames[pInfo->nType] << ' '
<< CardUIDToStr(pInfo->nType, pInfo->rUID) << ss.str() << std::endl;
if (g_oReadCmd) {
g_oReadCmd.Cancel();
g_oReadCmd.Close();
std::cout << "Чтение данных отменено" << std::endl;
}
auto pReader = static_cast<CReader*>(pUserData);
pReader->GetReaderInfo(rRI);
auto nRwCards = pReader->GetSupportedRewrittenCardTypes(rRI.nModel, rRI.nFwVersion);
g_nCardMemSize = pInfo->nMemSize;
switch (pInfo->nType) {
if (nRwCards & ILR_RWCT_F_TEMIC) {
g_nCardType = ILR_RWCT_F_TEMIC;
g_StartTime = ilr::now();
g_oReadCmd = pReader->Begin_ReadTemic(0, 10);
std::cout << "Чтение данных..." << std::endl;
}
break;
if (nRwCards & ILR_RWCT_F_MF_ULTRALIGHT) {
g_nCardType = ILR_RWCT_F_MF_ULTRALIGHT;
g_StartTime = ilr::now();
g_oReadCmd = pReader->Begin_ReadMfUltralight(0, 16);
std::cout << "Чтение данных..." << std::endl;
}
break;
if (nRwCards & ILR_RWCT_F_MF_CLASSIC) {
g_nCardType = ILR_RWCT_F_MF_CLASSIC;
g_StartTime = ilr::now();
auto nBlockCount = GetNumberOfMfBlocks(pInfo->nMemSize);
g_oReadCmd = pReader->Begin_ReadMfClassic(0, nBlockCount);
std::cout << "Чтение данных..." << std::endl;
}
break;
if (ILR_MF_PLUS_SL_SL3 == pInfo->nSL) {
if (nRwCards & ILR_RWCT_F_MF_PLUS_SL3) {
g_nCardType = ILR_RWCT_F_MF_PLUS_SL3;
g_StartTime = ilr::now();
auto nBlockCount = GetNumberOfMfBlocks(pInfo->nMemSize);
g_oReadCmd = pReader->Begin_ReadMfPlus(0, nBlockCount, g_fOpenText);
std::cout << "Чтение данных..." << std::endl;
}
}
else if (ILR_MF_PLUS_SL_SL1 == pInfo->nSL) {
if (nRwCards & ILR_RWCT_F_MF_CLASSIC) {
g_nCardType = ILR_RWCT_F_MF_CLASSIC;
g_StartTime = ilr::now();
auto nBlockCount = GetNumberOfMfBlocks(pInfo->nMemSize);
g_oReadCmd = pReader->Begin_ReadMfClassic(0, nBlockCount);
std::cout << "Чтение данных..." << std::endl;
}
}
break;
default:
std::cout << "Считыватель не поддерживает чтение данных из карты" << std::endl;
break;
}
// Если команда чтения не стартовала, то возобновляем сканирование карт
if (!g_oReadCmd)
pReader->SetAutoScan(true, false);
}
break;
case ILR_READER_MSG_CARD_LOST: // Карта потеряна
{
auto pInfo = static_cast<const ilr_card_info*>(pMsgData);
std::stringstream ss;
if (pInfo->nMpType != ILR_MF_PLUS_UNKNOWN)
ss << " " << kMpTypeNames[pInfo->nMpType];
if (pInfo->nSL != ILR_MF_PLUS_SL_UNKNOWN)
ss << " SL" << static_cast<int>(pInfo->nSL);
std::cout << "{!} Карта потеряна " << kCardTypeNames[pInfo->nType] << ' '
<< CardUIDToStr(pInfo->nType, pInfo->rUID) << ss.str() << std::endl;
if (g_oReadCmd) {
g_oReadCmd.Cancel();
g_oReadCmd.Close();
std::cout << "Чтение данных отменено" << std::endl;
// Возобновляем сканирование карт
auto pReader = (CReader*)pUserData;
pReader->SetAutoScan(true, false);
}
}
break;
case ILR_READER_MSG_COMMAND_FINISH: // Завершена команда чтения
if (g_oReadCmd) {
auto nSpan = since(g_StartTime).count();
auto pReader = static_cast<CReader*>(pUserData);
auto nStatus = g_oReadCmd.GetStatus();
// Возобновляем сканирование карт
pReader->SetAutoScan(true, false);
switch (g_nCardType) {
{
const uint* pBlocks = nullptr; // 10 блоков по 4 байта
size_t nCount = 0;
pReader->End_ReadTemic(g_oReadCmd, pBlocks, nCount);
const uint8_t* p;
for (size_t i = 0; i < nCount; i++) {
p = (const uint8_t*)&pBlocks[i];
std::cout << std::dec << std::setw(2) << i << ". " << std::hex
<< std::setw(2) << (uint)p[0] << ' ' << std::setw(2)
<< (uint)p[1] << ' ' << std::setw(2) << (uint)p[2] << ' '
<< std::setw(2) << (uint)p[3] << std::endl;
}
std::cout << "Прочитано " << std::dec << nCount << " блоков за " << nSpan
<< " мс" << std::endl;
}
break;
{
const uint* pPages = nullptr; // 16 страниц по 4 байта
size_t nCount = 0;
pReader->End_ReadMfUltralight(g_oReadCmd, pPages, nCount);
const uint8_t* p;
for (size_t i = 0; i < nCount; i++) {
p = (const uint8_t*)&pPages[i];
std::cout << std::dec << std::setw(2) << i << ". " << std::hex
<< std::setw(2) << (uint)p[0] << ' ' << std::setw(2)
<< (uint)p[1] << ' ' << std::setw(2) << (uint)p[2] << ' '
<< std::setw(2) << (uint)p[3] << std::endl;
}
std::cout << "Прочитано " << nCount << " страниц за " << nSpan << " мс"
<< std::endl;
}
break;
{
const ilr_mf_block_data* pBlocks = nullptr;
size_t nCount;
pReader->End_ReadMfClassic(g_oReadCmd, pBlocks, nCount);
const ilr_mf_block_data* pBlock;
for (size_t i = 0; i < nCount; i++) {
pBlock = &pBlocks[i];
std::cout
<< std::dec << std::setw(2) << i << ". " << std::hex << std::setw(2)
<< (uint)pBlock->a[0] << ' ' << std::setw(2) << (uint)pBlock->a[1]
<< ' ' << std::setw(2) << (uint)pBlock->a[2] << ' ' << std::setw(2)
<< (uint)pBlock->a[3] << ' ' << std::setw(2) << (uint)pBlock->a[4]
<< ' ' << std::setw(2) << (uint)pBlock->a[5] << ' ' << std::setw(2)
<< (uint)pBlock->a[6] << ' ' << std::setw(2) << (uint)pBlock->a[7]
<< ' ' << std::setw(2) << (uint)pBlock->a[8] << ' ' << std::setw(2)
<< (uint)pBlock->a[9] << ' ' << std::setw(2) << (uint)pBlock->a[10]
<< ' ' << std::setw(2) << (uint)pBlock->a[11] << ' ' << std::setw(2)
<< (uint)pBlock->a[12] << ' ' << std::setw(2) << (uint)pBlock->a[13]
<< ' ' << std::setw(2) << (uint)pBlock->a[14] << ' ' << std::setw(2)
<< (uint)pBlock->a[15] << std::endl;
}
std::cout << "Прочитано " << nCount << " блоков за " << nSpan << " мс"
<< std::endl;
}
break;
{
const ilr_mf_block_data* pBlocks = nullptr;
size_t nCount;
pReader->End_ReadMfPlus(g_oReadCmd, pBlocks, nCount);
const ilr_mf_block_data* pBlock;
for (size_t i = 0; i < nCount; i++) {
pBlock = &pBlocks[i];
std::cout
<< std::dec << std::setw(2) << i << ". " << std::hex << std::setw(2)
<< (uint)pBlock->a[0] << ' ' << std::setw(2) << (uint)pBlock->a[1]
<< ' ' << std::setw(2) << (uint)pBlock->a[2] << ' ' << std::setw(2)
<< (uint)pBlock->a[3] << ' ' << std::setw(2) << (uint)pBlock->a[4]
<< ' ' << std::setw(2) << (uint)pBlock->a[5] << ' ' << std::setw(2)
<< (uint)pBlock->a[6] << ' ' << std::setw(2) << (uint)pBlock->a[7]
<< ' ' << std::setw(2) << (uint)pBlock->a[8] << ' ' << std::setw(2)
<< (uint)pBlock->a[9] << ' ' << std::setw(2) << (uint)pBlock->a[10]
<< ' ' << std::setw(2) << (uint)pBlock->a[11] << ' ' << std::setw(2)
<< (uint)pBlock->a[12] << ' ' << std::setw(2) << (uint)pBlock->a[13]
<< ' ' << std::setw(2) << (uint)pBlock->a[14] << ' ' << std::setw(2)
<< (uint)pBlock->a[15] << std::endl;
}
std::cout << "Прочитано " << nCount << " блоков за " << nSpan << " мс"
<< std::endl;
}
break;
default:
std::cout << "Неожиданный тип карты!" << std::endl;
break;
}
if (ILR_SUCCEEDED(nStatus))
std::cout << "Успех" << std::endl;
else
std::cout << "Ошибка: " << ilr_get_error_text(nStatus) << std::endl;
g_oReadCmd.Close();
}
break;
case ILR_READER_MSG_CONNECTION_CHANGED: // Изменилось состояние подключения считывателя
{
auto pReader = static_cast<CReader*>(pUserData);
auto nStatus = pReader->GetConnectionStatus();
switch (nStatus) {
std::cout << "{!} Считыватель подключён" << std::endl;
break;
case ILR_CONNECTION_DISCONNECTED:
std::cout << "{!} Считыватель отключён" << std::endl;
default:
break;
}
}
break;
}
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
int main() {
try {
#ifdef ILR_LOG
#ifdef ILR_LOG_FILE
// Очищаем лог файл
std::ofstream file(kLogFileName, std::ios_base::out | std::ios_base::trunc);
file.close();
#endif
CILR::SetLogCallback(LogCallback);
CILR::SetLogLevel(ILR_LOG_LEVEL_DEBUG);
#endif
CILR oILR;
// Ищем считыватель
CReader oReader;
{
std::cout << "Поиск считывателя..." << std::endl;
CReaderSearch oSearch(oILR.GetSearch());
#if 0
// Выбираем типы считывателя для поиска
oSearch.GetOptions(rOptions);
oSearch.SetOptions(rOptions);
// Включаем поиск конвертеров в режиме "Клиент"
const uint16_t aListenPorts[] = {25000};
oSearch.SetListenPorts(aListenPorts, std::size(aListenPorts));
#endif
// Ищем
oSearch.Scan();
auto nCount = oSearch.GetReaderCount();
bool fFound = false;
for (size_t i = 0; i < nCount; i++) {
oSearch.GetReaderInfo(i, rInfo);
// Если порт занят, то пропускаем
if (*rInfo.pszConnect != '\0')
continue;
fFound = true;
break;
}
if (!fFound) {
std::cout << "Считыватель не найден" << std::endl;
return 0;
}
oReader = oILR.GetReader(rInfo.nPortType, rInfo.pszPortName);
// Устанавливает ключи аутентификации
oReader.LoadTemicPassword(g_TemicPassword);
oReader.LoadMfCKey(g_McKey);
oReader.LoadMfPKey(g_MpKey);
// Разрешаем сканировать Temic
oReader.SetScanTemic(true);
// Подключаемся к считывателю
std::cout << "Подключение к считывателю [" << kPortTypeNames[rInfo.nPortType] << ": "
<< rInfo.pszPortName << "]..." << std::endl;
oReader.Connect();
}
// Получаем информацию о считывателе
oReader.GetReaderInfo(rInfo);
std::stringstream ss;
ss << kReaderModelNames[rInfo.nModel];
if (rInfo.nSn != -1)
ss << " с/н:" << rInfo.nSn;
if (rInfo.nFwVersion != 0)
ss << " прошивка:" << ReaderVersionToStr(rInfo.nFwVersion);
if (rInfo.nFwBuildDate != 0)
ss << " сборка " << TimeToStr(rInfo.nFwBuildDate);
std::cout << "Считыватель успешно подключён [" << ss.str() << ']' << std::endl;
// Подписываемся на уведомления о поднесении/удалении карты
oReader.SetMessageCallback(MessageCallback, &oReader);
// Включаем задержку при поднесении перезаписываемой карты
oReader.GetOptions(rOptions);
oReader.SetOptions(rOptions);
// Ожидаем поднесение/удаление карты
std::cout << "Ожидание поднесения карты..." << std::endl;
std::cout << "Нажмите <Enter> для выхода..." << std::endl;
std::cin.get();
if (g_oReadCmd) {
g_oReadCmd.Cancel();
g_oReadCmd.Close();
std::cout << "Чтение данных отменено" << std::endl;
}
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
Класс команды SDK.
Definition: ilr_cpp_helpers.h:514
void Cancel()
Отменяет команду. Устанавливает статус ILR_E_ABORT.
Definition: ilr_cpp_helpers.h:564
ilr_status GetStatus() const
Возвращает состояние команды.
Definition: ilr_cpp_helpers.h:568
void Close()
Закрывает дескриптор SDK.
Definition: ilr_cpp_helpers.cpp:218
Класс для инициализации/финализации библиотеки SDK.
Definition: ilr_cpp_helpers.h:2607
CReaderSearch GetSearch()
Создаёт дескриптор поиска считывателей.
Definition: ilr_cpp_helpers.h:2761
CReader GetReader(ilr_port_type nPortType, const char *pszPortName)
Создаёт дескриптор считывателя.
Definition: ilr_cpp_helpers.h:2767
Класс ключа аутентификации Mifare Classic.
Definition: ilr_cpp_helpers.h:231
Ключ аутентификации Mifare Plus.
Definition: ilr_cpp_helpers.h:294
Класс поиска считывателей.
Definition: ilr_cpp_helpers.h:583
Класс считывателя.
Definition: ilr_cpp_helpers.h:996
ilr_connection_status GetConnectionStatus() const
Возвращает состояние подключения к считывателю
Definition: ilr_cpp_helpers.h:2217
void SetScanTemic(bool fEnable=true)
Вкл/выкл сканирование карт Temic (для Z-2 Rd-All и Z-2 EHR).
Definition: ilr_cpp_helpers.h:2518
void SetMessageCallback(ilr_reader_message_callback pCallback, void *pUserData=nullptr)
Устанавливает функцию обратного вызова для уведомлений считывателя.
Definition: ilr_cpp_helpers.h:2175
void Connect(bool fReconnect=false)
Подключается к считывателю.
Definition: ilr_cpp_helpers.h:2197
void SetOptions(const ilr_reader_options &rOptions)
Устанавливает параметры считывателя.
Definition: ilr_cpp_helpers.h:2189
void LoadTemicPassword(const int64_t nPassword)
Загружает пароль Temic в память объекта считывателя.
Definition: ilr_cpp_helpers.h:2504
void LoadMfCKey(const ilr_mf_classic_key &nKey)
Загружает ключ для авторизации сектора Mifare Classic / Plus SL1.
Definition: ilr_cpp_helpers.h:2290
void GetReaderInfo(ilr_reader_info &rInfo) const
Возвращает информацию о считывателе.
Definition: ilr_cpp_helpers.h:2223
void GetOptions(ilr_reader_options &rOptions) const
Возвращает параметры считывателя.
Definition: ilr_cpp_helpers.h:2193
void LoadMfPKey(const ilr_mf_plus_key &rKey)
Загружает ключ для авторизации сектора Mifare Plus SL3.
Definition: ilr_cpp_helpers.h:2294
ILR_API const char *ILR_CALL ilr_get_error_text(ilr_status nErrorCode)
Возвращает описание ошибки по её коду.
#define ILR_SUCCEEDED(status)
Проверяет код возврата SDK на успех.
Definition: ilreaders.h:194
ilr_rwcard_type_flags
Флаги типов перезаписываемых карт.
Definition: ilreaders.h:640
ilr_reader_msg
Сообщение считывателя.
Definition: ilreaders.h:502
@ ILR_RWCT_F_TEMIC
Temic.
Definition: ilreaders.h:641
@ ILR_RWCT_F_MF_CLASSIC
Mifare Classic или Plus SL1.
Definition: ilreaders.h:643
@ ILR_RWCT_F_MF_ULTRALIGHT
Mifare Ultralight.
Definition: ilreaders.h:642
@ ILR_RWCT_F_MF_PLUS_SL3
Mifare Plus SL3.
Definition: ilreaders.h:645
@ ILR_MF_PLUS_UNKNOWN
Не известно.
Definition: ilreaders.h:583
@ ILR_READER_MSG_CONNECTION_CHANGED
Definition: ilreaders.h:513
@ ILR_READER_MSG_CARD_FOUND
Definition: ilreaders.h:517
@ ILR_READER_MSG_CARD_LOST
Definition: ilreaders.h:521
@ ILR_READER_MSG_COMMAND_FINISH
Definition: ilreaders.h:508
@ ILR_MF_PLUS_SL_UNKNOWN
Не известно.
Definition: ilreaders.h:571
@ ILR_MF_PLUS_SL_SL3
Уровень 3.
Definition: ilreaders.h:575
@ ILR_MF_PLUS_SL_SL1
Уровень 1 (эмуляция Mifare Classic).
Definition: ilreaders.h:573
@ ILR_CONNECTION_CONNECTED
Подключён.
Definition: ilreaders.h:544
@ ILR_READER_CCID
Definition: ilreaders.h:467
Заголовочный файл SDK Readers с классами-помощниками C++.
size_t GetNumberOfMfBlocks(uint32_t nMemSize)
Вычисляет количество блоков карты Mifare Classic/Plus по размеру её памяти.
Definition: ilr_cpp_helpers.h:2881
auto since(std::chrono::time_point< clock_t, duration_t > const &start)
Возвращает интервал времени в миллисекундах от времени start до текущего времени.
Definition: ilr_cpp_helpers.h:2802
std::chrono::steady_clock::time_point now()
Definition: ilr_cpp_helpers.h:2791
Заголовочный файл API SDK Readers.
#define ILR_CALL
Макрос, определяющий соглашение о вызове функций.
Definition: ilreaders.h:56
ilr_log_level
Уровень лога.
Definition: ilreaders.h:319
@ ILR_LOG_LEVEL_DEBUG
Отладочные сообщения.
Definition: ilreaders.h:349
@ ILR_CARD_MF_PLUS_4K
Mifare Plus 4K.
Definition: ilreaders.h:281
@ ILR_CARD_SMART_MX_MF1K
Smart MX with Mifare 1K.
Definition: ilreaders.h:282
@ ILR_CARD_SMART_MX_MF4K
Smart MX with Mifare 4K.
Definition: ilreaders.h:283
@ ILR_CARD_MF_CLASSIC_2K
Mifare Classic 2K.
Definition: ilreaders.h:276
@ ILR_CARD_MF_ULTRALIGHT
Mifare UltraLight.
Definition: ilreaders.h:272
@ ILR_CARD_MF_PLUS_1K
Mifare Plus 1K.
Definition: ilreaders.h:279
@ ILR_CARD_MF_CLASSIC_4K
Mifare Classic 4K.
Definition: ilreaders.h:277
@ ILR_CARD_TEMIC
Temic (T5557).
Definition: ilreaders.h:270
@ ILR_CARD_MF_PLUS_2K
Mifare Plus 2K.
Definition: ilreaders.h:280
@ ILR_CARD_MF_CLASSIC_1K
Mifare Classic 1K.
Definition: ilreaders.h:275
@ ILR_CARD_MF_MINI
Mifare Mini.
Definition: ilreaders.h:274
@ ILR_READER_MODEL_UNKNOWN
Definition: ilreaders.h:213
Информация о карте.
Definition: ilreaders.h:596
Данные блока Mifare Classic/Plus.
Definition: ilreaders.h:631
uint8_t a[16]
Байты блока.
Definition: ilreaders.h:632
Информация о считывателе.
Definition: ilreaders.h:295
ilr_reader_model nModel
Definition: ilreaders.h:304
uint32_t nFwVersion
Definition: ilreaders.h:310
const char * pszConnect
Definition: ilreaders.h:302
const char * pszPortName
Definition: ilreaders.h:299
int64_t nFwBuildDate
Definition: ilreaders.h:313
ilr_port_type nPortType
Definition: ilreaders.h:297
int nSn
Definition: ilreaders.h:306
Настройки считывателя.
Definition: ilreaders.h:663
uint32_t nHoldCardTypes
Definition: ilreaders.h:668
Настройки поиска считывателей.
Definition: ilreaders.h:474
uint32_t nReaderTypes
Definition: ilreaders.h:479