完成读卡器API的所有功能,能够读写卡;修改开卡函数,添加初始化卡的代码,添加限制:只有在有充值权限的设备上才能够开卡

This commit is contained in:
Jingfan Ke 2024-07-31 14:27:48 +08:00
parent 63fc2d966c
commit 06d8a5343e
4 changed files with 250 additions and 3 deletions

View File

@ -12,7 +12,6 @@
#include <QRandomGenerator> #include <QRandomGenerator>
#include <vector> #include <vector>
#include <set>
#include <readerAPI.h> #include <readerAPI.h>
#include <databaseAPI.h> #include <databaseAPI.h>

View File

@ -91,6 +91,12 @@ void MainWindow::on_newCardButton_clicked()
return; return;
} }
if (!device.is_depositAllowed())
{
QMessageBox::warning(this, QString("提示"), QString("本设备不支持开卡。"));
return;
}
if (!newCardUserIdFilled) if (!newCardUserIdFilled)
{ {
QMessageBox::warning(this, "提示", "请填写学/工号。"); QMessageBox::warning(this, "提示", "请填写学/工号。");
@ -164,7 +170,19 @@ void MainWindow::on_newCardButton_clicked()
query.prepare("insert into card " query.prepare("insert into card "
"values (:cardId, 0, 0.00, null);"); "values (:cardId, 0, 0.00, null);");
query.bindValue(":cardId", cardIdSelected); query.bindValue(":cardId", cardIdSelected);
query.exec(); success = query.exec();
if (!success)
{
QMessageBox::warning(this, "提示", QString("数据库异常。开卡失败,请重试。"));
return;
}
success = reader.initCard(cardIdSelected); // 初始化卡
if (!success)
{
QMessageBox::warning(this, "提示", QString("读卡器设备异常。写卡失败,请重试。"));
return;
}
} }
// 检查是否是新用户 // 检查是否是新用户
@ -195,6 +213,14 @@ void MainWindow::on_newCardButton_clicked()
return; return;
} }
QMessageBox::information(this, "提示", "新用户开卡成功。"); QMessageBox::information(this, "提示", "新用户开卡成功。");
success = reader.initCard(cardIdSelected); // 初始化卡
if (!success)
{
QMessageBox::warning(this, "提示", QString("读卡器设备异常。写卡失败,请重试。"));
return;
}
return; return;
} }
else // 库中有用户记录 else // 库中有用户记录
@ -221,7 +247,7 @@ void MainWindow::on_newCardButton_clicked()
} }
else if (userCardStatus == -1) // 用户有挂失卡,需要移资 else if (userCardStatus == -1) // 用户有挂失卡,需要移资
{ {
/// @todo 弹出验证用户界面,要求用户输入密码;将挂失卡的信息和消费记录移到新卡 /// @todo 弹出验证用户界面,要求用户输入密码;在数据库中将挂失卡的信息和消费记录移到新卡
QString info, prompt = QString("如需将挂失卡移资到本卡,请输入密码。"); QString info, prompt = QString("如需将挂失卡移资到本卡,请输入密码。");
bool success = verifyUser(userId, prompt, info); bool success = verifyUser(userId, prompt, info);
if (!success) if (!success)
@ -238,6 +264,13 @@ void MainWindow::on_newCardButton_clicked()
return; return;
} }
success = reader.initCard(cardIdSelected); // 初始化卡
if (!success)
{
QMessageBox::warning(this, "提示", QString("读卡器设备异常。写卡失败,请重试。"));
return;
}
QMessageBox::information(this, "提示", "移资成功。"); QMessageBox::information(this, "提示", "移资成功。");
return; return;
} }
@ -251,6 +284,14 @@ void MainWindow::on_newCardButton_clicked()
QMessageBox::warning(this, "提示", info + QString("\n注册失败,请重新开卡。")); QMessageBox::warning(this, "提示", info + QString("\n注册失败,请重新开卡。"));
return; return;
} }
success = reader.initCard(cardIdSelected); // 初始化卡
if (!success)
{
QMessageBox::warning(this, "提示", QString("读卡器设备异常。写卡失败,请重试。"));
return;
}
QMessageBox::information(this, "提示", "新用户开卡成功。"); QMessageBox::information(this, "提示", "新用户开卡成功。");
return; return;
} }

View File

@ -74,6 +74,10 @@ int Reader::getComNumber()
* inventory方法获取最大数量为maxViccNum的卡片UIDQStringList返回 * inventory方法获取最大数量为maxViccNum的卡片UIDQStringList返回
* @param maxViccNum * @param maxViccNum
* @return UID的QStringList * @return UID的QStringList
* @details
* inventory方法获取最大数量为maxViccNum的卡片UIDQStringList返回
* UIDCVCDOurs::inventory来获取卡片信息
* UID会转换为字符串并添加到QStringList中
* @author * @author
* @date 2024-07-29 * @date 2024-07-29
*/ */
@ -100,3 +104,198 @@ QStringList Reader::inventory(int maxViccNum)
free(aucUID); free(aucUID);
return uidList; return uidList;
} }
/**
* @brief index
* block0中读取记录数量和最近一条记录的索引
* @param recordNum int
* @param recordIndex int
* @param cardId ID QString
* @return bool
* - true
* - false
* @details
* ID转换为 `uchar_t` `readBlocks` block0中读取记录数量和索引
* `readBlocks` hex数量为0 `false`
* `recordNum` `recordIndex`
* @author
* @date 2024-07-31
*/
bool Reader::readRecordNumber(int &recordNum, int &recordIndex, QString cardId)
{
// 记录数量在block0的byte0的bit0-3中
// 最近一条记录的index在block0的byte0的bit4-7中
// 分配内存用于存储读取结果字符串
uchar_t recordIndexHex[4] = {0}; // 一个block有4个byte1个byte有两个hex会返回8个hex存在4个uchar_t中
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
int hexNum = readBlocks(0, 1, recordIndexHex, nullptr, cardIdHex);
if (hexNum == 0) return false;
recordNum = (int)(recordIndexHex[0] & 0x0F);
recordIndex = (int)(recordIndexHex[1] >> 4);
return true;
}
/**
* @brief index
* block0中
* @param recordNum int
* @param recordIndex int
* @param cardId ID QString
* @return bool
* - true
* - false
* @details
* `uchar_t` `recordIndexStr`
* ID转换为 `uchar_t` `writeBlock` block0中
* `writeBlock` 1 `true` `false`
* @author
* @date 2024-07-31
*/
bool Reader::writeRecordNumber(int recordNum, int recordIndex, QString cardId)
{
// 记录数量在block0的byte0的bit0-3中
// 最近一条记录的index在block0的byte0的bit4-7中
// 分配内存用于存储读取结果字符串
uchar_t recordIndexStr[4] = {0};
recordIndexStr[0] = (uchar_t)(recordIndex << 4);
recordIndexStr[0] += (uchar_t)(recordNum);
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
int success = writeBlock(0, recordIndexStr, cardIdHex);
return success == 1;
}
/**
* @brief
*
* @param record QString
* @param cardId ID QString
* @return bool
* - true
* - false
* @details
* `false`
* `uchar_t`
* `writeBlocks` 0 `true` `false`
* @author
* @date 2024-07-31
*/
bool Reader::insertRecord(QString record, QString cardId)
{
int recordNum, recordIndex;
bool success = readRecordNumber(recordNum, recordIndex, cardId);
if (!success) return false;
recordNum = std::min(maxRecordNum, ++recordNum);
recordIndex = (recordIndex + 1) % maxRecordNum;
success = writeRecordNumber(recordNum, recordIndex, cardId);
if (!success) return false;
int blockIndex = 1 + 4 * recordIndex;
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
uchar_t recordHex[4 * 4] = {0};
ba = record.toLatin1();
StringToHex(ba.data(), recordHex);
int writeLineNumber = writeBlocks(blockIndex, 4, recordHex, cardIdHex);
return writeLineNumber != 0;
}
/**
* @brief
*
* @param cardId ID QString
* @param ok bool
* @return QStringList
* @details
* `ok` `false`
* ID转换为 `uchar_t`
* 4block组成block包含8个hex字符block的内容转换为字符串并拼接成完整的记录字符串
* `QStringList`
* @author
* @date 2024-07-31
*/
QStringList Reader::getRecords(QString cardId, bool &ok)
{
QStringList recordList;
int recordNum, recordStartIndex;
bool success = readRecordNumber(recordNum, recordStartIndex, cardId);
if (!success)
{
ok = false;
return recordList;
}
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
for (int i = 0; i < recordNum; i++)
{
QString recordStr = "";
int recordIndex = 1 + 4 * ((recordStartIndex + i) % maxRecordNum);
for (int j = 0; j < 4; j++)
{
uchar_t blockHex[4] = {0}; // 一个block有4个byte1个byte有两个hex会返回8个hex存在4个uchar_t中
int hexNum = readBlocks(recordIndex + j, 1, blockHex, nullptr, cardIdHex);
if (hexNum == 0)
{
ok = false;
return recordList;
}
char blockStr[9] = {0};
HexToString(blockHex, 4, blockStr);
recordStr += QString(blockStr);
}
recordList.push_back(recordStr);
}
return recordList;
}
/**
* @brief
* 1block初始化为全0
* @param cardId ID QString
* @return bool
* - true
* - false
* @details
* `QString` ID转换为 `uchar_t`
* 0 `writeBlocks` 1block
* `writeBlocks` 0 `true` `false`
* @author
* @date 2024-07-31
*/
bool Reader::initCard(QString cardId)
{
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
uchar_t allZeroHex[4] = {0};
int writeLineNumber = writeBlock(0, allZeroHex, cardIdHex);
return writeLineNumber != 0;
}

View File

@ -20,6 +20,10 @@ class Reader : private CVCDOurs
{ {
private: private:
int comNumber = -1; ///< 硬件连接com口号若未连接为-1 int comNumber = -1; ///< 硬件连接com口号若未连接为-1
int maxRecordNum = 6; ///< 每条记录4个block最多28-1=27个block所以最多支持6条记录
bool readRecordNumber(int &recordNum, int &recordIndex, QString cardId);
bool writeRecordNumber(int recordNum, int recordIndex, QString cardId);
public: public:
void setComNumber(int comNumber); void setComNumber(int comNumber);
@ -29,6 +33,10 @@ public:
bool connect(); bool connect();
QStringList inventory(int maxViccNum); QStringList inventory(int maxViccNum);
bool insertRecord(QString record, QString cardId);
bool writeRecords(QStringList recordList, QString cardId);
QStringList getRecords(QString cardId, bool &ok);
bool initCard(QString cardId);
}; };
#endif // READERAPI_H #endif // READERAPI_H