Как подключить 2 RFID Reader одновременно в C ++?

У меня есть 2 RFID-считывателя.

  • Читатель 1: port=com4 а также baud=9600
  • Читатель 2: port=com9 а также baud=9600

Я хочу подключить 2 RFID-ридера одновременно, но одновременно подключить только один ридер.

Я делаю следующее:

  1. 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;
    }
    
  2. 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
    }
    

-1

Решение

Ваша проблема в том, что DLL, которую вы используете для доступа к RFID-устройству, поддерживает доступ только к одному устройству за раз. Каждый из двух звонков, которые вы делаете MifareOne::OpenComm вызов метода один и тот же rf_init_com функция в том же MasterRD.dll, rf_init_com Метод не возвращает какого-либо дескриптора, который вы можете использовать, чтобы различать несколько соединений, поэтому нет никакого способа для вашего MifareOne::Write способ сообщить DLL, какое из двух соединений вы хотите использовать.

Учитывая, что DLL не позволяет открывать более одного устройства одновременно, у вас есть только два возможных обходных пути. Первый — использовать DLL в двух разных процессах, каждый из которых взаимодействует с различным устройством RFID. В этом случае DLL будет иметь отдельное внутреннее состояние в каждом процессе, что позволит вам использовать его для открытия разных устройств в каждом процессе. Затем вам придется использовать один из многих методов межпроцессного взаимодействия Windows, чтобы эти два процесса могли координироваться друг с другом или с основным процессом.

Во-вторых, общаться с устройством RFID напрямую через последовательный порт. Windows позволяет открывать несколько последовательных устройств, открытых в одном и том же процессе одновременно. Использование этого обходного пути означает, что вам придется самостоятельно обрабатывать все подробности протокола низкого уровня при общении с устройством. Те же самые низкоуровневые детали, от которых вы пользуетесь DLL, предназначены для вашей изоляции. Вы также, вероятно, будете использовать либо асинхронный ввод-вывод, либо несколько потоков, чтобы избежать взаимных блокировок при чтении и записи с двух устройств.

1

Другие решения

Я могу думать о трех возможностях.

Во-первых, вы тестируете одного читателя с Request() метод, а другой с Write() метод. Может быть так Write() это неверно. Попробуйте использовать Request() и для ваших читателей, и посмотрите, что произойдет.

Во-вторых, у вас неправильные COM-порты. Откройте диспетчер устройств и определите, на каких портах работают ваши устройства. Убедитесь, что вы используете правильные порты после подключив их обоих.

В-третьих, COM-порт использует другая программа, возможно, более старая версия вашего программного обеспечения. Попробуйте перезагрузить компьютер или проверить, не используется ли порт.

0

Интерфейс 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 не отслеживает множественные соединения, теперь могут произойти две мысли:

  1. Первое соединение отбрасывается в пользу второго, или
  2. второй запрос на подключение будет проигнорирован, поскольку все еще существует открытое соединение с первым считывателем.

Итак, однажды вы использовали 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 не была предназначена для использования с несколькими читателями.

0
По вопросам рекламы [email protected]