У меня есть 2 RFID-считывателя.
port=com4
а также baud=9600
port=com9
а также baud=9600
Я хочу подключить 2 RFID-ридера одновременно, но одновременно подключить только один ридер.
Я делаю следующее:
MifareOne.CPP
MifareOne::MifareOne()
{
LoadDll();
}
MifareOne::~MifareOne()
{
CloseComm();
CloseDll();
}
bool IsLoadDLL = false;
bool MifareOne::LoadDll()
{
if (IsLoadDLL)
return true;
// TODO: Add extra initialization here
TCHAR szBuf[MAX_PATH];
GetModuleFileName(NULL, (LPTSTR)szBuf, MAX_PATH);
sprintf(szBuf, "../../../CardReader\\MasterRD.dll");
m_hInstMaster = LoadLibrary(_T(szBuf));if (m_hInstMaster)
{
IsLoadDLL = true;
(FARPROC&)lib_ver = GetProcAddress(m_hInstMaster, _T("lib_ver"));
(FARPROC&)des_encrypt = GetProcAddress(m_hInstMaster, _T("des_encrypt"));
(FARPROC&)des_decrypt = GetProcAddress(m_hInstMaster, _T("des_decrypt"));
(FARPROC&)rf_init_com = GetProcAddress(m_hInstMaster, _T("rf_init_com"));
(FARPROC&)rf_init_device_number = GetProcAddress(m_hInstMaster, _T("rf_init_device_number"));
(FARPROC&)rf_get_device_number = GetProcAddress(m_hInstMaster, _T("rf_get_device_number"));
(FARPROC&)rf_get_model = GetProcAddress(m_hInstMaster, _T("rf_get_model"));
(FARPROC&)rf_get_snr = GetProcAddress(m_hInstMaster, _T("rf_get_snr"));
(FARPROC&)rf_beep = GetProcAddress(m_hInstMaster, _T("rf_beep"));
(FARPROC&)rf_init_sam = GetProcAddress(m_hInstMaster, _T("rf_init_sam"));
(FARPROC&)rf_sam_rst = GetProcAddress(m_hInstMaster, _T("rf_sam_rst"));
(FARPROC&)rf_sam_cos = GetProcAddress(m_hInstMaster, _T("rf_sam_cos"));
(FARPROC&)rf_init_type = GetProcAddress(m_hInstMaster, _T("rf_init_type"));
(FARPROC&)rf_antenna_sta = GetProcAddress(m_hInstMaster, _T("rf_antenna_sta"));
(FARPROC&)rf_request = GetProcAddress(m_hInstMaster, _T("rf_request"));
(FARPROC&)rf_anticoll = GetProcAddress(m_hInstMaster, _T("rf_anticoll"));
(FARPROC&)rf_select = GetProcAddress(m_hInstMaster, _T("rf_select"));
(FARPROC&)rf_halt = GetProcAddress(m_hInstMaster, _T("rf_halt"));
(FARPROC&)rf_download_key = GetProcAddress(m_hInstMaster, _T("rf_download_key"));
(FARPROC&)rf_M1_authentication1 = GetProcAddress(m_hInstMaster, _T("rf_M1_authentication1"));
(FARPROC&)rf_M1_authentication2 = GetProcAddress(m_hInstMaster, _T("rf_M1_authentication2"));
(FARPROC&)rf_M1_read = GetProcAddress(m_hInstMaster, _T("rf_M1_read"));
(FARPROC&)rf_M1_write = GetProcAddress(m_hInstMaster, _T("rf_M1_write"));
(FARPROC&)rf_M1_initval = GetProcAddress(m_hInstMaster, _T("rf_M1_initval"));
(FARPROC&)rf_M1_readval = GetProcAddress(m_hInstMaster, _T("rf_M1_readval"));
(FARPROC&)rf_M1_decrement = GetProcAddress(m_hInstMaster, _T("rf_M1_decrement"));
(FARPROC&)rf_M1_increment = GetProcAddress(m_hInstMaster, _T("rf_M1_increment"));
(FARPROC&)rf_M1_restore = GetProcAddress(m_hInstMaster, _T("rf_M1_restore"));
(FARPROC&)rf_M1_transfer = GetProcAddress(m_hInstMaster, _T("rf_M1_transfer"));
(FARPROC&)rf_typea_rst = GetProcAddress(m_hInstMaster, _T("rf_typea_rst"));
(FARPROC&)rf_cos_command = GetProcAddress(m_hInstMaster, _T("rf_cos_command"));
(FARPROC&)rf_atqb = GetProcAddress(m_hInstMaster, _T("rf_atqb"));
(FARPROC&)rf_attrib = GetProcAddress(m_hInstMaster, _T("rf_attrib"));
(FARPROC&)rf_typeb_cos = GetProcAddress(m_hInstMaster, _T("rf_typeb_cos"));
(FARPROC&)rf_hltb = GetProcAddress(m_hInstMaster, _T("rf_hltb"));
(FARPROC&)rf_at020_check = GetProcAddress(m_hInstMaster, _T("rf_at020_check"));
(FARPROC&)rf_at020_read = GetProcAddress(m_hInstMaster, _T("rf_at020_read"));
(FARPROC&)rf_at020_write = GetProcAddress(m_hInstMaster, _T("rf_at020_write"));
(FARPROC&)rf_at020_lock = GetProcAddress(m_hInstMaster, _T("rf_at020_lock"));
(FARPROC&)rf_at020_count = GetProcAddress(m_hInstMaster, _T("rf_at020_count"));
(FARPROC&)rf_at020_deselect = GetProcAddress(m_hInstMaster, _T("rf_at020_deselect"));
(FARPROC&)rf_light = GetProcAddress(m_hInstMaster, _T("rf_light"));
(FARPROC&)rf_ClosePort = GetProcAddress(m_hInstMaster, _T("rf_ClosePort"));
(FARPROC&)rf_GetErrorMessage = GetProcAddress(m_hInstMaster, _T("rf_GetErrorMessage"));
if (NULL == lib_ver ||
NULL == des_encrypt ||
NULL == des_decrypt ||
NULL == rf_init_com ||
NULL == rf_init_device_number ||
NULL == rf_get_device_number ||
NULL == rf_get_model ||
NULL == rf_beep ||
NULL == rf_init_sam ||
NULL == rf_sam_rst ||
NULL == rf_sam_cos ||
NULL == rf_init_type ||
NULL == rf_antenna_sta ||
NULL == rf_request ||
NULL == rf_anticoll ||
NULL == rf_select ||
NULL == rf_halt ||
NULL == rf_download_key ||
NULL == rf_M1_authentication1 ||
NULL == rf_M1_authentication2 ||
NULL == rf_M1_read ||
NULL == rf_M1_write ||
NULL == rf_M1_initval ||
NULL == rf_M1_readval ||
NULL == rf_M1_decrement ||
NULL == rf_M1_increment ||
NULL == rf_M1_restore ||
NULL == rf_M1_transfer ||
NULL == rf_typea_rst ||
NULL == rf_cos_command ||
NULL == rf_atqb ||
NULL == rf_attrib ||
NULL == rf_typeb_cos ||
NULL == rf_hltb ||
NULL == rf_at020_check ||
NULL == rf_at020_read ||
NULL == rf_at020_write ||
NULL == rf_at020_lock ||
NULL == rf_at020_count ||
NULL == rf_at020_deselect ||
NULL == rf_light ||
NULL == rf_ClosePort ||
NULL == rf_GetErrorMessage)
{
return false;
}
}
else
{
int err = GetLastError();
return false;
}
return true;
}
bool MifareOne::CloseDll()
{
if(m_hInstMaster)
{
FreeLibrary(m_hInstMaster);
lib_ver = NULL;
des_encrypt = NULL;
des_decrypt = NULL;
rf_init_com = NULL;
rf_init_device_number = NULL;
rf_get_device_number = NULL;
rf_get_model = NULL;
rf_beep = NULL;
rf_init_sam = NULL;
rf_sam_rst = NULL;
rf_sam_cos = NULL;
rf_init_type = NULL;
rf_antenna_sta = NULL;
rf_request = NULL;
rf_anticoll = NULL;
rf_select = NULL;
rf_halt = NULL;
rf_download_key = NULL;
rf_M1_authentication1 = NULL;
rf_M1_authentication2 = NULL;
rf_M1_read = NULL;
rf_M1_write = NULL;
rf_M1_initval = NULL;
rf_M1_readval = NULL;
rf_M1_decrement = NULL;
rf_M1_increment = NULL;
rf_M1_restore = NULL;
rf_M1_transfer = NULL;
rf_typea_rst = NULL;
rf_cos_command = NULL;
rf_atqb = NULL;
rf_attrib = NULL;
rf_typeb_cos = NULL;
rf_hltb = NULL;
rf_at020_check = NULL;
rf_at020_read = NULL;
rf_at020_write = NULL;
rf_at020_lock = NULL;
rf_at020_count = NULL;
rf_at020_deselect = NULL;
rf_light = NULL;
rf_ClosePort = NULL;
rf_GetErrorMessage = NULL;
m_hInstMaster = NULL;
return true;
}
return false;
}
bool MifareOne::OpenComm(int com, int baud)
{
//save port and baud
mCommPort = com;
mBandRate = baud;
//open port
int state = 1;
state = rf_init_com(com, baud);
if (state != LIB_SUCCESS){
rf_ClosePort();
return false;
}
return true; // return TRUE unless you set the focus to a control
}
bool IsCloseComm = false;
void MifareOne::CloseComm()
{
if (IsCloseComm)
return;
rf_ClosePort();
IsCloseComm = true;
}
int MifareOne::Write(unsigned char* strData)
{
WORD icdev = 0x0000;
unsigned char mode = 0x60; // key A
unsigned char secnr = '\x1';
int state;
unsigned char strKey[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0 };
int nSel = 1;
state = rf_M1_authentication2(icdev, mode, (secnr / 4) * 4, strKey);
if (state){
return -1;
}
unsigned char strEncryptData[MAX_RF_BUFFER];
state = Encrypt(strEncryptData, strData, (unsigned char*)Encrypt_Key);
if (state){
return -1;
}
state = rf_M1_write(icdev, secnr, strEncryptData);
if (state){
return -1;
}
return 1;
}
main.cpp
int main(int argc, const char* argv[])
{
MifareOne cardReader1;
MifareOne cardReader2;
cardReader1.OpenComm(4, 9600);
cardReader2.OpenComm(9, 9600);
cardReader1.Write((unsigned char*) "testing"); // Not work
cardReader2.Request((unsigned char*) "testing"); // Work fine
}
Ваша проблема в том, что DLL, которую вы используете для доступа к RFID-устройству, поддерживает доступ только к одному устройству за раз. Каждый из двух звонков, которые вы делаете MifareOne::OpenComm
вызов метода один и тот же rf_init_com
функция в том же MasterRD.dll
, rf_init_com
Метод не возвращает какого-либо дескриптора, который вы можете использовать, чтобы различать несколько соединений, поэтому нет никакого способа для вашего MifareOne::Write
способ сообщить DLL, какое из двух соединений вы хотите использовать.
Учитывая, что DLL не позволяет открывать более одного устройства одновременно, у вас есть только два возможных обходных пути. Первый — использовать DLL в двух разных процессах, каждый из которых взаимодействует с различным устройством RFID. В этом случае DLL будет иметь отдельное внутреннее состояние в каждом процессе, что позволит вам использовать его для открытия разных устройств в каждом процессе. Затем вам придется использовать один из многих методов межпроцессного взаимодействия Windows, чтобы эти два процесса могли координироваться друг с другом или с основным процессом.
Во-вторых, общаться с устройством RFID напрямую через последовательный порт. Windows позволяет открывать несколько последовательных устройств, открытых в одном и том же процессе одновременно. Использование этого обходного пути означает, что вам придется самостоятельно обрабатывать все подробности протокола низкого уровня при общении с устройством. Те же самые низкоуровневые детали, от которых вы пользуетесь DLL, предназначены для вашей изоляции. Вы также, вероятно, будете использовать либо асинхронный ввод-вывод, либо несколько потоков, чтобы избежать взаимных блокировок при чтении и записи с двух устройств.
Я могу думать о трех возможностях.
Во-первых, вы тестируете одного читателя с Request()
метод, а другой с Write()
метод. Может быть так Write()
это неверно. Попробуйте использовать Request()
и для ваших читателей, и посмотрите, что произойдет.
Во-вторых, у вас неправильные COM-порты. Откройте диспетчер устройств и определите, на каких портах работают ваши устройства. Убедитесь, что вы используете правильные порты после подключив их обоих.
В-третьих, COM-порт использует другая программа, возможно, более старая версия вашего программного обеспечения. Попробуйте перезагрузить компьютер или проверить, не используется ли порт.
Интерфейс DLL читателя выглядит так, как будто только один читатель поддерживается одновременно. Явным признаком этого является то, что функции API не используют дескриптор, с помощью которого они могли бы отслеживать два одновременных сеанса.
Так, например,
cardReader1.OpenComm(4, 9600);
вызывает следующий вызов API:
state = rf_init_com(4, 9600);
где state
0 при успехе. Следовательно, не существует «ручки», которая могла бы использоваться для отслеживания этого конкретного rf_init_com
вызов.
Так что если вы в следующий раз используете
cardReader2.OpenComm(9, 9600);
открыть порт второго читателя. Это вызовет следующий вызов API:
state = rf_init_com(9, 9600);
Поскольку DLL не отслеживает множественные соединения, теперь могут произойти две мысли:
Итак, однажды вы использовали OpenComm
для обоих MifareOne
объекты, вызовы обоих объектов будут идти либо ко второму (случай 1), либо к первому (случай 2) читателю. В частности, если вы посмотрите на вызов API, который выполняется как следствие
cardReader1.Write((unsigned char*) "testing");
и из
cardReader2.Write((unsigned char*) "testing");
Вы увидите, что оба метода вызовут smae Вызовы API:
state = rf_M1_authentication2 (icdev, mode, (secnr / 4) * 4, strKey);
state = rf_M1_write (icdev, secnr, strEncryptData);
Таким образом, DLL не может отличить двух читателей.
Таким образом, по моему мнению, DLL не была предназначена для использования с несколькими читателями.