#include "G1G2Scanner.h" #include <3rdparty/comm/hgscanner_error.h> #include "json.hpp" #include #include #include #include #include #include "LineContinuityAndRGBDetection.h" #include "applog.h" #include "stringex.h" using json = nlohmann::json; using namespace std; static const std::string loggername = "G1G2SCANNER"; #define USB_REQ_GET_FPGA_REGS 0x40 #define USB_REQ_SET_FPGA_REGS 0x41 #define USB_REQ_GET_MOTOR_REGS 0x42 #define USB_REQ_SET_MOTOR_REGS 0x43 #define USB_REQ_GET_DEV_STATUS 0x60 #define USB_REQ_GET_DEV_CONFIGURATION 0x61 #define USB_REQ_SET_DEV_CONFIGURATION 0x62 #define USB_REQ_GET_DEV_REGS 0x63 #define USB_REQ_SET_DEV_REGS 0x64 #define GET_BIT(x, bit) ((x & (1 << bit)) >> bit) /* 获取第bit位 */ #define THIS_MODULE_NAME "G1G2ScannerChecker.exe" void json2struct(json& j, ScannerSysInfo& info) { j["CPU"].get_to(info.CPU); j["Systype"].get_to(info.Systype); j["Screentype"].get_to(info.Screentype); j["MtBoardVersion"].get_to(info.MtBoardVersion); j["MtType"].get_to(info.MtType); j["FPGAVersion"].get_to(info.FPGAVersion); j["Cistype"].get_to(info.Cistype); j["MaxRes"].get_to(info.ResSup); j["MemTotal"].get_to(info.MemTotal); j["DiskTotal"].get_to(info.DiskTotal); j["DiskUsed"].get_to(info.DiskUsed); j["KernelVersion"].get_to(info.KernelVersion); j["Have_EthernPort"].get_to(info.Have_EthernPort); j["ServiceVersion"].get_to(info.ServiceVersion); j["UsbProtocol"].get_to(info.UsbProtocol); } static std::string u2a(const wchar_t* u, UINT cp = CP_ACP) { std::string a(""); if (u) { char stack[256] = { 0 }, * ansi = NULL; int len = 0; len = WideCharToMultiByte(cp, 0, u, lstrlenW(u), NULL, 0, NULL, NULL); ansi = new char[len + 2]; len = WideCharToMultiByte(cp, 0, u, lstrlenW(u), ansi, len, NULL, NULL); ansi[len--] = 0; a = ansi; delete[] ansi; } return a; } std::string get_moudle_path() { wchar_t path[MAX_PATH] = { 0 }; GetModuleFileNameW(GetModuleHandleA(THIS_MODULE_NAME), path, _countof(path) - 1); return u2a(path, CP_UTF8); } G1G2Scanner::G1G2Scanner(usb_io* usb) : m_bwork(false), m_online(false) { LOG_INITX(); m_usb = usb; if (m_usb) { m_usb->add_ref(); auto status = m_usb->last_error(); m_online = status == SCANNER_ERR_OK; } //LOG_INFO("Init Thread"); init_work_thread(); //LOG_INFO("Init Thread Done"); } G1G2Scanner::~G1G2Scanner() { LOG_INFO("disctor G1G2Scanner,start join m_work_thread"); if (m_work_thread.get() && m_work_thread->joinable()) { m_bwork = false; m_work_thread->join(); } //LOG_INFO("disctor G1G2Scanner,start release usb"); if (m_usb) { m_usb->close(); m_usb->release(); m_usb = NULL; } //LOG_INFO("disctor G1G2Scanner,start release proc thread"); if (m_imgprocthread.get() && m_imgprocthread->joinable()) { m_bproc = false; imgs.ShutDown(); m_paths.ShutDown(); m_imgprocthread->join(); } //LOG_INFO("disctor G1G2Scanner,start release msgproc thread"); if (m_msgProcThread.get() && m_msgProcThread->joinable()) { m_bprocmsg = false; m_msg.ShutDown(); m_msgProcThread->join(); } LOG_INFO("disctor G1G2Scanner exit"); } void G1G2Scanner::USBDisconnect() { lock_guard m_mtx(m_mtx_usb); m_online = false; m_usb->on_disconnected(); } void G1G2Scanner::Reboot(bool b_loader) { lock_guard m_mtx(m_mtx_usb); if (m_usb && m_online) { write_register(SR_REBOOT, b_loader ? 1 : 0); } } void G1G2Scanner::PowerOFF() { lock_guard m_mtx(m_mtx_usb); if (m_usb && m_online) { write_register(SR_POWEROFF, 0); } } void G1G2Scanner::GetFile(std::string path, std::string& content) { lock_guard m_mtx(m_mtx_usb); if (path.empty()) return; if (m_usb && m_online) { write_register(SR_SET_JSON_PATH, path.length()); int len = path.length(); m_usb->write_bulk((void*)&path[0], &len); int size = 0; if (SCANNER_ERR_OK == read_register(SR_GET_JSON_SIZE, &size)) { content.resize(size); write_register(SR_GET_JSON, size); m_usb->read_bulk((void*)&content[0], &size); } } } void G1G2Scanner::GetIOStatus(int type) { } int G1G2Scanner::RecordFinalResult(std::string res) { std::string recordpath = "/usr/local/huago/boardtest.json"; write_file(recordpath, res); return 0; } int G1G2Scanner::CheckLEDDisplay(std::string display) { lock_guard m_mtx(m_mtx_usb); if (m_usb && m_online) { int val = 0; return write_register(SR_TESTDISPLAY, val); } return 0; } int G1G2Scanner::Flat(unsigned int mode) { lock_guard m_mtx(m_mtx_usb); int color = mode; if (m_usb && m_online) { return write_register(SR_TESTBOARD, color); } return SCANNER_ERR_DEVICE_UNKNOWN_STATUS; } void G1G2Scanner::Snap(unsigned int mode, unsigned int count) { lock_guard m_mtx(m_mtx_usb); int color = mode; if (m_usb && m_online) { write_register(SC_START, 0); } } void G1G2Scanner::SetScannerCallback(scanner_call_handler callback, void* user) { m_callback = callback; m_user = user; } int G1G2Scanner::RecordTestInfo(std::string info) { std::string bd_save_path = "/usr/local/huagao/"; return 0; } bool G1G2Scanner::CheckSwitchs(int idx0, int idx1, int idx2, int idx3) { lock_guard m_mtx(m_mtx_usb); bool ret = true; if (m_usb && m_online) { int val = 0; int ret_code = read_register(SR_GET_DAIL_CODE, &val); if (ret_code == SCANNER_ERR_OK) { HG_Dail_Struct dst_val; dst_val.value = 0; dst_val.dails.in_voltage0 = idx0; dst_val.dails.in_voltage2 = idx1; dst_val.dails.in_voltage3 = idx2; dst_val.dails.in_voltage4 = idx3; std::string notify_info; { if (val != (int)dst_val.value) { ret = false; dst_val.value = val; } for (size_t i = 0; i < 4; i++) { std::string info = " 拨码" + std::to_string(i); int va = GET_BIT(val, i); info += (va == 1 ? ": ON \r\n " : ": OFF \r\n"); notify_info += info; } notify_info += (ret ? "拨码自动校验与目标一致,测试通过\r\n" : "拨码自动校验失败与目标不一致,测试不通过\r\n"); } m_msg.Put({ TASK_ID_CHECK_HW_CAPACITY,DAT_STRING ,notify_info }, 0); } } return ret; } bool G1G2Scanner::CheckCapacity(int dst_mem, int dst_disk) { bool ret_code = false; auto ret = read_file("/usr/local/huago/sysinfo.json"); json j = json::parse(ret); ScannerSysInfo sysinfo; json2struct(j, sysinfo); if (sysinfo.MemTotal >= dst_mem && sysinfo.DiskTotal >= dst_disk) { ret_code = true; } std::string notify_info = "内存总量: " + std::to_string(sysinfo.MemTotal / 1024.0 / 1024.0 / 1024.0) + " GB" + " 磁盘总量: " + std::to_string(sysinfo.DiskTotal / 1024.0 / 1024.0) + "GB \r\n" + (ret_code ? " 校验通过\r\n 测试结果已自动更新\r\n" : " 校验不通过\r\n"); m_msg.Put({ TASK_ID_CHECK_HW_CAPACITY,DAT_STRING ,notify_info }, 0); return ret_code; } void G1G2Scanner::init_work_thread() { if (m_work_thread.get() && m_work_thread->joinable()) { m_bwork = false; m_work_thread->join(); } m_bwork = true; m_work_thread.reset(new std::thread(&G1G2Scanner::workrun, this)); if (m_imgprocthread.get() && m_imgprocthread->joinable()) { m_bproc = false; m_paths.ShutDown(); m_imgprocthread->join(); } m_bproc = true; m_imgprocthread.reset(new std::thread(&G1G2Scanner::proc, this, 0)); if (m_msgProcThread.get() && m_msgProcThread->joinable()) { m_bprocmsg = false; m_msg.ShutDown(); m_msgProcThread->join(); } m_bprocmsg = true; m_msgProcThread.reset(new std::thread(&G1G2Scanner::procmsg, this)); } void G1G2Scanner::workrun() { int ret = SCANNER_ERR_OK; while (m_bwork) { unsigned char int_buffer[64]; std::string s_info; memset(int_buffer, 0, sizeof(int_buffer)); { lock_guard m_mtx(m_mtx_usb); int sz = sizeof(int_buffer); ret = m_usb->read_interrupt(int_buffer, &sz); } if (ret == SCANNER_ERR_TIMEOUT) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); continue; } else if (ret != SCANNER_ERR_OK) { cout << "read_interrupt error ret = " << (ret) << endl; break; } else { if (sizeof(int_buffer) == 64) { HGEIntInfo* info = (HGEIntInfo*)int_buffer; switch (info->From) { case HGType::MtBoard: //if(info->Code==) break; case HGType::IMG: { if (is_running() && im_dev_count() > 0) xfer_image(); } break; case HGType::STOPSCAN: break; case HGType::AutoCorrect: if (info->Img_Index != 0) { s_info.resize(info->Img_Index); int len = s_info.length(); m_usb->read_bulk(&s_info[0], &len); m_msg.Put({ TASK_ID_CHECK_IMGS, DAT_FLATINFO ,s_info }, 0); } if (info->Code == 4)//flat done { s_info = "校正完成 \r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS,DAT_FLATINFO ,s_info }, 0); } break; case HGType::FPGA: { if (info->Code == 0x80) { while (get_imgproc_done()) { if (!m_bwork) return; this_thread::sleep_for(chrono::microseconds(30)); } while (im_dev_count()) { if (!m_bwork) return; xfer_image(); } } update_statue(info); } break; case HGType::V4L2: break; case HGType::TESTBOARD: { if (info->Code == 0x10) { s_info = "测试台复位完成\r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS,DAT_STRING ,s_info }, 0); } else if (info->Code == 0x20) { s_info = "测试液晶显示中... \r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS, DAT_STRING ,s_info }, 0); } else if (info->Code == 0x30) { s_info = "板级已更新液晶显示...\r\n 请检查液晶屏显示字体是否完整\r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS, DAT_STRING ,s_info }, 0); } } break; default: break; } } } } } int G1G2Scanner::read_register(int addr, int* val) { int l = sizeof(*val); int ret = m_usb->control_io(0x0c0, USB_REQ_GET_DEV_REGS, addr, 0, val, &l); return ret; } int G1G2Scanner::write_register(int addr, int val) { int l = sizeof(val); int ret = m_usb->control_io(0x040, USB_REQ_SET_DEV_REGS, addr, 0, &val, &l); return ret; } std::string G1G2Scanner::read_file(std::string path) { lock_guard m_mtx(m_mtx_usb); if (m_usb && m_online) { int l = path.size(); auto ret_code = write_register(SR_SET_JSON_PATH, l); if (ret_code != SCANNER_ERR_OK) LOG_INFO(string_format("write_register sr_set_json_path error: %d \n", ret_code)); ret_code = m_usb->write_bulk(&path[0], &l); if (ret_code != SCANNER_ERR_OK) LOG_INFO(string_format("write_bulk last_error: %d \n", ret_code)); int size = 0; ret_code = read_register(SR_GET_JSON_SIZE, &size); if (ret_code != SCANNER_ERR_OK) LOG_INFO(string_format("write_register get_json_size error: %d \n", ret_code)); if (size > 0) { static std::string buff; buff.resize(size); ret_code = write_register(SR_GET_JSON, size); LOG_INFO(string_format("write_register get_json size: %d \n", size)); ret_code = m_usb->read_bulk(&buff[0], &size); if (ret_code != SCANNER_ERR_OK) LOG_INFO(string_format("write_bulk last_error: %d \n", ret_code)); return buff; } } return ""; } int G1G2Scanner::write_file(std::string path, std::string content) { std::lock_guard m_lock(m_mtx_usb); if (m_usb && m_online) { int ret_code = 0; ret_code = write_register(SR_SET_JSON_PATH, path.size()); int len = path.size(); ret_code = m_usb->write_bulk(&path[0], &len); if (ret_code != SCANNER_ERR_OK) LOG_INFO(string_format("write json path failed: %d ,path:%s \n", ret_code, path)); ret_code = write_register(SR_SET_JSON, content.size()); len = content.size(); ret_code = m_usb->write_bulk(&content[0], &len); if (ret_code != SCANNER_ERR_OK) LOG_INFO(string_format("update json failed: %d ,file content length = %d \n", ret_code, len)); } return 0; } int G1G2Scanner::read_data(void* data, int length, int timeout) { if (m_usb && m_online) { timeout = max(1500, timeout); int readed = 0; int reading = 0; const int buffer_size = 512 * 1024; StopWatch sw; while (readed < length) { if (sw.elapsed_ms() < timeout && m_usb && m_online) { reading = max(0, min(length - readed, buffer_size)); auto code = m_usb->read_bulk((unsigned char*)data + readed, &reading); if (code != SCANNER_ERR_OK) { LOG_INFO(string_format("read_data failed: %d \n", code)); } if (reading > 0) { readed += reading; sw.reset(); } } else { LOG_INFO(string_format("read_data timeout: %.2f \n", sw.elapsed_ms())); break; } } return readed; } return 0; } bool G1G2Scanner::is_running() { std::lock_guard m_lock(m_mtx_usb); if (m_usb && m_online) { bool ret = false; int val = 0; int code = read_register(SR_STATUS, &val); val &= 0x3; return val > 0 && val < 4; } return 0; } int G1G2Scanner::im_dev_count() { std::lock_guard m_lock(m_mtx_usb); int ret = 0; if (m_usb && m_online) { read_register(SR_IM_COUNT, &ret); } return ret; } bool G1G2Scanner::is_xferfing() { std::lock_guard m_lock(m_mtx_usb); int ret = 0; if (m_usb && m_online) { read_register(SR_IM_TXING, &ret); } return ret; } void G1G2Scanner::xfer_start() { auto ret = write_register(8, 1); if (ret != SCANNER_ERR_OK) LOG_INFO(string_format("xfer_start error:%d \n", ret)); } void G1G2Scanner::xfer_image() { if (is_xferfing()) { std::cout << "is_xferfing return now" << std::endl; LOG_INFO("is_xferfing return now\n"); return; } std::shared_ptr> buffi(new std::vector); int data_size = get_image_size(); int rcv_size = 0; buffi->resize(data_size); xfer_start(); std::this_thread::sleep_for(std::chrono::milliseconds(50)); rcv_size = read_data(buffi->data(), data_size, data_size / (0.005 * 1024 * 1024)); LOG_INFO(string_format("xfer_image %d ,total len =%d \n",++img_index, rcv_size)); imgs.Put(buffi, buffi->size(), 0); popimage(); } int G1G2Scanner::get_image_size() { std::lock_guard m_lock(m_mtx_usb); int len; read_register(SR_IM_FRONT_SIZE, &len); return len; } int G1G2Scanner::get_imgproc_done() { std::lock_guard m_lock(m_mtx_usb); int len; read_register(SR_GET_IMAGEPROCESSDONE, &len); return len; } void G1G2Scanner::popimage() { std::lock_guard m_lock(m_mtx_usb); int ret = 0; if (m_usb && m_online) { write_register(SR_IM_POP, 1); } } void G1G2Scanner::get_cur_dir(std::string& dir) { dir = std::filesystem::current_path().u8string(); } void G1G2Scanner::proc(bool bcachemode) { std::string cur_dir = get_moudle_path(); cur_dir = cur_dir.substr(0, cur_dir.find_last_of("\\/")); cur_dir += "\\CacheImage\\"; LOG_INFO(string_format("current cache dir:%s \n", cur_dir.c_str())); while (m_bproc) { if (imgs.Size() == 0) { this_thread::sleep_for(chrono::milliseconds(10)); continue; } auto img_data = imgs.Take(); static int idx_image = 0; std::string filename = cur_dir+std::to_string(++idx_image) + ".jpg"; LOG_INFO(string_format("cache file:%s \n", filename.c_str())); std::string notify_info; std::ofstream o(filename, std::ios::binary | std::ios::app); if (o.is_open()) { o.write(img_data->data(), img_data->size()); o.close(); m_msg.Put({ TASK_ID_CHECK_IMGS, DAT_IMAGE_PATH ,filename }, 0); m_paths.Put(filename, filename.size()); cv::Mat mat = cv::imdecode(*img_data.get(),cv::IMREAD_ANYCOLOR); if (!mat.empty()) { notify_info += filename + " \r\n"; auto is_continuos = LineContinuityAndRGBDetection::isContinuous(mat); notify_info += is_continuos ? " 条带连续性检测:通过\r\n":" 条带连续性检测:异常,不通过\r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS, DAT_STRING,notify_info },0); if (mat.channels() == 3) { notify_info = ""; auto detect = LineContinuityAndRGBDetection::RGB_Judge(mat); if (detect > 0) { notify_info += GET_BIT(detect, 0) == 1 ? "检测到->红通道 \r\n":"未检测到红通道 \r\n"; notify_info += GET_BIT(detect, 1) == 1 ? "检测到->绿通道 \r\n" : "未检测到绿通道 \r\n"; notify_info += GET_BIT(detect, 2) == 1 ? "检测到->蓝通道 \r\n" : "未检测到蓝通道 \r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS ,DAT_STRING ,notify_info }, 0); notify_info = ""; if (detect == 7) { notify_info = " 颜色检测参考结果: 通过 \r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS ,DAT_STRING ,notify_info }, 0); } else { notify_info = " 颜色检测参考结果: 不通过,请人工校验 \r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS ,DAT_STRING ,notify_info }, 0); } } } } else { notify_info = " 图像解码失败!!! \r\n"; m_msg.Put({ TASK_ID_CHECK_IMGS ,DAT_STRING ,notify_info }, 0); LOG_INFO(string_format("decode error,empty mat, filename:%s \n", filename.c_str())); } } } } void G1G2Scanner::procmsg() { while (m_bprocmsg) { if (m_msg.Size() == 0) { std::this_thread::sleep_for(std::chrono::milliseconds(2)); continue; } auto call_info = m_msg.Take(); if (call_info.msg.length()) { if (m_callback) { m_callback(call_info.id, call_info.type, call_info.msg.length(), &call_info.msg[0], m_user); LOG_INFO(call_info.msg); std::this_thread::sleep_for(std::chrono::milliseconds(2));//以防界面更新过快 } } } } int G1G2Scanner::update_statue(HGEIntInfo* info) { std::string msg_info; switch (info->Code) { case 0x10: { msg_info = "开始自动校正... \r\n"; } break; case 0x20: { msg_info = "自动校正完成... \r\n"; } break; case 0x30: { msg_info = "开始自动采集300DPI 灰度图像中... \r\n"; } break; case 0x40: { msg_info = "开始自动采集300DPI 彩色图像中... \r\n"; } break; case 0x50: { msg_info = "开始自动采集600DPI 灰度图像中... \r\n"; } break; case 0x60: { msg_info = "开始自动采集600DPI 彩色图像中... \r\n"; } break; case 0x80: { msg_info = "开始自动采集图像已完成,请确认图像 \r\n"; } break; default: msg_info = "未知消息"; break; } m_msg.Put({ TASK_ID_CHECK_IMGS, DAT_STRING ,msg_info }, 0); return 0; }