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

Демонстрирует работу с картами Temic: поиск, чтение и запись данных карты.

#include <fstream> // для std::fstream
#include <iomanip> // для std::put_time
#include <iostream> // для std::cout и std::cin
#include "ilreaders.h"
#define ILR_LOG // Раскомментируйте, чтобы включить отладочные сообщения
#define ILR_LOG_FILE // Писать лог в файл
using namespace ilr;
// Глобальные параметры
const int64_t kPassword = -1; // Пароль для доступа к Temic, =-1 нет пароля
#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 DoReadTemic(CReader& oReader) {
size_t nRead = 0;
std::ios_base::fmtflags ff(std::cout.flags());
try {
const uint kBitRates[8] = {8, 16, 32, 40, 50, 64, 100, 128};
const char* kPskCf[4] = {"RF/2", "RF/4", "RF/8", "Reserved"};
const char* kFlagStrs[2] = {"False", "True"};
std::cout << "Чтение данных карты..." << std::endl;
uint aBlocks[10]; // 10 блоков по 4 байта
auto tStartTime = now();
oReader.LoadTemicPassword(kPassword);
oReader.ReadTemic(0, aBlocks, std::size(aBlocks), -1, &nRead);
std::cout << "Прочитано за " << since(tStartTime).count() << " мс" << std::endl;
uint nConfig = 0;
uint nDataRate = 0;
uint nModulation = 0;
uint nMaxBlock = 0;
uint nBlockData;
uint8_t* pBytes;
for (size_t i = 0; i < std::size(aBlocks); ++i) {
nBlockData = aBlocks[i];
// printf("%.2lu. %.2X %.2X %.2X %.2X ", i, nBlockData & 0xff, (nBlockData >> 8) & 0xff,
// (nBlockData >> 16) & 0xff, nBlockData >> 24);
pBytes = (uint8_t*)&nBlockData;
std::cout << std::noshowbase << std::dec << std::setw(2) << i << ". " << std::hex
<< std::setw(2) << (uint)pBytes[0] << ' ' << std::setw(2) << (uint)pBytes[1]
<< ' ' << std::setw(2) << (uint)pBytes[2] << ' ' << std::setw(2)
<< (uint)pBytes[3] << ' ';
switch (i) {
case 0: // Configuration data
{
std::cout << "Конфигурация" << std::endl;
nConfig = nBlockData;
bool fXMode = GET_BIT(nConfig, 9);
if (fXMode)
std::cout << "\tРежим: X-Mode" << std::endl;
else
std::cout << "\tРежим: e5550 Compatibility Mode" << std::endl;
std::cout << "\tMaster Key: " << std::dec << ((nConfig >> 4) & 0xf)
<< std::endl;
if (fXMode)
nDataRate = ((nConfig >> 10) & 0x3F) * 2 + 2;
else
nDataRate = kBitRates[(nConfig >> 10) & 7];
std::cout << "\tData Bit Rate: RF/" << std::dec << nDataRate << std::endl;
nModulation = ((nConfig >> 20) & 0xF) | (((nConfig >> 8) & 1) << 4);
std::cout << "\tModulation: ";
switch (nModulation) {
case 0: // 0 0 0 0 0
std::cout << "Direct";
break;
case 1: // 0 0 0 0 1
std::cout << "PSK1";
break;
case 2: // 0 0 0 1 0
std::cout << "PSK2";
break;
case 3: // 0 0 0 1 1
std::cout << "PSK3";
break;
case 4: // 0 0 1 0 0
std::cout << "FSK1";
break;
case 5: // 0 0 1 0 1
std::cout << "FSK2";
break;
case 6: // 0 0 1 1 0
std::cout << "FSK1a";
break;
case 7: // 0 0 1 1 1
std::cout << "FSK2a";
break;
case 8: // 0 1 0 0 0
std::cout << "Manchester";
break;
case 0x10: // 1 0 0 0 0
std::cout << "Biphase('50)";
break;
case 0x18: // 1 1 0 0 0
std::cout << "Biphase('57)";
break;
}
std::cout << std::endl;
std::cout << "\tPSK-CF: " << kPskCf[(nConfig >> 18) & 3] << std::endl;
std::cout << "\tAOR: " << kFlagStrs[GET_BIT(nConfig, 17)] << std::endl;
if (fXMode)
std::cout << "\tOTP: " << kFlagStrs[GET_BIT(nConfig, 16)] << std::endl;
nMaxBlock = (nConfig >> 29) & 7;
std::cout << "\tMAX-BLOCK: " << std::dec << nMaxBlock << std::endl;
std::cout << "\tPassword: " << kFlagStrs[GET_BIT(nConfig, 28)] << std::endl;
if (fXMode) {
std::cout << "\tSST-Sequence Start Marker: "
<< kFlagStrs[GET_BIT(nConfig, 27)] << std::endl;
std::cout << "\tFastwrite: " << kFlagStrs[GET_BIT(nConfig, 26)]
<< std::endl;
std::cout << "\tInverse Data: " << kFlagStrs[GET_BIT(nConfig, 25)]
<< std::endl;
}
else
std::cout << "\tST-Sequence Terminator: " << kFlagStrs[GET_BIT(nConfig, 27)]
<< std::endl;
std::cout << "\tPOR delay: " << kFlagStrs[GET_BIT(nConfig, 24)] << std::endl;
break;
}
case 7: // User data or password
if (GET_BIT(nConfig, 28))
std::cout << "Пароль" << std::endl;
else
std::cout << "Данные пользователя" << std::endl;
break;
case 8: // Traceability data
std::cout << "Данные производителя" << std::endl;
std::cout << "\tACL: " << std::showbase << std::hex << std::setw(2)
<< (nBlockData & 0xff) << std::endl;
std::cout << "\tMFC: " << std::setw(2) << ((nBlockData >> 8) & 0xff) << std::endl;
std::cout << "\tICR: " << std::setw(2) << ((nBlockData >> 16) & 0xff) << std::endl;
std::cout << "\tMSN LotID: " << std::dec << (nBlockData >> 24) << std::endl;
break;
case 9: // Traceability data
std::cout << "Данные производителя" << std::endl;
std::cout << "\tLotID: " << std::dec << (nBlockData & 0xFFF) << std::endl;
std::cout << "\twafer #: " << std::showbase << std::hex << std::setw(2)
<< ((nBlockData >> 12) & 0x3F) << std::endl;
std::cout << "\tdie on wafer #: " << std::setw(2) << ((nBlockData >> 18) & 0x3FFF)
<< std::endl;
break;
default:
std::cout << "Данные пользователя" << std::endl;
break;
}
}
auto nType = ILR_CARD_UNKNOWN;
CCardUID rUID;
int nWiegand;
if ((64 == nDataRate) && (8 == nModulation) && (2 == nMaxBlock)) {
oReader.DecodeTemicEmMarine(aBlocks, 3, rUID);
if (!rUID.IsEmpty())
std::cout << "Эмулирует Em-Marine " << CardUIDToStr(nType, rUID) << std::endl;
}
else if ((50 == nDataRate) && (5 == nModulation) && (3 == nMaxBlock)) {
oReader.DecodeTemicHid(aBlocks, 4, rUID, nWiegand);
nType = ILR_CARD_HID;
if (!rUID.IsEmpty())
std::cout << "Эмулирует HID (W" << std::dec << nWiegand << ") "
<< CardUIDToStr(nType, rUID) << std::endl;
}
std::cout << "-----" << std::endl;
std::cout.flags(ff);
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
std::cout.flags(ff);
std::cout << "Прочитано " << nRead << " блока из 10" << std::endl;
}
}
void DoWriteTemic(CReader& oReader) {
size_t nWritten = 0;
try {
// Запрашиваем номер блока и значения байтов блока Temic
std::cout << "Введите номер блока и байты 0 1 2 3 (16-ричное):" << std::endl;
uint nBlockN, a[4];
std::cin >> std::hex >> nBlockN >> a[0] >> a[1] >> a[2] >> a[3];
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail()) {
std::cout << "Неправильный ввод" << std::endl;
return;
}
uint8_t aBytes[4];
for (size_t i = 0; i < std::size(aBytes); ++i)
aBytes[i] = (uint8_t)a[i];
std::cout << "Запись..." << std::endl;
auto tStartTime = now();
oReader.LoadTemicPassword(kPassword);
oReader.WriteTemic(nBlockN, (uint*)aBytes, 1, false, -1, &nWritten);
std::cout << "Записано за " << since(tStartTime).count() << " мс" << std::endl;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
std::cout << "Записано " << nWritten << " блока из 1" << std::endl;
}
}
void DoWriteEmMarine(CReader& oReader) {
size_t nWritten = 0;
try {
// Запрашиваем номер Em-Marine: 1) код производителя (шестнадцатеричное число),
// 2) номер серии (десятичное), 3) номер (десятичное)
std::cout
<< "Введите номер Em-Marine: код производителя (16-ричное), серия (10-тичное), номер "
"(10-тичное):"
<< std::endl;
uint nFacility, nSeries, nNumber;
std::cin >> std::hex >> nFacility >> std::dec >> nSeries >> nNumber;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail()) {
std::cout << "Неправильный ввод" << std::endl;
return;
}
// Подготавливаем данные для записи
ilr_card_uid rUID;
rUID.em_marine.nSeries = static_cast<uint8_t>(nSeries);
rUID.em_marine.nNumber = static_cast<uint16_t>(nNumber);
rUID.em_marine.nFacility = static_cast<uint16_t>(nFacility);
rUID.nLength = 5;
uint aBlocks[3];
oReader.EncodeTemicEmMarine(rUID, aBlocks, std::size(aBlocks));
// Пишем номер Em-Marine в Temic
std::cout << "Запись..." << std::endl;
auto tStartTime = now();
oReader.LoadTemicPassword(kPassword);
oReader.WriteTemic(0, aBlocks, std::size(aBlocks), false, -1, &nWritten);
std::cout << "Записано за " << since(tStartTime).count() << " мс" << std::endl;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
std::cout << "Записано " << nWritten << " блока из 3" << std::endl;
}
}
void DoWriteHID(CReader& oReader) {
size_t nWritten = 0;
try {
// Запрашиваем номер HID: 1) номер кодировки Wiegand (десятичное число),
// 2) код производителя (шестнадцатеричное), 3) номер (десятичное)
std::cout << "Введите номер HID: виганд (10-тичное), код производителя (16-ричное), номер "
"(10-тичное):"
<< std::endl;
int nWiegand, nNumber;
uint nFacility;
std::cin >> std::dec >> nWiegand >> std::hex >> nFacility >> std::dec >> nNumber;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail() || (nWiegand < 10) || (nWiegand > 37)) {
std::cout << "Неправильный ввод" << std::endl;
return;
}
// Подготавливаем данные для записи
ilr_card_uid rUID;
auto nFSize = static_cast<size_t>(nWiegand - 2 - 16);
auto nFCount = (nFSize / 8);
if ((nFSize % 8) != 0)
++nFCount;
*(uint16_t*)&rUID.aBytes[0] = static_cast<uint16_t>(nNumber);
if (nFCount > 0)
memcpy(&rUID.aBytes[2], &nFacility, nFCount);
rUID.nLength = static_cast<uint8_t>(nFCount + 2);
uint aBlocks[4];
oReader.EncodeTemicHid(rUID, aBlocks, std::size(aBlocks), nWiegand);
// Пишем номер HID в Temic
std::cout << "Запись..." << std::endl;
auto tStartTime = now();
oReader.LoadTemicPassword(kPassword);
oReader.WriteTemic(0, aBlocks, std::size(aBlocks), false, -1, &nWritten);
std::cout << "Записано за " << since(tStartTime).count() << " мс" << std::endl;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
std::cout << "Записано " << nWritten << " блока из 4" << std::endl;
}
}
void DoInitTemic(CReader& oReader) {
try {
// Подготавливаем данные для записи - стандартная конфигурация
uint nConfigData = 0x40801400;
std::cout << "Запись..." << std::endl;
auto tStartTime = now();
oReader.LoadTemicPassword(kPassword);
oReader.WriteTemic(0, &nConfigData, 1, false, 0x0002);
std::cout << "Записано за " << since(tStartTime).count() << " мс\n" << std::endl;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
bool DoConnectTo(CILR& oILR, CReader& oReader) {
CReaderSearch oSearch(oILR.GetSearch());
{
// Включаем поиск считывателя Z-2 MF CCID (по умолчанию выключен)
oSearch.GetOptions(rOptions);
oSearch.SetOptions(rOptions);
}
// Ищем считыватели
std::cout << "Поиск считывателей..." << std::endl;
oSearch.Scan();
auto nCount = oSearch.GetReaderCount();
if (0 == nCount) {
std::cout << "Считыватель не найден" << std::endl;
return false;
}
std::cout << "Найдено " << nCount << ':' << std::endl;
bool fFound = false;
for (size_t i = 0; i < nCount; i++) {
oSearch.GetReaderInfo(i, rInfo);
// Если порт занят, пропускаем его
if (*rInfo.pszConnect != '\0')
continue;
if (CReader::GetSupportedRewrittenCardTypes(rInfo.nModel, rInfo.nFwVersion) &
fFound = true;
break;
}
}
if (!fFound) {
std::cout << "Считыватель не поддерживает чтение/запись карт Temic" << std::endl;
return false;
}
// Подключаемся к считывателю
std::cout << "Подключение к считывателю [" << kPortTypeNames[rInfo.nPortType] << ": "
<< rInfo.pszPortName << "]..." << std::endl;
oReader = oILR.GetReader(rInfo.nPortType, rInfo.pszPortName);
// Отключаем авто поиск карт
oReader.SetAutoScan(false);
oReader.GetOptions(rOptions);
rOptions.nConnectModel = rInfo.nModel;
oReader.SetOptions(rOptions);
}
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;
return true;
}
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;
if (!DoConnectTo(oILR, oReader))
return 0;
// Включаем авто сканирование карт Temic
oReader.SetScanTemic();
// Основной цикл программы
while (true) {
std::cout << "Поиск карты Temic..." << std::endl;
oReader.Scan();
oReader.GetCardInfo(rCI);
auto fCardFound = (ILR_CARD_TEMIC == rCI.nType);
// Если карта Temic найдена,
if (fCardFound)
std::cout << kCardTypeNames[rCI.nType] << ' ' << CardUIDToStr(rCI.nType, rCI.rUID)
<< std::endl;
else // Temic не найдена
std::cout << "Карта Temic не найдена" << std::endl;
std::cout << "-----" << std::endl;
std::cout << "Введите номер команды:" << std::endl;
std::cout << "1 - Искать карту снова" << std::endl;
std::cout << "2 - Записать стандартную конфигурацию Temic" << std::endl;
if (fCardFound) {
std::cout << "3 - Прочитать данные из карты" << std::endl;
std::cout << "4 - Записать данные на карту..." << std::endl;
std::cout << "5 - Записать Em-Marine..." << std::endl;
std::cout << "6 - Записать HID..." << std::endl;
}
std::cout << "0 - Выйти из программы" << std::endl;
int nCommand;
std::cin >> nCommand;
if (std::cin.fail()) {
std::cin.clear();
nCommand = -1;
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
switch (nCommand) {
case 0:
return 0;
case 1:
break;
case 2:
if (!fCardFound)
DoInitTemic(oReader);
break;
case 3:
if (fCardFound)
DoReadTemic(oReader);
break;
case 4:
if (fCardFound)
DoWriteTemic(oReader);
break;
case 5:
if (fCardFound)
DoWriteEmMarine(oReader);
break;
case 6:
if (fCardFound)
DoWriteHID(oReader);
break;
default:
std::cout << "Неправильный ввод" << std::endl;
break;
}
}
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
Класс ID карты.
Definition: ilr_cpp_helpers.h:51
bool IsEmpty() const
Проверяет пустой ли ID карты.
Definition: ilr_cpp_helpers.h:93
Класс для инициализации/финализации библиотеки 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
Класс поиска считывателей.
Definition: ilr_cpp_helpers.h:583
Класс считывателя.
Definition: ilr_cpp_helpers.h:996
void WriteTemic(size_t nBlockIdx, const uint32_t *pData, size_t nBlockCount, bool fLock=false, int nScanParam=-1, size_t *pWritten=nullptr)
Пишет данные карты Temic.
Definition: ilr_cpp_helpers.h:2544
void SetAutoScan(bool fEnable=true, bool fWait=true)
Включает/выключает автоматическое сканирование карт.
Definition: ilr_cpp_helpers.h:2242
void SetScanTemic(bool fEnable=true)
Вкл/выкл сканирование карт Temic (для Z-2 Rd-All и Z-2 EHR).
Definition: ilr_cpp_helpers.h:2518
void Connect(bool fReconnect=false)
Подключается к считывателю.
Definition: ilr_cpp_helpers.h:2197
void SetOptions(const ilr_reader_options &rOptions)
Устанавливает параметры считывателя.
Definition: ilr_cpp_helpers.h:2189
static void DecodeTemicEmMarine(const uint32_t *pData3, size_t nBlockCount, ilr_card_uid &rUID, bool *pConfigOk=nullptr)
Декодирует номер Em-Marine из данных блоков 0..2 карты Temic.
Definition: ilr_cpp_helpers.h:2577
static void EncodeTemicHid(const ilr_card_uid &rUID, uint32_t *pBuf4, size_t nBlockCount, int nWiegand)
Кодирует данные для эмуляции HID, для записи в блоки 0..3.
Definition: ilr_cpp_helpers.h:2585
void Scan(bool fReset=false, bool fPowerOff=true)
Ищет карты.
Definition: ilr_cpp_helpers.h:2227
void LoadTemicPassword(const int64_t nPassword)
Загружает пароль Temic в память объекта считывателя.
Definition: ilr_cpp_helpers.h:2504
static void EncodeTemicEmMarine(const ilr_card_uid &rUID, uint32_t *pBuf3, size_t nBlockCount)
Кодирует данные для эмуляции Em-Marine, для записи в блоки 0..2.
Definition: ilr_cpp_helpers.h:2572
static void DecodeTemicHid(const uint32_t *pData4, size_t nBlockCount, ilr_card_uid &rUID, int &nWiegand, bool *pConfigOk=nullptr)
Декодирует номер HID из данных блоков 0..3 карты Temic.
Definition: ilr_cpp_helpers.h:2590
void ReadTemic(size_t nBlockIdx, uint32_t *pBuf, size_t nBlockCount, int nScanParam=-1, size_t *pRead=nullptr)
Читает данные карты Temic.
Definition: ilr_cpp_helpers.h:2528
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
bool GetCardInfo(ilr_card_info &rInfo) const
Возвращает информацию о карте в поле считывателя.
Definition: ilr_cpp_helpers.h:2237
@ ILR_RWCT_F_TEMIC
Temic.
Definition: ilreaders.h:641
@ ILR_READER_CCID
Definition: ilreaders.h:467
Заголовочный файл SDK Readers с классами-помощниками C++.
#define GET_BIT(val, bitN)
Возвращает true если бит bitN установлен в числе val.
Definition: ilr_cpp_helpers.h:2779
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_EM_MARINE
Em-Marine.
Definition: ilreaders.h:263
@ ILR_CARD_UNKNOWN
Не известно.
Definition: ilreaders.h:262
@ ILR_CARD_HID
HID.
Definition: ilreaders.h:264
@ ILR_CARD_TEMIC
Temic (T5557).
Definition: ilreaders.h:270
@ ILR_READER_MODEL_UNKNOWN
Definition: ilreaders.h:213
Информация о карте.
Definition: ilreaders.h:596
ilr_card_type nType
Тип карты.
Definition: ilreaders.h:597
ilr_card_uid rUID
Номер карты.
Definition: ilreaders.h:598
Информация о считывателе.
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
ilr_reader_model nConnectModel
Definition: ilreaders.h:665
Настройки поиска считывателей.
Definition: ilreaders.h:474
uint32_t nReaderTypes
Definition: ilreaders.h:479