tx-gxx-linux/device/gxx-linux/scanner/scanner.cpp

826 lines
20 KiB
C++
Raw 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 "scanner.h"
#include <iostream>
#include "motorboard.h"
#include "Capturer.h"
#include <opencv2/opencv.hpp>
#include "StopWatch.h"
#include "iimagehandler.h"
#include "applog.h"
#include "stringex.hpp"
#include "fpgacontrol.h"
#include "scannerregs.h"
#include "fpgacontrol.h"
#include "Gpio.h"
#include "deviceconfig.h"
#include <openssl/md5.h>
#include <openssl/aes.h>
#include <random>
#include <stdlib.h>
static const std::string loggername = "Scanner";
Scanner::Scanner(std::shared_ptr<ICapturer> capturer, std::shared_ptr<MotorBoard> mb, std::shared_ptr<WakeUp> wake)
: bMsgLoop(true),
scancount(1024)
// testGpio(new Gpio(153))
{
LOG_INIT();
this->wake = wake;
this->mb = mb;
this->capturer = capturer;
// threadRunMessageLoop = std::move(std::thread(&Scanner::runMessageLoop, this));
auto mb_error_call = [&](unsigned int error_code)
{
int code = 0;
LOG_TRACE(string_format("motorboard callback mb_error_call error code = %08x \n", error_code));
if (error_code & 0x2)
{
code = 2;
LOG_TRACE("callback NO FEED\n");
}
else if (error_code & 0x4)
{
code = 4;
LOG_TRACE("callback COVER OPEN\n");
}
else if (error_code & 0x8)
{
code = 0x8;
LOG_TRACE("callback FEED IN ERROR\n");
}
else if (error_code & 0x10)
{
code = 0x10;
LOG_TRACE("callback PAPER JAM\n");
}
else if (error_code & 0x20)
{
code = 0x20;
LOG_TRACE("callback DOUBLE FEED\n");
}
else if (error_code & 0x40)
{
code = 0x40;
LOG_TRACE("callback STABLE\n");
}
else if (error_code & 0x80)
{
code = 0x80;
LOG_TRACE("callback SKEW\n");
}
else if (error_code & 0x00010000)
{
code = 0x10000;
LOG_TRACE("callback AQUIREIMAGE TIMEOUT\n");
}
else if (error_code & 0x00020000)
{
code = 0x20000;
LOG_TRACE("callback SIZE ERROR\n");
}
mb_error_code = code;
printf("---------------mb_error_code value = %d ---------------\n", code);
if (code != 0)
{
HGIntInfo errType = {.From = MtBoard, .Code = code};
imagehandler->add_scanevent(errType);
done_scan = 1;
}
mb_error_code = code;
if (code != 0)
done_scan = 1;
};
auto mb_scandone_call = [&]()
{
done_scan = 1;
printf("motorboard callback scan_done");
};
auto mb_osmode_call = [&](unsigned int osmode)
{
done_scan = 1;
printf("motorboard callback mb_osmode_call changed");
};
auto mb_set_sleeptime_call = [&](unsigned int speedmode)
{
printf("\n mb_set_sleeptime_call val= %d ", speedmode);
switch (speedmode & 0xf000)
{
case 0xf000:
set_sleeptime(240 * 60);
break;
case 0x7000:
set_sleeptime(20 * 60);
break;
case 0xd000:
set_sleeptime(120 * 60);
break;
case 0xb000:
set_sleeptime(60 * 60);
break;
case 0x9000:
set_sleeptime(30 * 60);
break;
case 0x3000:
set_sleeptime(5 * 60);
break;
case 0x1000:
set_sleeptime(-1);
break;
case 0x5000:
set_sleeptime(10 * 60);
break;
default:
break;
}
};
auto mb_mltop_call = [&](unsigned int value)
{
if (value & 0x00080000)
is_ml_top = true; //升降台到<E58FB0>?
};
auto mb_auto_paper = [&](unsigned int value)
{
printf("连续扫描模式检测到有纸");
if (is_runscan())
return;
start_scan();
};
MotorBoardGlue mb_glue = {mb_error_call, mb_scandone_call, mb_osmode_call, mb_set_sleeptime_call, mb_mltop_call, mb_auto_paper};
mb->set_callbacks(mb_glue);
mb->set_capture(capturer);
scannerinfo = getscannerinfo();
auto capturecallback = [&](int cap_call_code, std::string s_info)
{
HGIntInfo info = {.From = AutoCorrect, .Code = cap_call_code, .Img_Index = s_info.length()};
imagehandler->add_scanevent(info);
if (s_info.length() > 0)
((ScannerRegAccess *)m_parent)->write_info(s_info);
};
this->capturer->setcapturecall(capturecallback);
mb->set_auto_paper(m_config.g200params.is_autopaper); //防止程序异常死掉后未关闭连续扫描导致升降台抬升扫<E58D87>?
u32 value;
mb->read(0x00, value);
printf("mb reg[0] = 0x%x \n", value);
value = 0;
mb->read(0x03, value);
if (value >= 35211210)
m_mbver = MotorVersion::Motor_paperout;
else if(value >= 35211126)
m_mbver = MotorVersion::Motor_mltop;
else
m_mbver = MotorVersion::Motor_old;
mbversion = std::to_string(value);
printf("mb reg[3] = 0x%x \n", value);
// capturer->open();
}
Scanner::~Scanner()
{
bMsgLoop = false;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
sysEvent.Put(ScanEvent::S_EVT_STOP_SCAN);
if (threadRunMessageLoop.joinable())
threadRunMessageLoop.join();
}
void Scanner::try_scan(const std::string encodehexstr)
{
bool is_scan = true;
printf("\n encodehexstr = ");
for(int i =0;i<encodehexstr.length();i++)
printf(" %x",encodehexstr[i]);
if(DeviceConfig().GetParam().is_lock)
{
auto tmp_token = DeviceConfig().GetParam().token;
if((encodehexstr.length() != 32) || (tmp_token.length() !=32))
is_scan = false;
else{
AES_KEY aes_key;
std::uint8_t key[16] ={0};
//tmp_token = "C34E58CD5F3F2FF703E1AA24892FBD69";
printf("tmp_token %s",tmp_token);
for(int i =0;i<16;i++)
{
key[i] = std::strtol(tmp_token.substr(i*2,2).c_str(),nullptr,16);
}
if(AES_set_decrypt_key(key,128,&aes_key)< 0)
{
is_scan = false;
}
std::uint8_t cipher[16] ={0};
std::uint8_t decode[16] ={0};
for(int i =0;i<16;i++)
{
cipher[i] = std::strtol(encodehexstr.substr(i*2,2).c_str(),nullptr,16);
}
AES_ecb_encrypt(cipher,decode,&aes_key,AES_DECRYPT);
for(int i =0;i<scannerinfo.SerialNum.length();i++)
{
if(decode[i]!= scannerinfo.SerialNum[i])
{
is_scan = false;
break;
}
if(i == (scannerinfo.SerialNum.length() - 1 ))
is_scan = true;
}
printf("\n decode %s",(char*)decode);
}
// tmp += scannerinfo.SerialNum;
// uchar md5[MD5_DIGEST_LENGTH];
// MD5_CTX ctx;
// MD5_Init(&ctx);
// MD5_Update(&ctx,tmp.c_str(),tmp.size());
// MD5_Final(md5,&ctx);
// printf("\n md5 = %s",md5);
// std::string md5_hex;
// const char map[]="0123456789abcdef";
// for(size_t i=0;i < MD5_DIGEST_LENGTH; i++)
// {
// md5_hex+=map[md5[i] /16];
// md5_hex+=map[md5[i] %16];
// }
// if(md5_hex.compare(encodehexstr.c_str()) != 0)
// is_scan = false;
//printf("\naes hex= %s",decode);
}
if(is_scan)
start_scan();
else
{
imagehandler->add_scanevent({.From = MtBoard, 0x100});
if (m_config.g200params.is_autopaper)
imagehandler->add_scanevent({.From = STOPSCAN, 1});
imagehandler->add_scanevent({.From = STOPSCAN, 0});
}
}
std::string Scanner::getmbversion()
{
return mbversion;
}
void Scanner::add_scansever(HGIntInfo event)
{
if (imagehandler.get())
imagehandler->add_scanevent(event);
}
bool Scanner::set_hgimgconfig(GScanCap config)
{
printf("enter config set_hgimgconfig \n");
scancount = config.is_duplex ? config.scannum / 2 : config.scannum;
m_cap = config;
if (imagehandler.get())
{
imagehandler->clear();
return imagehandler->set_config(config);
}
return false;
}
void Scanner::configparam(HGScanConfig config)
{
LOG_TRACE(string_format("******HGScanConfig******\n config.g200params.color = %d \n config.g200params.dpi = %d \n config.g200params.paper =%d \n config.g200params.double_feed_enbale = %d \n config.g200params.stable_enbale = %d \n config.g200params.iscorrect_mode = %d \n config.g200params.pc_correct = %d\n ",
config.g200params.color,
config.g200params.dpi,
config.g200params.paper,
config.g200params.double_feed_enbale,
config.g200params.stable_enbale,
config.g200params.iscorrect_mode,
config.g200params.pc_correct));
printf("******HGScanConfig******\n config.g200params.color = %d \n config.g200params.dpi = %d \n config.g200params.paper =%d \n config.g200params.double_feed_enbale = %d \n config.g200params.stable_enbale = %d \n config.g200params.iscorrect_mode = %d \n config.g200params.pc_correct = %d\n ",
config.g200params.color,
config.g200params.dpi,
config.g200params.paper,
config.g200params.double_feed_enbale,
config.g200params.stable_enbale,
config.g200params.iscorrect_mode,
config.g200params.pc_correct);
imagehandler->set_scanconfig(config);
m_config = config;
if (config.g200params.iscorrect_mode)
{
scancount = 65535;
}
}
void Scanner::start_scan()
{
printf("\n ------------------start_scan------------------ \n");
if (is_runscan())
return;
if (wake.get())
wake->setsleepfalg(true);
mb_error_code = is_ml_top = handstop = false;
capturer->open(m_config);
scannerinfo = getscannerinfo();
int spdmode = 0;
if (scannerSp.count((SpeedMode)scannerinfo.speedmode) <= 0)
{
#ifdef G200
spdmode = 0x00; // 100ppm
#else
spdmode = 0x01; // 70ppm
#endif
}
else
{
spdmode = scannerSp[(SpeedMode)scannerinfo.speedmode].motorSpeed;
}
mb->set_speed_mode(spdmode);
imagehandler->Set_ratio(scannerinfo.H_ratio,scannerinfo.V_ratio);
printf("\n set speedmode %d read speedmode %d", spdmode, mb->get_speed_mode());
// capturer->open();
imagehandler->resetimgstatus();
mb->clear_error();
fu_runscan.reset(new ThreadEx(&Scanner::runScan, this));
}
void Scanner::stop_scan()
{
mb->stop();
handstop = true;
if (m_config.g200params.is_autopaper == 1)
mb->set_auto_paper(false);
}
int Scanner::count()
{
return mb->paper_counter();
}
int Scanner::mode()
{
return mb->os_mode();
}
int Scanner::getimageprocedone()
{
if (imagehandler.get())
return imagehandler->done();
return true;
}
int Scanner::getmbstatus()
{
mb->clear_error();
uint val = 0;
mb->read(0x01, val);
printf("\n scan stop code =%d ", val & 0x700fe);
return val & 0x700fe;
}
void Scanner::test_autocorrect(int colormode)
{
printf("color mode =%s \n", colormode == 1 ? "COLOR" : "GRAY");
capturer->init_autocorrect(colormode);
}
bool Scanner::is_runscan()
{
return (fu_runscan && fu_runscan->is_runing()) || (imagehandler && !imagehandler->done());
}
void Scanner::set_imagehandler(std::shared_ptr<IImageHandler> handler)
{
imagehandler = handler;
}
void Scanner::clear_error()
{
mb->clear_error();
}
void Scanner::runMessageLoop()
{
FsmState *fsmState = FsmStateManagerEx<InitState>::GetState();
FsmState::setScanner(this);
do
{
ScanEvent evt = sysEvent.Take();
fsmState = fsmState->on_event(evt);
} while (bMsgLoop);
}
bool Scanner::paper_ready()
{
return mb->paper_ready();
}
bool Scanner::get_keeplastpaper()
{
return mb->get_keeplastpaper();
}
void Scanner::startcapimage()
{
FILE * fp =fopen("/sys/class/tty/ttyUSB0/device/huagao_scanner","w");
if (fp == NULL)
perror("startcapimage open filed");
else
fprintf(fp,"%d",1);
fclose(fp);
}
static int pickpapernum = 0;
void Scanner::runScan()
{
pickpapernum = 0;
// system("sudo cpufreq-set -g performance");
system("echo performance > /sys/devices/system/cpu/cpu5/cpufreq/scaling_governor");
LOG_TRACE("+++++++scanner runinng+++++++++++++\n");
mb->clear_error();
unsigned int val;
mb->set_double_inpect(m_config.g200params.double_feed_enbale);
mb->set_staple_inpect(m_config.g200params.stable_enbale);
// mb->set_paper_inspect(m_config.g200params.enable_sizecheck);
mb->set_auto_paper(m_config.g200params.is_autopaper);//m_config.g200params.is_autopaper
mb->set_screw_inpect(m_config.g200params.screw_detect_enable);
mb->set_screw_level(m_config.g200params.screw_detect_level);
mb->set_long_paper(m_config.g200params.paper);
//mb->set_cuospeed(41);
mb->start();
mb->read(0x01, val);
if ((val & 0x700fe) > 0)
{
if ((val & 0x700fe) == 0x14)
{
imagehandler->add_scanevent({.From = MtBoard, .Code = 4});
LOG_TRACE("\nCover Open status");
imagehandler->add_scanevent({.From = STOPSCAN, 0});
}
if (m_config.g200params.is_autopaper)
{
imagehandler->add_scanevent({.From = STOPSCAN, 1});
mb->set_auto_paper(false);
}
imagehandler->add_scanevent({.From = MtBoard, .Code = val & 0x700fe});
printf("\n scan stop code =%d ", val & 0x700fe);
}
else
{
#ifdef G200
if ((int)m_mbver > 0)
{
StopWatch top_wh;
while (top_wh.elapsed_s() < 10)
{
if (is_ml_top || mb_error_code || handstop)
break;
this_thread::sleep_for(chrono::milliseconds(1));
}
if (!is_ml_top || mb_error_code || handstop)
{
if (mb_error_code == 0 && handstop == 0) // 无其他异常时发送升降台未到达指定位置异<E7BDAE>?
{
imagehandler->add_scanevent({.From = MtBoard, 0x80000});
if (m_config.g200params.is_autopaper)
mb->set_auto_paper(false);
}
capturer->stop();
capturer->close();
capturer->reset();
this_thread::sleep_for(chrono::milliseconds(20));
imagehandler->add_scanevent({.From = STOPSCAN, 0});
return;
}
}
else
this_thread::sleep_for(chrono::milliseconds(2500));
#endif
done_scan = 0;
if((int)m_mbver > 1)
scanpaperout();
else
scanold();
}
this_thread::sleep_for(chrono::milliseconds(1000));
if (wake.get())
{
wake->resettime();
wake->setsleepfalg(false);
}
capturer->reset();
imagehandler->add_scanevent({.From = STOPSCAN, 0});
if ((mb_error_code != 0 || imagehandler->getimgstatus().status != NO_error ) && m_config.g200params.is_autopaper)
mb->set_auto_paper(false);
printf("\n-------scanner done-------\n");
}
void Scanner::set_motorboardcallback(MotorBoardGlue glue)
{
mb->set_callbacks(glue);
}
void Scanner::set_imgprocparams(HGImgProcParms params)
{
imagehandler->config_procparams(params);
}
void Scanner::test_cap(HGScanConfig config)
{
printf("capturer openning \n");
capturer->open(config);
capturer->snap();
void *data;
if (data = capturer->readFrame(2000))
{
int imtype = capturer->color() ? CV_8UC3 : CV_8UC1;
cv::Mat mat;
cv::Mat saveMat;
std::vector<cv::Mat> ch_mats;
int dstwidth, dstheight;
int width = capturer->width();
int height = capturer->height();
dstwidth = width * 3;
dstheight = height / 3;
if (imtype == CV_8UC3)
{
mat = cv::Mat(height / 3, width * 9, CV_8UC1, data);
saveMat = cv::Mat(dstheight, dstwidth, CV_8UC3);
}
else
{ // gray
saveMat = cv::Mat(height, width * 3, CV_8UC1, data);
}
static int savenum;
if (imtype == CV_8UC3)
{
for (int i = 0; i < 3; i++)
{ // B G R
cv::Mat mattemp = mat(cv::Rect(dstwidth * i, 0, dstwidth, dstheight));
ch_mats.push_back(mattemp);
}
swap(ch_mats[1], ch_mats[2]);
cv::merge(ch_mats, saveMat);
}
cv::imwrite(std::to_string(++savenum) + ".jpg", saveMat);
}
else
{
printf("LOST Image \n");
}
capturer->close();
printf("capturer closed \n");
}
void Scanner::set_sleeptime(int val)
{
if (wake.get())
wake->settime(val);
}
int Scanner::get_sleeptime()
{
if (wake.get())
return wake->gettime();
return 0;
}
void Scanner::resettime()
{
if (wake.get())
wake->resettime();
}
int Scanner::get_sleepstatus()
{
if (wake.get())
return wake->get_status();
return 0;
}
void Scanner::set_paprent(void *parent)
{
if (parent)
m_parent = parent;
}
void Scanner::set_sleepstatus(bool off)
{
if (wake.get())
{
if (off)
wake->power_on();
else
wake->power_off();
}
}
bool Scanner::getpaperon()
{
if (mb.get())
{
uint val = 0;
mb->read(2, val);
if ((val & 0x10000) && m_config.g200params.is_autopaper)
mb->set_auto_paper(false);
return val & 0x10000;
}
return 0;
}
void Scanner::scanpaperout()
{
StopWatch sw;
StopWatch swCap;
void *data = NULL;
int scannum = 0;
startcapimage();
printf("first page pick paper \n");
for (;;)
{
LOG_TRACE("waiting paper");
if (!done_scan) //
{
//LOG_TRACE(string_format("+++++paper on:%fms+++++++++++ ", swCap.elapsed_ms()));
if (mb->wait_paper_out(3000))
{
HG_LOG("wait_paper_out time =%f \n",sw.elapsed_ms());
sw.reset();
swCap.reset();
if (data = capturer->readFrame(2000))
{
printf("\n readFrame time =%f pickpapernum = %d",swCap.elapsed_ms(),pickpapernum++);
if (imagehandler)
{
imagehandler->add_image(data, capturer->width(), capturer->height() / 3 * 3, capturer->color(), scannum++);
data = NULL;
}
//std::this_thread::sleep_for(std::chrono::milliseconds(100));
swCap.reset();
scannerinfo.RollerNum++;
scannerinfo.TotalScanned++;
LOG_TRACE(string_format("capture one=%fms", swCap.elapsed_ms()));
}
else
{
imagehandler->add_scanevent({.From = V4L2, .Code = 0});
// LOG_TRACE("capture error");
// done_scan = 1;
// capturer->stop();
// mb->stop();
LOG_TRACE("capture error Stop Scan");
break;
}
}
else
{
if (!done_scan)
{
uint value = 0;
mb->read(0x2, value);
if (!(value & 0x20000))//bit 17 scandone
{
done_scan = 1;
LOG_TRACE("---------Time out-----");
}
}
}
}
else
{
break;
}
if (imagehandler->getimgstatus().status != NO_error)
{
mb->stop();
done_scan = 1;
capturer->stop();
LOG_TRACE("imagehandler->getimgstatus().dogear_error ");
break;
}
if ((scancount <= scannum))
{
done_scan = 1;
capturer->stop();
this_thread::sleep_for(chrono::milliseconds(2000));
mb->stop();
break;
}
if (m_cap.resolution_dst >= 400 && papersMap[(PaperSize)m_config.g200params.paper].height <= 8100)
this_thread::sleep_for(chrono::milliseconds(3000));
else if (m_cap.resolution_dst >= 400 && (papersMap[(PaperSize)m_config.g200params.paper].height > 8100 && papersMap[(PaperSize)m_config.g200params.paper].height <= 10800))
this_thread::sleep_for(chrono::milliseconds(5000));
else if (m_cap.resolution_dst >= 400 && papersMap[(PaperSize)m_config.g200params.paper].height > 10800)
this_thread::sleep_for(chrono::milliseconds(8000));
startcapimage();
mb->pick_paper();
printf(" pick_paper time =%f \n", swCap.elapsed_ms());
LOG_TRACE("pick_paper");
}
savescannerinfo(scannerinfo);
while (!imagehandler->done())
this_thread::sleep_for(chrono::milliseconds(10));
capturer->close();
done_scan = 0;
system("sudo cpufreq-set -g ondemand");
// system("sudo echo ondemand > /sys/devices/system/cpu/cpu5/cpufreq/scaling_governor");
LOG_TRACE("-------scanner done-------\n");
}
void Scanner::scanold()
{
StopWatch sw;
StopWatch swCap;
void *data = NULL;
int scannum = 0;
for (;;)
{
LOG_TRACE("waiting paper");
sw.reset();
if (!done_scan && mb->wait_paper_in(1000))
{
printf("wait_paper_in time =%f \n",swCap.elapsed_ms());
//testGpio->setValue(Gpio::High);
LOG_TRACE(string_format("+++++paper on:%fms+++++++++++ ", swCap.elapsed_ms()));
capturer->snap();
//testGpio->setValue(Gpio::Low);
swCap.reset();
if (data = capturer->readFrame(2000))
{
printf("readFrame time =%f \n",swCap.elapsed_ms());
swCap.reset();
if (imagehandler)
{
imagehandler->add_image(data, capturer->width(), capturer->height() / 3 * 3, capturer->color(), scannum++);
data = NULL;
}
LOG_TRACE(string_format("readFrame time =%f ",swCap.elapsed_ms()));
printf("addimage time =%f \n",swCap.elapsed_ms());
swCap.reset();
scannerinfo.RollerNum++;
scannerinfo.TotalScanned++;
}
else
{
imagehandler->add_scanevent({.From = V4L2, .Code = 0});
LOG_TRACE("capture error");
}
swCap.reset();
}
else if (done_scan)
{
break;
}
else
{
if (!done_scan)
{
uint value = 0;
mb->read(0x2, value);
if (!(value & 0x20000))//bit 17 scandone
{
printf("\n mb 02 reg value =%d ",value);
done_scan = 1;
LOG_TRACE("---------Time out-----");
break;
}
}
}
if (imagehandler->getimgstatus().status != NO_error)
{
mb->stop();
done_scan = 1;
capturer->stop();
LOG_TRACE("imagehandler->getimgstatus().dogear_error ");
break;
}
if ((scancount <= scannum))
{
done_scan = 1;
capturer->stop();
this_thread::sleep_for(chrono::milliseconds(2000));
mb->stop();
break;
}
if(m_cap.resolution_dst>=400 && papersMap[(PaperSize)m_config.g200params.paper].height<=8100)
this_thread::sleep_for(chrono::milliseconds(3000));
else if(m_cap.resolution_dst>=400 && (papersMap[(PaperSize)m_config.g200params.paper].height>8100&&papersMap[(PaperSize)m_config.g200params.paper].height<=10800))
this_thread::sleep_for(chrono::milliseconds(5000));
else if(m_cap.resolution_dst>=400 && papersMap[(PaperSize)m_config.g200params.paper].height>10800)
this_thread::sleep_for(chrono::milliseconds(8000));
mb->pick_paper();
swCap.reset();
LOG_TRACE("pick_paper");
}
savescannerinfo(scannerinfo);
while(!imagehandler->done())
this_thread::sleep_for(chrono::milliseconds(10));
capturer->close();
done_scan = 0;
system("sudo cpufreq-set -g ondemand");
//system("sudo echo ondemand > /sys/devices/system/cpu/cpu5/cpufreq/scaling_governor");
}