Browse Source

update

master
zhaohe 1 year ago
parent
commit
572e6d19d9
  1. 1
      CMakeLists.txt
  2. 2
      iflytop_canbus/iflytop_canbus_master.cpp
  3. 14
      libzqt/zexception.hpp
  4. 292
      src/basic/a8k_id_card_writer.cpp
  5. 52
      src/basic/a8k_id_card_writer.hpp
  6. 93
      src/tab/id_card_read_tab.cpp
  7. 2
      src/tab/id_card_read_tab.hpp
  8. 4
      src/tab/module_opera_tab.cpp

1
CMakeLists.txt

@ -72,6 +72,7 @@ set(PROJECT_SOURCES
src/tab/id_card_read_tab.cpp
src/basic/format_memory.cpp
src/basic/smtp2_constant.cpp
src/basic/a8k_id_card_writer.cpp
app.rc

2
iflytop_canbus/iflytop_canbus_master.cpp

@ -8,7 +8,7 @@ using namespace iflytop;
using namespace zcr;
#define TAG "IflytopCanbusMaster"
#define G_OVERTIME 100
#define G_OVERTIME 150
IflytopCanbusMaster *IflytopCanbusMaster::ins() {
static IflytopCanbusMaster *ins = new IflytopCanbusMaster();

14
libzqt/zexception.hpp

@ -21,11 +21,13 @@ class zexception : public exception {
};
typedef enum {
ke_ok = 10000 + 0,
ke_channel_is_close = 10000 + 1,
ke_invalid_param = 10000 + 2,
ke_invalid_packet_format = 10000 + 3,
ke_overtime = 10000 + 4,
ke_ok = 10000 + 0,
ke_error = 10000 + 1,
ke_channel_is_close = 10000 + 2,
ke_invalid_param = 10000 + 3,
ke_invalid_packet_format = 10000 + 4,
ke_overtime = 10000 + 5,
ke_parse_config_file_fail = 10000 + 6,
} zecode_t;
static inline const char* zecode2str(zecode_t ecode) {
@ -40,6 +42,8 @@ static inline const char* zecode2str(zecode_t ecode) {
return "invalid_packet_format";
case ke_overtime:
return "overtime";
case ke_parse_config_file_fail:
return "parse_config_file_fail";
default:
return "unkown error";
}

292
src/basic/a8k_id_card_writer.cpp

@ -0,0 +1,292 @@
#include "a8k_id_card_writer.hpp"
#include "libzqt/zexception.hpp"
#include "zui/zqui.hpp"
using namespace iflytop;
eeprom_cfg_iterm_t iterms[] = {
{"项目名称", 0x0001, 15},
{"批次名称", 0x0010, 12},
{"有效日期", 0x001C, 3},
{"项目名称代码", 0x001F, 1},
{"板条条码代码", 0x0020, 1},
{"更新芯片版本号", 0x0021, 1},
{"质控峰最小值", 0x0022, 5},
{"质控峰最大值", 0x0027, 5},
{"光学类型", 0x002C, 1},
{"光学固定增益设置", 0x002D, 1},
{"光学面积峰个数是否跟设置值一致", 0x002E, 1},
{"计算方向", 0x002F, 1},
{"样本类型", 0x0030, 1},
{"设备厂商", 0x0031, 1},
{"T光学持续光照时间", 0x0032, 2},
{"是否包含多款仪器数据合并", 0x0034, 1},
{"多款仪器数据合并", 0x0035, 1},
{"多款仪器数据合并", 0x0036, 1},
{"全血样本量", 0x0037, 1},
{"血清", 0x0038, 1},
{"试管混匀次数", 0x0039, 1},
{"缓冲液瓶大小", 0x003A, 1},
{"缓冲液逻辑", 0x003B, 1},
{"缓冲液瓶容量", 0x003B, 1},
{"缓冲液吸吐混匀次数", 0x003C, 1},
{"缓冲液吐混混匀量", 0x003D, 1},
{"缓冲液反应时间", 0x003E, 1},
{"反应板反应时间", 0x003F, 1},
{"反应板滴样量", 0x0040, 1},
{"结果小数点位数", 0x0041, 1},
{"扫描范围", 0x0042, 1},
{"当前项目是几联卡项目", 0x0100, 5},
{"项目1 结果曲线是否为分段函数", 0x0105, 5},
{"项目2 结果曲线是否为分段函数", 0x010A, 5},
{"项目3 结果曲线是否为分段函数", 0x010F, 5},
{"项目1-函数未知数是 ", 0x0150, 5},
{"项目1-函数未知数下限闻值 ", 0x0155, 5},
{"项目1-函数未知数上限闻值 ", 0x015A, 5},
{"项目1-A ", 0x015F, 5},
{"项目1-B ", 0x0164, 5},
{"项目1-C ", 0x0169, 5},
{"项目1-D ", 0x016E, 5},
{"项目1-resultLowLimit ", 0x0173, 5},
{"项目1-resultUpLimit ", 0x0178, 5},
{"项目1-A ", 0x017D, 5},
{"项目1-B ", 0x0182, 5},
{"项目1-C ", 0x0187, 5},
{"项目1-D ", 0x018C, 5},
{"项目1-resultLowLimit ", 0x0191, 5},
{"项目1-resultUpLimit ", 0x0196, 5},
{"项目1-分界判断数据来源", 0x01F0, 5},
{"项目1-分界判断数据值", 0x01F5, 5},
{"项目1-低浓度曲线未知数是", 0x01FA, 5},
{"项目1-高浓度曲线未知数是 ", 0x01FF, 5},
{"项目1-未知数下限闻值", 0x0204, 5},
{"项目1-未知数上限闻值", 0x0209, 5},
{"项目1-A", 0x020E, 5},
{"项目1-B", 0x0213, 5},
{"项目1-C", 0x0218, 5},
{"项目1-D", 0x021D, 5},
{"项目1-A", 0x0222, 5},
{"项目1-B", 0x0227, 5},
{"项目1-C", 0x022C, 5},
{"项目1-D", 0x0231, 5},
{"项目1-resultLowLimit", 0x0236, 5},
{"项目1-resultUpLimit", 0x023B, 5},
{"项目1-A", 0x0240, 5},
{"项目1-B", 0x0245, 5},
{"项目1-C", 0x024A, 5},
{"项目1-D", 0x024F, 5},
{"项目1-A", 0x0254, 5},
{"项目1-B", 0x0259, 5},
{"项目1-C", 0x025E, 5},
{"项目1-D", 0x0263, 5},
{"项目1-resultLowLimit", 0x0268, 5},
{"项目1-resultUpLimit", 0x026D, 5},
{"项目1-第一单位", 0x02E0, 5},
{"项目1-第二单位", 0x02E5, 5},
{"项目1-第三单位", 0x02EA, 5},
{"项目1-第二单位换算公式一次方式系数A值", 0x02EF, 5},
{"项目1-第二单位换算公式常数B值", 0x02F4, 5},
{"项目1-第三单位换算公式一次方式系数A值", 0x02F9, 5},
{"项目1-第三单位换算公式常数B值 ", 0x02FE, 5},
{"项目2-函数未知数是 ", 0x0330, 5},
{"项目2-函数未知数下限闻值 ", 0x0335, 5},
{"项目2-函数未知数上限闻值 ", 0x033a, 5},
{"项目2-A ", 0x033f, 5},
{"项目2-B ", 0x0344, 5},
{"项目2-C ", 0x0349, 5},
{"项目2-D ", 0x034e, 5},
{"项目2-resultLowLimit ", 0x0353, 5},
{"项目2-resultUpLimit ", 0x0358, 5},
{"项目2-A ", 0x035d, 5},
{"项目2-B ", 0x0362, 5},
{"项目2-C ", 0x0367, 5},
{"项目2-D ", 0x036c, 5},
{"项目2-resultLowLimit ", 0x0371, 5},
{"项目2-resultUpLimit ", 0x0376, 5},
{"项目2-分界判断数据来源", 0x03d0, 5},
{"项目2-分界判断数据值", 0x03d5, 5},
{"项目2-低浓度曲线未知数是", 0x03da, 5},
{"项目2-高浓度曲线未知数是 ", 0x03df, 5},
{"项目2-未知数下限闻值", 0x03e4, 5},
{"项目2-未知数上限闻值", 0x03e9, 5},
{"项目2-A", 0x03ee, 5},
{"项目2-B", 0x03f3, 5},
{"项目2-C", 0x03f8, 5},
{"项目2-D", 0x03fd, 5},
{"项目2-A", 0x0402, 5},
{"项目2-B", 0x0407, 5},
{"项目2-C", 0x040c, 5},
{"项目2-D", 0x0411, 5},
{"项目2-resultLowLimit", 0x0416, 5},
{"项目2-resultUpLimit", 0x041b, 5},
{"项目2-A", 0x0420, 5},
{"项目2-B", 0x0425, 5},
{"项目2-C", 0x042a, 5},
{"项目2-D", 0x042f, 5},
{"项目2-A", 0x0434, 5},
{"项目2-B", 0x0439, 5},
{"项目2-C", 0x043e, 5},
{"项目2-D", 0x0443, 5},
{"项目2-resultLowLimit", 0x0448, 5},
{"项目2-resultUpLimit", 0x044d, 5},
{"项目2-第一单位", 0x04c0, 5},
{"项目2-第二单位", 0x04c5, 5},
{"项目2-第三单位", 0x04ca, 5},
{"项目2-第二单位换算公式一次方式系数A值", 0x04cf, 5},
{"项目2-第二单位换算公式常数B值", 0x04d4, 5},
{"项目2-第三单位换算公式一次方式系数A值", 0x04d9, 5},
{"项目2-第三单位换算公式常数B值 ", 0x04de, 5},
{"项目3-函数未知数是 ", 0x0510, 5},
{"项目3-函数未知数下限闻值 ", 0x0515, 5},
{"项目3-函数未知数上限闻值 ", 0x051a, 5},
{"项目3-A ", 0x051f, 5},
{"项目3-B ", 0x0524, 5},
{"项目3-C ", 0x0529, 5},
{"项目3-D ", 0x052e, 5},
{"项目3-resultLowLimit ", 0x0533, 5},
{"项目3-resultUpLimit ", 0x0538, 5},
{"项目3-A ", 0x053d, 5},
{"项目3-B ", 0x0542, 5},
{"项目3-C ", 0x0547, 5},
{"项目3-D ", 0x054c, 5},
{"项目3-resultLowLimit ", 0x0551, 5},
{"项目3-resultUpLimit ", 0x0556, 5},
{"项目3-分界判断数据来源", 0x05b0, 5},
{"项目3-分界判断数据值", 0x05b5, 5},
{"项目3-低浓度曲线未知数是", 0x05ba, 5},
{"项目3-高浓度曲线未知数是 ", 0x05bf, 5},
{"项目3-未知数下限闻值", 0x05c4, 5},
{"项目3-未知数上限闻值", 0x05c9, 5},
{"项目3-A", 0x05ce, 5},
{"项目3-B", 0x05d3, 5},
{"项目3-C", 0x05d8, 5},
{"项目3-D", 0x05dd, 5},
{"项目3-A", 0x05e2, 5},
{"项目3-B", 0x05e7, 5},
{"项目3-C", 0x05ec, 5},
{"项目3-D", 0x05f1, 5},
{"项目3-resultLowLimit", 0x05f6, 5},
{"项目3-resultUpLimit", 0x05fb, 5},
{"项目3-A", 0x0600, 5},
{"项目3-B", 0x0605, 5},
{"项目3-C", 0x060a, 5},
{"项目3-D", 0x060f, 5},
{"项目3-A", 0x0614, 5},
{"项目3-B", 0x0619, 5},
{"项目3-C", 0x061e, 5},
{"项目3-D", 0x0623, 5},
{"项目3-resultLowLimit", 0x0628, 5},
{"项目3-resultUpLimit", 0x062d, 5},
{"项目3-第一单位", 0x06a0, 5},
{"项目3-第二单位", 0x06a1, 5},
{"项目3-第三单位", 0x06a2, 5},
{"项目3-第二单位换算公式一次方式系数A值", 0x06a3, 5},
{"项目3-第二单位换算公式常数B值", 0x06a4, 5},
{"项目3-第三单位换算公式一次方式系数A值", 0x06a5, 5},
{"项目3-第三单位换算公式常数B值 ", 0x06a6, 5},
};
static std::string zhex2str(const uint8_t* hex, size_t len) {
std::string str;
for (size_t i = 0; i < len; i++) {
char buf[4] = {0};
snprintf(buf, sizeof(buf), "%02x ", hex[i]);
str += buf;
}
return str;
}
bool parseIDWString(const std::string& input, uint32_t& add, std::vector<unsigned char>& data) {
size_t posColon = input.find(':');
if (posColon == std::string::npos) {
return false; // 没有找到冒号,格式错误
}
// 提取版本号部分 "0x0001"
size_t posSpace = input.find(' ');
if (posSpace == std::string::npos || posSpace >= posColon) {
return false; // 没有找到空格或者空格位置在冒号之后,格式错误
}
string addstr = input.substr(posSpace + 1, posColon - posSpace - 1);
add = std::stoul(addstr, nullptr, 16);
// 提取数据部分 "68 73 43 52 50 FF FF FF FF FF FF FF FF FF FF"
std::string dataString = input.substr(posColon + 1);
std::istringstream iss(dataString);
iss >> std::hex;
int byte;
while (iss >> byte) {
data.push_back(static_cast<unsigned char>(byte));
}
return true;
}
void hexStringToBytes(const std::string& hexString, std::vector<unsigned char>& byteArray) {
std::istringstream iss(hexString);
iss >> std::hex;
int byte;
while (iss >> byte) {
byteArray.push_back(static_cast<unsigned char>(byte));
}
}
bool A8kIdCardWriter::parse(string filepath) {
/**
* @brief
*/
string filecontent;
ifstream ifs(filepath);
if (!ifs.is_open()) {
cout << "open file failed" << endl;
return false;
}
m_cmdNum = 0;
memset(eeprom, 0, sizeof(eeprom));
while (getline(ifs, filecontent)) {
wcmd_t cmd;
cout << filecontent << endl;
if (filecontent.find("IDW") != string::npos) {
char wdatastr[256] = {0};
uint32_t add;
std::vector<unsigned char> byteArray;
parseIDWString(filecontent, add, byteArray);
if (byteArray.size() == 0) {
ZQUI::ins()->ishow("parse %s failed,%s", filepath.c_str(), filecontent.c_str());
return false;
}
ZQUI::ins()->ishow("IDW 0x%04X:%s", add, zhex2str(byteArray.data(), byteArray.size()).c_str());
cmd.wadd = add;
memcpy(cmd.wdata, byteArray.data(), byteArray.size());
cmd.wdata_len = byteArray.size();
m_cmds[m_cmdNum] = cmd;
m_cmdNum++;
memcpy(&eeprom[cmd.wadd], cmd.wdata, cmd.wdata_len);
}
}
m_configIsLegal = true;
return true;
}
uint32_t A8kIdCardWriter::readEepromWriteData(int32_t add) {
uint32_t data;
memcpy(&data, eeprom + add, 4);
return data;
}
void A8kIdCardWriter::dumpcfg(uint8_t* cfg, int len) {
for (int i = 0; i < sizeof(iterms) / sizeof(eeprom_cfg_iterm_t); i++) {
eeprom_cfg_iterm_t* iterm = &iterms[i];
ZQUI::ins()->ishow("0x%04x: %25s %20s", iterm->add, zhex2str(cfg + iterm->add, iterm->len).c_str(), iterm->descript);
}
}

52
src/basic/a8k_id_card_writer.hpp

@ -0,0 +1,52 @@
#pragma once
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <vector>
namespace iflytop {
using namespace std;
typedef struct {
const char* descript;
uint32_t add;
uint32_t len;
} eeprom_cfg_iterm_t;
class A8kIdCardWriter {
public:
typedef struct {
uint32_t wadd;
uint8_t wdata[128];
uint8_t wdata_len;
} wcmd_t;
uint8_t eeprom[2048 + 100] = {0};
wcmd_t m_cmds[500] = {0};
int32_t m_cmdNum = 0;
bool m_configIsLegal = false;
public:
static A8kIdCardWriter* instance() {
static A8kIdCardWriter* ins = nullptr;
if (ins == nullptr) {
ins = new A8kIdCardWriter();
}
return ins;
}
bool parse(string filepath);
bool cfgIsLegal() { return m_configIsLegal; }
uint32_t readEepromWriteData(int32_t add);
void dumpcfg(uint8_t* cfg, int len);
};
} // namespace iflytop

93
src/tab/id_card_read_tab.cpp

@ -8,9 +8,12 @@
#include "zui/z_reg_table_list_box.hpp"
#include "zui/zq_vtab_page.hpp"
//
#include <QFileDialog>
#include "../basic/format_memory.hpp"
#include "../basic/stm32_pin.hpp"
#include "./mainwindow.h"
#include "basic/a8k_id_card_writer.hpp"
#include "zui\zqui.hpp"
//
using namespace iflytop;
@ -19,6 +22,12 @@ using namespace std;
extern Ui::MainWindow *main_ui;
extern int getDeviceId();
#define EEPROM_MAX_ADD (2 * 1024)
typedef struct {
uint32_t add;
uint8_t buf[32];
} id_card_write_cmd_t;
IDCardReaderTab *IDCardReaderTab::inst() {
static IDCardReaderTab *ins = new IDCardReaderTab();
@ -47,7 +56,10 @@ string format_memery(uint8_t *mem, int len) {
char buf[128];
}
static uint8_t eeprom_rd_buf[2048 + 100];
void IDCardReaderTab::construct(QTabWidget *fathertab) {
m_fathertab = fathertab;
ZQVTabPage *tab = new ZQVTabPage(fathertab, "A8K读卡器");
/***********************************************************************************************************************
* *
@ -64,13 +76,92 @@ void IDCardReaderTab::construct(QTabWidget *fathertab) {
if (resultlen > 0) {
QString result = QString(format_memory(resultbuf, resultlen).c_str());
ZQUI::ins()->ishow("读卡结果: %s", result.toStdString().c_str());
ZQUI::ins()->ishow("读卡结果", result.toStdString().c_str());
ZQUI::ins()->ishow("%s", result.toStdString().c_str());
} else {
ZQUI::ins()->ishow("读卡失败");
}
});
}
{
ZQFunctionListBox *box = new ZQFunctionListBox(tab, "测试", 4);
box->newSubButton("读全部", [this](int argn, const char **args) {
int sector_num;
int sector_size;
ICM->readreg(getDeviceId(), kreg_id_card_reader_raw_sector_num, &sector_num);
ICM->readreg(getDeviceId(), kreg_id_card_reader_raw_sector_size, &sector_size);
for (int sectorIndex = 0; sectorIndex < sector_num; sectorIndex++) {
ICM->callcmd1(getDeviceId(), ka8000_idcard_reader_read_raw, sectorIndex);
this_thread::sleep_for(chrono::milliseconds(10));
uint8_t *resultbuf = ICM->getAckBuf();
int32_t resultlen = ICM->getAckBufLen();
memcpy(eeprom_rd_buf + sectorIndex * sector_size, resultbuf, resultlen);
ZQUI::ins()->ishow("read sector%d", sectorIndex);
}
ZQUI::ins()->ishow("read all done.");
for (int i = 0; i < sector_num * sector_size; i += 4) {
ZQUI::ins()->ishow("0x%04x(%8d): %02x %02x %02x %02x", i, i, eeprom_rd_buf[i], eeprom_rd_buf[i + 1], eeprom_rd_buf[i + 2], eeprom_rd_buf[i + 3]);
}
A8kIdCardWriter::instance()->dumpcfg(eeprom_rd_buf, sector_num * sector_size);
});
box->newSubButtonEnd();
box->newSubButton("解锁写保护", [this](int argn, const char **args) { ICM->callcmd0(getDeviceId(), ka8000_idcard_earse_unlock); });
box->newSubButtonEnd();
box->newSubButton("写测试数据1", [this](int argn, const char **args) {
uint32_t cnt = 0;
for (int i = 0; i < EEPROM_MAX_ADD; i += 4) {
cnt++;
uint32_t writeval = cnt + (cnt << 16);
ZQUI::ins()->ishow("write 0x%04x 0x%02x 0x%02x 0x%02x 0x%02x", i, (writeval >> 0) & 0xff, (writeval >> 8) & 0xff, (writeval >> 16) & 0xff, (writeval >> 24) & 0xff);
// ICM->callcmd2(getDeviceId(), ka8000_idcard_write_raw, i, 0xffffffff);
ICM->callcmd2(getDeviceId(), ka8000_idcard_write_raw, i, writeval);
}
});
box->newSubButton("写测试数据2", [this](int argn, const char **args) {
uint32_t cnt = 512;
for (int i = 0; i < EEPROM_MAX_ADD; i += 4) {
cnt--;
uint32_t writeval = cnt + (cnt << 16);
ZQUI::ins()->ishow("write 0x%04x 0x%02x 0x%02x 0x%02x 0x%02x", i, (writeval >> 0) & 0xff, (writeval >> 8) & 0xff, (writeval >> 16) & 0xff, (writeval >> 24) & 0xff);
ICM->callcmd2(getDeviceId(), ka8000_idcard_write_raw, i, writeval);
}
});
box->newSubButtonEnd();
box->newSubButton("读取配置文件", [this](int argn, const char **args) {
DoInUi([]() {
QString filePath = QFileDialog::getOpenFileName(nullptr, "Select a file");
if (!filePath.isEmpty()) {
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
ZQUI::ins()->ishow("open file fail");
return;
}
A8kIdCardWriter::instance()->parse(filePath.toStdString());
}
});
});
box->newSubButton("写入配置文件", [this](int argn, const char **args) {
bool legal = A8kIdCardWriter::instance()->cfgIsLegal();
if (!legal) {
throw zexception(ke_error, "配置文件不合法");
}
for (int i = 0; i < EEPROM_MAX_ADD; i += 4) {
uint32_t writeval = A8kIdCardWriter::instance()->readEepromWriteData(i);
ZQUI::ins()->ishow("write 0x%04x 0x%02x 0x%02x 0x%02x 0x%02x", i, (writeval >> 0) & 0xff, (writeval >> 8) & 0xff, (writeval >> 16) & 0xff, (writeval >> 24) & 0xff);
ICM->callcmd2(getDeviceId(), ka8000_idcard_write_raw, i, writeval);
}
ZQUI::ins()->ishow("write all done.");
});
}
/***********************************************************************************************************************
* *
***********************************************************************************************************************/

2
src/tab/id_card_read_tab.hpp

@ -35,6 +35,8 @@ namespace iflytop {
using namespace std;
class IDCardReaderTab {
QTabWidget *m_fathertab;
public:
static IDCardReaderTab *inst();

4
src/tab/module_opera_tab.cpp

@ -38,7 +38,7 @@ static const char *module_type2_str(int id) {
case kboard:
return "板子";
case ka8000_idcard_reader:
return "id卡读卡器";
return "A8K读卡器";
case ka8000_plate_code_scaner:
return "反应板条扫码器";
default:
@ -73,7 +73,7 @@ void ModuleOperaTab::construct(QWidget *parent) {
if (i % 10 == 0) {
ZQUI::ins()->ishow("");
}
ZQUI::ins()->ishow("module :%d isOnline type:%10s(%d) v(%d)", i, module_type2_str(moduleType), moduleType, moduleVersion);
ZQUI::ins()->ishow("module :%d isOnline type:%15s(%d) v(%d)", i, module_type2_str(moduleType), moduleType, moduleVersion);
} catch (const zexception &e) {
if (e.ecode() != ke_overtime) {
ZQUI::ins()->ishow("%s", e.what());

Loading…
Cancel
Save