完成所有功能。(硬件接口存在部分问题无法解决,直接跳过处理)

This commit is contained in:
Jingfan Ke 2024-07-31 22:26:24 +08:00
parent 20604b7f22
commit 6a6f666e46
11 changed files with 216 additions and 61 deletions

View File

@ -1,5 +1,6 @@
#include <cstdlib>
#include "VCDOurs.h"
#include "qlogging.h"
CVCDOurs::CVCDOurs(void)
{
@ -422,7 +423,7 @@ int CVCDOurs::writeBlocks( int nFirstBlock, int nBlockNum, uchar_t *pDat, uchar_
int k = 0;
for( int i = 0; i < nBlockNum; i++ )
{
k += writeBlock( nFirstBlock + i, pDat+i*8, pucUID );
k += writeBlock( nFirstBlock + i, pDat+i*4, pucUID );
}
return k;
}

View File

@ -71,12 +71,12 @@ public:
virtual int readMultipleBlocks(
uchar_t *pucUID, // NULL表示select模式
uchar_t optional_flag, // optional bit = 1, 要求返回block的安全状态
uchar_t ucBlkno, // 开始block no
uchar_t blocknum, // 实际读的block是blocknum+1;
uchar_t ucBlkno, // 开始block no
uchar_t blocknum, // 实际读的block是blocknum+1;
uchar_t buf[], // 返回读取的数据
uchar_t aucSecurity[] // 如果optional_flag = 1, 返回该block的安全状态1表示locked.
)
{
{
t15bOption = optional_flag;
return readBlocks( ucBlkno, blocknum+1, buf, aucSecurity, pucUID );
}

View File

@ -172,6 +172,12 @@ void MainWindow::on_consumeButton_clicked()
return;
}
success = reader.insertRecord(recordId, cardId);
if (!success)
{
QMessageBox::warning(this, "提示", "消费完成。写卡失败。本交易不记录在卡上。");
}
QString consumeResultMessage = QString("消费成功:") + QString::number(deductValue) + QString("\n");
consumeResultMessage += QString("原余额:") + QString::number(originalBalance) + QString("\n");
consumeResultMessage += QString("消费后余额:") + QString::number(finalBalance) + QString("\n");
@ -263,8 +269,6 @@ bool MainWindow::deductCard(QString cardId, double deductValue, double &original
query.next();
finalBalance = query.value("@newBalance").toDouble();
/// @todo 写卡
return true;
}

View File

@ -118,6 +118,12 @@ void MainWindow::on_depositByCardIdButton_clicked()
return;
}
success = reader.insertRecord(recordId, cardId);
if (!success)
{
QMessageBox::warning(this, "提示", "充值成功。写卡失败。本交易不记录在卡上。");
}
QString depositResultMessage = QString("充值成功:") + QString::number(topUpValue) + QString("\n");
depositResultMessage += QString("原余额:") + QString::number(originalBalance) + QString("\n");
depositResultMessage += QString("充值后余额:") + QString::number(finalBalance) + QString("\n");
@ -223,9 +229,10 @@ void MainWindow::on_depositByUserIdButton_clicked()
* @param finalBalance
* @param recordId
* @param info
* @return bool
* - true
* - false
* @return int
* - 0
* - 1
* - 2
* @details
*
*
@ -299,8 +306,6 @@ bool MainWindow::topUpCard(QString cardId, double topUpValue, double &originalBa
query.next();
finalBalance = query.value("@newBalance").toDouble();
/// @todo 写卡
return true;
}
@ -327,5 +332,5 @@ QString MainWindow::getRecordId(QDateTime currentTime, int userId, int recordTyp
QString typeStr = QString::number(recordType); // 第25位记录类型
QString randomHex = QString::number(QRandomGenerator::global()->bounded(0x10000), 16).rightJustified(4, '0'); // 第26-29位随机十六进制数
QString recordId = timeStr + userIdStr + typeStr + randomHex; // 共30位
return recordId;
return recordId.toUpper();
}

View File

@ -83,7 +83,6 @@ MainWindow::MainWindow(QWidget *parent)
ui->queryResultTable->setColumnWidth(5, 240);
// 设置启动页面
ui->stackedWidget->setCurrentWidget(ui->settingPage);
}
@ -93,4 +92,3 @@ MainWindow::~MainWindow()
{
delete ui;
}

View File

@ -71,6 +71,7 @@ private slots:
void on_queryInventoryButton_clicked();
void on_userRecordQueryButton_clicked();
void on_userIdRecordQueryButton_clicked();
void on_cardRecordQueryButton_clicked();
private:
Ui::MainWindow *ui;

View File

@ -247,7 +247,7 @@ void MainWindow::on_newCardButton_clicked()
}
else if (userCardStatus == -1) // 用户有挂失卡,需要移资
{
/// @todo 弹出验证用户界面,要求用户输入密码;在数据库中将挂失卡的信息和消费记录移到新卡
// 弹出验证用户界面,要求用户输入密码;在数据库中将挂失卡的信息和消费记录移到新卡
QString info, prompt = QString("如需将挂失卡移资到本卡,请输入密码。");
bool success = verifyUser(userId, prompt, info);
if (!success)
@ -333,8 +333,6 @@ bool MainWindow::bindUserWithCard(int userId, QString cardId, QString &info)
return false;
}
/// @todo 写卡
return true;
}
@ -570,8 +568,6 @@ bool MainWindow::transferCard(int userId, QString newCardId, QString oldCardId,
return false;
}
/// @todo 将数据库上的记录写到新卡上
return true;
}
@ -606,7 +602,5 @@ bool MainWindow::reopenCard(QString cardId, QString &info)
return false;
}
/// @todo 看看是否有写卡需求
return true;
}

View File

@ -283,6 +283,136 @@ void MainWindow::on_userIdRecordQueryButton_clicked()
}
/**
* @brief
* @param void
* @return void
* @author
* @date 2024-07-31
*/
void MainWindow::on_cardRecordQueryButton_clicked()
{
if (!databaseReady())
{
QMessageBox::warning(this, QString("提示"), QString("数据库未连接,请设置。"));
if (ui->stackedWidget->currentWidget() != ui->settingPage)
{
ui->stackedWidget->setCurrentWidget(ui->settingPage);
}
return;
}
if (ui->queryCardIdBox->currentIndex() == -1)
{
QMessageBox::warning(this, "提示", "请放置卡片并点击查询按钮。");
return;
}
QString cardId = ui->queryCardIdBox->currentText();
int cardStatus;
double balance;
// 检查和获取绑定用户
QSqlQuery query(db->getDatabase());
query.prepare(QString("select userId, `status`, balance from card "
"where id = :cardId;"));
query.bindValue(":cardId", cardId);
bool success = false;
success = query.exec();
if (!success)
{
QMessageBox::warning(this, QString("提示"), QString("数据库异常。查询失败。"));
queryPageInitContent();
return;
}
if (query.next()) // 卡已被注册获取用户ID
{
cardStatus = query.value("status").toInt();
if (cardStatus == 0)
{
QMessageBox::warning(this, QString("提示"), QString("此卡未被启用。"));
queryPageInitContent();
return;
}
if (cardStatus == -1)
{
ui->queryCardStatusLabel->setText(QString("已被挂失"));
}
balance = query.value("balance").toDouble();
ui->queryBalanceShowEdit->setText(QString::number(balance, 'f', 2));
}
else // 卡没有注册
{
query.finish();
query.prepare(QString("insert into card "
"values (:cardId, 0, 0.0, null);"));
query.bindValue(":cardId", cardId);
success = query.exec();
if (!success)
{
QMessageBox::warning(this, QString("提示"), QString("数据库异常。查询失败。"));
queryPageInitContent();
return;
}
QMessageBox::warning(this, QString("提示"), QString("此卡未被启用。"));
queryPageInitContent();
return;
}
QStringList cardRecordIdList = reader.readAllRecords(cardId, success);
if (!success)
{
QMessageBox::warning(this, QString("提示"), QString("读卡器异常。查询失败。"));
queryPageInitContent();
return;
}
query.finish();
query.prepare(QString("select time, type, value, balance, device, id from record_view "
"where cardId = :cardId and id = :recordId;"));
query.bindValue(":cardId", cardId);
std::vector<QStringList> transactionRecordList;
for (int i = 0; i < cardRecordIdList.size(); i++)
{
QString recordId = cardRecordIdList[i];
query.bindValue(":recordId", recordId);
success = query.exec();
if (!success)
{
QMessageBox::warning(this, QString("提示"), QString("数据库异常。查询失败。"));
queryPageInitContent();
return;
}
if (!query.next()) {
// 原来的代码
// QMessageBox::warning(this, QString("提示"), QString("数据库异常。查询失败。"));
// queryPageInitContent();
// return;
// 这里本来应该报错退出但是读卡器经常发疯见Reader::readAllRecords(QString cardId, bool &ok)
// 所以发现有不在数据库中的记录号,直接跳过
continue;
}
QStringList transactionRecord = transactionRecord2QStringList
(
query.value("time").toDateTime(),
query.value("type").toInt(),
query.value("value").toDouble(),
query.value("balance").toDouble(),
query.value("device").toString(),
query.value("id").toString()
);
transactionRecordList.push_back(transactionRecord);
}
displayInTableWidget(transactionRecordList);
}
/**
* @brief QStringList
* `QStringList`便
@ -374,4 +504,3 @@ void MainWindow::displayInTableWidget(std::vector<QStringList> transactionRecord
}
}
}

View File

@ -18,7 +18,8 @@ void MainWindow::on_quitAppAction_triggered()
/**
* @brief 退
* 退
* 退
*
* @param void
* @return void
* @author
@ -26,5 +27,7 @@ void MainWindow::on_quitAppAction_triggered()
*/
void MainWindow::on_confirmQuitButton_clicked()
{
if (reader.is_connected()) reader.disconnect();
free(db);
this->close();
}

View File

@ -1,4 +1,5 @@
#include "readerAPI.h"
#include "qdebug.h"
/**
@ -29,7 +30,7 @@ bool Reader::is_connected()
*/
bool Reader::connect()
{
if (CVCDOurs::connectReaderByCOM(comNumber))
if (connectReaderByCOM(comNumber))
{
return true;
}
@ -41,6 +42,19 @@ bool Reader::connect()
}
/**
* @brief
* @param void
* @return void
* @author
* @date 2024-07-31
*/
void Reader::disconnect()
{
disconnectReaderByCOM();
}
/**
* @brief COM口号
* @param comNumber COM口号
@ -131,14 +145,13 @@ bool Reader::readRecordNumber(int &recordNum, int &recordIndex, QString cardId)
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);
StringToHex(cardId.toLatin1().data(), cardIdHex);
int hexNum = readBlocks(0, 1, recordIndexHex, nullptr, cardIdHex);
int hexNum = readSingleBlock(cardIdHex, 0, 0, recordIndexHex, nullptr);
if (hexNum == 0) return false;
recordNum = (int)(recordIndexHex[0] & 0x0F);
recordIndex = (int)(recordIndexHex[1] >> 4);
recordIndex = (int)(recordIndexHex[0] >> 4);
return true;
}
@ -171,10 +184,9 @@ bool Reader::writeRecordNumber(int recordNum, int recordIndex, QString cardId)
recordIndexStr[0] += (uchar_t)(recordNum);
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
StringToHex(cardId.toLatin1().data(), cardIdHex);
int success = writeBlock(0, recordIndexStr, cardIdHex);
int success = writeSingleBlock(cardIdHex, 0, 4, recordIndexStr);
return success == 1;
}
@ -207,14 +219,12 @@ bool Reader::insertRecord(QString record, QString cardId)
int blockIndex = 1 + 4 * recordIndex;
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
StringToHex(cardId.toLatin1().data(), cardIdHex);
uchar_t recordHex[4 * 4] = {0};
ba = record.toLatin1();
StringToHex(ba.data(), recordHex);
StringToHex(record.toLatin1().data(), recordHex);
int writeLineNumber = writeBlocks(blockIndex, 4, recordHex, cardIdHex);
int writeLineNumber = writeMultipleBlocks(cardIdHex, blockIndex, 4, 4, recordHex);
return writeLineNumber != 0;
}
@ -234,7 +244,7 @@ bool Reader::insertRecord(QString record, QString cardId)
* @author
* @date 2024-07-31
*/
QStringList Reader::getRecords(QString cardId, bool &ok)
QStringList Reader::readAllRecords(QString cardId, bool &ok)
{
QStringList recordList;
@ -247,37 +257,43 @@ QStringList Reader::getRecords(QString cardId, bool &ok)
}
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
StringToHex(cardId.toLatin1().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++)
StringToHex(cardId.toLatin1().data(), cardIdHex); // readMultipleBlocks不知为何会改变cardIdHex的值要重新赋值
int recordBlockIndex = 1 + 4 * ((recordStartIndex + i) % maxRecordNum);
uchar_t recordHex[4 * 4] = {0};
int hexNum = readMultipleBlocks(cardIdHex, 0, recordBlockIndex, 4, recordHex, nullptr);
if (hexNum == 0)
{
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;
}
// 原来的处理代码
// ok = false;
// return recordList;
char blockStr[9] = {0};
HexToString(blockHex, 4, blockStr);
recordStr += QString(blockStr);
// 这里经常出现hexNum == 0循环终止的情况原因是返回的reply为空值: “[]”
// 一旦出现[],后面的值大概率会出错。
// 出现主要集中在第二遍循环时。
// 尝试解决方案每一遍循环重新inventory重置一下环境怀疑某些变量被改了、每一遍循环睡眠2秒都没有解决这个问题
// 因此在发生错误时直接返回能够正确读取的记录ID。
break;
}
recordList.push_back(recordStr);
char recordStr[33] = {0};
HexToString(recordHex, 4 * 4, recordStr);
recordStr[30] = '\0';
QString qRecordStr = QString(recordStr).toUpper();
recordList.push_back(qRecordStr);
}
ok = true;
return recordList;
}
/**
* @brief
* 1block初始化为全0
* 1block的记录数量设置为0maxRecordNum-1
* @param cardId ID QString
* @return bool
* - true
@ -292,10 +308,10 @@ QStringList Reader::getRecords(QString cardId, bool &ok)
bool Reader::initCard(QString cardId)
{
uchar_t cardIdHex[8] = {0};
QByteArray ba = cardId.toLatin1();
StringToHex(ba.data(), cardIdHex);
StringToHex(cardId.toLatin1().data(), cardIdHex);
uchar_t allZeroHex[4] = {0};
int writeLineNumber = writeBlock(0, allZeroHex, cardIdHex);
uchar_t initHex[4] = {0};
initHex[0] = (char)(maxRecordNum - 1) << 4;
int writeLineNumber = writeSingleBlock(cardIdHex, 0, 4, initHex);
return writeLineNumber != 0;
}

View File

@ -2,9 +2,11 @@
#define READERAPI_H
#include <HF15693.h>
#include <VCDOurs.h>
#include <QString>
#include <QStringList>
#include <VCDOurs.h>
#include <QElapsedTimer>
typedef unsigned char uchar_t;
@ -29,13 +31,15 @@ public:
void setComNumber(int comNumber);
int getComNumber();
bool is_connected();
bool connect();
void disconnect();
QStringList inventory(int maxViccNum);
bool insertRecord(QString record, QString cardId);
bool writeRecords(QStringList recordList, QString cardId);
QStringList getRecords(QString cardId, bool &ok);
QStringList readAllRecords(QString cardId, bool &ok);
bool initCard(QString cardId);
};