From 258a480bff5caaaf6a0a0a610e624526d39cbcdb Mon Sep 17 00:00:00 2001 From: luoliangyi <87842688@qq.com> Date: Wed, 17 May 2023 15:37:04 +0800 Subject: [PATCH] =?UTF-8?q?websdk=EF=BC=9A=201=EF=BC=89=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=98=AF=E5=90=A6=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E5=92=8C=E6=98=AF=E5=90=A6=E6=AD=A3=E5=9C=A8=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E7=9A=84=E6=8E=A5=E5=8F=A3=202=EF=BC=89=E5=BD=93=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E8=BF=9E=E6=8E=A5=E6=97=B6=EF=BC=8C=E5=90=AF=E5=8A=A8?= =?UTF-8?q?10=E5=88=86=E9=92=9F=E5=AE=9A=E6=97=B6=E5=99=A8=EF=BC=8C?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/demo/mainwindow.cpp | 48 ++++++++++++++++++ build2/qt/HGDemo/HGDemo.pro | 2 +- build2/qt/HGVersion/HGVersion.pro | 7 ++- doc/webservice/新版websdk接口说明.doc | Bin 344717 -> 352009 bytes modules/base/HGInfoImpl.cpp | 3 +- modules/version/HGVersionImpl.cpp | 19 +++---- sdk/webservice/ManagerV2.cpp | 57 +++++++++++++++++++++ sdk/webservice/ManagerV2.h | 8 +++ sdk/webservice/Msg.h | 10 +++- sdk/webservice/MsgPumpCallback.cpp | 7 +++ sdk/webservice/WSUser.cpp | 70 ++++++++++++++++++++++++++ sdk/webservice/WSUser.h | 2 + test/webservice/demo.html | 24 +++++++++ 13 files changed, 242 insertions(+), 15 deletions(-) diff --git a/app/demo/mainwindow.cpp b/app/demo/mainwindow.cpp index f1d49353..910b9c31 100644 --- a/app/demo/mainwindow.cpp +++ b/app/demo/mainwindow.cpp @@ -1,6 +1,11 @@ #include "mainwindow.h" #include "ui_mainwindow.h" #include "imgfmt/HGImgFmt.h" +#include +#include +#include +#include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -39,6 +44,7 @@ void MainWindow::on_newImage(void *image) void MainWindow::on_pushButton_selectDev_clicked() { +#if 1 if (nullptr != m_devUser) { disconnect(m_devUser, SIGNAL(newImage(void*)), this, SLOT(on_newImage(void*))); @@ -54,6 +60,48 @@ void MainWindow::on_pushButton_selectDev_clicked() connect(m_devUser, SIGNAL(newImage(void*)), this, SLOT(on_newImage(void*))); ui->label_currDevName->setText(m_devUser->GetName()); } +#else + QString filePath("D:\\1.jpg"); + QFileInfo info(filePath); + QFile *file = new QFile(filePath); + file->open(QIODevice::ReadOnly); + + QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + + QHttpPart filePart; + filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"123456.jpg\"")); + filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + filePart.setBodyDevice(file); + multiPart->append(filePart); + + QHttpPart machinePart; + machinePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"machine\"")); + machinePart.setBody(QByteArray("M2")); + multiPart->append(machinePart); + + QHttpPart submitPart; + submitPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"submit\"")); + submitPart.setBody(QByteArray("Submit")); + multiPart->append(submitPart); + + QNetworkRequest request; + request.setUrl(QUrl("http://47.104.31.27:8500/v1/api/file/upload")); + QNetworkAccessManager *accessManager = new QNetworkAccessManager(this); + QNetworkReply *reply = accessManager->post(request, multiPart); + + multiPart->setParent(reply); + QEventLoop loop; + QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); + loop.exec(); + + QString s = QString(reply->readAll()); + qDebug(s.toStdString().c_str()); + + file->close(); + reply->abort(); + accessManager->deleteLater();//不主动释放会在卸载DLL时造成耗时 + accessManager=NULL; +#endif } void MainWindow::on_pushButton_setting_clicked() diff --git a/build2/qt/HGDemo/HGDemo.pro b/build2/qt/HGDemo/HGDemo.pro index 5ce5ec1d..3c991a8b 100644 --- a/build2/qt/HGDemo/HGDemo.pro +++ b/build2/qt/HGDemo/HGDemo.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets diff --git a/build2/qt/HGVersion/HGVersion.pro b/build2/qt/HGVersion/HGVersion.pro index 95038b09..805de7e5 100644 --- a/build2/qt/HGVersion/HGVersion.pro +++ b/build2/qt/HGVersion/HGVersion.pro @@ -101,6 +101,7 @@ unix { } INCLUDEPATH += $$PWD/../../../third_party/json +INCLUDEPATH += $$PWD/../../../utility DESTDIR = $$PWD/../../build/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE} UI_DIR = $$PWD/../../temp/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE}/$${TARGET} @@ -172,10 +173,12 @@ unix { SOURCES += \ ../../../modules/version/HGVersion.cpp \ ../../../modules/version/HGVersionImpl.cpp \ - ../../../third_party/json/cJSON.c + ../../../third_party/json/cJSON.c \ + ../../../utility/HGString.cpp HEADERS += \ ../../../modules/version/HGVersion.h \ ../../../modules/version/HGVersionImpl.hpp \ ../../../modules/version/HGVersionMsg.hpp \ - ../../../third_party/json/cJSON.h + ../../../third_party/json/cJSON.h \ + ../../../utility/HGString.h diff --git a/doc/webservice/新版websdk接口说明.doc b/doc/webservice/新版websdk接口说明.doc index 7b1b6e2cd2faa42b489dd042a73abc0513306928..1e328964a3c2fa233b9f6e40407d4c41dc22e127 100644 GIT binary patch delta 29805 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 F{yz>lXBGee delta 28705 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�kWFksEoGbD-Pv z%0GS9Swe`5AmPIjD=cxs5(g}yyV+)~g8@cmX*9Jokdoom_m zAi<^?wKv~uG{{xG{agvs{#5LI5SG&-Yyx9}<=q`mXJ=Bw25dfzV4M#mAT9+Gp(YV&5_u-EWD-Y~`Td)!jfOin zs)3ozlejVo2$R4s3Gk9YE{V#Lh%0k+mF;KU9XM@Bz?C)FN&>AU$V#H7H1DxBAi+(w zn0!wSUQ<5f`b*p8A5mXURQ{u>Q%MdWXVvF(4xf9(S;CVfuBv43Vex$2d0(2zQ zMq+6qn{5{*Rt{kamXTg$iENRcWC=%+uoDR)kpL129+~^0?Z=Y%Sg^#BXbij^VMswO zmSGL3Fb7lIeDouyEbGo85f=xLNQ;mkaXdkS9wcHxq7WpOAgkr3BFjlj0s^EzTb|*| z)A)o|?i7#;dD1S=%*R@7KbE6>Tl*6GxZPFl)&He1HPjA z{SUc>%Q3NeTPcqLMB%wxrRt0jGWKq6fLJwIUmZ&P0mGfPLTs&4q!PN<>-+^LH29e9cAB= z=Ogl4%kLu3L7Y0w&j!|iqCOPk5Nv!y=WwF^n4O#D;QV!>aUj;gSNnS(d~DzmDbt!} z$p5w66HoAeHK+dF6AquY`=!0nF3!Qr?%}WezD6VDKP~^WzPA3=8~-rg;lF8(o(T?Z zTI2B34sG|S3C}z18AJ6BHTK5Q7afA^jN4ywFlg1%mmHegvmB~|Wht#s #endif +#include "HGString.h" struct VersionInfoImpl { @@ -74,7 +75,7 @@ static HGResult GetServerConfig(HGServerConfig& config) else { std::string str_json = out.str(); // 返回值 - HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", Utf8ToStdString(str_json).c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (NULL != json) @@ -158,7 +159,7 @@ static HGResult CrashFileUpload(const std::string& crashFilePath, std::string& c else { std::string str_json = out.str(); // 返回值 - HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", Utf8ToStdString(str_json).c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (NULL != json) @@ -596,7 +597,7 @@ static HGResult PostInfo(int type, const std::string& appName, const std::string else { std::string str_json = out.str(); // 返回值 - HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", Utf8ToStdString(str_json).c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (NULL != json) @@ -703,7 +704,7 @@ static HGResult PostDeviceInfo(const std::string& devName, const std::string& de else { std::string str_json = out.str(); // 返回值 - HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", Utf8ToStdString(str_json).c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (NULL != json) @@ -801,7 +802,7 @@ static HGResult PostDeviceLockInfo(const std::string& devName, const std::string else { std::string str_json = out.str(); // 返回值 - HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", Utf8ToStdString(str_json).c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (NULL != json) @@ -906,7 +907,7 @@ static HGResult PostUserInfo(const std::string& appName, const std::string& oemN else { std::string str_json = out.str(); // 返回值 - HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", Utf8ToStdString(str_json).c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (NULL != json) @@ -970,7 +971,7 @@ static HGResult GetVersionList(const std::string& appName, const std::string& oe else { std::string str_json = out.str(); // 返回值 - HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", Utf8ToStdString(str_json).c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (NULL != json) @@ -1592,7 +1593,7 @@ HGResult HGVersionMgrImpl::BlackListCheck(const HGChar* devSN, HGBool* inList) else { std::string str_json = out.str(); // 返回值 - HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", str_json.c_str()); + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "str_json=%s", Utf8ToStdString(str_json).c_str()); cJSON* json = cJSON_Parse(str_json.c_str()); if (NULL != json) @@ -1657,7 +1658,7 @@ static HGResult GetDriverVersionList(const std::string& devType, std::listmgr); + + std::string errInfo; + DeinitDevice(errInfo); + } + void ManagerV2::CloseDev(const CloseDevParam* param) { assert(NULL != param && this == param->mgr); @@ -210,6 +232,8 @@ namespace ver_2 assert(NULL != user); HGBase_EnterLock(m_lock); m_user.push_back(user); + m_timeout = 0xFFFFFFFF; + HGBase_SetEvent(m_event); HGBase_LeaveLock(m_lock); } @@ -223,6 +247,12 @@ namespace ver_2 if (*iter == user) { m_user.erase(iter); + if (m_user.empty()) + { + m_timeout = 1000 * 10 * 60; + HGBase_SetEvent(m_event); + } + break; } } @@ -4202,4 +4232,31 @@ namespace ver_2 return 0; } + + void HGAPI ManagerV2::ThreadFunc(HGThread thread, HGPointer param) + { + ManagerV2 *p = (ManagerV2 *)param; + while (!p->m_stopThread) + { + HGBase_EnterLock(p->m_lock); + HGUInt timeout = p->m_timeout; + HGBase_LeaveLock(p->m_lock); + HGResult ret = HGBase_WaitEventTimeout(p->m_event, timeout); + if (HGBASE_ERR_TIMEOUT == ret) + { + HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "timeout, deinit device"); + + DeinitDevParam* deinitDevParam = new DeinitDevParam; + deinitDevParam->mgr = p; + + HGMsg msg; + msg.id = MSGID_DEINIT_DEVICE; + msg.data = deinitDevParam; + if (HGBASE_ERR_OK != HGBase_PostPumpMessage(p->m_msgPump, &msg)) + { + delete deinitDevParam; + } + } + } + } } diff --git a/sdk/webservice/ManagerV2.h b/sdk/webservice/ManagerV2.h index 841001a8..6e48e4b2 100644 --- a/sdk/webservice/ManagerV2.h +++ b/sdk/webservice/ManagerV2.h @@ -6,6 +6,7 @@ #include "base/HGImage.h" #include "base/HGMsgPump.h" #include "base/HGEvent.h" +#include "base/HGThread.h" #include "sane/sane_ex.h" #include "sane/sane_option_definitions.h" #include "Manager.h" @@ -117,6 +118,8 @@ namespace ver_2 ManagerV2(HGMsgPump msgPump); virtual ~ManagerV2(); + // 反初始化 + void DeinitDev(const DeinitDevParam* param); // 关闭设备 void CloseDev(const CloseDevParam* param); // 扫描完成 @@ -293,11 +296,16 @@ namespace ver_2 void ClearBindFolderImageList(const std::vector& tables); static int sane_ex_callback(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param); + static void HGAPI ThreadFunc(HGThread thread, HGPointer param); private: HGLock m_lock; GlobalConfig m_globalCfg; std::list m_user; + HGBool m_stopThread; + HGUInt m_timeout; + HGEvent m_event; + HGThread m_thread; bool m_initDevice; std::vector m_devNameList; diff --git a/sdk/webservice/Msg.h b/sdk/webservice/Msg.h index e82ceab1..b8cf855d 100644 --- a/sdk/webservice/Msg.h +++ b/sdk/webservice/Msg.h @@ -94,7 +94,8 @@ namespace ver_2 { enum { - MSGID_CLOSE_DEVICE = 3L, + MSGID_DEINIT_DEVICE = 3L, + MSGID_CLOSE_DEVICE, MSGID_SCAN_FINISH, MSGID_ADD_SAVEDFILE, MSGID_REMOVE_SAVEDFILE, @@ -105,6 +106,11 @@ namespace ver_2 class ManagerV2; class WSServer; + struct DeinitDevParam + { + ManagerV2* mgr; + }; + struct CloseDevParam { ManagerV2* mgr; @@ -143,4 +149,4 @@ namespace ver_2 HGByte* data; HGUInt size; }; -} \ No newline at end of file +} diff --git a/sdk/webservice/MsgPumpCallback.cpp b/sdk/webservice/MsgPumpCallback.cpp index 7e119138..a26af955 100644 --- a/sdk/webservice/MsgPumpCallback.cpp +++ b/sdk/webservice/MsgPumpCallback.cpp @@ -102,6 +102,13 @@ namespace ver_2 delete param; } break; + case MSGID_DEINIT_DEVICE: + { + DeinitDevParam* param = (DeinitDevParam*)msg->data; + param->mgr->DeinitDev(param); + delete param; + } + break; case MSGID_CLOSE_DEVICE: { CloseDevParam* param = (CloseDevParam*)msg->data; diff --git a/sdk/webservice/WSUser.cpp b/sdk/webservice/WSUser.cpp index ac260e22..be869d2b 100644 --- a/sdk/webservice/WSUser.cpp +++ b/sdk/webservice/WSUser.cpp @@ -298,6 +298,10 @@ namespace ver_2 { DeinitDevice(json); } + else if ("is_device_init" == func) + { + IsDeviceInit(json); + } else if ("get_device_name_list" == func) { GetDeviceNameList(json); @@ -334,6 +338,10 @@ namespace ver_2 { StopScan(json); } + else if ("is_device_scanning" == func) + { + IsDeviceScanning(json); + } else if ("get_batch_id_list" == func) { GetBatchIdList(json); @@ -2281,6 +2289,37 @@ namespace ver_2 } } + void WSUser::IsDeviceInit(cJSON* json) + { + assert(NULL != json); + + std::string errInfo; + int ret = GetManager()->IsDeviceInit() ? 0 : -1; + + bool findIden = false; + std::string iden = GetJsonStringValue(json, "iden", &findIden); + + cJSON* retJson = cJSON_CreateObject(); + if (NULL != retJson) + { + cJSON_AddItemToObject(retJson, "func", cJSON_CreateString("is_device_init")); + if (findIden) + cJSON_AddItemToObject(retJson, "iden", cJSON_CreateString(iden.c_str())); + cJSON_AddItemToObject(retJson, "ret", cJSON_CreateNumber(ret)); + if (0 != ret) + cJSON_AddItemToObject(retJson, "err_info", cJSON_CreateString(StdStringToUtf8(errInfo).c_str())); + + char* resp = cJSON_Print(retJson); + if (NULL != resp) + { + SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE); + free(resp); + } + + cJSON_Delete(retJson); + } + } + void WSUser::GetDeviceNameList(cJSON* json) { assert(NULL != json); @@ -2770,6 +2809,37 @@ namespace ver_2 } } + void WSUser::IsDeviceScanning(cJSON* json) + { + assert(NULL != json); + + std::string errInfo; + int ret = GetManager()->IsScanning() ? 0 : -1; + + bool findIden = false; + std::string iden = GetJsonStringValue(json, "iden", &findIden); + + cJSON* retJson = cJSON_CreateObject(); + if (NULL != retJson) + { + cJSON_AddItemToObject(retJson, "func", cJSON_CreateString("is_device_scanning")); + if (findIden) + cJSON_AddItemToObject(retJson, "iden", cJSON_CreateString(iden.c_str())); + cJSON_AddItemToObject(retJson, "ret", cJSON_CreateNumber(ret)); + if (0 != ret) + cJSON_AddItemToObject(retJson, "err_info", cJSON_CreateString(StdStringToUtf8(errInfo).c_str())); + + char* resp = cJSON_Print(retJson); + if (NULL != resp) + { + SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE); + free(resp); + } + + cJSON_Delete(retJson); + } + } + void WSUser::GetBatchIdList(cJSON* json) { assert(NULL != json); diff --git a/sdk/webservice/WSUser.h b/sdk/webservice/WSUser.h index 44caeaae..896d5788 100644 --- a/sdk/webservice/WSUser.h +++ b/sdk/webservice/WSUser.h @@ -53,6 +53,7 @@ namespace ver_2 void InitDevice(cJSON* json); void DeinitDevice(cJSON* json); + void IsDeviceInit(cJSON* json); void GetDeviceNameList(cJSON* json); void OpenDevice(cJSON* json); void CloseDevice(cJSON* json); @@ -62,6 +63,7 @@ namespace ver_2 void GetCurrDeviceName(cJSON* json); void StartScan(cJSON* json); void StopScan(cJSON* json); + void IsDeviceScanning(cJSON* json); void GetBatchIdList(cJSON* json); void OpenBatch(cJSON* json); diff --git a/test/webservice/demo.html b/test/webservice/demo.html index 853791fb..2915bf2f 100644 --- a/test/webservice/demo.html +++ b/test/webservice/demo.html @@ -121,6 +121,10 @@ { alert(msg.data); } + else if ("is_device_init" == message['func']) + { + alert(msg.data); + } else if ("get_device_name_list" == message['func']) { alert(msg.data); @@ -189,6 +193,10 @@ { alert(msg.data); } + else if ("is_device_scanning" == message['func']) + { + alert(msg.data); + } else if ("get_batch_id_list" == message['func']) { alert(msg.data); @@ -523,6 +531,13 @@ })); } + function IsDeviceInit() + { + socket.send(JSON.stringify({ + 'func':'is_device_init' + })); + } + function GetDevNameList() { socket.send(JSON.stringify({ @@ -588,6 +603,13 @@ })); } + function IsDeviceScanning() + { + socket.send(JSON.stringify({ + 'func':'is_device_scanning' + })); + } + function GetBatchIdList() { socket.send(JSON.stringify({ @@ -907,6 +929,7 @@ + @@ -916,6 +939,7 @@ +