g1g2hardwarechecker/Scanner/G1G2Scanner.cpp

757 lines
18 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "G1G2Scanner.h"
#include <3rdparty/comm/hgscanner_error.h>
#include "json.hpp"
#include <algorithm>
#include <StopWatch.h>
#include <iostream>
#include <fstream>
#include <filesystem>
#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<mutex> m_mtx(m_mtx_usb);
m_online = false;
m_usb->on_disconnected();
}
void G1G2Scanner::Reboot(bool b_loader)
{
lock_guard<mutex> m_mtx(m_mtx_usb);
if (m_usb && m_online)
{
write_register(SR_REBOOT, b_loader ? 1 : 0);
}
}
void G1G2Scanner::PowerOFF()
{
lock_guard<mutex> 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<mutex> 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<mutex> 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<mutex> 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<mutex> 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<mutex> 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<mutex> 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<mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::vector<char>> buffi(new std::vector<char>);
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<std::mutex> m_lock(m_mtx_usb);
int len;
read_register(SR_IM_FRONT_SIZE, &len);
return len;
}
int G1G2Scanner::get_imgproc_done()
{
std::lock_guard<std::mutex> m_lock(m_mtx_usb);
int len;
read_register(SR_GET_IMAGEPROCESSDONE, &len);
return len;
}
void G1G2Scanner::popimage()
{
std::lock_guard<std::mutex> 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;
}