Browse Source

Z991239-1672 #comment 更新cw二期源码 cw/2021.0126.01

ITC\80296915 4 years ago
parent
commit
547191b99a
41 changed files with 5336 additions and 92 deletions
  1. 2 2
      DevAdapter/CMakeLists.txt
  2. 22 4
      DevAdapter/cw/CMakeLists.txt
  3. 1 1
      DevAdapter/cw/cardissuer.1.1/cardissuerdev.cpp
  4. 85 80
      DevAdapter/cw/cardissuer.1.1/cardissuerimpl.cpp
  5. 8 2
      DevAdapter/cw/cardissuer.1.1/cardissuerimpl.h
  6. 25 0
      DevAdapter/cw/cardissuer.1.1/idcsankyoimpl.cpp
  7. 1 0
      DevAdapter/cw/cardissuer.1.1/idcsankyoimpl.h
  8. 26 0
      DevAdapter/cw/contactlesscard.1.1/CMakeLists.txt
  9. 257 0
      DevAdapter/cw/contactlesscard.1.1/PcscLibrary.cpp
  10. 698 0
      DevAdapter/cw/contactlesscard.1.1/PcscLibrary.h
  11. 59 0
      DevAdapter/cw/contactlesscard.1.1/contactlessdev.cpp
  12. 361 0
      DevAdapter/cw/contactlesscard.1.1/contactlessimpl.cpp
  13. 93 0
      DevAdapter/cw/contactlesscard.1.1/contactlessimpl.h
  14. 4 2
      DevAdapter/cw/deps/cw.baseio/serial.cpp
  15. 47 0
      DevAdapter/cw/hspscanner.1.1/CMakeLists.txt
  16. 61 0
      DevAdapter/cw/hspscanner.1.1/hspscannerdev.cpp
  17. 256 0
      DevAdapter/cw/hspscanner.1.1/hspscannerform.cpp
  18. 71 0
      DevAdapter/cw/hspscanner.1.1/hspscannerform.h
  19. 32 0
      DevAdapter/cw/hspscanner.1.1/hspscannerform.ui
  20. 294 0
      DevAdapter/cw/hspscanner.1.1/hspscannerimpl.cpp
  21. 107 0
      DevAdapter/cw/hspscanner.1.1/hspscannerimpl.h
  22. 52 0
      DevAdapter/cw/hspscanner.1.1/ui_hspscannerform.h
  23. 1 1
      DevAdapter/cw/pinpad.1.1/pinpadimpl.cpp
  24. 26 0
      DevAdapter/cw/termalprint.1.1/CMakeLists.txt
  25. 1001 0
      DevAdapter/cw/termalprint.1.1/ReceiptBase.cpp
  26. 160 0
      DevAdapter/cw/termalprint.1.1/ReceiptBase.h
  27. 59 0
      DevAdapter/cw/termalprint.1.1/ReceiptSnbc.cpp
  28. 27 0
      DevAdapter/cw/termalprint.1.1/ReceiptSnbc.h
  29. 58 0
      DevAdapter/cw/termalprint.1.1/termalprintdev.cpp
  30. 458 0
      DevAdapter/cw/termalprint.1.1/termalprintimpl.cpp
  31. 110 0
      DevAdapter/cw/termalprint.1.1/termalprintimpl.h
  32. 26 0
      DevAdapter/cw/ups.1.1/CMakeLists.txt
  33. 136 0
      DevAdapter/cw/ups.1.1/deviceconnect.cpp
  34. 39 0
      DevAdapter/cw/ups.1.1/deviceconnect.h
  35. 60 0
      DevAdapter/cw/ups.1.1/upsdev.cpp
  36. 195 0
      DevAdapter/cw/ups.1.1/upsimpl.cpp
  37. 49 0
      DevAdapter/cw/ups.1.1/upsimpl.h
  38. 26 0
      DevAdapter/cw/watchdog.1.1/CMakeLists.txt
  39. 60 0
      DevAdapter/cw/watchdog.1.1/watchdogdev.cpp
  40. 224 0
      DevAdapter/cw/watchdog.1.1/watchdogimpl.cpp
  41. 59 0
      DevAdapter/cw/watchdog.1.1/watchdogimpl.h

+ 2 - 2
DevAdapter/CMakeLists.txt

@@ -142,10 +142,10 @@ if(DEVADAPTER_USING_CONAN)
     set(KEBA_CONAN_LIB_NAME keba/2021.0201.01@LR04.02_VendorLib/testing)
 	set(NANTIAN_CONAN_LIB_NAME nantian/2021.0119.01@LR04.02_VendorLib/testing)
 	set(GRG_CONAN_LIB_NAME grg/2021.0111.01@LR04.02_VendorLib/testing)
-	set(CW_CONAN_LIB_NAME cw/2020.1222.01@LR04.02_VendorLib/testing)
+	set(CW_CONAN_LIB_NAME cw/2021.0126.01@LR04.02_VendorLib/testing)
     set(GWI_CONAN_LIB_NAME gwi/2021.0119.01@LR04.02_VendorLib/testing)
 endif(DEVADAPTER_USING_CONAN)
-
+ 
     file(GLOB all_valid_subdirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/CMakeLists.txt")
       foreach(dir ${all_valid_subdirs})
 	    if(${dir} MATCHES "^([^/]*)/+CMakeLists.txt")

+ 22 - 4
DevAdapter/cw/CMakeLists.txt

@@ -4,11 +4,29 @@ project(cw C CXX)
 
 set(CMAKE_COLOR_MAKEFILE ON)
 
-# VENDOR_CURRENT_{DEPS|INCLUDE|ASSET|LIB|BIN}_DIR 等定义已集成到该宏内
-rvc_define_dependen_dirs()
 
-# 遍历当前目录下带有CMakeLists.txt文件的文件夹
-rvc_traverse_sub_cmake_dirs()
+if(RVC_INTEGRATE_BUILD)
+	rvc_define_dependen_dirs()
+	rvc_traverse_sub_cmake_dirs()
+else()
+	# 放置有源码的适配器依赖库工程文件
+	set(VENDOR_CURRENT_DEPS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps")
+	set(VENDOR_CURRENT_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
+	set(VENDOR_CURRENT_ASSET_DIR "${CMAKE_CURRENT_SOURCE_DIR}/assets")
+
+	set(VENDOR_CURRENT_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib/${DIFF_PLATFORM_SUB_DIR}")
+	set(VENDOR_CURRENT_BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bin/${DIFF_PLATFORM_SUB_DIR}")
+
+	 file(GLOB all_valid_subdirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/CMakeLists.txt")
+
+	 foreach(dir ${all_valid_subdirs})
+		if(${dir} MATCHES "^([^/]*)/+CMakeLists.txt")
+			string(REGEX REPLACE "^([^/]*)/+CMakeLists.txt" "\\1" dir_trimmed ${dir})
+			message(STATUS "add module ${dir_trimmed}")
+			add_subdirectory(${dir_trimmed})
+		endif()
+	 endforeach(dir)
+ endif(RVC_INTEGRATE_BUILD)
 
 #  =-=-=-=-=-=-=-=-=-= {VendorName}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
 rvc_aggereate_runtime_file()

+ 1 - 1
DevAdapter/cw/cardissuer.1.1/cardissuerdev.cpp

@@ -11,7 +11,7 @@ void __attribute__((destructor)) uninit()
         delete g_pCardIssuer;
         g_pCardIssuer = NULL;
     }
-} 
+}
 
 void __attribute__((constructor)) init()
 {

+ 85 - 80
DevAdapter/cw/cardissuer.1.1/cardissuerimpl.cpp

@@ -1,7 +1,8 @@
 #include "cardissuerimpl.h"
-#include<cstring>
+#include <cstring>
 #include <cstdio>
 #include "sini.h"
+#include "public.h"
 
 CardIssuerClassImpl::CardIssuerClassImpl()
         :m_mode(0)
@@ -9,6 +10,7 @@ CardIssuerClassImpl::CardIssuerClassImpl()
     m_pDriver = new IDCSankyoImpl ();
     m_T = 0;
     m_bIsOpen = false;
+    m_bCardRead = false;
 }
 
 CardIssuerClassImpl::~CardIssuerClassImpl()
@@ -206,7 +208,7 @@ ErrorCodeEnum CardIssuerClassImpl::GetDevStatus(CardIssuerStatus& devStatus)
             eRt = HandleDevError(iRt, "GetDevStatus getStatus");
             break;
         }
-
+//*
         //get box status
         CUStatus cuStatus;
         RetainBinStatus rtStatus;
@@ -272,6 +274,7 @@ ErrorCodeEnum CardIssuerClassImpl::GetDevStatus(CardIssuerStatus& devStatus)
                 devStatus.eIssuerBin[i] = CI_ISSUEHOPPER_NOTSUPP;
             }
         }
+//*/
     }while(0);
 
     char outputParam[512] = { 0 };
@@ -316,7 +319,7 @@ ErrorCodeEnum CardIssuerClassImpl::MoveCard(CardPosEnum eCardPos, int hopperNo)
     LOG4VTM(INFO, inputParam);
     ErrorCodeEnum eRt = Error_Succeed;
     int iRt = 0;
-
+    m_bCardRead = false;
     eRt = ReleaseIC();
     if(CI_MOVECARD_FRONT_GATE == eCardPos)
     {
@@ -389,6 +392,7 @@ ErrorCodeEnum CardIssuerClassImpl::SetCardInType(CardInEnum eCardIn)
     LOG4VTM_FUNCTION();
     if (!m_bIsOpen)
         return HandleDevError(DEVICE_NOT_OPEN, "SetCardInType");
+    m_bCardRead = false;
     char sTemp[128] = { 0 };
     sprintf(sTemp, "SetCardInType eCardIn(%s)", FormatCardIn(eCardIn));
     LOG4VTM(INFO, sTemp);
@@ -424,6 +428,46 @@ ErrorCodeEnum CardIssuerClassImpl::SetCardInType(CardInEnum eCardIn)
     return eRt;
 }
 
+bool SetCardData(TrackInfo& track, char* sData, TrackSrcEnum eTrack)
+{
+    track.eSource = eTrack;
+    int iLen = strlen(sData);
+    if(iLen)
+    {
+        track.eStatus = CI_DATA_OK;
+        strcpy((char*)track.data, sData);
+        track.dwSize = iLen;
+        return true;
+    }
+    else
+    {
+        track.eStatus = CI_DATA_INVALID;
+        track.data[0] = 0;
+        track.dwSize = 0;
+        return false;
+    }
+}
+
+void CardIssuerClassImpl::ReadMagData()
+{
+    memset(m_saMagData, 0, sizeof(m_saMagData));
+    if (m_pDriver->getStatus() != CWINFO_IDC_S_INSIDE)
+    {
+        m_iReadReturn = DEVICE_NO_MEDIA;
+        m_bCardRead = false;
+        return;
+    }
+//    m_iReadCode = m_pDriver->readRawData(m_rawDataArr, 3);
+    m_pDriver->readTrack(1, m_saMagData[0]);
+    m_pDriver->readTrack(2, m_saMagData[1]);
+    m_pDriver->readTrack(3, m_saMagData[2]);
+    if (strlen(m_saMagData[0]) || strlen(m_saMagData[1]) || strlen(m_saMagData[2]))
+        m_iReadReturn = 0;
+    else
+        m_iReadReturn = DEVICE_NO_DATA;
+    m_bCardRead = true;
+}
+
 //	Read data from magnetic track.
 ErrorCodeEnum CardIssuerClassImpl::MagRead(MagTracks& magTracks)
 {
@@ -434,72 +478,21 @@ ErrorCodeEnum CardIssuerClassImpl::MagRead(MagTracks& magTracks)
     sprintf(sTemp, "MagRead eRange(%s)", FormatTrackRange(magTracks.eRange));
     LOG4VTM(INFO, sTemp);
     ErrorCodeEnum eRt = Error_Succeed;
-    int iRt = 0;
-    bool bReadSucc = false;
-    do
-    {
-        IDCRawData rawDataArr[3];
-        unsigned short itemsCount = 0;
-        memset(rawDataArr, 0, sizeof(rawDataArr));
-        rawDataArr[itemsCount++].source = O_Source_Track1;
-        rawDataArr[itemsCount++].source = O_Source_Track2;
-        rawDataArr[itemsCount++].source = O_Source_Track3;
-        iRt = m_pDriver->readRawData(rawDataArr, itemsCount);
-        eRt = HandleDevError(iRt, "MagRead");
-        IDCRawData* trackTmp = 0;
-        for (int rawIndex = 0; rawIndex < itemsCount; ++rawIndex)
-        {
-            trackTmp = rawDataArr + rawIndex;
-            // Track data source
-            if (O_Source_Track1 == trackTmp->source)
-            {
-                magTracks.track[0].eSource = CI_TRACK_SOURCE_1;
-                if(CWINFO_IDC_S_INSIDE == trackTmp->status)
-                {
-                    bReadSucc = true;
-                    magTracks.track[0].eStatus = CI_DATA_OK;
-                    memcpy(magTracks.track[0].data, trackTmp->rawData, trackTmp->len);
-                    magTracks.track[0].dwSize = trackTmp->len;
-                }
-                else
-                {
-                    magTracks.track[0].eStatus = CI_DATA_INVALID;
-                }
-            }
-            if (O_Source_Track2 == trackTmp->source)
-            {
-                magTracks.track[1].eSource = CI_TRACK_SOURCE_2;
-                if(CWINFO_IDC_S_INSIDE == trackTmp->status)
-                {
-                    bReadSucc = true;
-                    magTracks.track[1].eStatus = CI_DATA_OK;
-                    memcpy(magTracks.track[1].data, trackTmp->rawData, trackTmp->len);
-                    magTracks.track[1].dwSize = trackTmp->len;
-                }
-                else
-                {
-                    magTracks.track[1].eStatus = CI_DATA_INVALID;
-                }
-            }
-            if (O_Source_Track3 == trackTmp->source)
-            {
-                magTracks.track[2].eSource = CI_TRACK_SOURCE_3;
-                if(CWINFO_IDC_S_INSIDE == trackTmp->status)
-                {
-                    bReadSucc = true;
-                    magTracks.track[2].eStatus = CI_DATA_OK;
-                    memcpy(magTracks.track[2].data, trackTmp->rawData, trackTmp->len);
-                    magTracks.track[2].dwSize = trackTmp->len;
-                }
-                else
-                {
-                    magTracks.track[2].eStatus = CI_DATA_INVALID;
-                }
-            }
-        }
-    }while(0);
-
-    sprintf(sTemp, "MagRead track1len(%d) track2len(%d) track3len(%d)", magTracks.track[0].dwSize, magTracks.track[1].dwSize, magTracks.track[2].dwSize);
+    if (!m_bCardRead)
+        ReadMagData();
+    bool    bReadSucc = false;
+    //上层要求必须有数据长度,只有错误码会报错
+    if (SetCardData(magTracks.track[0], m_saMagData[0], CI_TRACK_SOURCE_1))
+        bReadSucc=true;
+    if (SetCardData(magTracks.track[1], m_saMagData[1], CI_TRACK_SOURCE_2))
+        bReadSucc=true;
+    if (SetCardData(magTracks.track[2], m_saMagData[2], CI_TRACK_SOURCE_3))
+        bReadSucc=true;
+    eRt = HandleDevError(m_iReadReturn, "MagRead");
+    sprintf(sTemp, "MagRead track%dlen(%d) track%dlen(%d) track%dlen(%d)",
+            magTracks.track[0].eSource, magTracks.track[0].dwSize,
+            magTracks.track[1].eSource, magTracks.track[1].dwSize,
+            magTracks.track[2].eSource, magTracks.track[2].dwSize);
     LOG4VTM(INFO, sTemp);
     return bReadSucc ? Error_Succeed : eRt;
 }
@@ -540,7 +533,6 @@ ErrorCodeEnum CardIssuerClassImpl::MagWrite(MagTracks magTracks, MagWriteModeEnu
             {
                 if(CI_TRACK_SOURCE_1 == magTracks.track[i].eSource)
                 {
-
                     rawDataArr[itemsCount].source = O_Source_Track1;
                     rawDataArr[itemsCount].len = magTracks.track[i].dwSize;
                     memcmp(rawDataArr[itemsCount].rawData, magTracks.track[i].data, magTracks.track[i].dwSize);
@@ -608,13 +600,16 @@ ErrorCodeEnum CardIssuerClassImpl::ActiveICCard()
     {
         IDCRawData chipATR;
         memset(&chipATR, 0, sizeof(chipATR));
-        iRt = m_pDriver->icPressAndActive(&chipATR);
-        eRt = HandleDevError(iRt, "icPressAndActive");
+        iRt = m_pDriver->icActive(&chipATR);
+        eRt = HandleDevError(iRt, "ActiveICCard");
         if(Error_Succeed != eRt)
         {
             break;
         }
         unsigned char p = (chipATR.rawData[0] & 0xF0);
+        char sTemp[256];
+        sprintf(sTemp, "ActiveICCard Card type %02x", chipATR.rawData[0]);
+        LOG4VTM(WARN, sTemp);
         if(p == 0xe0)
             m_T = 1;
         else if (p == 0x60)
@@ -629,7 +624,14 @@ ErrorCodeEnum CardIssuerClassImpl::ActiveICCard()
 //	Move IC card to contact position
 ErrorCodeEnum CardIssuerClassImpl::ContactIC()
 {
-    return ActiveICCard();
+    LOG4VTM_FUNCTION();
+    if (!m_bIsOpen)
+        return HandleDevError(DEVICE_NOT_OPEN, "ContactIC");
+    if (!m_bCardRead)
+        ReadMagData();
+    int iRt = m_pDriver->icPress();
+    return HandleDevError(iRt, "ContactIC");
+//    return Error_Succeed;
 }
 
 ErrorCodeEnum CardIssuerClassImpl::ReleaseIC()
@@ -639,11 +641,8 @@ ErrorCodeEnum CardIssuerClassImpl::ReleaseIC()
         return HandleDevError(DEVICE_NOT_OPEN, "ReleaseIC");
     ErrorCodeEnum eRt = Error_Succeed;
     int iRt = 0;
-    do
-    {
-        iRt = m_pDriver->icDeactiveAndRelease();
-        eRt = HandleDevError(iRt, "ReleaseIC");
-    }while(0);
+//    iRt = m_pDriver->icDeactiveAndRelease();
+    eRt = HandleDevError(iRt, "ReleaseIC");
     return eRt;
 }
 
@@ -665,13 +664,14 @@ ErrorCodeEnum CardIssuerClassImpl::WarmReset()
 
     return eRt;
 }
+
 ErrorCodeEnum CardIssuerClassImpl::ICCommand(CmdInfo sendBuf, CmdInfo& recvBuf)
 {
     LOG4VTM_FUNCTION();
     if (!m_bIsOpen)
         return HandleDevError(DEVICE_NOT_OPEN, "ICCommand");
-    char sTemp[128] = { 0 };
-    sprintf(sTemp, "ICCommand sendlen(%d)", sendBuf.dwSize);
+    char sTemp[512] = { 0 };
+    sprintf(sTemp, "ICCommand sendlen (%d)", sendBuf.dwSize);
     LOG4VTM(INFO, sTemp);
     ErrorCodeEnum eRt = Error_Succeed;
     int iRt = 0;
@@ -694,6 +694,7 @@ ErrorCodeEnum CardIssuerClassImpl::ICCommand(CmdInfo sendBuf, CmdInfo& recvBuf)
         if(Error_Succeed != eRt)    break;
         memcpy(recvBuf.data, chipOutput.rawData, chipOutput.len);
         recvBuf.dwSize = chipOutput.len;
+        recvBuf.data[recvBuf.dwSize] = 0;
     }while(0);
 
     sprintf(sTemp, "ICCommand recvlen(%d)", recvBuf.dwSize);
@@ -873,6 +874,10 @@ ErrorCodeEnum CardIssuerClassImpl::HandleDevError(int nRt, LPCTSTR lpszFormat, .
         eRt = Error_Hardware;
         sprintf(strErrInfo, "device not opened");
         break;
+    case  DEVICE_NO_DATA:
+        eRt = Error_Stoped;
+        sprintf(strErrInfo, "read track no data");
+        break;
     //成功
     case  0:
         eRt = Error_Succeed;

+ 8 - 2
DevAdapter/cw/cardissuer.1.1/cardissuerimpl.h

@@ -3,7 +3,7 @@
 
 #include "CardIssuerClass.h"
 #include "idcsankyoimpl.h"
-#include "../../include/log4vendor.h"
+#include "log4vendor.h"
 
 #define FILE_VERSION    1
 
@@ -11,6 +11,7 @@
 #define RETAIN_BIN_ERROR    -2
 #define DEVICE_NO_MEDIA     -3
 #define DEVICE_NOT_SUPP     -4
+#define DEVICE_NO_DATA      -5
 
 class CardIssuerClassImpl : public CardIssuerClass
 {
@@ -18,7 +19,6 @@ public:
     CardIssuerClassImpl();
     ~CardIssuerClassImpl();
 
-
     //DeviceBaseClass
     ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
     ErrorCodeEnum Reset();
@@ -276,6 +276,12 @@ private:
     int             m_mode;
     IDCSankyoImpl*  m_pDriver;
     DevErrorInfo    m_DevErrInfo;
+    //行里流程为进卡后上电判断IC,之后读磁,会再次读取,此处为缓存磁条数据
+    int             m_bCardRead;
+    int             m_iReadReturn;
+    void            ReadMagData();
+    char            m_saMagData[3][512];
+
     char            m_pformatStatus[64];
     bool            m_T;
 };

+ 25 - 0
DevAdapter/cw/cardissuer.1.1/idcsankyoimpl.cpp

@@ -162,6 +162,7 @@ int IDCSankyoImpl::getFirmversion(unsigned char * version)
         if ('P' == rsp.jdgPart)
         {
             memcpy(version, rsp.rdt, rsp.rdtLen);
+            version[rsp.rdtLen] = 0;
         }
         else if ('N' == rsp.jdgPart)
         {
@@ -303,6 +304,30 @@ int IDCSankyoImpl::ejectCard()
     return ret;
 }
 
+int IDCSankyoImpl::readTrack(int iTrack, char* sOut)
+{
+    SANKYO_CMD cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.idn = 'C';
+    cmd.command[0] = 0x36;
+    cmd.command[1] = 0x30 + iTrack;
+
+    SANKYO_RSP rsp;
+    memset(&rsp, 0, sizeof(SANKYO_RSP));
+    int ret = executeCmd(&cmd, &rsp, "readRawData");
+    if (CWERR_IDC_S_SOFT_UNK != ret)
+    {
+        //获取磁条数据
+        strcpy(sOut, (char*)rsp.rdt);
+        return 0;
+    }
+    else
+    {
+        sOut[0] = 0;
+        return ret;
+    }
+}
+
 int IDCSankyoImpl::readRawData(IDCRawData* rawDataArr, const unsigned itemsCount)
 {
     SANKYO_CMD cmd;

+ 1 - 0
DevAdapter/cw/cardissuer.1.1/idcsankyoimpl.h

@@ -41,6 +41,7 @@ public:
     int ejectCard();
 
     int readRawData(IDCRawData* rawDataArr, const unsigned itemsCount);
+    int readTrack(int iTrack, char* sOut);
     int	setTrackData(BYTE *pTrackData, int iTrackNum);
     int writeRawData(IDCRawData* rawDataArr, const unsigned itemsCount);
     int icPress();

+ 26 - 0
DevAdapter/cw/contactlesscard.1.1/CMakeLists.txt

@@ -0,0 +1,26 @@
+
+# 声明模块名称的前缀和名称
+rvc_dev_define_module("ContactlessCard")
+
+# rvc_dev_config_library 内需要使用这三个参数,用于拼接输出的适配器文件名称
+set(${MODULE_PREFIX}_VENDOR "cw")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+# 包含要编译的实现文件,rvc_dev_config_library 内使用
+set(${MODULE_PREFIX}_SRCS SHARED
+        contactlessimpl.cpp contactlessdev.cpp  PcscLibrary.cpp
+    )
+
+# 适配器工程需要通过此宏替代 add_library
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+# ${MODULE_FULL_NAME} 是 TAGET 名称,在 rvc_dev_config_library 中定义
+target_include_directories(${MODULE_FULL_NAME} PRIVATE ${VENDOR_CURRENT_INCLUDE_DIR})
+target_link_libraries(${MODULE_FULL_NAME} baseio ${VENDOR_LOG_LIB_NAME})
+
+SET(LIBRARY_OUTPUT_PATH ${VENDOR_CURRENT_LIB_DIR})
+
+#  =-=-=-=-=-=-=-=-=-= {适配器工程}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
+rvc_dev_target_install(${MODULE_FULL_NAME})
+

+ 257 - 0
DevAdapter/cw/contactlesscard.1.1/PcscLibrary.cpp

@@ -0,0 +1,257 @@
+#include "PcscLibrary.h"
+
+CPcscLibrary::CPcscLibrary(void)
+{
+	hModule = NULL;
+    OpenConnect            = NULL;
+    CloseConnect           = NULL;
+    GetReaderListName      = NULL;
+    SetReaderName          = NULL;
+    GetReaderType          = NULL;
+    GetCardStatus          = NULL;
+    EjectCard              = NULL;
+    ReaderConnect          = NULL;
+    SendApdu               = NULL;
+    SendControlCMD         = NULL;
+    HotReset               = NULL;
+    SetReaderType          = NULL;
+    GetVersionInfo         = NULL;
+    AutoBeel               = NULL;
+    Beel                   = NULL;
+    SetLightMode           = NULL;
+    GetLightMode           = NULL;
+    SetLightStatus         = NULL;
+    GetLightStatus         = NULL;
+    BanTypeBCap            = NULL;
+    LoadMifareKey          = NULL;
+    CheckMifareKey         = NULL;
+    Read                   = NULL;
+    Write                  = NULL;
+    GetCardUID             = NULL;
+    SAMSlotActivation      = NULL;
+    ReadMagAllTracks       = NULL;
+    GetRFCardType          = NULL;
+    ReadIDCardInifo        = NULL;
+    M1ValueProcess         = NULL;
+    M1InquireBalance       = NULL;
+    M1BackBlock            = NULL;
+    GetIDFinger            = NULL;
+    GetIDDNNums            = NULL;
+    GetSAMID               = NULL;
+    SwitchRF               = NULL;
+    GetLastError           = NULL;
+}
+
+CPcscLibrary::~CPcscLibrary(void)
+{
+	if (hModule != NULL)
+	{
+		dlclose(hModule);
+		hModule = NULL;
+	}
+}
+
+bool CPcscLibrary::Load(const char* lpDllPath, char* ErrorInfo)
+{
+	//定义变量
+	returnValue = false;
+
+	//判断参数
+	if(ErrorInfo == NULL)
+	{
+		goto ExitLine;
+	}
+	//加载动态库
+	if(hModule)
+	{
+		returnValue = true;
+		goto ExitLine;
+	}
+
+	hModule = dlopen(lpDllPath, RTLD_LAZY);
+	if(hModule == NULL)
+	{
+		sprintf(ErrorInfo, "加载传入:%s失败!",lpDllPath);
+		//加载传入路径失败,再加载一次当前路径默认DLL
+		hModule = dlopen("./CRT_603_CZ7.so", RTLD_LAZY);
+		if(hModule == NULL)
+		{
+			sprintf(ErrorInfo, "加载默认及传入路径失败!");
+			goto ExitLine;
+		}
+	}
+
+	//******************************************************************************************************************
+	//加载CRT_OpenConnect
+    OpenConnect = (pCRT_OpenConnect)dlsym(hModule, "CRT_OpenConnect");
+    if(!OpenConnect)
+	{
+		sprintf(ErrorInfo, "加载'CRT_OpenConnect'失败!");
+		goto ExitLine;
+	}
+	
+	//******************************************************************************************************************
+	//加载CRT_CloseConnect
+    CloseConnect = (pCRT_CloseConnect)dlsym(hModule, "CRT_CloseConnect");
+    if(!CloseConnect)
+	{
+		sprintf(ErrorInfo, "加载'CRT_CloseConnect'失败!");
+		goto ExitLine;
+	}
+	
+    GetReaderListName = (pCRT_GetReaderListName)dlsym(hModule, "CRT_GetReaderListName");
+	
+	//******************************************************************************************************************
+	//加载CRT_SetReaderName
+    SetReaderName = (pCRT_SetReaderName)dlsym(hModule, "CRT_SetReaderName");
+	
+	//******************************************************************************************************************
+	//加载CRT_GetReaderType
+    GetReaderType = (pCRT_GetReaderType)dlsym(hModule, "CRT_GetReaderType");
+
+	//******************************************************************************************************************
+	//加载CRT_GetCardStatus
+    GetCardStatus = (pCRT_GetCardStatus)dlsym(hModule, "CRT_GetCardStatus");
+
+	//******************************************************************************************************************
+	//加载CRT_EjectCard
+    EjectCard = (pCRT_EjectCard)dlsym(hModule, "CRT_EjectCard");
+
+	//******************************************************************************************************************
+	//加载CRT_ReaderConnect
+    ReaderConnect = (pCRT_ReaderConnect)dlsym(hModule, "CRT_ReaderConnect");
+
+	//******************************************************************************************************************
+	//加载CRT_SendApdu
+    SendApdu = (pCRT_SendApdu)dlsym(hModule, "CRT_SendApdu");
+
+	//******************************************************************************************************************
+	//加载CRT_SendControlCMD
+    SendControlCMD = (pCRT_SendControlCMD)dlsym(hModule, "CRT_SendControlCMD");
+
+	//******************************************************************************************************************
+	//加载CRT_HotReset
+    HotReset = (pCRT_HotReset)dlsym(hModule, "CRT_HotReset");
+
+	//******************************************************************************************************************
+	//加载CRT_SetReaderType
+    SetReaderType = (pCRT_SetReaderType)dlsym(hModule, "CRT_SetReaderType");
+
+	//******************************************************************************************************************
+	//加载CRT_GetVersionInfo
+    GetVersionInfo = (pCRT_GetVersionInfo)dlsym(hModule, "CRT_GetVersionInfo");
+	
+	//******************************************************************************************************************
+	//加载CRT_AutoBeel
+    AutoBeel = (pCRT_AutoBeel)dlsym(hModule, "CRT_AutoBeel");
+
+	//******************************************************************************************************************
+	//加载CRT_Beel
+    Beel = (pCRT_Beel)dlsym(hModule, "CRT_Beel");
+
+	//******************************************************************************************************************
+	//加载CRT_SetLightMode
+    SetLightMode = (pCRT_SetLightMode)dlsym(hModule, "CRT_SetLightMode");
+	
+	//******************************************************************************************************************
+	//加载CRT_GetLightMode
+    GetLightMode = (pCRT_GetLightMode)dlsym(hModule, "CRT_GetLightMode");
+
+	//******************************************************************************************************************
+	//加载CRT_SetLightStatus
+    SetLightStatus = (pCRT_SetLightStatus)dlsym(hModule, "CRT_SetLightStatus");
+
+	//******************************************************************************************************************
+	//加载CRT_GetLightStatus
+    GetLightStatus = (pCRT_GetLightStatus)dlsym(hModule, "CRT_GetLightStatus");
+
+	//******************************************************************************************************************
+	//加载CRT_BanTypeBCap
+    BanTypeBCap = (pCRT_BanTypeBCap)dlsym(hModule, "CRT_BanTypeBCap");
+	
+	//******************************************************************************************************************
+	//加载CRT_LoadMifareKey
+    LoadMifareKey = (pCRT_LoadMifareKey)dlsym(hModule, "CRT_LoadMifareKey");
+	
+	//******************************************************************************************************************
+	//加载CRT_CheckMifareKey
+    CheckMifareKey = (pCRT_CheckMifareKey)dlsym(hModule, "CRT_CheckMifareKey");
+	
+	//******************************************************************************************************************
+	//加载CRT_Read
+    Read = (pCRT_Read)dlsym(hModule, "CRT_Read");
+	
+	//******************************************************************************************************************
+	//加载CRT_Write
+    Write = (pCRT_Write)dlsym(hModule, "CRT_Write");
+	
+	//******************************************************************************************************************
+	//加载CRT_GetCardUID
+    GetCardUID = (pCRT_GetCardUID)dlsym(hModule, "CRT_GetCardUID");
+	
+	//******************************************************************************************************************
+	//加载CRT_SAMSlotActivation
+    SAMSlotActivation = (pCRT_SAMSlotActivation)dlsym(hModule, "CRT_SAMSlotActivation");
+	
+	//******************************************************************************************************************
+	//加载CRT_ReadMagAllTracks
+    ReadMagAllTracks = (pCRT_ReadMagAllTracks)dlsym(hModule, "CRT_ReadMagAllTracks");
+
+	
+	//******************************************************************************************************************
+	//加载CRT_GetRFCardType
+    GetRFCardType = (pCRT_GetRFCardType)dlsym(hModule, "CRT_GetRFCardType");
+	
+	//******************************************************************************************************************
+	//加载CRT_ReadIDCardInifo
+    ReadIDCardInifo = (pCRT_ReadIDCardInifo)dlsym(hModule, "CRT_ReadIDCardInifo");
+
+	//******************************************************************************************************************
+	//加载CRT_M1ValueProcess
+    M1ValueProcess = (pCRT_M1ValueProcess)dlsym(hModule, "CRT_M1ValueProcess");
+
+	//******************************************************************************************************************
+	//加载CRT_M1InquireBalance
+    M1InquireBalance = (pCRT_M1InquireBalance)dlsym(hModule, "CRT_M1InquireBalance");
+	
+	//******************************************************************************************************************
+	//加载CRT_M1BackBlock
+    M1BackBlock = (pCRT_M1BackBlock)dlsym(hModule, "CRT_M1BackBlock");
+	
+	//******************************************************************************************************************
+	//加载CRT_GetIDFinger
+    GetIDFinger = (pCRT_GetIDFinger)dlsym(hModule, "CRT_GetIDFinger");
+	
+	//******************************************************************************************************************
+	//加载CRT_GetIDDNNums
+    GetIDDNNums = (pCRT_GetIDDNNums)dlsym(hModule, "CRT_GetIDDNNums");
+	
+	//******************************************************************************************************************
+	//加载CRT_GetSAMID
+    GetSAMID = (pCRT_GetSAMID)dlsym(hModule, "CRT_GetSAMID");
+	
+	//******************************************************************************************************************
+	//加载CRT_SwitchRF
+    SwitchRF = (pCRT_SwitchRF)dlsym(hModule, "CRT_SwitchRF");
+	
+	//******************************************************************************************************************
+	//加载CRT_GetLastError
+    GetLastError = (pCRT_GetLastError)dlsym(hModule, "CRT_GetLastError");
+	returnValue = true;
+
+ExitLine:
+	if(!returnValue && hModule)
+	{
+		dlclose(hModule);
+	}
+	return returnValue;
+}
+
+bool CPcscLibrary::IsLoadSucceed()
+{
+	if (!hModule && !returnValue)
+	{
+		return false;
+	}
+	return true;
+}

+ 698 - 0
DevAdapter/cw/contactlesscard.1.1/PcscLibrary.h

@@ -0,0 +1,698 @@
+#ifndef  __LoadLibrary_H__
+#define  __LoadLibrary_H__
+
+
+#include <stdio.h>       //标准输入输出定义
+#include <string.h>
+#include <stdlib.h>      //标准函数库定义
+#include <unistd.h>      //Unix标准函数定义
+#include <sys/types.h>
+#include <sys/stat.h>  
+#include <fcntl.h>       //文件控制定义
+#include <termios.h>     //PPSIX终端控制定义
+#include <errno.h>       //错误号定义
+
+#include <dlfcn.h>
+
+//二代证信息
+typedef struct
+{
+	char szName[31];   //姓名
+	char szSex[5];     //性别
+	char szNation[20]; //民族
+	char szBornDay[10]; //出生
+	char szAddress[128]; //地址
+	char szIDNum[20];   //身份证编号
+	char szIssued[51];  //签发机关
+	char szBeginValidity[10]; //开始有效日期
+	char szEndValidity[10];   //截止有效日期
+	char szHeadPath[256];      //小头像路径
+}CRTDef_IDInfo, *pCRTDef_IDInf;
+
+
+/** 
+ * @fn		CRT_OpenConnect 
+ * @detail	打开CRT智能读卡器
+ * @see		...
+ * @param	iListNums:输出 连接的读卡器列表个数
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_OpenConnect)(int* iListNums);
+
+
+
+
+/** 
+ * @fn		CRT_CloseConnect 
+ * @detail	关闭CRT智能读卡器
+ * @see		...
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_CloseConnect)();
+
+
+
+
+/** 
+ * @fn		CRT_GetReaderListName 
+ * @detail	获取智能读卡器列表名字
+ * @see		...
+ * @param	iListNum:需获取的读卡器序列号(0为起始)
+ * @param	szListName:输出 获取到的读卡器名字
+ * @return	0 成功, 非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_GetReaderListName)(int iListNum, char szListName[]);
+
+
+
+
+/** 
+ * @fn		CRT_SetReaderName 
+ * @detail	设置当前工作的读卡器序列号(打开时,默认设置为第一个读卡器)
+ * @see		...
+ * @param	iListNum:需设置的读卡器序列号(0为起始)
+ * @return	0 成功, 非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_SetReaderName)(int iListNum);
+
+
+
+
+/** 
+ * @fn		CRT_GetCardStatus 
+ * @detail	获取读卡器上卡状态
+ * @see		...
+ * @return	1 有卡, 2 无卡, 9 状态未知
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_GetCardStatus)();
+
+
+
+
+/** 
+ * @fn		CRT_EjectCard 
+ * @detail	弹卡下电,读卡器断开连接
+ * @see		...
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_EjectCard)();
+
+
+
+
+/** 
+ * @fn		CRT_ReaderConnect 
+ * @detail	读卡器卡片上电
+ * @see		...
+ * @param	byAtrData:输出 上电成功返回的ATR数据
+ * @param	iAtrLen: 输出 上电成功返回的ATR数据长度
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_ReaderConnect)(unsigned char byAtrData[], int* iAtrLen);
+
+
+
+
+/** 
+ * @fn		CRT_SendApdu 
+ * @detail	读卡器发送APDU指令
+ * @see		...
+ * @param	bySendData:需发送的APDU指令(支持acsii码与BCD码)
+ * @param	iSendDataLen: 需发送的APDU指令长度
+ * @param	byRecvData:输出 APDU通讯后返回的数据
+ * @param	iRecvDataLen: 输出 APDU通讯后返回的数据长度
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_SendApdu)(unsigned char bySendData[], int iSendDataLen, unsigned char byRecvData[], int* iRecvDataLen);
+
+
+
+
+/** 
+ * @fn		CRT_SendControlCMD 
+ * @detail	读卡器发送扩展控制命令
+ * @see		...
+ * @param	bySendData:需发送的扩展控制命令数据(支持acsii码与BCD码)
+ * @param	iSendDataLen: 需发送的扩展控制命令数据长度
+ * @param	byRecvData:输出 扩展控制命令通讯后返回的数据
+ * @param	iRecvDataLen: 输出 扩展控制命令通讯后返回的数据长度
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_SendControlCMD)(unsigned char bySendData[], int iSendDataLen, unsigned char byRecvData[], int* iRecvDataLen);
+
+
+
+
+//***********************发送CRT603具体功能扩展命令****************************
+/** 
+ * @fn		CRT_HotReset 
+ * @detail	读卡器热复位
+ * @see		...
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_HotReset)();
+
+
+
+
+/** 
+ * @fn		CRT_SetReaderType 
+ * @detail	设置读卡器操作模式
+ * @see		...
+ * @param	iType: 1 正常RF卡模式, 2 Felica模式, 3 点对点模式, 4 二代证模式, 5 卡模拟模式
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_SetReaderType)(int iType);
+
+
+
+
+/** 
+ * @fn		CRT_GetReaderType 
+ * @detail	获取读卡器操作模式
+ * @see		...
+ * @return	>0 失败 1 正常RF卡模式, 2 Felica模式, 3 点对点模式, 4 二代证模式, 5 卡模拟模式
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_GetReaderType)();
+
+
+
+
+/** 
+ * @fn		CRT_GetVersionInfo 
+ * @detail	获取读卡器版本信息
+ * @see		...
+ * @param	iVerType: 需获取的版本 0 P/N信息, 1 SN信息, 2, 固件版本信息, 3 生成版本信息, 4 EMID信息, 5 动态库版本信息
+ * @param	szVersionInfo: 输出 返回的版本信息
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_GetVersionInfo)(int iVerType, char szVersionInfo[]);
+
+
+
+
+/** 
+ * @fn		CRT_AutoBeel 
+ * @detail	读卡器自动蜂鸣
+ * @see		...
+ * @param	bAutoBeel: 是否自动蜂鸣,true 开启,false 关闭
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_AutoBeel)(bool bAutoBeel);
+
+
+
+
+/** 
+ * @fn		CRT_Beel 
+ * @detail	读卡器蜂鸣设置
+ * @see		...
+ * @param	MultipleTime: 蜂鸣时间:0.25秒的倍数,比如2,蜂鸣时间:2*0.25 即0.5秒(0-20 默认为1)
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_Beel)(int MultipleTime);
+
+
+
+
+/** 
+ * @fn		CRT_SetLightMode 
+ * @detail	设置读卡器指示灯模式
+ * @see		...
+ * @param	iType: 指示灯模式 0 自动模式, 1 手动模式
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_SetLightMode)(int iType);
+
+
+
+
+/** 
+ * @fn		CRT_GetLightMode 
+ * @detail	获取读卡器指示灯模式
+ * @see		...
+ * @return	0 自动模式,1 手动模式, 9模式未知
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_GetLightMode)();
+
+
+
+
+/** 
+ * @fn		CRT_SetLightStatus 
+ * @detail	设置读卡器指示灯状态
+ * @see		...
+ * @param	iYellowType: 黄色指示灯状态 0 关, 1 开, 2 闪烁
+ * @param	iBlueType:   蓝色指示灯状态 0 关, 1 开, 2 闪烁
+ * @param	iGreenType:  绿色指示灯状态 0 关, 1 开, 2 闪烁
+ * @param	iRedType:    红色指示灯状态 0 关, 1 开, 2 闪烁
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_SetLightStatus)(int iYellowType, int iBlueType, int iGreenType,  int iRedType);
+
+
+
+
+/** 
+ * @fn		CRT_SetLightStatus 
+ * @detail	获取读卡器指示灯状态
+ * @see		...
+ * @param	iYellowType: 输出 黄色指示灯状态 0 关, 1 开, 2 闪烁
+ * @param	iBlueType:   输出 蓝色指示灯状态 0 关, 1 开, 2 闪烁
+ * @param	iGreenType:  输出 绿色指示灯状态 0 关, 1 开, 2 闪烁
+ * @param	iRedType:    输出 红色指示灯状态 0 关, 1 开, 2 闪烁
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_GetLightStatus)(int* iYellowType, int* iBlueType, int* iGreenType,  int* iRedType);
+
+
+
+
+/** 
+ * @fn		CRT_BanTypeBCap 
+ * @detail	设置读卡器读取TYPE B卡能力
+ * @see		...
+ * @param	bBan: 是否关闭读TYPE B卡能力。 true 关闭, false 打开 
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_BanTypeBCap)(bool bBan);
+
+
+
+
+//***********************发送CRT603具体功能APDU命令****************************
+/** 
+ * @fn		CRT_LoadMifareKey 
+ * @detail	Mifare卡下载密码
+ * @see		...
+ * @param	ilocal:   密码存储位置。 0 临时性存储器, 1 非易失存储器
+ * @param	iKeyType: 密钥类型。 0 TYPE A类型, 1 TYPE B类型 
+ * @param	iKeyNum:  将保存到密钥组号(共0-15组) 
+ * @param	byInKeyData: 密码信息。 (共6位,如0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_LoadMifareKey)(int ilocal, int iKeyType, int iKeyNum, unsigned char byInKeyData[]);
+
+
+
+
+/** 
+ * @fn		CRT_CheckMifareKey 
+ * @detail	Mifare卡校验密码
+ * @see		...
+ * @param	iKeyType: 密钥类型。 0 TYPE A类型, 1 TYPE B类型 
+ * @param	iKeyNum:  已下载好的密钥组号(共0-15组) 
+ * @param	iBlockNum: 需校验的Mifare卡块号(0为起始位)
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_CheckMifareKey)(int iKeyType, int iKeyNum, int iBlockNum);
+
+
+
+
+/** 
+ * @fn		CRT_Read 
+ * @detail	非CPU卡读数据操作
+ * @see		...
+ * @param	bFilica: 是否为filica卡读操作。 true 是filica, false 非filica 
+ * @param	iBlockNum: 需读取的卡块号(0为起始位)
+ * @param	byReadData: 输出 读取到的数据
+ * @param	iReadDataLen: 输出 读取到的数据长度
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_Read)(bool bFilica, int iBlockNum, unsigned char byReadData[], int* iReadDataLen);
+
+
+
+
+/** 
+ * @fn		CRT_Write 
+ * @detail	非CPU卡写数据操作
+ * @see		...
+ * @param	bFilica: 是否为filica卡读操作。 true 是filica, false 非filica 
+ * @param	iBlockNum: 需写入的卡块号(0为起始位)
+ * @param	byWriteData: 写入到读卡器上的数据
+ * @param	iWriteLen: 写入到读卡器上的数据长度
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_Write)(bool bFilica, int iBlockNum, unsigned char byWriteData[], int iWriteLen);
+
+
+
+
+/** 
+ * @fn		CRT_GetCardUID 
+ * @detail	获取卡片UID信息
+ * @see		...
+ * @param	szUID: 输出 卡片的UID信息
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_GetCardUID)(char szUID[]);
+
+
+
+
+//***********************发送CRT603具体功能SAM卡命令****************************
+/** 
+ * @fn		CRT_SAMSlotActivation 
+ * @detail	SAM卡切换并激活卡座
+ * @see		...
+ * @param	iSlotNum: 需切换激活的卡座号 (1-4个,如 1表示SAM1卡座) 
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_SAMSlotActivation)(int iSlotNum);
+
+
+
+//***********************磁条卡操作命令****************************
+/** 
+ * @fn		CRT_ReadMagAllTracks
+ * @detail	读所有磁道操作
+ * @see		...
+ * @param	szTrack1: 磁道1数据 ‘Not’未读取到
+ * @param	szTrack2: 磁道2数据 ‘Not’未读取到
+ * @param	szTrack3: 磁道3数据 ‘Not’未读取到
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_ReadMagAllTracks)(char szTrack1[], char szTrack2[], char szTrack3[]);
+
+
+//***********************获取RF卡类型****************************
+/** 
+ * @fn		CRT_GetRFCardType 
+ * @detail	获取RF卡类型
+ * @see		...
+ * @return	0 无卡,1 TYPE A类型卡, 2 TYPE B类型卡, 3 身份证, 其他 失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_GetRFCardType)();
+
+
+//***********************读二代证信息命令****************************
+/** 
+ * @fn		CRT_ReadIDCardInifo 
+ * @detail	读二代证信息
+ * @see		...
+ * @param	crtdef_IdInfo: 输出,读取到的二代证信息
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef int (*pCRT_ReadIDCardInifo)(CRTDef_IDInfo* crtdef_IdInfo);
+
+
+
+
+/** 
+ * @fn		CRT_M1ValueProcess 
+ * @detail	M1卡值操作
+ * @see		...
+ * @param	iMode: 输入,操作模式。 1 初始化钱包, 2 增值, 3 减值
+ * @param	iBlock: 输入,操作块区。 需绝对地址
+ * @param	iValue: 输入,操作金额
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2016/9/19
+ */
+typedef int (*pCRT_M1ValueProcess)(int iMode, int iBlock, int iValue);
+
+
+
+/** 
+ * @fn		CRT_M1InquireBalance 
+ * @detail	M1卡查询余额
+ * @see		...
+ * @param	iBlock: 输入,操作块区。 需绝对地址
+ * @param	iValue: 输出,查询到的金额值
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2016/9/19
+ */
+typedef int (*pCRT_M1InquireBalance)(int iBlock, int* iValue);
+
+
+
+/** 
+ * @fn		CRT_M1BackBlock 
+ * @detail	M1卡备份钱包
+ * @see		...
+ * @param	iBlock: 输入,需备份块区。 需绝对地址
+ * @param	iBackBlock: 输入,备份到块区。 需绝对地址
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2016/9/19
+ */
+typedef int (*pCRT_M1BackBlock)(int iBlock, int iBackBlock);
+
+
+
+/** 
+ * @fn		CRT_GetIDFinger 
+ * @detail	获取二代证指纹信息
+ * @see		...
+ * @param	byFinger: 输出,获取到的指纹信息(一般为1024个字节)
+ * @param	iFingerLen: 输出,指纹信息长度
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2016/10/27
+ */
+typedef int (*pCRT_GetIDFinger)(unsigned char byFinger[], int *iFingerLen);
+
+
+
+/** 
+ * @fn		CRT_GetIDFinger 
+ * @detail	获取二代证DN号
+ * @see		...
+ * @param	szDNNums: 输出,获取到的DN号
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2016/10/30
+ */
+typedef int (*pCRT_GetIDDNNums)(char szDNNums[]);
+
+
+
+/** 
+ * @fn		CRT_GetSAMID 
+ * @detail	获取身份证盒子SAM ID
+ * @see		...
+ * @param	szSAMID: 输出,获取到的SAM ID
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2016/10/30
+ */
+typedef int (*pCRT_GetSAMID)(char szSAMID[]);
+
+
+
+/** 
+ * @fn		CRT_SwitchRF 
+ * @detail	读卡器开关射频场
+ * @see		...
+ * @param	iMode: 输入 开关射频场方式,0 开启, 1 关闭
+ * @return	0 成功,非0失败
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2016/10/30
+ */
+typedef int (*pCRT_SwitchRF)(int iMode);
+
+
+
+//***********************获取最后一次错误描叙****************************
+/** 
+ * @fn		CRT_GetLastError 
+ * @detail	获取最后一次错误描叙
+ * @see		...
+ * @return	获取信息
+ * @exception ...
+ *
+ * @author	luowei
+ * @date	2015/12/1
+ */
+typedef char* (*pCRT_GetLastError)();
+
+
+
+class CPcscLibrary
+{
+//对外接口函数
+public:
+    bool Load(const char* lpDllPath, char* ErrorInfo);
+	bool IsLoadSucceed();
+    pCRT_OpenConnect          OpenConnect ;
+    pCRT_CloseConnect         CloseConnect;
+    pCRT_GetReaderListName    GetReaderListName;
+    pCRT_SetReaderName        SetReaderName;
+    pCRT_GetReaderType        GetReaderType;
+    pCRT_GetCardStatus        GetCardStatus;
+    pCRT_EjectCard            EjectCard;
+    pCRT_ReaderConnect        ReaderConnect;
+    pCRT_SendApdu             SendApdu;
+    pCRT_SendControlCMD       SendControlCMD;
+    pCRT_HotReset             HotReset;
+    pCRT_SetReaderType        SetReaderType;
+    pCRT_GetVersionInfo       GetVersionInfo;
+    pCRT_AutoBeel	          AutoBeel;
+    pCRT_Beel                 Beel;
+    pCRT_SetLightMode	      SetLightMode;
+    pCRT_GetLightMode         GetLightMode;
+    pCRT_SetLightStatus       SetLightStatus;
+    pCRT_GetLightStatus       GetLightStatus;
+    pCRT_BanTypeBCap          BanTypeBCap;
+    pCRT_LoadMifareKey        LoadMifareKey;
+    pCRT_CheckMifareKey       CheckMifareKey;
+    pCRT_Read                 Read;
+    pCRT_Write                Write;
+    pCRT_GetCardUID           GetCardUID;
+    pCRT_SAMSlotActivation    SAMSlotActivation;
+    pCRT_ReadMagAllTracks     ReadMagAllTracks;
+    pCRT_GetRFCardType        GetRFCardType;
+    pCRT_ReadIDCardInifo      ReadIDCardInifo;
+    pCRT_M1ValueProcess       M1ValueProcess;
+    pCRT_M1InquireBalance     M1InquireBalance;
+    pCRT_M1BackBlock          M1BackBlock;
+    pCRT_GetIDFinger          GetIDFinger;
+    pCRT_GetIDDNNums          GetIDDNNums;
+    pCRT_GetSAMID             GetSAMID;
+    pCRT_SwitchRF             SwitchRF;
+    pCRT_GetLastError         GetLastError;
+
+
+private:
+	void *  hModule;
+	bool returnValue;
+
+public:
+    CPcscLibrary(void);
+    ~CPcscLibrary(void);
+};
+
+#endif //__LoadLibrary_H__

+ 59 - 0
DevAdapter/cw/contactlesscard.1.1/contactlessdev.cpp

@@ -0,0 +1,59 @@
+#include "contactlessimpl.h"
+#include "log4vendor.h"
+
+
+ContactlessCardImpl*     g_pRFICDev = NULL;
+
+void __attribute__((destructor)) uninit()
+{
+    if (g_pRFICDev)
+    {
+        delete g_pRFICDev;
+        g_pRFICDev = NULL;
+    }
+}
+
+void __attribute__((constructor)) init()
+{
+}
+
+
+
+DEVICEBASE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(NULL == g_pRFICDev)
+    {
+        g_pRFICDev = new ContactlessCardImpl();
+        baseObj = (DeviceBaseClass *)g_pRFICDev;
+
+        cmb::log_init_config config;
+        config.log_level=CMB_LOG_LEVEL_ALL;
+        config.dev_name = "ContactlessCard";
+    #if defined(_MSC_VER)
+        config.log_dir = ("C:\\rvc\\dbg\\");
+    #else
+        config.log_dir = ("/opt/rvc/dbg/");
+    #endif //_MSC_VER
+        std::string str;
+        cmb::log4vendor::init(config, str);
+        printf("init after: %s\n", str.c_str());
+    }
+    else
+    {
+        eRt = Error_AlreadyExist;
+    }
+    return eRt;
+
+}
+DEVICEBASE_API ErrorCodeEnum  ReleaseDevComponent(DeviceBaseClass *&pBaseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(pBaseObj == (DeviceBaseClass*)g_pRFICDev)
+    {
+        delete g_pRFICDev;
+        g_pRFICDev = NULL;
+        return Error_Succeed;
+    }
+    return Error_Param;
+}

+ 361 - 0
DevAdapter/cw/contactlesscard.1.1/contactlessimpl.cpp

@@ -0,0 +1,361 @@
+#include "contactlessimpl.h"
+#include "cmb.h"
+
+#define DEVICE_NAME "CREATOR CRT-603 (CZ1) CCR RF 0"
+
+ContactlessCardImpl::ContactlessCardImpl()
+{
+    m_pConnect = new CPcscLibrary();
+    m_bCardConn = false;
+}
+
+ContactlessCardImpl::~ContactlessCardImpl()
+{
+    delete m_pConnect;
+}
+
+ErrorCodeEnum ContactlessCardImpl::DevOpen(DWORD dwPort,DWORD dwBaudRate)
+{
+    LOG4VTM_FUNCTION();
+
+    char cFilePath[300] = {0};
+    GetCurLibsPath(m_sLibPath, cFilePath);
+
+    sprintf(cFilePath, "DevOpen GetCurProcPath = %s", m_sLibPath);
+    LOG4VTM(INFO, cFilePath);
+    sprintf(cFilePath, "%s/cw/libcw.CRT_603.so", m_sLibPath); //usr symbolic link to point the real so
+
+    bool bOK = m_pConnect->Load(cFilePath, cFilePath);
+    if (!bOK) return GetErrorInfo(PCSC_HARDWARE_ERROR, "DevOpen");
+    int iCount = 0;
+    int iRt = m_pConnect->OpenConnect(&iCount);
+    if (iRt != 0)
+        return GetErrorInfo(PCSC_HARDWARE_ERROR, "DevOpen OpenConnect %d", iRt);
+    iRt = m_pConnect->SetReaderName(0);
+    if (iRt != 0)
+        return GetErrorInfo(PCSC_HARDWARE_ERROR, "DevOpen SetReaderName %d", iRt);
+    return GetErrorInfo(0, "DevOpen %d", iRt);
+}
+
+int getFileVer(char* sFile, short& ch1, short& ch2)
+{
+    ch1 = 0;
+    ch2 = 0;
+    char* pFind = strstr(sFile, ".so");
+    char* pTemp = pFind;
+    while (pTemp)
+    {
+        pFind = pTemp;
+        pTemp = strstr(pFind + 3, ".so");
+    }
+    if (pFind == NULL) return 0;
+
+    pTemp = pFind - 1;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch2 = atoi(pTemp+1);
+    pTemp--;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch1 = atoi(pTemp+1);
+    return 1;
+}
+
+ErrorCodeEnum ContactlessCardImpl::GetDevCategory(DevCategoryInfo &devCategory)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pConnect->IsLoadSucceed())
+        return GetErrorInfo(PCSC_NOT_OPEN, "GetDevCategory");
+
+    ErrorCodeEnum err = Error_Succeed;
+
+    char sSer[256];
+    memset(sSer, 0, sizeof(sSer));
+    if (m_pConnect->GetVersionInfo(2, sSer) == 0)
+    {
+        sSer[32] = 0;
+        strcpy(devCategory.szType, sSer);
+    }
+    else
+        strcpy(devCategory.szType, DEVICE_NAME);
+    strcpy(devCategory.szModel, "WID=Cashway001");
+    strcpy(devCategory.szVendor, "cw");
+
+    char cFilePath[300] = {0};
+    GetCurLibsPath(m_sLibPath, cFilePath);
+    short v1,v2;
+    getFileVer(cFilePath, v1, v2);
+
+    devCategory.version.wMajor = v1;
+    devCategory.version.wMinor = v2;
+    devCategory.version.wRevision = 0xffff;
+    devCategory.version.wBuild = FILE_VERSION;
+    char szRet[512] = {0};
+    sprintf(szRet, "szType:%s,szModel:%s,szVendor:%s,version.wMajor:%d,version.wMinor:%d,version.wBuild:%d,version.wRevision:%d,eState:%d(0:故障1:正常)",
+            devCategory.szType,devCategory.szModel,devCategory.szVendor,devCategory.version.wMajor,devCategory.version.wMinor,devCategory.version.wBuild,devCategory.version.wRevision,devCategory.eState);
+    LOG4VTM(INFO, szRet);
+
+    return Error_Succeed;
+}
+
+ErrorCodeEnum ContactlessCardImpl::Reset()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pConnect->IsLoadSucceed())
+        return GetErrorInfo(PCSC_NOT_OPEN, "Reset");
+
+    m_pConnect->CloseConnect();
+    int iCount = 0;
+    int iRt = m_pConnect->OpenConnect(&iCount);
+    if (iRt != 0)
+        return GetErrorInfo(PCSC_HARDWARE_ERROR, "Reset OpenConnect %d", iRt);
+    iRt = m_pConnect->SetReaderName(0);
+    if (iRt != 0)
+        return GetErrorInfo(PCSC_HARDWARE_ERROR, "Reset SetReaderName %d", iRt);
+    return GetErrorInfo(0, "Reset %d", iRt);
+}
+
+ErrorCodeEnum ContactlessCardImpl::DevClose()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pConnect->IsLoadSucceed())
+        return GetErrorInfo(PCSC_NOT_OPEN, "DevClose");
+
+    m_pConnect->CloseConnect();
+    ErrorCodeEnum err = Error_Succeed;
+    return err;
+}
+
+//  DEC_SUCCESS DEC_HARDWARE DEC_TIMEOUT DEC_INVALID_PARAMETER DEC_INVALID_MASTER_KEY
+const static CmbErrorDef RFICErrorDat[] = {
+    {0,                 "成功", Error_Succeed, DEC_SUCCESS},
+    {PCSC_NOT_OPEN,     "设备没有打开", Error_Hardware, DEC_DEV_NOT_OPENED},
+    {PCSC_HARDWARE_ERROR,"设备硬件故障", Error_Hardware, DEC_HARDWARE},
+    {PCSC_TIMEOUT,      "设备响应超时", Error_DevCommFailed, DEC_TIMEOUT},
+    {PCSC_PARA_ERR,     "传入参数错误", Error_Param, DEC_INVALID_PARAMETER},
+    {PCSC_NOT_CONN,     "未建立连接", Error_DevMedia, DEC_INVALID_PARAMETER},
+    {PCSC_NO_CARD,      "未检测到卡", Error_DevMedia, DEC_INVALID_PARAMETER},
+    {-105,              "卡已经移除", Error_DevMedia, DEC_INVALID_PARAMETER},
+};
+
+ErrorCodeEnum ContactlessCardImpl::GetErrorInfo(int iCode, char* sErr, ...)
+{
+    size_t iLenOne = sizeof(CmbErrorDef);
+    size_t iLenAll = sizeof(RFICErrorDat);
+    int iCount = iLenAll / iLenOne;
+    char sErrInfo[256]="";
+    DWORD dSta = 0;
+    int iErr = -1;
+    for (int ia = 0; ia < iCount; ia++)
+    {
+        if (RFICErrorDat[ia].iCode == iCode)
+        {
+            dSta = RFICErrorDat[ia].iInf;
+            strcpy(sErrInfo, RFICErrorDat[ia].sInf);
+            iErr = RFICErrorDat[ia].iRet;
+            break;
+        }
+    }
+
+    char sErrAll[300];
+    va_list arglist;
+    va_start(arglist, sErr);
+    _vsnprintf(sErrAll, 128, sErr, arglist);
+    va_end(arglist);
+
+    if (sErrInfo[0])
+    {
+        strcat(sErrAll, " ");
+        strcat(sErrAll, sErrInfo);
+    }
+    sErrAll[200] = 0;
+    iLenOne = strlen(sErrAll);
+    sprintf(m_DevErrInfo.szErrMsg, "{\"ErrCode\":\"%04x\",\"Description\":\"%s\"}", iErr, sErrAll);
+//    strcpy(m_DevErrInfo.szErrMsg, sErrAll);
+    m_DevErrInfo.dwErrMsgLen = ((dSta << 16) & 0xffff0000) + iLenOne;
+    if (iErr != Error_Succeed)
+        LOG4VTM(WARN, m_DevErrInfo.szErrMsg);
+    else
+        LOG4VTM(INFO, m_DevErrInfo.szErrMsg);
+    return (ErrorCodeEnum)iErr;
+}
+
+ErrorCodeEnum ContactlessCardImpl::GetLastErr(DevErrorInfo &devErrInfo)
+{
+    memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
+    return Error_Succeed;
+}
+
+//
+ErrorCodeEnum ContactlessCardImpl::GetDevStatus(RFICReaderStatus& devStatus)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pConnect->IsLoadSucceed())
+        return GetErrorInfo(PCSC_NOT_OPEN, "GetDevStatus");
+    int ia = m_pConnect->GetCardStatus();
+    switch(ia){
+    case 1:
+        devStatus.eMediaPos = CI_MEDIA_RF;
+        break;
+    case 2:
+        devStatus.eMediaPos = CI_MEDIA_NOTPRESENT;
+        m_bCardConn = false;
+        break;
+    default:
+        devStatus.eMediaPos = CI_MEDIA_NOTPRESENT;
+        m_bCardConn = false;
+    }
+    return Error_Succeed;
+}
+//
+//	Abort current operation.
+//
+ErrorCodeEnum ContactlessCardImpl::AbortRead()
+{
+    return Error_Succeed;
+}
+//
+//	Active contactless card(Type A,B,Mifare)
+//	The first,second,third activation order decided by fstType,scdType,thdType respectively
+//	fstType,scdType,thdType can be one of 'A','B','M','0'(30H,no type)
+//	outType indicates the type of  activation result
+//
+ErrorCodeEnum ContactlessCardImpl::ActiveContactlessICCard(char fstType, char scdType, char thdType, char& outType)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pConnect->IsLoadSucceed())
+        return GetErrorInfo(PCSC_NOT_OPEN, "ActiveContactlessICCard");
+
+    BYTE byAtrData[256] =  {0};
+    int iAtrLen = 0;
+    m_bCardConn = false;
+    int iRet = m_pConnect->ReaderConnect(byAtrData, &iAtrLen);
+    if (iRet != 0 || iAtrLen < 1)
+    {
+        outType = '0';
+        return GetErrorInfo(PCSC_NO_CARD, "ActiveContactlessICCard ReaderConnect %d %s", iRet, m_pConnect->GetLastError());
+    }
+    char sHexData[512];
+    ::ANSIToHexStr(byAtrData, iAtrLen, sHexData);
+    printf("ATR %d %s\n", iAtrLen, sHexData);
+    outType = 'A';
+    if (strcmp(sHexData, "3B8F8001804F0CA000000306030001E00000018B") == 0)
+        outType = '0';
+    if (strcmp(sHexData, "3B8F8001804F0CA000000306030001000000006A") == 0)  // 公交卡、房卡
+        outType = 'M';
+    if (strcmp(sHexData, "3B8F8001804F0CA0000003060300020000000069") == 0)
+        outType = 'M';
+    if (strcmp(sHexData, "3B8F8001804F0CA000000306030001E00000018B") == 0)
+        outType = '0';
+
+//    if (strcmp(sHexData, "3B8E800180318066B1C5240100ED83009000F7") == 0)  //
+//        outType = '2';
+    if (iAtrLen == 13 && strstr(sHexData, "3B888001D103"))   //身份证
+        outType = 'B';
+
+    m_bCardConn = true;
+    return GetErrorInfo(iRet, "ActiveContactlessICCard");
+}
+//
+//	Deactivate contactless IC card
+//
+ErrorCodeEnum ContactlessCardImpl::DeactContactlessICCard()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pConnect->IsLoadSucceed())
+        return GetErrorInfo(PCSC_NOT_OPEN, "DeactContactlessICCard");
+
+    m_bCardConn = false;
+    int iRet = m_pConnect->EjectCard();
+    if (iRet == 0)
+        return GetErrorInfo(0, "DeactContactlessICCard");
+    return GetErrorInfo(PCSC_HARDWARE_ERROR, "ActiveCDeactContactlessICCard %d", iRet);;
+}
+//
+//	Warm reset card(IC)
+//
+ErrorCodeEnum ContactlessCardImpl::WarmReset()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pConnect->IsLoadSucceed())
+        return GetErrorInfo(PCSC_NOT_OPEN, "WarmReset");
+
+    m_bCardConn = false;
+    if (m_pConnect->GetCardStatus() != 1)
+        return GetErrorInfo(PCSC_NO_CARD, "WarmReset");
+    int iRet = m_pConnect->EjectCard();
+    if (iRet != 0)
+        return GetErrorInfo(iRet, "WarmReset");
+
+    BYTE byAtrData[256] =  {0};
+    int iAtrLen = 0;
+    iRet = m_pConnect->ReaderConnect(byAtrData, &iAtrLen);
+    if (iRet == 0)
+    {
+        m_bCardConn = true;
+        return GetErrorInfo(0, "WarmReset");
+    }
+    return GetErrorInfo(PCSC_HARDWARE_ERROR, "WarmReset %d", iRet);;
+}
+//
+//	Mifare operation
+//	Arguments:
+//	- eFunType:function type as load key,authentication and so on
+//	- return/data(hex) byte order like BIG EDIAN. ex:0x12345678 --> data[i] = 0x12,data[i+1] = 0x34,data[i+2] = 0x56,data[i+3] = 0x78
+//	- sendBuf:[parameter(hex)][data(hex)]
+//	- recvBuf:[status(1byte)][return data(hex)]
+//		-- [eFunType],[parameter,data],[status(1byte),return data]
+//		-- [CI_MIFARE_LOAD_KEY],[key select(1byte),sector num(1byte),uncoded keys(6bytes)],[status(1byte)]
+//		-- [CI_MIFARE_AUTH],[key select(1byte),sector num(1byte)],[status(1byte)]
+//		-- [CI_MIFARE_READ],[block num(1byte)],[status(1byte),data(16bytes)]
+//		-- [CI_MIFARE_WRITE],[block num(1byte),data(16bytes)],[status(1byte)]
+//		-- [CI_MIFARE_INC],[source block num(1byte),destination block num(1byte),inc value(4bytes)],[status(1byte)]
+//		-- [CI_MIFARE_DEC],[source block num(1byte),destination block num(1byte),dec value(4bytes)],[status(1byte)]
+//		-- key select(1byte):AKey(00h),BKey(01h)
+//		-- status(1byte):OK(00h),other error code(!00h)
+
+ErrorCodeEnum ContactlessCardImpl::MifareCommand(MifareFuctionEnum eFunType, CmdInfo sendBuf, CmdInfo& recvBuf)
+{
+    LOG4VTM_FUNCTION();
+    return Error_NotImpl;
+}
+//
+//	RF Type A,B command.
+//	APDU:Application Protocol Data Unit
+//	Arguments:
+// 	- CmdSend.lpCmd:Command-APDU
+// 	- CmdRecv.lpData:Response-APDU
+//
+ErrorCodeEnum ContactlessCardImpl::RFTypeABCommand(CmdInfo sendBuf, CmdInfo& recvBuf)
+{
+    LOG4VTM_FUNCTION();
+    if (m_bCardConn == false)
+        return GetErrorInfo(PCSC_NOT_CONN, "RFTypeABCommand");
+
+    unsigned char sAnsi[1024];
+    int iRetCount = 0;
+    ::HexStrToANSI((char*)sendBuf.data, sAnsi, sendBuf.dwSize);
+    int iRet = m_pConnect->SendApdu(sAnsi, sendBuf.dwSize << 1, sAnsi, &iRetCount);
+    if (iRet != 0)
+        return GetErrorInfo(iRet, "RFTypeABCommand SendApdu %d %s", iRet, m_pConnect->GetLastError());
+    ::ANSIToHexStr(sAnsi, iRetCount, (char*)recvBuf.data);
+    recvBuf.dwSize = iRetCount << 1;
+    return Error_Succeed;
+}
+
+//halt card
+//card have been halted must move from induction zone then can be found again
+ErrorCodeEnum ContactlessCardImpl::HaltCard()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pConnect->IsLoadSucceed())
+        return GetErrorInfo(PCSC_NOT_OPEN, "HaltCard");
+
+    int iRet = m_pConnect->EjectCard();
+    if (iRet == 0)
+    {
+        m_bCardConn = false;
+        return GetErrorInfo(0, "HaltCard");
+    }
+    return GetErrorInfo(PCSC_HARDWARE_ERROR, "HaltCard %d", iRet);;
+}

+ 93 - 0
DevAdapter/cw/contactlesscard.1.1/contactlessimpl.h

@@ -0,0 +1,93 @@
+#ifndef LIBFRAMEWORK_CONTACTLESSCARD_IMPL_H
+#define LIBFRAMEWORK_CONTACTLESSCARD_IMPL_H
+
+#include "RFICClass.h"
+#include "PcscLibrary.h"
+
+#define PCSC_SUCCESS				 0	// command succeeded
+#define PCSC_NOT_OPEN				-1	// command succeeded
+#define PCSC_HARDWARE_ERROR         -2	// command failed because of hardware error
+#define PCSC_TIMEOUT				-3	// wait for user interaction timed out
+#define PCSC_PARA_ERR				-4	//
+#define PCSC_NOT_CONN				-5	//未连接卡片
+#define PCSC_NO_CARD				-12	//
+
+#define FILE_VERSION    1
+
+class ContactlessCardImpl : public RFICClass
+{
+public:
+    ContactlessCardImpl();
+    ~ContactlessCardImpl();
+
+
+    //DeviceBaseClass
+    virtual ErrorCodeEnum DevOpen(DWORD dwPort,DWORD dwBaudRate);
+    virtual ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
+    virtual ErrorCodeEnum Reset();
+    virtual ErrorCodeEnum DevClose();
+    virtual ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+
+    //
+//	Get card reader status
+//
+    virtual ErrorCodeEnum GetDevStatus(RFICReaderStatus& devStatus);
+    //
+    //	Abort current operation.
+    //
+    virtual ErrorCodeEnum AbortRead();
+    //
+    //	Active contactless card(Type A,B,Mifare)
+    //	The first,second,third activation order decided by fstType,scdType,thdType respectively
+    //	fstType,scdType,thdType can be one of 'A','B','M','0'(30H,no type)
+    //	outType indicates the type of  activation result
+    //
+    virtual ErrorCodeEnum ActiveContactlessICCard(char fstType, char scdType, char thdType, char& outType);
+    //
+    //	Deactivate contactless IC card
+    //
+    virtual ErrorCodeEnum DeactContactlessICCard();
+    //
+    //	Warm reset card(IC)
+    //
+    virtual ErrorCodeEnum WarmReset();
+    //
+    //	Mifare operation
+    //	Arguments:
+    //	- eFunType:function type as load key,authentication and so on
+    //	- return/data(hex) byte order like BIG EDIAN. ex:0x12345678 --> data[i] = 0x12,data[i+1] = 0x34,data[i+2] = 0x56,data[i+3] = 0x78
+    //	- sendBuf:[parameter(hex)][data(hex)]
+    //	- recvBuf:[status(1byte)][return data(hex)]
+    //		-- [eFunType],[parameter,data],[status(1byte),return data]
+    //		-- [CI_MIFARE_LOAD_KEY],[key select(1byte),sector num(1byte),uncoded keys(6bytes)],[status(1byte)]
+    //		-- [CI_MIFARE_AUTH],[key select(1byte),sector num(1byte)],[status(1byte)]
+    //		-- [CI_MIFARE_READ],[block num(1byte)],[status(1byte),data(16bytes)]
+    //		-- [CI_MIFARE_WRITE],[block num(1byte),data(16bytes)],[status(1byte)] 
+    //		-- [CI_MIFARE_INC],[source block num(1byte),destination block num(1byte),inc value(4bytes)],[status(1byte)]
+    //		-- [CI_MIFARE_DEC],[source block num(1byte),destination block num(1byte),dec value(4bytes)],[status(1byte)]
+    //		-- key select(1byte):AKey(00h),BKey(01h)
+    //		-- status(1byte):OK(00h),other error code(!00h)
+
+    virtual ErrorCodeEnum MifareCommand(MifareFuctionEnum eFunType, CmdInfo sendBuf, CmdInfo& recvBuf);
+
+    //
+    //	RF Type A,B command.
+    //	APDU:Application Protocol Data Unit
+    //	Arguments:
+    // 	- CmdSend.lpCmd:Command-APDU
+    // 	- CmdRecv.lpData:Response-APDU
+    //
+    virtual ErrorCodeEnum RFTypeABCommand(CmdInfo sendBuf, CmdInfo& recvBuf);
+    //halt card
+    //card have been halted must move from induction zone then can be found again
+    virtual ErrorCodeEnum HaltCard();
+private:
+    CPcscLibrary*       m_pConnect;
+    ErrorCodeEnum       GetErrorInfo(int iCode, char* sErr, ...);
+    DevErrorInfo        m_DevErrInfo;
+    char                m_sLibPath[260];
+    bool                m_bCardConn;
+};
+
+
+#endif //LIBFRAMEWORK_CONTACTLESSCARD_IMPL_H

+ 4 - 2
DevAdapter/cw/deps/cw.baseio/serial.cpp

@@ -255,10 +255,11 @@ int SSerial::Send(const char *sData, int iLen, int iTimeout)
         nBytesThisTime = SendOnce(sData, iLen - nBytesSent, iTimeWait);
         if (nBytesThisTime < 0) return -1;
         nBytesSent += nBytesThisTime;
+        if (nBytesSent >= iLen) break;
         sData += nBytesThisTime;
         Sleep(10);
         iNow = GetSystemTime();
-    }while(nBytesSent < iLen && iNow < iEnd);
+    }while(iNow < iEnd);
     return nBytesSent;
 }
 
@@ -279,10 +280,11 @@ int SSerial::Receive ( char *sData, int iLen, int iTimeout )
         nBytesThisTime = ReceiveOnce(sData, iLen - nBytesRead, iTimeWait);
         if (nBytesThisTime < 0) return nBytesRead;
         nBytesRead += nBytesThisTime;
+        if (nBytesRead >= iLen) break;
         sData += nBytesThisTime;
         Sleep(10);
         iNow = GetSystemTime();
-    }while(nBytesRead < iLen && iNow < iEnd);
+    }while(iNow < iEnd);
 
     if (nBytesRead)
         return nBytesRead;

+ 47 - 0
DevAdapter/cw/hspscanner.1.1/CMakeLists.txt

@@ -0,0 +1,47 @@
+
+# 声明模块名称的前缀和名称
+rvc_dev_define_module("HSPScanner")
+# rvc_dev_config_library 内需要使用这三个参数,用于拼接输出的适配器文件名称
+
+set(${MODULE_PREFIX}_VENDOR "cw")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+if(RVC_INTEGRATE_BUILD)
+	conan_cmake_run( REQUIRES opencv/3.1.0@LR04.02_ThirdParty/stable BASIC_SETUP CMAKE_TARGETS)
+	set(OpenCV_INCLUDE_DIRS ${CONAN_INCLUDE_DIRS_OPENCV})
+	set(OpenCV_LIBS ${CONAN_LIBS_OPENCV})
+else()
+#	find_package(OpenCV REQUIRED)
+#	include_directories(${OpenCV_INCLUDE_DIRS})
+endif(RVC_INTEGRATE_BUILD)
+
+find_package (Qt5 COMPONENTS Core Gui Widgets REQUIRED)
+
+# 包含要编译的实现文件,rvc_dev_config_library 内使用
+set(${MODULE_PREFIX}_SRCS SHARED
+		hspscannerimpl.cpp hspscannerdev.cpp  hspscannerform.cpp
+		hspscannerimpl.h   hspscannerform.h
+)
+
+# 适配器工程需要通过此宏替代 add_library
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+# ${MODULE_FULL_NAME} 是 TAGET 名称,在 rvc_dev_config_library 中定义
+target_include_directories(${MODULE_FULL_NAME} PRIVATE ${VENDOR_CURRENT_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS})
+target_link_directories(${MODULE_FULL_NAME} PRIVATE ${CONAN_LIB_DIRS_OPENCV})
+target_link_libraries(${MODULE_FULL_NAME} baseio ${VENDOR_LOG_LIB_NAME} ${OpenCV_LIBS})
+#target_link_libraries(${MODULE_FULL_NAME} )
+
+#qt5_use_modules(${MODULE_FULL_NAME} Core Gui Widgets)
+
+SET(LIBRARY_OUTPUT_PATH ${VENDOR_CURRENT_LIB_DIR})
+
+#  =-=-=-=-=-=-=-=-=-= {适配器工程}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
+rvc_dev_target_install(${MODULE_FULL_NAME})
+
+target_link_libraries(${MODULE_FULL_NAME}
+		Qt5::Core
+		Qt5::Gui
+		Qt5::Widgets rt dl
+		)

+ 61 - 0
DevAdapter/cw/hspscanner.1.1/hspscannerdev.cpp

@@ -0,0 +1,61 @@
+#include "hspscannerimpl.h"
+#include "log4vendor.h"
+
+HSPSClassImpl*     g_pHSPSDevice = NULL;
+
+
+void __attribute__((destructor)) uninit()
+{
+    if (g_pHSPSDevice)
+    {
+        delete g_pHSPSDevice;
+        g_pHSPSDevice = NULL;
+    }
+}
+
+void __attribute__((constructor)) init()
+{
+}
+
+
+
+DEVICEBASE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(NULL == g_pHSPSDevice)
+    {
+        g_pHSPSDevice = new HSPSClassImpl();
+        baseObj = (DeviceBaseClass *)g_pHSPSDevice;
+
+        cmb::log_init_config config;
+        config.log_level=CMB_LOG_LEVEL_ALL;
+        config.dev_name = "HSPScanner";
+    #if defined(_MSC_VER)
+        config.log_dir = ("C:\\rvc\\dbg\\");
+    #else
+        config.log_dir = ("/opt/rvc/dbg/");
+    #endif //_MSC_VER
+        std::string str;
+        cmb::log4vendor::init(config, str);
+        printf("init after: %s\n", str.c_str());
+    }
+    else
+    {
+        eRt = Error_AlreadyExist;
+    }
+    return eRt;
+}
+
+DEVICEBASE_API ErrorCodeEnum  ReleaseDevComponent(DeviceBaseClass *&pBaseObj)
+{
+
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(pBaseObj == (DeviceBaseClass*)g_pHSPSDevice)
+    {
+        delete g_pHSPSDevice;
+        g_pHSPSDevice = NULL;
+        return Error_Succeed;
+    }
+    return Error_Param;
+}
+

+ 256 - 0
DevAdapter/cw/hspscanner.1.1/hspscannerform.cpp

@@ -0,0 +1,256 @@
+#include "hspscannerform.h"
+#include "ui_hspscannerform.h"
+
+HSPScannerForm::HSPScannerForm(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::HSPScannerForm)
+{
+    ui->setupUi(this);
+
+    Qt::WindowFlags flags = windowFlags();
+    this->setWindowFlags(flags | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
+
+    m_ViewTimer = new QTimer(this);
+    connect(m_ViewTimer, SIGNAL(timeout()),this,SLOT(onCamTimer()));
+
+    m_bIsGrey = false;
+    m_bIsOpen = m_bIsView = false;
+    m_bIsHide = true;
+    m_iRotate = 0;
+    m_iScanSz = 0;
+    m_iCamIdx = -1;
+    SetPos(1080, 0, 384,216);
+    m_dA4Pos[0] = 0.07;
+    m_dA4Pos[1] = 0.07;
+    m_dA4Pos[2] = 0.93;
+    m_dA4Pos[3] = 0.93;
+
+    m_dIDPos[0] = 0.35;
+    m_dIDPos[1] = 0.35;
+    m_dIDPos[2] = 0.65;
+    m_dIDPos[3] = 0.65;
+
+    m_iCamAll[0] = 2560;
+    m_iCamAll[1] = 1440;
+}
+
+HSPScannerForm::~HSPScannerForm()
+{
+    delete ui;
+    delete m_ViewTimer;
+}
+
+void    HSPScannerForm::SetPos(int iX, int iY, int iW, int iH)
+{
+    this->move(iX, iY);
+    ui->labViewPos->move(0, 0);
+    this->resize(iW, iH);
+    ui->labViewPos->resize(iW, iH);
+    ui->labViewPos->setAlignment(Qt::AlignCenter);
+    QPalette label_palette;
+    label_palette.setColor(QPalette::Background, QColor(200, 200, 200));
+    ui->labViewPos->setAutoFillBackground(true);
+    ui->labViewPos->setPalette(label_palette);
+}
+
+void    HSPScannerForm::SetSize(float dA4[4], float dID[4], int iAll[2])
+{
+    memcpy(m_dA4Pos, dA4, sizeof(m_dA4Pos));
+    memcpy(m_dIDPos, dID, sizeof(m_dIDPos));
+    memcpy(m_iCamAll, iAll, sizeof(m_iCamAll));
+}
+
+QImage  HSPScannerForm::Mat2QImage(cv::Mat cvImg)
+{
+    QImage qImg;
+    if(cvImg.channels()==3)                             //3 channels color image
+    {
+        qImg =QImage((const unsigned char*)(cvImg.data),
+                     cvImg.cols, cvImg.rows,
+                     cvImg.cols*cvImg.channels(),
+                     QImage::Format_RGB888);
+    }
+    else if(cvImg.channels()==1)                    //grayscale image
+    {
+        qImg =QImage((const unsigned char*)(cvImg.data),
+                     cvImg.cols,cvImg.rows,
+                     cvImg.cols*cvImg.channels(),
+                     QImage::Format_Indexed8);
+    }
+    else
+    {
+        qImg =QImage((const unsigned char*)(cvImg.data),
+                     cvImg.cols,cvImg.rows,
+                     cvImg.cols*cvImg.channels(),
+                     QImage::Format_RGB888);
+    }
+    return qImg.rgbSwapped();
+}
+
+#include "cmb.h"
+void HSPScannerForm::onCamTimer()
+{
+    cv::Mat mMat1, mMat2;
+
+    LOG4VTM(WARN, "Read Start!");
+    m_cvCamera.read(mMat1);
+    LOG4VTM(WARN, "Read End!");
+    cv::Size size = mMat1.size();
+    if (mMat1.empty())
+    {
+        m_cvCamera.release();
+        m_ViewTimer->stop();
+        m_bIsView = false;
+    }
+    if (m_bIsGrey)
+        cv::cvtColor(mMat1, mMat2, cv::COLOR_RGB2GRAY);
+    else
+        mMat2 = mMat1;
+
+    if (m_iScanSz == 0)
+    {
+        mMat1 = mMat2;
+        m_Capture = mMat1;
+    }
+    if (m_iScanSz == 1)
+    {
+        cv::Rect rA4((int)(size.width * m_dA4Pos[0]), (int)(size.height * m_dA4Pos[1]),
+                (int)(size.width * (m_dA4Pos[2] - m_dA4Pos[0])), (int)(size.height * (m_dA4Pos[3] - m_dA4Pos[1])));
+        mMat1  = cv::Mat(cv::Size(rA4.width, rA4.height), mMat2.type());
+        mMat2(rA4).convertTo(mMat1, mMat1.type(), 1, 0);
+        m_Capture = mMat1;
+    }
+    if (m_iScanSz == 2)
+    {
+        cv::Rect rID((int)(size.width * m_dIDPos[0]), (int)(size.height * m_dIDPos[1]),
+                (int)(size.width * (m_dIDPos[2] - m_dIDPos[0])), (int)(size.height * (m_dIDPos[3] - m_dIDPos[1])));
+
+        m_Capture  = cv::Mat(cv::Size(rID.width, rID.height), mMat2.type());
+        mMat2(rID).convertTo(m_Capture, m_Capture.type(), 1, 0);
+        mMat1 = mMat2;
+        rectangle(mMat1, rID, cv::Scalar(0,255,0));
+    }
+//*
+    if (m_iRotate == 0)
+        mMat2 = mMat1;
+    if (m_iRotate == 1)
+        cv::flip(mMat1.t(), mMat2, 1);
+    if (m_iRotate == 2)
+        cv::flip(mMat1.t(), mMat2, -1);
+    if (m_iRotate == 3)
+        cv::flip(mMat1.t(), mMat2, 0);
+//        cv::rotate(mMat1, mMat2, 0);
+/*/
+    mMat2 = mMat1;
+//*/
+    if (this->isHidden()) return;
+    QImage  image = Mat2QImage(mMat2);
+    QPixmap pixmap = QPixmap::fromImage(image);
+    int iH = height();
+    int iW = ((iH * pixmap.width()) / pixmap.height());
+    QPixmap fiPixmap = pixmap.scaled(iW, iH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+    ui->labViewPos->setPixmap(fiPixmap);
+}
+
+int HSPScannerForm::GetPic(const char* sFile)
+{
+    if (!m_cvCamera.isOpened()) return ERR_NOT_OPENED;
+    if (m_Capture.empty())  return ERR_VIEW_FAIL;
+
+    if (cv::imwrite(sFile, m_Capture)) return 0;
+    return ERR_VIEW_FAIL;
+}
+
+int HSPScannerForm::Open(const char* sID)
+{
+    if (m_cvCamera.isOpened()) return 0;
+    m_iCamIdx = GetCamIndex(sID);
+    if (m_iCamIdx < 0) return ERR_NO_DEVICE;
+    m_cvCamera.open(m_iCamIdx);
+    if (m_cvCamera.isOpened())
+    {
+        m_cvCamera.release();
+        m_bIsOpen = true;
+        return 0;
+    }
+    m_bIsOpen = false;
+    return ERR_OPEN_FAIL;
+}
+
+int HSPScannerForm::Close()
+{
+    if (isVisible())    hide();
+    if (m_cvCamera.isOpened())
+        m_cvCamera.release();
+    m_bIsOpen = false;
+    return 0;
+}
+
+int     HSPScannerForm::Preview(bool b)
+{
+    if (!m_bIsOpen)
+        return ERR_NOT_OPENED;
+    if (b)
+    {
+        if (!m_cvCamera.isOpened())
+            m_cvCamera.open(m_iCamIdx);
+        if (!m_cvCamera.isOpened())
+            return ERR_OPEN_FAIL;
+
+        m_cvCamera.set(CV_CAP_PROP_FRAME_WIDTH, m_iCamAll[0]);
+        m_cvCamera.set(CV_CAP_PROP_FRAME_HEIGHT, m_iCamAll[1]);
+
+        double fps = m_cvCamera.get(CV_CAP_PROP_FPS);
+        if (fps < 10) fps = 10;
+        m_ViewTimer->start(int(1000/fps));
+        m_bIsView = true;
+    }
+    else
+    {
+        m_bIsView = false;
+        m_ViewTimer->stop();
+        m_cvCamera.release();
+    }
+    return 0;
+}
+
+int     HSPScannerForm::Show(bool b)
+{
+    if (!m_bIsOpen)
+        return ERR_NOT_OPENED;
+    m_bIsHide = !b;
+    if (b)
+        this->show();
+    else
+        this->hide();
+    return 0;
+}
+
+int     HSPScannerForm::State()
+{
+    return 0;
+}
+
+bool    HSPScannerForm::GetVideoID(int iIndex, char* sGet)
+{
+    char sTemp[128];
+    sprintf(sTemp, "/sys/class/video4linux/video%d/device/modalias", iIndex);
+    FILE* fp=fopen(sTemp, "r");
+    if (fp == NULL) return false;
+    int iLen = fread(sTemp, 1, 100, fp);
+    sTemp[iLen]=0;
+    fclose(fp);
+    strcpy(sGet, sTemp);
+    return true;
+}
+
+int     HSPScannerForm::GetCamIndex(const char* sIn)
+{
+    char sSys[128];    //usb:v04F2pB61E  d0425dcE
+    for (int ia=0; ia<10; ia++){
+        if (GetVideoID(ia, sSys) == false) return -1;
+        if (memcmp(sIn, sSys, strlen(sIn)) == 0) return ia;
+    }
+    return -1;
+}
+

+ 71 - 0
DevAdapter/cw/hspscanner.1.1/hspscannerform.h

@@ -0,0 +1,71 @@
+#ifndef HSPSCANNERFORM_H
+#define HSPSCANNERFORM_H
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgcodecs/imgcodecs.hpp>
+#include <opencv2/core/mat.hpp>
+#include <opencv2/core/mat.inl.hpp>
+#include <QWidget>
+#include <QTimer>
+
+#define ERR_NO_DEVICE   -1
+#define ERR_NOT_OPENED  -2
+#define ERR_OPEN_FAIL   -3
+#define ERR_VIEW_FAIL   -4
+
+namespace Ui {
+class HSPScannerForm;
+}
+
+class HSPScannerForm : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit HSPScannerForm(QWidget *parent = nullptr);
+    ~HSPScannerForm();
+
+    int                 Open(const char* sID);
+    int                 Close();
+
+    void                SetPos(int iX, int iY, int iW, int iH);
+    void                SetSize(float dA4[4], float dID[4], int iAll[2]);
+    int                 Preview(bool b);
+    int                 Show(bool b);
+    int                 State();
+    int                 GetPic(const char* sFile);
+
+    bool                m_bIsGrey;
+    int                 m_iRotate;
+    int                 m_iScanSz;
+
+    bool                m_bIsOpen;
+    bool                m_bIsView;
+    bool                m_bIsHide;
+
+    cv::VideoCapture    m_cvCamera;
+protected:
+    bool                GetVideoID(int iIndex, char* sGet);
+    int                 GetCamIndex(const char* sIn);
+    int                 CameraState();
+
+private:
+    Ui::HSPScannerForm *ui;
+
+    float               m_dA4Pos[4];
+    float               m_dIDPos[4];
+    int                 m_iCamAll[2];
+
+    cv::Mat             m_Capture;
+    int                 m_iCamIdx;
+
+    QImage              Mat2QImage(cv::Mat cvImg);
+    QTimer *            m_ViewTimer;
+public slots:
+    void                onCamTimer();
+
+};
+
+#endif // HSPSCANNERFORM_H

+ 32 - 0
DevAdapter/cw/hspscanner.1.1/hspscannerform.ui

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HSPScannerForm</class>
+ <widget class="QWidget" name="HSPScannerForm">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>886</width>
+    <height>616</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <widget class="QLabel" name="labViewPos">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>891</width>
+     <height>591</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string/>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 294 - 0
DevAdapter/cw/hspscanner.1.1/hspscannerimpl.cpp

@@ -0,0 +1,294 @@
+#include "hspscannerimpl.h"
+#include "cmb.h"
+
+
+HSPSThread::HSPSThread()
+    :QThread (0)
+{
+    start();
+}
+
+void HSPSThread::run()
+{
+    exec();
+}
+
+/////////////////////////////////////////////////////////////////////
+
+HSPSClassImpl::HSPSClassImpl()
+{
+    m_sLibPath[0] = 0;
+    m_CamDevice.moveToThread(&m_HSPSThread);
+}
+
+HSPSClassImpl::~HSPSClassImpl()
+{
+    m_HSPSThread.exit();
+}
+
+ErrorCodeEnum HSPSClassImpl::DevOpen()
+{
+    LOG4VTM_FUNCTION();
+    SIni ini;
+    char sA4[32], sID[32], sAll[32], sUsb[64];
+    //拍照裁剪范围设置
+    if (ini.GetValueFromIniFile("/cashway/setting/cashway.ini", "HSPScan", "SizeA4", sA4, 30) &&
+        ini.GetValueFromIniFile("/cashway/setting/cashway.ini", "HSPScan", "SizeID", sID, 30) &&
+        ini.GetValueFromIniFile("/cashway/setting/cashway.ini", "HSPScan", "SizeAll", sAll, 30))
+    {
+        float dA4[4], dID[4];
+        int iSize[2];
+        int i1 = sscanf(sA4, "%f,%f,%f,%f", &dA4[0], &dA4[1], &dA4[2], &dA4[3]);
+        int i2 = sscanf(sID, "%f,%f,%f,%f", &dID[0], &dID[1], &dID[2], &dID[3]);
+        int i3 = sscanf(sAll, "%dx%d", &iSize[0], &iSize[1]);
+        if (i1 > 3 && i2 > 3 && i3 > 1)   m_CamDevice.SetSize(dA4, dID, iSize);
+    }
+    //摄像头的pid vid
+    if (!ini.GetValueFromIniFile("/cashway/setting/cashway.ini", "HSPScan", "Camera", sUsb, 30))
+    {
+        strcpy(sUsb, "usb:v04F2pB61E");
+    }
+
+    GetCurLibsPath(m_sLibPath, NULL);
+
+    int iRet = m_CamDevice.Open(sUsb);
+    return GetErrorInfo(iRet, "DevOpen");
+}
+
+int getFileVer(char* sFile, short& ch1, short& ch2)
+{
+    ch1 = 0;
+    ch2 = 0;
+    char* pFind = strstr(sFile, ".so");
+    char* pTemp = pFind;
+    while (pTemp)
+    {
+        pFind = pTemp;
+        pTemp = strstr(pFind + 3, ".so");
+    }
+    if (pFind == NULL) return 0;
+
+    pTemp = pFind - 1;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch2 = atoi(pTemp+1);
+    pTemp--;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch1 = atoi(pTemp+1);
+    return 1;
+}
+
+ErrorCodeEnum HSPSClassImpl::GetDevCategory(DevCategoryInfo &devCategory)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_CamDevice.m_bIsOpen)
+        return GetErrorInfo(ERR_NOT_OPENED, "ScanImage");
+    memset(&devCategory, 0, sizeof(devCategory));
+    strcpy(devCategory.szModel , "FWID=Cam00001");
+    strcpy(devCategory.szVendor , "cw");
+    strcpy(devCategory.szType ,"00000000");
+
+    char sPath[256], sFile[128] = {0};
+    GetCurLibsPath(sPath, sFile);
+    short v1,v2;
+    getFileVer(sFile, v1, v2);
+    devCategory.version.wMajor = v1;
+    devCategory.version.wMinor = v2;
+
+    devCategory.version.wRevision = 0xffff;
+    devCategory.version.wBuild = FILE_VERSION;
+
+    if (m_CamDevice.State())
+        devCategory.eState = DEVICE_STATUS_NORMAL;
+    else
+        devCategory.eState = DEVICE_STATUS_NOT_READY;
+    return Error_Succeed;
+}
+
+ErrorCodeEnum HSPSClassImpl::Reset()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_CamDevice.m_bIsOpen)
+        return GetErrorInfo(ERR_NOT_OPENED, "ScanImage");
+    int iRet = 0;
+    return GetErrorInfo(iRet, "Reset");
+}
+ErrorCodeEnum HSPSClassImpl::DevClose()
+{
+    LOG4VTM_FUNCTION();
+    m_CamDevice.Close();
+    Sleep(50);
+    return Error_Succeed;
+}
+
+ErrorCodeEnum HSPSClassImpl::GetLastErr(DevErrorInfo &devErrInfo)
+{
+    memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
+    return Error_Succeed;
+}
+
+ErrorCodeEnum HSPSClassImpl::SetParam(ParamType type, ParamTypeValue value)
+{
+    LOG4VTM_FUNCTION();
+    switch(type){
+    case HSPS_MODEL_COLOR:
+        m_CamDevice.m_bIsGrey = (value == HSPS_COLOR_GREY);
+        break;
+    case HSPS_MODEL_ROTATE:
+        m_CamDevice.m_iRotate = (value - HSPS_ROTATE_NOANGLE);
+        break;
+    case HSPS_MODEL_SCANSIZE:
+        m_CamDevice.m_iScanSz = (value - HSPS_SCAN_FULL);
+        break;
+    case HSPS_MODEL_VIEW:
+        m_CamDevice.Show(value == HSPS_VIEW_SHOW);
+    }
+    return Error_Succeed;
+}
+
+//  更新20161117: nValue值为 1 时打开预览,确保当前打开预览过程执行结束且窗口处于显示状态才返回Error_Succeed,
+//	nValue值为 0 时关闭预览并隐藏窗口
+ErrorCodeEnum HSPSClassImpl::SetPreview(short nValue)
+{
+    LOG4VTM_FUNCTION();
+    int iRet = 0;
+    if (nValue == 1)
+    {
+        iRet = m_CamDevice.Preview(nValue == 1);
+        if (iRet == 0)
+            m_CamDevice.Show(true);
+    }
+    else {
+        iRet = m_CamDevice.Preview(nValue == 1);
+    }
+    return GetErrorInfo(iRet, "SetPreview");
+}
+
+//		specifies that where the image will be located and what it would be named.
+//	拍摄照片,传入的文件名已带绝对路径,无需再进行拼接处理
+//
+ErrorCodeEnum HSPSClassImpl::ScanImage(const char* pszFileName)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_CamDevice.m_bIsView)
+        return GetErrorInfo(ERR_NOT_OPENED, "ScanImage");
+    int iRet = m_CamDevice.GetPic(pszFileName);
+    return GetErrorInfo(iRet, "ScanImage");
+}
+
+//	Scan Image from device and return the image data in byte format.
+//	-pBtImg[out] The buffer used to store the scanned image data.
+//		存储图片字节流的缓冲区,大小为 nBtLen 字节
+//	-nBtLen[in,out] Indicate the max byte-type size of pBtImg could be stored
+//		and Store the real byte-type size of pBtImg had used when returned.
+//		when detect value of nBtLen is 0 or smaller that necessary size, please
+//		set nBtlen with real byte-type size and return Error_TooSmallBuffer.
+//		如果nBtLen指定的字节数过小,那么对nBtLen赋值实际所需的大小并返回 Error_TooSmallBuffer,此操作仅允许一次
+//	-pszFileName[in] Store the path and name where the image file should be located
+//		while "" indicates that the image file shouldn't be stored at locate.
+//		文件名长度为零表示不在本地生成图片文件
+ErrorCodeEnum HSPSClassImpl::ScanImageEx(BYTE* pBtImg, int& nBtLen, const char* pszFileName)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_CamDevice.m_bIsView)
+        return GetErrorInfo(ERR_NOT_OPENED, "ScanImageEx");
+    char sFile[300];
+    bool bFile = false;
+    if (strlen(pszFileName))
+    {
+        strcpy(sFile, pszFileName);
+        bFile = true;
+    }
+    else
+        sprintf(sFile, "%s/hsps-temp.jpg", m_sLibPath);
+
+    ErrorCodeEnum eRet = Error_Succeed;
+    int iRet = m_CamDevice.GetPic(sFile);
+    if (iRet != 0)  return GetErrorInfo(iRet, "ScanImageEx");
+    FILE* fp = fopen(sFile, "rb");
+    fseek(fp, 0, SEEK_END);
+    int iLen = ftell(fp);
+    if (iLen < nBtLen)
+    {
+        fseek(fp, 0, SEEK_SET);
+        fread(pBtImg, 1, iLen, fp);
+    }
+    else
+        eRet = Error_TooSmallBuffer;
+    fclose(fp);
+    if (!bFile) remove(sFile);
+    return eRet;
+}
+
+//	传入预览窗口显示的坐标,左上角的横坐标nX,左上角的纵坐标nY,以及预览窗口的宽,宽与高的比例为 16:9
+ErrorCodeEnum HSPSClassImpl::SetViewPos(int nX, int nY, int nWidth)
+{
+    LOG4VTM_FUNCTION();
+    m_CamDevice.SetPos(nX, nY, nWidth, nWidth*9/16);
+    return Error_Succeed;
+}
+
+ErrorCodeEnum HSPSClassImpl::GetDevStatus(HspsDevStatus& status)
+{
+    LOG4VTM_FUNCTION();
+    status.isConnected = m_CamDevice.m_bIsOpen;
+    status.inPreview = m_CamDevice.m_bIsView;
+    status.inShow = !m_CamDevice.m_bIsHide;
+    return Error_Succeed;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+//  DEC_SUCCESS DEC_HARDWARE DEC_TIMEOUT DEC_INVALID_PARAMETER DEC_INVALID_MASTER_KEY
+const static CmbErrorDef HSPSErrInfo[] = {
+    {0,             "命令执行成功", Error_Succeed, DEC_SUCCESS},
+    {ERR_NO_DEVICE, "未发现设备", Error_Hardware, DEC_DEV_NOT_FOUND},
+    {ERR_NOT_OPENED, "设备尚未打开", Error_Param, DEC_DEV_NOT_OPENED},
+    {ERR_OPEN_FAIL, "设备打开失败", Error_Hardware, DEC_HARDWARE},
+    {ERR_VIEW_FAIL, "启动预览失败", Error_Hardware, DEC_HARDWARE},
+
+};
+
+ErrorCodeEnum HSPSClassImpl::GetErrorInfo(int iCode, char* sErr, ...)
+{
+    size_t iLenOne = sizeof(CmbErrorDef);
+    size_t iLenAll = sizeof(HSPSErrInfo);
+    int iCount = iLenAll / iLenOne;
+    char sErrInfo[256]="";
+    DWORD dSta = 0;
+    int iErr = -1;
+    for (int ia = 0; ia < iCount; ia++)
+    {
+        if (HSPSErrInfo[ia].iCode == iCode)
+        {
+            dSta = HSPSErrInfo[ia].iInf;
+            strcpy(sErrInfo, HSPSErrInfo[ia].sInf);
+            iErr = HSPSErrInfo[ia].iRet;
+            break;
+        }
+    }
+
+    char sErrAll[300];
+    va_list arglist;
+    va_start(arglist, sErr);
+    _vsnprintf(sErrAll, 128, sErr, arglist);
+    va_end(arglist);
+
+    if (sErrInfo[0])
+    {
+        strcat(sErrAll, " ");
+        strcat(sErrAll, sErrInfo);
+    }
+    sErrAll[200] = 0;
+    iLenOne = strlen(sErrAll);
+    sprintf(m_DevErrInfo.szErrMsg, "{\"ErrCode\":\"%04x\",\"Description\":\"%s\"}", iErr, sErrAll);
+//    strcpy(m_DevErrInfo.szErrMsg, sErrAll);
+    m_DevErrInfo.dwErrMsgLen = ((dSta << 16) & 0xffff0000) + iLenOne;
+    if (iErr != Error_Succeed)
+        LOG4VTM(WARN, m_DevErrInfo.szErrMsg);
+    else
+        LOG4VTM(INFO, m_DevErrInfo.szErrMsg);
+    return (ErrorCodeEnum)iErr;
+}
+

+ 107 - 0
DevAdapter/cw/hspscanner.1.1/hspscannerimpl.h

@@ -0,0 +1,107 @@
+#ifndef LIBFRAMEWORK_HSPS_IMPL_H
+#define LIBFRAMEWORK_HSPS_IMPL_H
+
+#include <QThread>
+#include "HSPScannerClass.h"
+#include "hspscannerform.h"
+
+#define FILE_VERSION    1
+
+//本类的目的只是为了实现一个线程容器,dbus的事件必须和主线程在不同的线程容器里面
+class HSPSThread : public QThread
+{
+    Q_OBJECT
+public:
+    HSPSThread();
+    virtual void run();
+};
+
+class HSPSClassImpl : public CHSPSClass
+{
+public:
+    HSPSClassImpl();
+    ~HSPSClassImpl();
+
+
+    //DeviceBaseClass
+    ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
+    ErrorCodeEnum Reset();
+    ErrorCodeEnum DevClose();
+    ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+
+    virtual ErrorCodeEnum DevOpen();
+
+    //
+    //	Set param, more detail please to see ParamType and its according ParamTypeValue.
+    //
+    virtual ErrorCodeEnum SetParam(ParamType type, ParamTypeValue value);
+
+    //
+    //	Command the device to start to preview or stop previewing.
+    //	-nValue[in] set 1 means StartPreview while 0 means StopPreview.
+    //	If the device' state had been setted before what the nValue commanded, ignore it and
+    //		return Error_Succeed.
+    //	The function returns only the specified behavior is done completely, StartPreview in special.
+    //  更新20161117: nValue值为 1 时打开预览,确保当前打开预览过程执行结束且窗口处于显示状态才返回Error_Succeed,
+    //	nValue值为 0 时关闭预览并隐藏窗口
+    virtual ErrorCodeEnum SetPreview(short nValue);
+
+    //	Scan Image from device and store the image.
+    //	-pszFileName[in] Store the path and name using suffix ".jpg"
+    //		specifies that where the image will be located and what it would be named.
+    //	拍摄照片,传入的文件名已带绝对路径,无需再进行拼接处理
+    //
+    virtual ErrorCodeEnum ScanImage(const char* pszFileName);
+    //
+    //	Scan Image from device and return the image data in byte format.
+    //	-pBtImg[out] The buffer used to store the scanned image data.
+    //		存储图片字节流的缓冲区,大小为 nBtLen 字节
+    //	-nBtLen[in,out] Indicate the max byte-type size of pBtImg could be stored 
+    //		and Store the real byte-type size of pBtImg had used when returned.
+    //		when detect value of nBtLen is 0 or smaller that necessary size, please
+    //		set nBtlen with real byte-type size and return Error_TooSmallBuffer.
+    //		如果nBtLen指定的字节数过小,那么对nBtLen赋值实际所需的大小并返回 Error_TooSmallBuffer,此操作仅允许一次
+    //	-pszFileName[in] Store the path and name where the image file should be located
+    //		while "" indicates that the image file shouldn't be stored at locate.
+    //		文件名长度为零表示不在本地生成图片文件
+    virtual ErrorCodeEnum ScanImageEx(BYTE* pBtImg, int& nBtLen, const char* pszFileName = "");
+
+    //
+    //	Set position and width of preview dialog with the rate of length to width: 16:9.
+    //	-nX[in] The X coordinate of leftTop point.
+    //  -nY[in] The Y coordinate of leftTop point.
+    //	-nWidth[in] The Width of Preview Dialog .
+    //	传入预览窗口显示的坐标,左上角的横坐标nX,左上角的纵坐标nY,以及预览窗口的宽,宽与高的比例为 16:9
+    //
+    virtual ErrorCodeEnum SetViewPos(int nX, int nY, int nWidth);
+
+    //
+    //	Show property dialog of HSPS of LiangTian.
+    //	If there is no property dialog function, ignore it and return Error_NotImpl(更新20161117).
+    //  更新20161117:用于打开良田高拍仪设备的设置属性页,可能用不到
+    //
+    virtual ErrorCodeEnum SetProperty()
+    {
+        return Error_NotImpl;
+    }
+
+    //
+    //	Get current status of device.
+    virtual ErrorCodeEnum GetDevStatus(HspsDevStatus& status);
+
+    ////////////////////////////////////
+
+public:
+    int         Run();
+
+protected:
+    ErrorCodeEnum       GetErrorInfo(int iCode, char* sErr, ...);
+    DevErrorInfo        m_DevErrInfo;
+    HSPScannerForm      m_CamDevice;
+    HSPSThread          m_HSPSThread;
+
+    char                m_sLibPath[260];
+};
+
+
+#endif //LIBFRAMEWORK_HSPS_IMPL_H

+ 52 - 0
DevAdapter/cw/hspscanner.1.1/ui_hspscannerform.h

@@ -0,0 +1,52 @@
+/********************************************************************************
+** Form generated from reading UI file 'hspscannerform.ui'
+**
+** Created by: Qt User Interface Compiler version 5.11.3
+**
+** WARNING! All changes made in this file will be lost when recompiling UI file!
+********************************************************************************/
+
+#ifndef UI_HSPSCANNERFORM_H
+#define UI_HSPSCANNERFORM_H
+
+#include <QtCore/QVariant>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_HSPScannerForm
+{
+public:
+    QLabel *labViewPos;
+
+    void setupUi(QWidget *HSPScannerForm)
+    {
+        if (HSPScannerForm->objectName().isEmpty())
+            HSPScannerForm->setObjectName(QLatin1String("HSPScannerForm"));
+        HSPScannerForm->resize(886, 616);
+        labViewPos = new QLabel(HSPScannerForm);
+        labViewPos->setObjectName(QLatin1String("labViewPos"));
+        labViewPos->setGeometry(QRect(0, 0, 891, 591));
+
+        retranslateUi(HSPScannerForm);
+
+        QMetaObject::connectSlotsByName(HSPScannerForm);
+    } // setupUi
+
+    void retranslateUi(QWidget *HSPScannerForm)
+    {
+        HSPScannerForm->setWindowTitle(QApplication::translate("HSPScannerForm", "Form", nullptr));
+        labViewPos->setText(QString());
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class HSPScannerForm: public Ui_HSPScannerForm {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_HSPSCANNERFORM_H

+ 1 - 1
DevAdapter/cw/pinpad.1.1/pinpadimpl.cpp

@@ -54,7 +54,7 @@ ErrorCodeEnum PinPadImpl::GetDevCategory(DevCategoryInfo &devCategory)
     if (!m_bIsOPen)
         return GetErrorInfo(-1, "GetDevCategory");
     char szType[] = {"Pin Just E6020"};
-    char szModel[] = {"PM=V2.0#FWID=00000000"};
+    char szModel[] = {"PM=V2.0#MID=100N-BJHY-E42-A01#PID=0000#FWID=00000000"};
     char szVendor[] = {"cw"};
 
     ErrorCodeEnum err = Error_Succeed;

+ 26 - 0
DevAdapter/cw/termalprint.1.1/CMakeLists.txt

@@ -0,0 +1,26 @@
+
+# 声明模块名称的前缀和名称
+rvc_dev_define_module("ThermalPrint")
+
+# rvc_dev_config_library 内需要使用这三个参数,用于拼接输出的适配器文件名称
+set(${MODULE_PREFIX}_VENDOR "cw")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+# 包含要编译的实现文件,rvc_dev_config_library 内使用
+set(${MODULE_PREFIX}_SRCS SHARED
+    termalprintimpl.cpp termalprintdev.cpp ReceiptBase.cpp ReceiptSnbc.cpp
+   )
+
+# 适配器工程需要通过此宏替代 add_library
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+# ${MODULE_FULL_NAME} 是 TAGET 名称,在 rvc_dev_config_library 中定义
+target_include_directories(${MODULE_FULL_NAME} PRIVATE ${VENDOR_CURRENT_INCLUDE_DIR})
+target_link_libraries(${MODULE_FULL_NAME} baseio usb-1.0 ${VENDOR_LOG_LIB_NAME})
+
+SET(LIBRARY_OUTPUT_PATH ${VENDOR_CURRENT_LIB_DIR})
+
+#  =-=-=-=-=-=-=-=-=-= {适配器工程}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
+rvc_dev_target_install(${MODULE_FULL_NAME})
+

+ 1001 - 0
DevAdapter/cw/termalprint.1.1/ReceiptBase.cpp

@@ -0,0 +1,1001 @@
+// ReceiptBase.cpp : Defines the entry point for the DLL application.
+//
+
+#include "ReceiptBase.h"
+
+//m_iUsedLeng修改成用纸长度,原为行数。
+
+ReceiptBase::ReceiptBase()
+{
+    m_iLetSpace = 0;
+    m_iUsedLeng = 0;
+	m_iMinPaper = 400;	//400*0.125=50mm
+    m_iLineHeight = 30;
+	m_iNVHeight = 0;
+    m_iLineLeng = 48;
+	m_iLastPos = 0;
+	m_iLinesPrted = 0;
+    m_iMMPerSec = 80;
+}
+
+ReceiptBase::~ReceiptBase()
+{
+    m_cSerial.Close();
+}
+
+void	ReceiptBase::SetLinePara(int iLineLeng, int iLeftSpace, int iSpeed)
+{
+    m_iLetSpace = iLeftSpace;
+    m_iLineLeng = iLineLeng;
+    m_iMMPerSec = iSpeed;
+}
+
+//凭条打印机 判断端口打开
+bool	ReceiptBase::Isopen()
+{
+    return m_cSerial.IsOpen();
+}
+
+int ReceiptBase::Open(const int iVID, const int iPID, const int iFD)
+{
+    if(m_cSerial.IsOpen()) return RECEIPT_SUCCESS;
+    //sew此处需要修改
+    if (m_cSerial.Open("{28d78fad-5a12-11D1-ae5b-0000f803a8c2}", iVID, iPID) == false)
+        return -1;
+	Init();
+    return RECEIPT_SUCCESS;
+}
+
+// 关闭端口
+int ReceiptBase::Close()
+{
+    if(m_cSerial.IsOpen() == false)
+        return RECEIPT_SUCCESS;
+
+    m_cSerial.Close();
+    return RECEIPT_SUCCESS;
+}
+
+//通用发送数据接口
+int ReceiptBase::SendData(const unsigned char *sSend,int iDatLen,int iTimeout)
+{
+	int iCount = 0;
+	int ia;
+	for (ia=0; ia<iDatLen; ia++)
+		if (sSend[ia] == '\n') iCount++;
+	if (iCount > 50 && iCount > iDatLen / 10)
+		iCount = 50;
+	static INT64 iPrintTime = 0;
+	if (iCount)
+	{
+		m_iLinesPrted += iCount;
+        if (m_iLinesPrted > 20)	//50行处理一次
+		{
+            int iTimeWant = m_iLinesPrted * m_iLineHeight * 1000 / (8 * m_iMMPerSec);
+
+            INT64 iCurTime = ::GetSystemTime();
+			int   iUse = (int)(iCurTime - iPrintTime);
+			if (iUse < 0 || iUse > iTimeWant) iUse = iTimeWant;
+            int iSleep = iTimeWant - iUse;
+            if (iSleep > 0)
+				Sleep(iSleep);
+			iPrintTime = iCurTime;
+
+			m_iLinesPrted = 0;
+		}
+	}
+    return	m_cSerial.Send(sSend, iDatLen, iTimeout);
+}
+
+//通用接收数据接口
+int		ReceiptBase::ReadData(unsigned char *sRead,int iWant,int iTimeout)
+{
+    return m_cSerial.Receive((unsigned char *)sRead, iWant, iTimeout);
+}
+
+//打印机初始化
+int	ReceiptBase::Init()
+{
+    if(m_cSerial.IsOpen() == false) return RECEIPT_ERR_NO_OPEN;
+    unsigned char szSendBuf[20];
+    szSendBuf[0] = 0x1b;
+    szSendBuf[1] = 0x40;
+    int nRet = SendData(szSendBuf, 2, 3000);
+    if (nRet < 2)
+        return RECEIPT_ERR_RCV_ERR;
+
+    SetRowDistance(0);
+    SetLeftDistance(0);
+    SetFont(false, false, false, false, false);
+    SetAlign(0);
+    SetScale(1,1);
+    SetInverse(false);
+    SetRotate(false);
+    SetBlackFlag(false);
+    return RECEIPT_SUCCESS;
+}
+
+//通用发送数据接口
+int ReceiptBase::SendHexStr(const char *sData, int iDataLen)
+{
+	if (iDataLen == 0) iDataLen = strlen(sData);
+    if (iDataLen > 1000) return RECEIPT_ERR_IN_ERR;
+	unsigned char	sSend[512];
+    int		iCount = ::HexStrToANSI(sData, sSend, iDataLen);
+	if (iCount <= 0)
+        return RECEIPT_ERR_IN_ERR;
+	int iRet = SendData(sSend, iCount);
+	return iRet;
+}
+
+//数据输出,打印
+int		ReceiptBase::PrintData(const char * sData)
+{
+    unsigned char sSend[128];
+    if(sData == NULL || strlen((char*)sData) < 1)
+    {
+        return RECEIPT_ERR_IN_ERR;
+    }
+    int iLeng = strlen((char*)sData);
+    int iPos = 0, iLinePos = 0;
+    int iChCount = 0;
+    unsigned char chTemp;
+    bool	bLineMax, bLineEnd, bDataEnd;
+    int iLengMax = m_iLineLeng;
+
+    for (iPos = 0 ; iPos < iLeng; )
+    {
+        bLineMax = FALSE;
+        bLineEnd = FALSE;
+        bDataEnd = FALSE;
+        iChCount = 0;	//半个汉字计算
+        memset(sSend, ' ', m_iLetSpace);
+		if (m_iLastPos)
+			iLinePos = m_iLastPos;
+		else
+			iLinePos = m_iLetSpace;
+        while (iLinePos < iLengMax)
+        {
+            chTemp = (unsigned char)sData[iPos++];
+
+            if (chTemp == '\r' || chTemp == '\n')
+            {	//一行结束
+                bLineEnd = TRUE;
+                break;
+            }
+            //数据不包含换行
+            sSend[iLinePos++] = chTemp;
+
+            //计算半个汉字
+            if (chTemp >= 128)
+                iChCount++;
+            else
+                iChCount = 0;
+
+            if (iPos >= iLeng)
+            {	//总数据结束
+                bDataEnd = TRUE;
+                break;
+            }
+        }
+        if (iLinePos >= iLengMax)
+            bLineMax = TRUE;
+
+        //处理半个汉字,最后是半个汉字,前移一字节
+        if ((iChCount % 2) == 1 && (bLineMax || bDataEnd))
+        {
+            iLinePos--;
+            iPos--;
+        }
+
+        if (bLineMax || bLineEnd)
+        {
+            sSend[iLinePos] = '\n';
+            iLinePos++;
+            m_iUsedLeng += m_iLineHeight;
+        }
+
+        sSend[iLinePos] = 0;
+        int iStart = 0;
+        if (m_iLastPos)
+        {
+            iStart = m_iLastPos;
+            m_iLastPos = 0;
+        }
+
+        if (SendData(sSend + iStart, iLinePos - iStart, 1000) < iLinePos - iStart)
+            return RECEIPT_ERR_RCV_ERR;
+
+        //数据的最后一个字符是汉字的半个字符
+        if ((iChCount % 2) == 1 &&  iPos == (iLeng - 1))
+		{
+			m_iLastPos = iLinePos;
+            return iPos;
+		}
+
+        //windows格式\r\n换行处理
+        if (chTemp == '\r' && sData[iPos] == '\n')
+            iPos++;
+    }
+	if (bLineMax || bLineEnd)
+		m_iLastPos = 0;
+	else
+		m_iLastPos = iLinePos;
+    return iPos;
+}
+
+//走纸n行
+int		ReceiptBase::FeedLines(int iLines)
+{
+    for (int ia = 0; ia < iLines; ia++)
+    {
+        int iRet = SendData((unsigned char*)"\r\n", 2, 500);
+		Sleep(40);
+        m_iUsedLeng += m_iLineHeight;
+		m_iLastPos = 0;
+        if (iRet < 1) return RECEIPT_ERR_RCV_ERR;
+    }
+    return RECEIPT_SUCCESS;
+}
+
+//走纸n行
+int		ReceiptBase::PrintChar(char ch, int iCount)
+{
+    for (int ia = 0; ia < iCount; ia++)
+    {
+        int iRet = SendData((unsigned char*)&ch, 1, 500);
+        if (ch == '\n'){
+			SendData((unsigned char*)"\r", 1, 500);
+            Sleep(40);
+            m_iUsedLeng += m_iLineHeight;
+            m_iLastPos = 0;
+        }
+        if (iRet < 1) return RECEIPT_ERR_RCV_ERR;
+    }
+    return RECEIPT_SUCCESS;
+}
+
+//走纸n行
+int		ReceiptBase::PrintLine(const char* sLine)
+{
+    int iRet = PrintData(sLine);
+    if (iRet < 0) return iRet;
+    return FeedLines(1);
+}
+
+//走纸1点阵
+int ReceiptBase::FeedPaper(short iMode, short iDistance)
+{
+    unsigned char cpSend[10]={0};
+    int nRet = 0;
+    if ( iMode == 0 )	//往前走
+    {
+        m_iUsedLeng += iDistance;
+        cpSend[0] = 0x1B;
+        cpSend[1] = 0x4A;
+
+        while (iDistance > 0 ) //line 大于 0 才执行后走纸命令
+        {
+            if (iDistance > 80)
+            {
+                cpSend[2] = 80;
+                iDistance -= 80;
+            }
+            else
+            {
+                cpSend[2] = (char)iDistance;
+                iDistance = 0;
+            }
+            nRet = SendData(cpSend,3,500);
+        }
+        if (nRet < 0)	return nRet;
+		SendData((unsigned char*)"\r", 1, 500);
+        return RECEIPT_SUCCESS;
+    }
+    return RECEIPT_ERR_RCV_ERR;
+}
+
+//0:全切 1:半切
+int ReceiptBase::Cut(int iMode)
+{
+    SetFont(0, 0, 0, 0, 0);
+	SendData((unsigned char*)"\r", 1, 500);		//为保证最后一行数据输出
+    if (m_iUsedLeng < m_iMinPaper -160 )
+		FeedPaper(0, (m_iMinPaper - m_iUsedLeng - 160) >> 3);
+	//机械结构,切刀位置在2cm位置,必须走纸2cm后切纸,否则最后数据被切掉
+    FeedPaper(0, 160);
+
+    unsigned char cpSend[20];
+    int nRet = 0;
+    cpSend[0]=0x1B;
+    cpSend[1]=0x4E;
+    cpSend[2]=0x03;
+    cpSend[3]=iMode;
+    SendData(cpSend,4,300);
+
+    cpSend[0]=0x1D;
+    cpSend[1]=0x56;
+    cpSend[2]=0x42;
+    cpSend[3]=0x00;
+	Sleep(300);
+    nRet = SendData(cpSend,4,300);
+    m_iUsedLeng=0;
+	m_cSerial.Flush();
+
+	Sleep(300);
+	if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+//nAlign 0 - 左对齐 ,1 - 居中, 2 - 右对齐
+int ReceiptBase::SetAlign(short nAlign)
+{
+    if(nAlign > 2 || nAlign <0)
+    {
+        return RECEIPT_ERR_IN_ERR;
+    }
+    unsigned char szSendBuf[20];
+    int nRet = 0;
+    memset(szSendBuf,'\0',20);
+    szSendBuf[0] = 0x1b;
+    szSendBuf[1] = 0x61;
+    szSendBuf[2] = (char)nAlign;//0 - 左对齐 ,1 - 居中, 2 - 右对齐
+    nRet = SendData(szSendBuf,3);
+    if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//DH 倍高 DW倍宽 DD黑体 UL下划线
+int		ReceiptBase::SetFont(bool bDH, bool bDW, bool bDD, bool bUL, bool bCharB)
+{
+    unsigned char sCmd[4], chChi = 0, chAsc = 0;
+    //英文模式
+    sCmd[0]=0x1B;
+    sCmd[1]=0x21;
+
+    if (bDH)
+    {
+        chAsc += 16;
+        chChi += 8;
+        m_iLineHeight = 54;
+    }
+    else
+        m_iLineHeight = 30;
+    if (bUL)
+    {
+        chAsc += 0x80;
+        chChi += 0x80;
+    }
+    if (bDW)
+    {
+        chAsc += 32;
+        chChi += 4;
+    }
+
+    if (bDD)
+    {
+        chAsc += 8;
+    }
+    if (bCharB)
+    {
+        chAsc += 1;
+    }
+    sCmd[2] = chAsc;
+    SendData(sCmd,3,500);
+
+    //汉字倍宽倍高模式
+    sCmd[0]=0x1C;
+    sCmd[1]=0x21;
+    sCmd[2] = chChi;
+    SendData(sCmd,3,500);
+
+//    sCmd[0]=0x1b;
+//    sCmd[1]=0x2d;
+//    sCmd[2]=bUL ? 1 : 0;
+//    SendData(sCmd,3,500);
+
+//    sCmd[0]=0x1c;
+//    sCmd[1]=0x57;
+//    sCmd[2]=(bDW | bDH) ? 1 : 0;
+//    SendData(sCmd,3,500);
+    return RECEIPT_SUCCESS;
+}
+
+//设置打印放大倍数(1-6)
+int		ReceiptBase::SetScale(int iX, int iY)
+{
+	iX--;
+	iY--;
+	if (iX < 0 || iX > 5)	iX = 0;
+	if (iY < 0 || iY > 5)	iY = 0;
+    unsigned char sCmd[4];
+    sCmd[0]=0x1D;
+    sCmd[1]=0x21;
+	sCmd[2] = (iX << 4) + iY;
+
+    int nRet = SendData(sCmd,3,300);
+	m_cSerial.Flush();
+	if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//设置黑白反显打印模式
+int		ReceiptBase::SetInverse(bool b)
+{
+    unsigned char sCmd[4];
+    sCmd[0]=0x1D;
+    sCmd[1]=0x42;
+    sCmd[2] = b;
+	
+    int nRet = SendData(sCmd,3,300);
+	m_cSerial.Flush();
+	if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//选择/取消顺时针旋转90度
+int		ReceiptBase::SetRotate(bool b)
+{
+    unsigned char sCmd[4];
+    sCmd[0]=0x1B;
+    sCmd[1]=0x56;
+	sCmd[2] = b;
+	
+    int nRet = SendData(sCmd,3,300);
+	m_cSerial.Flush();
+	if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//是否黑标纸
+int		ReceiptBase::SetBlackFlag(bool b)
+{
+    unsigned char sCmd[4];
+    sCmd[0]=0x1B;
+    sCmd[1]=0x63;
+	sCmd[2]=0x30;
+	sCmd[3]=b?153:0;
+	
+    int nRet = SendData(sCmd,4,300);
+	m_cSerial.Flush();
+	if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//设置黑标位置
+int		ReceiptBase::SetBlackPos(int iLen)
+{
+	int iRet = SetBlackFlag(true);
+    if (iRet!=RECEIPT_SUCCESS)
+		return iRet;
+
+    unsigned char sCmd[6];
+    sCmd[0]=0x1B;
+    sCmd[1]=0x63;
+	sCmd[2]=0x31;
+    if (iLen < 19)
+        iLen = 19;
+    if (iLen > 65534)
+        iLen = 65534;
+
+    sCmd[3] = iLen%256;
+    sCmd[4] = iLen/256;
+	
+    int nRet = SendData(sCmd,5,300);
+	m_cSerial.Flush();
+	if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//获取固件版本
+int		ReceiptBase::GetFirmware(char* s)
+{
+    unsigned char sCmd[128];
+    sCmd[0]=0x1D;
+    sCmd[1]=0x49;
+    sCmd[2]=3;
+
+    int nRet = SendData(sCmd,3,300);
+    if (nRet < 0)	return nRet;
+    //Sleep(10);
+
+    int iLen = ReadData(sCmd, 127, 300);
+    if(iLen < 1)
+        return RECEIPT_ERR_RCV_ERR;
+
+    sCmd[iLen] = 0;
+    strcpy(s, (char*)sCmd);
+    return RECEIPT_SUCCESS;
+}
+
+//打印高速20,中速10,低速 00
+int		ReceiptBase::SetPrintSpeed(short nSpeed)
+{
+    return RECEIPT_SUCCESS;
+}
+
+int		ReceiptBase::SetRowDistance(int nDis)
+{
+    unsigned char cpSend[10]={0};
+    int nRet = 0;
+    if(nDis == 0)
+    {
+        cpSend[0]=0x1B;
+        cpSend[1]=0x32;
+        nRet = SendData(cpSend,2,300);
+        m_iLineHeight = 30;
+    }
+    else
+    {
+        cpSend[0]=0x1B;
+        cpSend[1]=0x33;
+        cpSend[2]=(char)nDis&0xFF;
+        nRet = SendData(cpSend,3,300);
+        m_iLineHeight = nDis;
+    }
+
+    if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//设置左边空白
+int ReceiptBase::SetLeftDistance(int iLeft)
+{
+	unsigned char cmd[]={0x1D, 0x4C, 0x00, 0x00};
+	cmd[2] = iLeft%256;
+	cmd[3] = iLeft/256;
+	int nRet = SendData(cmd,4,300);
+    if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//设置打印区域
+int ReceiptBase::SetPrintArea(int iLeng)
+{
+    unsigned char cmd[]={0x1D, 0x57, 0x00, 0x00};
+    cmd[2] = iLeng%256;
+    cmd[3] = iLeng/256;
+    int nRet = SendData(cmd,4,300);
+    if (nRet < 0)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+//	ctype  1 EAN13 =2CODE128-A  =3 CODE128-B  =4 CODE128-C
+//	iBytePos 0不打印HRI字符 1条码上方打印 2条码下方打印 3条码上下方打印
+int		ReceiptBase::PrinterCode(const char* cdata, UINT ctype,
+                UINT iBytePos,UINT BarCodeWidth,UINT BarCodeHeight, bool bCharB)
+{
+    if(iBytePos > 3) return RECEIPT_ERR_IN_ERR;
+    if(strlen(cdata) > 80) return RECEIPT_ERR_IN_ERR;
+
+	//字符打印位置	0不打印HRI字符 1条码上方打印 2条码下方打印 3条码上下方打印
+    char szSendBuf[100];
+    szSendBuf[0]=0x1D;
+    szSendBuf[1]=0x48;
+    szSendBuf[2]=iBytePos;
+    int nRet = SendData((unsigned char*)szSendBuf, 3,3000);
+    if(nRet < RECEIPT_SUCCESS)	return nRet;
+    if(BarCodeWidth<2)
+        BarCodeWidth = 2;
+    if(BarCodeWidth>6)
+        BarCodeWidth = 6;
+	//设置条形码宽度	2 - 6
+    szSendBuf[0]=0x1D;
+    szSendBuf[1]=0x77;
+    szSendBuf[2]=BarCodeWidth;
+    nRet = SendData((unsigned char*)szSendBuf, 3,3000);
+    if(nRet < RECEIPT_SUCCESS)	return nRet;
+    memset(szSendBuf, 0x00, sizeof(szSendBuf));
+	//条码高度,点
+    szSendBuf[0]=0x1D;
+    szSendBuf[1]=0x68;
+    szSendBuf[2]=BarCodeHeight;
+	m_iUsedLeng += BarCodeHeight;
+    nRet = SendData((unsigned char*)szSendBuf, 3,3000);
+    if(nRet < RECEIPT_SUCCESS)	return nRet;
+    memset(szSendBuf, 0x00, sizeof(szSendBuf));
+
+	//条码下面字符的字体
+    szSendBuf[0]=0x1D;
+    szSendBuf[1]=0x66;
+    szSendBuf[2]=bCharB;
+    nRet = SendData((unsigned char*)szSendBuf, 3,3000);
+    if(nRet < RECEIPT_SUCCESS)	return nRet;
+    memset(szSendBuf, 0x00, sizeof(szSendBuf));
+
+    unsigned char cmdbuf[256] = {0x1d, 0x6b, };
+    int iDatPos = 0;
+	if (ctype > 0 && ctype < 9)
+	    cmdbuf[2] = ctype + 'A';
+	else
+        return RECEIPT_ERR_IN_ERR;
+    int nInLen = strlen(cdata);
+	cmdbuf[3] = nInLen;
+    iDatPos = 4;
+    memcpy(cmdbuf+iDatPos,cdata,nInLen);
+	FeedLines(1);
+    nRet = SendData(cmdbuf, iDatPos + nInLen + 1, 3000);
+    if(nRet < RECEIPT_SUCCESS)	return nRet;
+    return RECEIPT_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////
+int	ReceiptBase::Bit24ToBit1(const unsigned char* sInData, int iWidth, int iHigh, unsigned char** psOutData)
+{
+	//存储模式为4字节对齐
+	int		iInXBytes = ((iWidth * 3) + 3) & 0xfffc;
+	int		iX, iY, iPos, iRGB;
+	int		iOutXytes = ((iWidth + 31) >> 3) & 0xfffc;
+	int		iSizeOut = iOutXytes * iHigh;
+	unsigned char*	sOutData = new unsigned char[iSizeOut];
+	memset(sOutData, 0, iSizeOut);
+	for(iY = 0; iY < iHigh; iY++)
+	{
+		for (iX = 0; iX < iWidth; iX++)
+		{
+			//在真彩图位置和数据
+			iPos = (iInXBytes * iY) + iX * 3;
+			iRGB = sInData[iPos++] + sInData[iPos++] + sInData[iPos];
+			//在单色图位置
+			if (iRGB > 100)
+			{
+				iPos = (iOutXytes * iY) + (iX >> 3);
+				sOutData[iPos] |= (1 << (7-(iX % 8)));
+			}
+		}
+	}
+	*psOutData = sOutData;
+	return iSizeOut;
+}
+
+int	ReceiptBase::Bit1ToPrint(unsigned char* sInData, int iWidth, int iHigh, BOOL bRotate, unsigned char** psOutData)
+{
+	//旋转后的位图
+	int nBytesOfWidth = ((iWidth+31) >> 3) & 0xfffc;	//bmp为标准4字节对齐
+    int nBytesOfHeight = (iHigh+7) >> 3;	//打印像素竖向排列
+	int nBytesOutWidth = (iWidth+7) >> 3;	//bmp为标准4字节对齐,输出为1字节对齐
+
+    int iBufSize= nBytesOutWidth * nBytesOfHeight * 8;
+    unsigned char *pOutData = new unsigned char[iBufSize];
+	*psOutData = pOutData;
+    memset(pOutData,0x00,iBufSize);
+    //反色,BMP的 1 为白色的底色,与打印机定义相反
+	int iTemp = 0;
+    for(iTemp = 0; iTemp < nBytesOfWidth * iHigh; iTemp++)
+    {
+        sInData[iTemp] = 0xff - sInData[iTemp];
+    }
+
+	//BMP为横向排列,先从左到右再从下到上,
+	if (bRotate)
+	{
+		//打印机下载数据为纵向排列,先从上到下再从左到右
+		for (int iX = 0; iX < iWidth; iX++)
+		{
+			for (int iY = 0; iY < iHigh; iY++)
+			{
+				//计算在bmp中的位置
+				int iYPos = iHigh - 1 - iY;//Y向倒转后的位置
+				int iXPos = iX >> 3;	//字节位置,/8
+				//位图中字节位置
+				iTemp = (nBytesOfWidth * iYPos) + iXPos;
+				//字节中的位置
+				iXPos = 7 - (iX % 8);	//测试结果,高位在左
+				bool bIsBlack = (sInData[iTemp] >> iXPos) & 1;
+
+				//打印机单个字节内的顺序为从下到上
+				//打印机字节位置
+				iTemp = iX * nBytesOfHeight + (iY >> 3);
+				//字节中的位置,需要Y向倒置
+				iYPos = (7 - (iY % 8));
+				pOutData[iTemp] |= (bIsBlack << iYPos);
+			}
+		}
+	}
+	else
+	{
+		int iRight = iWidth % 8;
+		unsigned char chRight = 0;
+		while (iRight)
+		{
+			chRight |= (1 << (8 - iRight));
+			iRight--;
+		}
+		//打印机下载数据为从上到下
+		for (int iY = 0; iY < iHigh; iY++)
+		{
+			//计算在bmp中的位置
+			int iOldStart = nBytesOfWidth * (iHigh - 1 - iY);
+			int iNewStart = nBytesOutWidth * iY;
+			memcpy(pOutData + iNewStart, sInData + iOldStart, nBytesOutWidth);
+			//此处可能会出现右侧黑边,需要处理最后一个字节像素
+			if (chRight) *(pOutData + iNewStart + nBytesOutWidth - 1) &= chRight;
+		}
+	}
+    return iBufSize;
+}
+
+//位图打印
+int		ReceiptBase::GetBmpData(const char *sData, bool bBASE64, unsigned char** psOut, int* iPrintW, int* iPrintH, BOOL bRotate)
+{
+    if (sData==NULL)
+        return RECEIPT_ERR_IN_ERR;
+    unsigned char*	sBmpDat=NULL;
+    int		iBmpLen=0;
+    if (bBASE64)
+	{
+        int iLen = strlen(sData);
+        if (iLen < 256)
+            return RECEIPT_ERR_IN_ERR;
+        sBmpDat = new unsigned char[iLen+1];
+        iBmpLen = ::Base64Decode(sData, iLen, sBmpDat, iLen);
+        if (iBmpLen < 256) {
+			delete sBmpDat;
+            return RECEIPT_ERR_IN_ERR;
+		}
+    }
+    else
+	{
+        char	sName[128];
+        if (sData==NULL || sData[0]==0)
+            strcpy(sName,"logo.bmp");
+        else
+            strcpy(sName,sData);
+
+        FILE* file = fopen(sName, "rb");
+        if (file == NULL)
+            return RECEIPT_ERR_IN_ERR;
+        fseek(file, 0, SEEK_END);
+        iBmpLen=ftell(file);
+        fseek(file,0, SEEK_SET);
+        if (iBmpLen<192)
+            return RECEIPT_ERR_IN_ERR;
+        sBmpDat=new unsigned char[iBmpLen+1];
+        fread(sBmpDat, 1, iBmpLen,file);
+        fclose(file);
+    }
+	///////////////////////////////
+	BITMAPFILEHEADER bfh;
+    BITMAPINFOHEADER bih;
+
+    int iReadPos = 0;
+    memcpy(&bfh, sBmpDat, sizeof(bfh));
+    iReadPos = sizeof(bfh);
+    memcpy(&bih, sBmpDat + iReadPos, sizeof(bih));
+    iReadPos = bfh.bfOffBits;
+
+	int iSizeAll = (bih.biWidth * bih.biHeight * bih.biBitCount) >> 3;
+    if (iBmpLen < iSizeAll + iReadPos)	return RECEIPT_ERR_IN_ERR;
+    //获得实际图像尺寸
+    *iPrintW = bih.biWidth;
+    *iPrintH = bih.biHeight;
+
+	unsigned char* sTemp = NULL;
+	if (bih.biBitCount == 24)
+	{
+		Bit24ToBit1(sBmpDat + iReadPos, bih.biWidth, bih.biHeight, &sTemp);
+		iBmpLen = Bit1ToPrint(sTemp, bih.biWidth, bih.biHeight, bRotate, psOut);
+		delete sBmpDat;
+		return iBmpLen;
+	}
+	if (bih.biBitCount == 1)
+	{
+		iBmpLen = Bit1ToPrint(sBmpDat+iReadPos, bih.biWidth, bih.biHeight, bRotate, psOut);
+		delete sBmpDat;
+		return iBmpLen;
+	}
+	//////////////////////////////
+    return RECEIPT_ERR_IN_ERR;
+}
+
+//功能:将单色 bmp 图像数据下载到硬件
+int		ReceiptBase::DownloadNVBmp(const char *sData, bool bBASE64)
+{
+    unsigned char*	sBmpDat=NULL;
+	int iWidth, iHeight;
+	int		iRet = GetBmpData(sData, bBASE64, &sBmpDat, &iWidth, &iHeight, TRUE);
+	if (iRet < 0) return iRet;
+    int iWidthByte = (iWidth+7) >> 3;	//bmp4字节对齐,此处不需要,1字节对齐即可
+    int iHeightByte = (iHeight+7) >> 3;
+
+	m_iNVHeight = iHeightByte * 8;
+	//下载位图
+	unsigned char cmd1[8]={0x1C, 0x71, 1, 0, 0, 0, 0};
+    cmd1[3] = iWidthByte;
+    cmd1[5] = iHeightByte;
+	SendData(cmd1, 7);
+//	Sleep(10);
+	int iMax = iWidthByte * iHeightByte * 8;
+	for (int ia=0; ia<iMax; )
+	{
+		int iOnce = min(iMax - ia, 2000);
+		SendData((unsigned char*)sBmpDat + ia, iOnce);
+		ia += iOnce;
+		Sleep(100);
+	}
+//	Sleep(50);
+	delete sBmpDat;
+    return RECEIPT_SUCCESS;
+}
+
+//打印NV位图
+int  ReceiptBase::PrintNVBmp(bool bDH, bool bDW)
+{
+    //打印位图
+    unsigned char cmd2[]={0x1C,0x70,1,0};
+	if (bDH) cmd2[3] += 2;
+	if (bDW) cmd2[3] += 1;
+    SendData(cmd2, 4);
+    m_iUsedLeng += m_iNVHeight;
+    return 0;
+}
+
+//功能:将单色 bmp 图像数据下载到硬件
+int		ReceiptBase::PrintMemBmp(const char *sData, bool bBASE64)
+{
+	//光栅位图方试
+    unsigned char*	sBmpDat=NULL;
+    int		iWidth, iHeight;
+	int		iRet = GetBmpData(sData, bBASE64, &sBmpDat, &iWidth, &iHeight, FALSE);
+	if (iRet < 0) return iRet;
+
+    int iWidthByte = (iWidth + 7) >> 3;	//宽度字节数
+    int iWidthDown = iWidthByte < 80 ? iWidthByte : 80;
+    int iOutHeight = ((4096 / iWidthDown) / 24) * 24;	//高度需要是24倍数
+
+	unsigned char sSend[4*1024];
+	sSend[0] = 0x1D;	//光栅位图打印
+	sSend[1] = 0x76;
+	sSend[2] = 0x30;
+	sSend[3] = 0;
+	sSend[4] = iWidthDown;	//宽度方向字节数
+	sSend[5] = 0;
+	sSend[7] = 0;
+	int iSendPos;
+	for (int iHPos = 0; iHPos < iHeight; iHPos += iOutHeight)
+	{
+		int iBmpHeight = (iHeight - iHPos < iOutHeight) ? iHeight - iHPos : iOutHeight;
+		sSend[6] = iBmpHeight;	//高度方向点数
+		iSendPos = 8;
+		for ( int ia = 0; ia < iBmpHeight; ia++)//宽度循环
+		{
+			memcpy(sSend + iSendPos, sBmpDat + iWidthByte * (iHPos + ia), iWidthDown);
+			iSendPos += iWidthDown;
+		}
+		SendData(sSend, iSendPos);
+		Sleep(100);
+	}
+	delete sBmpDat;
+    m_iUsedLeng += iHeight;
+    return RECEIPT_SUCCESS;
+}
+
+//原有,转换成字符串
+short ReceiptBase::GetBinBuf(short val,char *buf)
+{
+	char sBufs[][8]=
+	{
+		"0000", "0001", "0010", "0011",
+		"0100", "0101", "0110", "0111",
+		"1000", "1001", "1010", "1011",
+		"1100", "1101", "1110", "1111"
+	};
+	if (val >= 0 && val <= 15)
+	{
+        memcpy(buf, sBufs[val], 4);
+		return 0;
+	}
+	return 1;
+}
+
+//原有,变量转化成字串
+short	ReceiptBase::ByteToBytes(short value,char *buf)
+{
+    char low_byte,high_byte,low_buf[5],high_buf[5];
+    short ret1,ret2;
+    memset(low_buf,'\0',5);
+    memset(high_buf,'\0',5);
+
+    if(value<0 || value>255)
+        return 2;    //非法值
+    low_byte=value%16;
+    high_byte=value/16;
+    ret1=GetBinBuf(low_byte,low_buf);
+    ret2=GetBinBuf(high_byte,high_buf);
+    if(ret1!=0 || ret2!=0)
+        return 1;    //计算错误
+    memcpy(buf,high_buf,4);
+    memcpy(buf+4,low_buf,4);
+    return 0;
+}
+
+int		ReceiptBase::GetStateData(const char* sCmd1, const char* sCmd2, const char* sCmd3, const char* sCmd4)
+{
+	if(sCmd2[1] == '1' || sCmd3[4]=='1')		//打印机故障
+        return RECEIPT_ERR_DEV_ERR;
+	if(sCmd2[5] == '1')	//打印机头抬起
+        return RECEIPT_WARN_HEAD_UP;
+	if(sCmd4[7] == '1')	//卡纸
+        return RECEIPT_WARN_JAMMED;
+	if(sCmd4[2] == '1')		//缺纸
+        return RECEIPT_WARN_NO_MEDIA;
+	if(sCmd4[4] == '1')		//纸将尽
+        return RECEIPT_WARN_PAP_LOW;
+    return RECEIPT_SUCCESS;
+}
+
+int		ReceiptBase::GetState()
+{
+	char sState[4][16];
+    int iRet = ReadStateData(NULL, sState[1], sState[2], sState[3]);
+    if (iRet != RECEIPT_SUCCESS)	return iRet;
+    return GetStateData(NULL, sState[1], sState[2], sState[3]);
+}
+
+//发送状态查询命令
+int		ReceiptBase::ReadStateData(short nNum,char * buf)
+{
+    unsigned char szSendBuf[20];
+    int ret,back;
+    char chRcvbuf[10] = {0};
+    short nRcvlen;
+    int nRet = 0;
+    memset(szSendBuf,'\0',20);
+
+    szSendBuf[0]=0x10;
+    szSendBuf[1]=0x04;
+    szSendBuf[2]=(char)nNum;
+    nRet = SendData(szSendBuf,3,300);
+    if(nRet <=0 )
+    {
+        return RECEIPT_ERR_RCV_ERR;
+    }
+    //Sleep(10);
+    nRcvlen = ReadData((unsigned char*)chRcvbuf, 1, 3000);
+    if(nRcvlen < 1)
+    {
+        return RECEIPT_ERR_RCV_ERR;
+    }
+    back=chRcvbuf[0];
+
+    ret=ByteToBytes(back,buf);
+    if(ret!=0)
+    {
+        return RECEIPT_ERR_IN_ERR;
+    }
+    buf[8] = 0;
+    return RECEIPT_SUCCESS;
+}
+
+//取状态
+int		ReceiptBase::ReadStateData(char * buf1, char* buf2, char * buf3, char * buf4)
+{
+    int nRet = 0;
+    if(buf1)
+    {
+        nRet = ReadStateData(1,buf1);
+        if(nRet != RECEIPT_SUCCESS)
+            return nRet;
+    }
+    /////////////////
+    if(buf2)
+    {
+        nRet = ReadStateData(2,buf2);
+        if(nRet != RECEIPT_SUCCESS)
+            return nRet;
+    }
+    /////////////////
+    if(buf3)
+    {
+        nRet = ReadStateData(3,buf3);
+        if(nRet != RECEIPT_SUCCESS)
+            return nRet;
+    }
+    /////////////////
+    if(buf4)
+    {
+        nRet = ReadStateData(4,buf4);
+            return nRet;
+    }
+    return RECEIPT_SUCCESS;
+}
+

+ 160 - 0
DevAdapter/cw/termalprint.1.1/ReceiptBase.h

@@ -0,0 +1,160 @@
+// Scan5180.h: interface for the Scan5180 class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(_ReceiptBase_SUNEW_20170608_INCLUDED_)
+#define _ReceiptBase_SUNEW_20170608_INCLUDED_
+
+#include "cmb.h"
+
+//成功,正常
+#define RECEIPT_SUCCESS			0
+//错误状态
+#define RECEIPT_ERR_NO_FOND		-1	//设备未找到
+#define RECEIPT_ERR_NO_OPEN		-2	//设备未打开
+#define RECEIPT_ERR_RCV_ERR		-3	//数据接收错误
+#define RECEIPT_ERR_IN_ERR		-4	//输入参数错误
+#define RECEIPT_ERR_DEV_ERR		-5	//设备硬件故障
+
+//警告类状态
+#define RECEIPT_WARN_NO_MEDIA	-6	//缺纸
+#define RECEIPT_WARN_HEAD_UP	-7	//机头抬起
+#define RECEIPT_WARN_JAMMED     -8	//卡纸
+
+#define RECEIPT_WARN_PAP_LOW	1	//纸少
+
+#ifndef _WIN32
+
+#pragma pack(1)
+typedef struct tagBITMAPFILEHEADER {
+	UINT16	bfType;
+	UINT32	bfSize;
+	UINT16	bfReserved1;
+	UINT16	bfReserved2;
+	UINT32	bfOffBits;
+} BITMAPFILEHEADER;
+
+typedef struct tagBITMAPINFOHEADER{
+	UINT32	biSize;
+	INT32	biWidth;
+	INT32	biHeight;
+	UINT16	biPlanes;
+	UINT16	biBitCount;
+	UINT32	biCompression;
+	UINT32	biSizeImage;
+	INT32	biXPelsPerMeter;
+	INT32	biYPelsPerMeter;
+	UINT32	biClrUsed;
+	UINT32	biClrImportant;
+} BITMAPINFOHEADER;
+
+#pragma pack()
+#endif
+
+class ReceiptBase
+{
+public:
+	ReceiptBase();
+	virtual ~ReceiptBase();
+protected:
+    SUsb	m_cSerial;
+
+	int		m_iLetSpace;	//左边空格
+	int		m_iLineHeight;	//行高度:点
+	int		m_iLineLeng;	//每行字符数
+	int		m_iUsedLeng;	//已打印纸张长度
+	int		m_iMinPaper;	//切纸最短长度
+	int		m_iLastPos;		//上次打印一行内结束位置
+
+    int		m_iMMPerSec;	//打印速度,毫米每秒,延时用
+	int		m_iLinesPrted;	//已打印行数,每20行做一次延时
+
+public:
+	//打印高速20,中速10,低速 00
+	virtual int		SetPrintSpeed(short nSpeed);
+	//凭条打印机 初始化
+	virtual int		Init();
+
+public:
+	//凭条打印机 判断端口打开
+	bool	Isopen();
+	//凭条打印机 打开端口
+	int		Open(const int iVID, const int iPID, const int iFD = 0);
+	//打印机 关闭端口
+	int		Close();
+	int		GetState();
+
+	//最少纸长度,部分打印机出纸口限制,太短无法出来
+	int		SetMinLen(int iLen){m_iMinPaper = iLen;};
+	//设置打印机基本参数(如不设置则使用默认值)每行字符数,左空白字符数,打印速度(无流控延时用)
+    void	SetLinePara(int iLineLeng, int iLeftSpace, int iSpeed);
+	//设置左边距,单位为点(0.125mm)
+	int		SetLeftDistance(int iLeft);
+    //设置打印区域
+    int     SetPrintArea(int iLeng);
+    //设置行高,单位为点(0.125mm)
+	int		SetRowDistance(int iH);
+	//DH 倍高 DW倍宽 DD黑体 UL下划线 XT斜体
+	int 	SetFont(bool bDH, bool bDW, bool bDD, bool bUL, bool bCharB);
+	//nAlign 0左对齐 ,1居中, 2右对齐
+	int		SetAlign(short nAlign);
+	//设置打印放大倍数(1-6)
+	int		SetScale(int iX, int iY);
+	//设置黑白反显打印模式
+	int		SetInverse(bool b);
+	//选择/取消顺时针旋转90度
+	int		SetRotate(bool b);
+	//是否黑标纸
+	int		SetBlackFlag(bool b);
+	//设置黑标位置
+	int		SetBlackPos(int i);
+    //获取固件版本
+    int		GetFirmware(char* s);
+    //打印不自动添加换行
+	int		SendHexStr(const char *sData, int iDataLen = 0);
+	//打印不自动添加换行
+	int		PrintData(const char *sData);
+	//打印数据并自动添加换行
+	int		PrintLine(const char* sLine);
+	int		PrintChar(char ch, int iCount);
+	//走纸n行
+	int		FeedLines(int iLines);
+	//走纸1点,iMode 0向前,1后退,单位为点(0.125mm)
+	int		FeedPaper(short iMode, short iDistance);
+	//	ctype	0 UPC-A(11-12)		1 UPC-E(11-12)		2 JAN13,EAN13(12-13)
+	//			3 JAN8,EAN8(7-8)	4 CODE39(1-255)		5 ITF(1-255偶)
+	//			6 CODABAR(1-255)	7 CODE93(1-255)		8 CODE128(1-255)
+	//	iBytePos 0不打印HRI字符 1条码上方打印 2条码下方打印 3条码上下方打印
+	int		PrinterCode(const char* cdata,UINT ctype,
+		UINT iBytePos,UINT BarCodeWidth,UINT BarCodeHeight,bool bCharB);
+	int		Cut(int iMode);	//0:全切 1:半切
+
+
+	//功能:将单色 bmp 图像数据下载到硬件
+	int		PrintMemBmp(const char *sData, bool bBASE64);
+
+	//sData文件名或者BASE64数据 返回图片高度,失败返回负值
+	int		DownloadNVBmp(const char *sData,bool bBASE64);
+	int		PrintNVBmp(bool bDH, bool bDW);
+
+protected:
+	//凭条发送命令,超时时间为毫秒
+	int		SendData(const unsigned char *sSend,int iDatLen,int iTimeout=300);
+	int		ReadData(unsigned char *sRead,int iWant,int iTimeout);
+	/* 凭条打印机 获取状态 */
+    int		ReadStateData(short nNum,char * buf);
+    int		ReadStateData(char * sCmd1, char* sCmd2, char * sCmd3, char * sCmd4);
+    virtual int		GetStateData(const char* sCmd1, const char* sCmd2, const char* sCmd3, const char* sCmd4);
+
+	int		m_iNVHeight;
+
+protected:
+	int		Bit24ToBit1(const unsigned char* sInData, int iWidth, int iHigh, unsigned char** psOutData);
+	int		Bit1ToPrint(unsigned char* sInData, int iWidth, int iHigh, BOOL bRotate, unsigned char** psOutData);
+
+	short	GetBinBuf(short val,char *buf);
+	short	ByteToBytes(short value,char *buf);
+	int		GetBmpData(const char *sData,bool bBASE64,unsigned char** psOut,int* iPrintW, int* iPrintH, BOOL bChgPrt);
+};
+
+#endif // !defined(_ReceiptBase_SUNEW_20170608_INCLUDED_)

+ 59 - 0
DevAdapter/cw/termalprint.1.1/ReceiptSnbc.cpp

@@ -0,0 +1,59 @@
+// ReceiptSnbc.cpp: implementation of the ReceiptSnbc class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "ReceiptSnbc.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+ReceiptSnbc::ReceiptSnbc()
+{
+
+}
+
+ReceiptSnbc::~ReceiptSnbc()
+{
+
+}
+
+//打印机初始化
+int	ReceiptSnbc::Init()
+{
+    int iRet = ReceiptBase::Init();
+    if (iRet != 0) return iRet;
+
+    unsigned char szSendBuf[20];
+    szSendBuf[0] = 0x1d;
+    szSendBuf[1] = 0x45;
+    szSendBuf[2] = 0x20;//打印低速20,中速10,高速 00
+    SendData(szSendBuf,3,3000);
+    szSendBuf[0] = 0x1d;
+    szSendBuf[1] = 0x28;
+    szSendBuf[2] = 0x4b;//
+    szSendBuf[3] = 0x02;//
+    szSendBuf[4] = 0x00;//
+    szSendBuf[5] = 0x31;//
+	szSendBuf[6] = 6;	//清晰度,-6->6 数字越高越清晰
+	//新北洋位-6 至 6,证通为 0 至 14
+    SendData(szSendBuf,7,3000);
+    SetPrintArea(640);
+    return RECEIPT_SUCCESS;
+}
+
+int		ReceiptSnbc::GetStateData(const char* sCmd1, const char* sCmd2, const char* sCmd3, const char* sCmd4)
+{
+	if(sCmd2[1] == '1' || sCmd3[4]=='1')		//打印机故障
+        return RECEIPT_ERR_DEV_ERR;
+    if(sCmd2[5] == '1')	//打印机头抬起
+        return RECEIPT_WARN_HEAD_UP;
+	if(sCmd4[7] == '1')	//卡纸
+        return RECEIPT_WARN_JAMMED;
+	if(sCmd4[2] == '1')		//缺纸
+        return RECEIPT_WARN_NO_MEDIA;
+	if(sCmd4[4] == '1')		//纸将尽
+        return RECEIPT_WARN_PAP_LOW;
+    return RECEIPT_SUCCESS;
+}
+

+ 27 - 0
DevAdapter/cw/termalprint.1.1/ReceiptSnbc.h

@@ -0,0 +1,27 @@
+// ReceiptT80.h: interface for the ReceiptT80 class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_RECEIPTT80_H__54F58090_42FE_4599_B2FD_049800D413D3__INCLUDED_)
+#define AFX_RECEIPTT80_H__54F58090_42FE_4599_B2FD_049800D413D3__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "ReceiptBase.h"
+
+class ReceiptSnbc: public ReceiptBase
+{
+public:
+    ReceiptSnbc();
+    virtual ~ReceiptSnbc();
+
+	//凭条打印机 初始化
+	virtual int		Init();
+protected:
+    virtual int		GetStateData(const char* sCmd1, const char* sCmd2, const char* sCmd3, const char* sCmd4);
+};
+
+#endif // !defined(AFX_RECEIPTT80_H__54F58090_42FE_4599_B2FD_049800D413D3__INCLUDED_)
+

+ 58 - 0
DevAdapter/cw/termalprint.1.1/termalprintdev.cpp

@@ -0,0 +1,58 @@
+#include "termalprintimpl.h"
+#include "log4vendor.h"
+
+
+ThermalPrintClassImpl*     g_pThermalPrint = NULL;
+
+void __attribute__((destructor)) uninit()
+{
+    if (g_pThermalPrint)
+    {
+        delete g_pThermalPrint;
+        g_pThermalPrint = NULL;
+    }
+}
+
+void __attribute__((constructor)) init()
+{
+}
+
+DEVICEBASE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(NULL == g_pThermalPrint)
+    {
+        g_pThermalPrint = new ThermalPrintClassImpl();
+        baseObj = (DeviceBaseClass *)g_pThermalPrint;
+
+        cmb::log_init_config config;
+        config.log_level=CMB_LOG_LEVEL_ALL;
+        config.dev_name = "WatchDog";
+    #if defined(_MSC_VER)
+        config.log_dir = ("C:\\rvc\\dbg\\");
+    #else
+        config.log_dir = ("/opt/rvc/dbg/");
+    #endif //_MSC_VER
+        std::string str;
+        cmb::log4vendor::init(config, str);
+        printf("init after: %s\n", str.c_str());
+    }
+    else
+    {
+        eRt = Error_AlreadyExist;
+    }
+    return eRt;
+}
+
+DEVICEBASE_API ErrorCodeEnum  ReleaseDevComponent(DeviceBaseClass *&pBaseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(pBaseObj == (DeviceBaseClass*)g_pThermalPrint)
+    {
+        delete g_pThermalPrint;
+        g_pThermalPrint = NULL;
+        return Error_Succeed;
+    }
+    return Error_Param;
+}
+

+ 458 - 0
DevAdapter/cw/termalprint.1.1/termalprintimpl.cpp

@@ -0,0 +1,458 @@
+#include "termalprintimpl.h"
+#include "SUcs.h"
+
+ThermalPrintClassImpl::ThermalPrintClassImpl()
+{
+    m_pPrint = new ReceiptSnbc();
+    m_bStartup = false;
+}
+
+ThermalPrintClassImpl::~ThermalPrintClassImpl()
+{
+    delete m_pPrint;
+}
+
+//	打开打印机
+ErrorCodeEnum ThermalPrintClassImpl::DevOpen(BYTE btPort,DWORD dwBaudRate)
+{
+    int iRet = m_pPrint->Open(0x154f, 0x154f);
+    if (iRet != 0)  return GetErrorInfo(iRet, "DevOpen");
+
+    iRet = m_pPrint->GetState();
+    return GetErrorInfo(iRet, "DevOpen");
+}
+
+int getFileVer(char* sFile, short& ch1, short& ch2)
+{
+    ch1 = 0;
+    ch2 = 0;
+    char* pFind = strstr(sFile, ".so");
+    char* pTemp = pFind;
+    while (pTemp)
+    {
+        pFind = pTemp;
+        pTemp = strstr(pFind + 3, ".so");
+    }
+    if (pFind == NULL) return 0;
+
+    pTemp = pFind - 1;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch2 = atoi(pTemp+1);
+    pTemp--;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch1 = atoi(pTemp+1);
+    return 1;
+}
+
+ErrorCodeEnum ThermalPrintClassImpl::GetDevCategory(DevCategoryInfo &devCategory)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "GetDevCategory");
+
+    char sSVer[256];
+    if (m_pPrint->GetFirmware(sSVer) == 0)
+        strcpy(devCategory.szType, sSVer);
+    else
+        strcpy(devCategory.szType, "DEVICE_NAME");
+    strcpy(devCategory.szModel, "WID=Cashway001");
+    strcpy(devCategory.szVendor, "cw");
+
+    char cFilePath[300] = {0};
+    GetCurLibsPath(m_sLibPath, cFilePath);
+    short v1,v2;
+    getFileVer(cFilePath, v1, v2);
+
+    devCategory.version.wMajor = v1;
+    devCategory.version.wMinor = v2;
+    devCategory.version.wRevision = 0xffff;
+    devCategory.version.wBuild = FILE_VERSION;
+    char szRet[512] = {0};
+    sprintf(szRet, "szType:%s,szModel:%s,szVendor:%s,version.wMajor:%d,version.wMinor:%d,version.wBuild:%d,version.wRevision:%d,eState:%d(0:故障1:正常)",
+            devCategory.szType,devCategory.szModel,devCategory.szVendor,devCategory.version.wMajor,devCategory.version.wMinor,devCategory.version.wBuild,devCategory.version.wRevision,devCategory.eState);
+    LOG4VTM(INFO, szRet);
+
+    return Error_Succeed;
+}
+
+ErrorCodeEnum ThermalPrintClassImpl::Reset()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "Reset");
+    m_pPrint->Init();
+    int iRet = m_pPrint->GetState();
+    return GetErrorInfo(iRet, "Reset");
+}
+
+ErrorCodeEnum ThermalPrintClassImpl::DevClose()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "DevClose");
+    int iRet = m_pPrint->Close();
+    return GetErrorInfo(iRet, "DevClose");
+}
+
+ErrorCodeEnum ThermalPrintClassImpl::GetLastErr(DevErrorInfo &devErrInfo)
+{
+    memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
+    return Error_Succeed;
+}
+
+//	获取打印机实时状态
+ErrorCodeEnum ThermalPrintClassImpl::GetDevState(ThermalState& devState)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "GetDevCategory");
+
+    int iRet = m_pPrint->GetState();
+    if (iRet < 0)
+        return GetErrorInfo(iRet, "Reset");
+    devState.hardwareState = STATE_OK;
+    switch(iRet)
+    {
+    case RECEIPT_SUCCESS:
+        devState.paperState = PAPER_FULL;
+        break;
+    case RECEIPT_WARN_NO_MEDIA:
+        devState.paperState = PAPER_EMPTY;
+        break;
+    case RECEIPT_WARN_PAP_LOW:
+        devState.paperState = PAPER_LOW;
+        break;
+    case RECEIPT_WARN_HEAD_UP:
+        devState.hardwareState = STATE_OTHER_ERROR;
+        break;
+    case RECEIPT_WARN_JAMMED:
+        devState.paperState = PAPER_JAMMED;
+        break;
+    }
+    return Error_Succeed;
+}
+
+//开始打印初始设置:paperWidth一般为80mm和57mm
+ErrorCodeEnum ThermalPrintClassImpl::BeginPrint(ThermalPaperType eType, int paperWidth)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "BeginPrint");
+    int iRet = m_pPrint->Init();
+    if (iRet != 0)
+        return GetErrorInfo(iRet, "BeginPrint");
+    m_bStartup = true;
+    return Error_Succeed;
+}
+
+
+//打印控制指令函数:主要是打印,切纸和控制打印光标指令函数
+//第三个参数是预留参数 暂时无用到
+ErrorCodeEnum ThermalPrintClassImpl::ControlAction(PrintAction eAction, DWORD dwValue1, DWORD dwValue2)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "ControlAction");
+    int iRet = 0;
+    switch(eAction)
+    {
+    case ACTION_PRINT_ONE_LINE:
+        iRet = m_pPrint->FeedLines(1);
+        break;
+    case ACTION_PRINT_MOVEFORWRAD_LINES:
+        iRet = m_pPrint->FeedLines(dwValue1);
+        break;
+//    case ACTION_PRINT_MOVEBACKWRAD_LINES:     //回纸n行(单位:字符行)
+//        iRet = m_pPrint->FeedLines(-dwValue1);
+//        break;
+    case ACTION_CUT_ALL:
+        iRet = m_pPrint->Cut(0);
+        break;
+    case ACTION_CUT_HALF:
+        iRet = m_pPrint->Cut(1);
+        break;
+//    case ACTION_MOVE_TO_POSITION_RELATIVE:    //把打印光标移动相对当前位置一段距离(横向),单位mm
+//        iRet = m_pPrint->(0, dwValue1 * 8);
+//        break;
+    case ACTION_MOVE_TO_FORWRAD_LENGTH:
+        iRet = m_pPrint->FeedPaper(0, dwValue1 * 8);
+        break;
+//    case ACTION_MOVE_TO_BLACKMARK:  //移动到黑标位置,把打印位置设置在行首(标记纸有效)
+//        iRet = m_pPrint->mo
+//        break;
+//    case ACTION_PRINT_MOVEBACK_TO_LINE: //设置起始位置在行首,取值(0:打印内容返回行首,1:清空要打印的内容返回行首)
+//        iRet = m_pPrint->FeedPaper(0, dwValue1 * 8);
+//        break;
+    }
+    return GetErrorInfo(iRet, "ControlAction");
+}
+
+//打印参数指令函数:
+//第三个参数是预留参数 暂时无用到
+ErrorCodeEnum ThermalPrintClassImpl::SetParam(CommandType eType, DWORD dwValue1, DWORD dwValue2)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "SetParam");
+    int iRet = 0;
+    switch(eType)
+    {
+    case COMMON_ROW_SPACE:
+        iRet = m_pPrint->SetRowDistance(dwValue1 * 8);
+        break;
+    case COMMON_ALIGN:
+        iRet = m_pPrint->SetAlign(dwValue1);
+        break;
+//    case COMMON_REVERSE:
+//        iRet = m_pPrint->SetInverse(dwValue1);
+//        break;
+    case COMMON_LEFT_MARGIN:
+        iRet = m_pPrint->SetLeftDistance(dwValue1 * 8);
+        break;
+    case COMMON_PRINTABLE_AREA:
+        iRet = m_pPrint->SetPrintArea(dwValue1 * 8);
+        break;
+    }
+    return GetErrorInfo(iRet, "SetParam");
+}
+
+//打印字体指令函数:主要是字体相关饿指令函数
+//第三个参数是预留参数 设置FONT_CUSTOM_SIZE用到,dwValue1表示宽,dwValue2表示长
+//					设置FONT_LEFT_RIGHT_SPACE用到 dwValue1表示左边距 dwValue2表示右边距
+ErrorCodeEnum ThermalPrintClassImpl::SetFont(FontStyle eType, DWORD dwValue1, DWORD dwValue2)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "SetFont");
+    int iRet = 0;
+    switch(eType)
+    {
+    case FONT_UNDERLINE:
+        m_FontParam.bUL = dwValue1;
+        m_bFontChanged = true;
+        break;
+    case FONT_BOLD:
+        m_FontParam.bold = dwValue1;
+        m_bFontChanged = true;
+        break;
+    case FONT_DOUBLEHEIGHT:
+        m_FontParam.bDH = dwValue1;
+        m_bFontChanged = true;
+        break;
+    case FONT_DOUBLEWIDE:
+        m_FontParam.bDW = dwValue1;
+        m_bFontChanged = true;
+        break;
+    case FONT_INVERSE:
+        iRet = m_pPrint->SetInverse(dwValue1);
+        break;
+    case FONT_CUSTOM_SIZE:
+        iRet = m_pPrint->SetScale(dwValue1, dwValue2);
+        break;
+    case FONT_ROTATE:
+        iRet = m_pPrint->SetRotate(dwValue1);
+        break;
+    case FONT_LEFT_RIGHT_SPACE:
+        iRet = m_pPrint->SetLeftDistance(dwValue1);
+        break;
+    }
+    return GetErrorInfo(iRet, "SetParam");;
+}
+
+//打印文本数据函数
+ErrorCodeEnum ThermalPrintClassImpl::PrintText(BYTE* pData, DWORD dwDataLen)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintText");
+    int iRet = 0;
+    if (m_bFontChanged)
+    {
+        iRet = m_pPrint->SetFont(m_FontParam.bDH, m_FontParam.bDW, m_FontParam.bold, m_FontParam.bUL, false);
+        m_bFontChanged = false;
+        if (iRet != 0)
+            return GetErrorInfo(iRet, "PrintText");
+    }
+    int iLen = dwDataLen > 0 ? dwDataLen : strlen((char*)pData);
+    char* pGB = new char[iLen+1];
+    iLen = SUcs::UTF8ToGB18030((char*)pData, pGB);
+    pGB[iLen] = 0;
+    iRet = m_pPrint->GetState();
+    if (iRet < 0)
+        GetErrorInfo(iRet, "PrintText");
+    iRet = m_pPrint->PrintData(pGB);
+    if (iRet < 0)
+        return GetErrorInfo(iRet, "PrintText");
+    return GetErrorInfo(0, "PrintText");
+}
+
+//打印条形码函数
+//dwUnitWidth 条形码基本模块宽度 取值{2..6} 默认2
+//dwHeight 条形码高度 单位mm
+//iHRIPosition hri字符打印位置 见枚举类型HriPosition
+ErrorCodeEnum ThermalPrintClassImpl::PrintBarCode(BarCodeType eType, BYTE* pData,
+                                   DWORD dwDataLen, DWORD dwUnitWidth,
+                                   DWORD dwHeight, HriPosition eHRIPosition)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintBarCode");
+    return Error_Succeed;
+}
+
+//打印二维码QRCode函数
+//dwUnitWidth 二维码基本元素宽度 取值{1..255} 默认3
+ErrorCodeEnum ThermalPrintClassImpl::PrintQRCode(BYTE* pData, DWORD dwDataLen, DWORD dwUnitWidth)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintQRCode");
+    return Error_Succeed;
+}
+
+//打印二维码QRCode函数
+//dwWidth 二维码长度 ,单位mm
+ErrorCodeEnum ThermalPrintClassImpl::PrintQRCodeByArea(BYTE* pData, DWORD dwDataLen, DWORD dwUnitWidth, DWORD dwWidth)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintQRCodeByArea");
+    return Error_Succeed;
+}
+
+//打印二维码PDF417函数
+//errorLevel pdf417纠错级别 取值{0..8}
+//dwUnitWidth  基本元素宽度 取值{3..90}
+//dwUnitHeight 基本元素长度 取值{1..30}
+//row  pdf417 行数 取值{1..7}
+//lines pdf417 列数 取值{2..25}
+ErrorCodeEnum ThermalPrintClassImpl::PrintPDF417code(BYTE* pData, DWORD dwDataLen, int errorLevel,
+                                      DWORD dwUnitWidth, DWORD dwUnitHeight, int rows, int lines)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintPDF417code");
+    return Error_Succeed;
+}
+
+
+//打印二维码PDF417函数
+//errorLevel pdf417纠错级别 取值{0..8}
+//dwWidth  pdf417宽度 单位mm
+//dwHeight pdf417长度 单位mm
+ErrorCodeEnum ThermalPrintClassImpl::PrintPDF417codeByArea(BYTE* pData, DWORD dwDataLen,
+                                            int errorLevel, DWORD dwWidth, DWORD dwHeight)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintPDF417codeByArea");
+    return Error_Succeed;
+}
+
+
+//打印图像函数:pData是base64编码的数据
+ErrorCodeEnum ThermalPrintClassImpl::PrintImage(BYTE* pData, DWORD dwDataLen)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintImage");
+    int iRet = m_pPrint->PrintMemBmp((char*)pData, true);
+    return GetErrorInfo(iRet, "PrintImage");
+}
+
+
+//获取打印失败后错误信息和错误状态
+ErrorCodeEnum ThermalPrintClassImpl::GetLastErrState(ThermalState& devState, DevErrorInfo& devErrInfo)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pPrint->Isopen())
+        return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "GetLastErrState");
+
+    int iRet = m_pPrint->GetState();
+    if (iRet < 0)
+        return GetErrorInfo(iRet, "Reset");
+    devState.hardwareState = STATE_OK;
+    switch(iRet)
+    {
+    case RECEIPT_SUCCESS:
+        devState.paperState = PAPER_FULL;
+        break;
+    case RECEIPT_WARN_NO_MEDIA:
+        devState.paperState = PAPER_EMPTY;
+        break;
+    case RECEIPT_WARN_PAP_LOW:
+        devState.paperState = PAPER_LOW;
+        break;
+    case RECEIPT_WARN_HEAD_UP:
+        devState.hardwareState = STATE_OTHER_ERROR;
+        break;
+    case RECEIPT_WARN_JAMMED:
+        devState.paperState = PAPER_JAMMED;
+        break;
+    }
+    memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
+    return Error_Succeed;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+//  DEC_SUCCESS DEC_HARDWARE DEC_TIMEOUT DEC_INVALID_PARAMETER DEC_INVALID_MASTER_KEY
+const static CmbErrorDef PrintErrInfo[] = {
+    {RECEIPT_SUCCESS,       "命令执行成功", Error_Succeed, DEC_SUCCESS},
+    {RECEIPT_ERR_NO_FOND,   "设备未找到", Error_Hardware, DEC_DEV_NOT_FOUND},
+    {RECEIPT_ERR_NO_OPEN,   "设备尚未打开", Error_Param, DEC_DEV_NOT_OPENED},
+    {RECEIPT_ERR_RCV_ERR,   "数据接收错误", Error_IO, DEC_COMMUNICATION_FAILED},
+    {RECEIPT_ERR_IN_ERR,    "输入参数错误", Error_Param, DEC_INVALID_PARAMETER},
+    {RECEIPT_ERR_DEV_ERR,   "设备硬件故障", Error_Hardware, DEC_HARDWARE},
+
+    {RECEIPT_WARN_NO_MEDIA,  "缺纸", Error_DevMedia, DEC_HARDWARE},
+    {RECEIPT_WARN_HEAD_UP,   "机头未闭合", Error_Hardware, DEC_HARDWARE},
+    {RECEIPT_WARN_JAMMED,    "卡纸", Error_Hardware, DEC_HARDWARE},
+
+    {RECEIPT_WARN_PAP_LOW,   "纸少", Error_Succeed, DEC_SUCCESS},
+};
+
+ErrorCodeEnum ThermalPrintClassImpl::GetErrorInfo(int iCode, char* sErr, ...)
+{
+    size_t iLenOne = sizeof(CmbErrorDef);
+    size_t iLenAll = sizeof(PrintErrInfo);
+    int iCount = iLenAll / iLenOne;
+    char sErrInfo[256]="";
+    DWORD dSta = 0;
+    int iErr = -1;
+    for (int ia = 0; ia < iCount; ia++)
+    {
+        if (PrintErrInfo[ia].iCode == iCode)
+        {
+            dSta = PrintErrInfo[ia].iInf;
+            strcpy(sErrInfo, PrintErrInfo[ia].sInf);
+            iErr = PrintErrInfo[ia].iRet;
+            break;
+        }
+    }
+
+    char sErrAll[300];
+    va_list arglist;
+    va_start(arglist, sErr);
+    _vsnprintf(sErrAll, 128, sErr, arglist);
+    va_end(arglist);
+
+    if (sErrInfo[0])
+    {
+        strcat(sErrAll, " ");
+        strcat(sErrAll, sErrInfo);
+    }
+    sErrAll[200] = 0;
+    iLenOne = strlen(sErrAll);
+    sprintf(m_DevErrInfo.szErrMsg, "{\"ErrCode\":\"%04x\",\"Description\":\"%s\"}", iErr, sErrAll);
+//    strcpy(m_DevErrInfo.szErrMsg, sErrAll);
+    m_DevErrInfo.dwErrMsgLen = ((dSta << 16) & 0xffff0000) + iLenOne;
+    if (iErr != Error_Succeed)
+        LOG4VTM(WARN, m_DevErrInfo.szErrMsg);
+    else
+        LOG4VTM(INFO, m_DevErrInfo.szErrMsg);
+    return (ErrorCodeEnum)iErr;
+}
+

+ 110 - 0
DevAdapter/cw/termalprint.1.1/termalprintimpl.h

@@ -0,0 +1,110 @@
+#ifndef LIBFRAMEWORK_THERM_IMPL_H
+#define LIBFRAMEWORK_THERM_IMPL_H
+
+#include "ThermalPrintClass.h"
+#include "ReceiptSnbc.h"
+
+#define FILE_VERSION    1
+
+class ThermalPrintClassImpl : public ThermalPrintClass
+{
+public:
+    ThermalPrintClassImpl();
+    ~ThermalPrintClassImpl();
+
+
+    //DeviceBaseClass
+    ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
+    ErrorCodeEnum Reset();
+    ErrorCodeEnum DevClose();
+    ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+
+    //	打开打印机
+    virtual ErrorCodeEnum DevOpen(BYTE btPort, DWORD dwBaudRate);
+    //	获取打印机实时状态
+    virtual ErrorCodeEnum GetDevState(ThermalState& devState);
+
+    //开始打印初始设置:paperWidth一般为80mm和57mm
+    virtual ErrorCodeEnum BeginPrint(ThermalPaperType eType, int paperWidth);
+
+    //打印控制指令函数:主要是打印,切纸和控制打印光标指令函数
+    //第三个参数是预留参数 暂时无用到
+    virtual ErrorCodeEnum ControlAction(PrintAction eAction, DWORD dwValue1, DWORD dwValue2 = 0);
+
+    //打印参数指令函数:
+    //第三个参数是预留参数 暂时无用到
+    virtual ErrorCodeEnum SetParam(CommandType eType, DWORD dwValue1, DWORD dwValue2 = 0);
+
+    //打印字体指令函数:主要是字体相关饿指令函数
+    //第三个参数是预留参数 设置FONT_CUSTOM_SIZE用到,dwValue1表示宽,dwValue2表示长
+    //					设置FONT_LEFT_RIGHT_SPACE用到 dwValue1表示左边距 dwValue2表示右边距
+    virtual ErrorCodeEnum SetFont(FontStyle eType, DWORD dwValue1, DWORD dwValue2 = 0);
+
+    //打印文本数据函数
+    virtual ErrorCodeEnum PrintText(BYTE* pData, DWORD dwDataLen);
+
+    //打印条形码函数
+    //dwUnitWidth 条形码基本模块宽度 取值{2..6} 默认2
+    //dwHeight 条形码高度 单位mm
+    //iHRIPosition hri字符打印位置 见枚举类型HriPosition
+    virtual ErrorCodeEnum PrintBarCode(BarCodeType eType, BYTE* pData, 
+                                       DWORD dwDataLen, DWORD dwUnitWidth,
+                                       DWORD dwHeight, HriPosition eHRIPosition);
+
+    //打印二维码QRCode函数
+    //dwUnitWidth 二维码基本元素宽度 取值{1..255} 默认3
+    virtual ErrorCodeEnum PrintQRCode(BYTE* pData, DWORD dwDataLen, DWORD dwUnitWidth);
+
+    //打印二维码QRCode函数
+    //dwWidth 二维码长度 ,单位mm
+    virtual ErrorCodeEnum PrintQRCodeByArea(BYTE* pData, DWORD dwDataLen, DWORD dwUnitWidth, DWORD dwWidth);
+
+    //打印二维码PDF417函数
+    //errorLevel pdf417纠错级别 取值{0..8}
+    //dwUnitWidth  基本元素宽度 取值{3..90}
+    //dwUnitHeight 基本元素长度 取值{1..30}
+    //row  pdf417 行数 取值{1..7}
+    //lines pdf417 列数 取值{2..25}
+    virtual ErrorCodeEnum PrintPDF417code(BYTE* pData, DWORD dwDataLen, int errorLevel, 
+                                          DWORD dwUnitWidth, DWORD dwUnitHeight, int rows, int lines);
+
+    //打印二维码PDF417函数
+    //errorLevel pdf417纠错级别 取值{0..8}
+    //dwWidth  pdf417宽度 单位mm
+    //dwHeight pdf417长度 单位mm
+    virtual ErrorCodeEnum PrintPDF417codeByArea(BYTE* pData, DWORD dwDataLen, 
+                                                int errorLevel, DWORD dwWidth, DWORD dwHeight);
+
+    //打印图像函数:pData是base64编码的数据
+    virtual ErrorCodeEnum PrintImage(BYTE* pData, DWORD dwDataLen);
+
+    //获取打印失败后错误信息和错误状态
+    virtual ErrorCodeEnum GetLastErrState(ThermalState& devState, DevErrorInfo& devErrInfo);
+
+private:
+    ReceiptSnbc*        m_pPrint;
+    bool                m_bStartup;
+    bool                m_bFontChanged;
+    struct FontParam
+    {
+        bool bUL;
+        bool bold;
+        bool bDW;
+        bool bDH;
+
+        FontParam()
+        {
+            bold = bUL = bDW = bDH = false;
+        }
+    };
+    FontParam       m_FontParam;
+
+protected:
+    ErrorCodeEnum       GetErrorInfo(int iCode, char* sErr, ...);
+    DevErrorInfo        m_DevErrInfo;
+    char                m_sLibPath[260];
+
+};
+
+
+#endif //LIBFRAMEWORK_THERM_IMPL_H

+ 26 - 0
DevAdapter/cw/ups.1.1/CMakeLists.txt

@@ -0,0 +1,26 @@
+
+# 声明模块名称的前缀和名称
+rvc_dev_define_module("Ups")
+
+# rvc_dev_config_library 内需要使用这三个参数,用于拼接输出的适配器文件名称
+set(${MODULE_PREFIX}_VENDOR "cw")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+# 包含要编译的实现文件,rvc_dev_config_library 内使用
+set(${MODULE_PREFIX}_SRCS SHARED
+    upsimpl.cpp upsdev.cpp deviceconnect.cpp
+        )
+
+# 适配器工程需要通过此宏替代 add_library
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+# ${MODULE_FULL_NAME} 是 TAGET 名称,在 rvc_dev_config_library 中定义
+target_include_directories(${MODULE_FULL_NAME} PRIVATE ${VENDOR_CURRENT_INCLUDE_DIR})
+target_link_libraries(${MODULE_FULL_NAME} baseio ${VENDOR_LOG_LIB_NAME})
+
+SET(LIBRARY_OUTPUT_PATH ${VENDOR_CURRENT_LIB_DIR})
+
+#  =-=-=-=-=-=-=-=-=-= {适配器工程}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
+rvc_dev_target_install(${MODULE_FULL_NAME})
+

+ 136 - 0
DevAdapter/cw/ups.1.1/deviceconnect.cpp

@@ -0,0 +1,136 @@
+#include "deviceconnect.h"
+
+#define poly8 0xD5
+
+DeviceConnect::DeviceConnect()
+{
+    m_pSerial = new SSerial();
+}
+
+DeviceConnect::~DeviceConnect()
+{
+    delete m_pSerial;
+}
+
+int DeviceConnect::Open(char* sPort, int iBaud)
+{
+    if (m_pSerial->IsOpen())
+        m_pSerial->Close();
+    if (!m_pSerial->Open(sPort, iBaud)) return UPS_HARDWARE_ERROR;
+    return 0;
+}
+
+int DeviceConnect::Close()
+{
+    m_pSerial->Close();
+    return 0;
+}
+
+// 是否连接
+BOOL DeviceConnect::IsOpen()
+{
+    return m_pSerial->IsOpen();
+}
+
+// 获取UPS状态
+int  DeviceConnect::GetStatus(bool& bUps, bool& bLow)
+{
+    BYTE Cmd[256] = {0x41, 0x22};
+    int iRecv = 0;
+    int iRet = Execute(Cmd, 2, Cmd, &iRecv, 2000);
+    if (iRet != 0)  return iRet;
+
+    BYTE bySt = Cmd[3]; //
+    bUps = (bySt & 0x04) > 0;
+    bLow = (bySt & 0x20) > 0;
+    return 0;
+}
+
+// 关闭UPS
+int DeviceConnect::ShutDown(int iMinite)
+{
+    BYTE Cmd[256] = {0x43, 0xc6, 0, 0};
+    Cmd[2] = iMinite % 256;
+    Cmd[3] = iMinite / 256;
+    int iRet = Execute(Cmd, 4, 2000);
+    if (iRet != 0)  return iRet;
+    return 0;
+}
+
+// 重启UPS
+int DeviceConnect::ReStart(int iMinite)
+{
+    BYTE Cmd[256] = {0x43, 0xc7, 0, 0x00};
+    Cmd[2] = iMinite % 256;
+    Cmd[3] = iMinite / 256;
+    int iRet = Execute(Cmd, 4, 2000);
+    if (iRet != 0)  return iRet;
+    return 0;
+}
+
+//获取版本信息
+int DeviceConnect::GetVersion(char* strVersion)
+{
+    BYTE Cmd[256] = {0x41, 0x1E};
+    int iRecv = 0;
+    int iRet = Execute(Cmd, 2, Cmd, &iRecv, 2000);
+    if (iRet != 0)  return iRet;
+    strcpy(strVersion, (const char*)Cmd + 3);
+    strVersion[iRecv - 4] = 0;
+    return 0;
+}
+
+BYTE DeviceConnect::CalBcc(BYTE* pData, BYTE iCount)
+{
+    unsigned char crc = 0;
+    unsigned char i;
+    while (iCount-- > 0) {
+        crc = crc ^ *pData;
+        for(i = 0; i < 8; i ++) {
+            if(crc & 0x80)
+                crc = (crc << 1) ^ poly8;
+            else
+                crc <<= 1;
+        }
+        pData++;
+    }
+    return crc;
+}
+
+//执行命令
+int DeviceConnect::Execute(BYTE* pData, int iLength, BYTE* pOut, int* pOutLen, int iTimeOut)
+{
+    BYTE    sData[1024];
+    memcpy(sData, pData, iLength);
+    sData[iLength] = CalBcc(sData, iLength);
+    iLength++;
+
+    int iSend = m_pSerial->Send((const char*)sData, iLength, iTimeOut);
+    if (iSend < iLength)    return UPS_TIMEOUT;
+
+    iSend = m_pSerial->Receive((char*)sData, 2, iTimeOut);
+    if (iSend < 2)  return UPS_TIMEOUT;
+    iSend += m_pSerial->Receive((char*)sData + 2, 1000, 100);
+
+    if (sData[0] != 0x40)
+        return UPS_HARDWARE_ERROR;
+    memcpy(pOut, sData, iSend);
+    pOut[iSend] = 0;
+    *pOutLen = iSend;
+    return 0;
+}
+
+//执行命令
+int DeviceConnect::Execute(BYTE* pData, int iLength, int iTimeOut)
+{
+    BYTE    sData[1024];
+    memcpy(sData, pData, iLength);
+    sData[iLength] = CalBcc(sData, iLength);
+    iLength++;
+
+    int iSend = m_pSerial->Send((const char*)sData, iLength, iTimeOut);
+    if (iSend < iLength)    return UPS_TIMEOUT;
+
+    m_pSerial->Receive((char*)sData, 1000, iTimeOut);
+    return 0;
+}

+ 39 - 0
DevAdapter/cw/ups.1.1/deviceconnect.h

@@ -0,0 +1,39 @@
+#ifndef DEVICECONNECT_H
+#define DEVICECONNECT_H
+#include "cmb.h"
+
+#define UPS_SUCCESS                 0	// command succeeded
+#define UPS_NOT_OPEN				-1	// command succeeded
+#define UPS_HARDWARE_ERROR          -2	// command failed because of hardware error
+#define UPS_TIMEOUT                 -3	// wait for user interaction timed out
+#define UPS_PARA_ERR				-4	//
+
+class DeviceConnect
+{
+public:
+    DeviceConnect();
+    ~DeviceConnect();
+
+    int    Open(char* sPort, int iBaud);
+    int    Close();
+    // 是否连接
+    BOOL    IsOpen();
+
+    // 获取UPS状态
+    int     GetStatus(bool& bUps, bool& bLow);
+    // 关闭UPS
+    int ShutDown(int iMinite);
+    // 重启UPS
+    int ReStart(int iMinite);
+    //获取版本信息
+    int GetVersion(char* strVersion);
+
+protected:
+    SSerial*    m_pSerial;
+    BYTE    CalBcc(BYTE* pData, BYTE iCount);
+    int     Execute(BYTE* pData, int iLength, BYTE* pOut, int* pOutLen, int iTimeOut);
+    int     Execute(BYTE* pData, int iLength, int iTimeOut);
+
+};
+
+#endif // DEVICECONNECT_H

+ 60 - 0
DevAdapter/cw/ups.1.1/upsdev.cpp

@@ -0,0 +1,60 @@
+#include "upsimpl.h"
+#include "log4vendor.h"
+
+
+UpsClassImpl*     g_pUpsDevice = NULL;
+
+void __attribute__((destructor)) uninit()
+{
+    if (g_pUpsDevice)
+    {
+        delete g_pUpsDevice;
+        g_pUpsDevice = NULL;
+    }
+}
+
+void __attribute__((constructor)) init()
+{
+}
+
+
+
+DEVICEBASE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(NULL == g_pUpsDevice)
+    {
+        g_pUpsDevice = new UpsClassImpl();
+        baseObj = (DeviceBaseClass *)g_pUpsDevice;
+
+        cmb::log_init_config config;
+        config.log_level=CMB_LOG_LEVEL_ALL;
+        config.dev_name = "Gpio";
+    #if defined(_MSC_VER)
+        config.log_dir = ("C:\\rvc\\dbg\\");
+    #else
+        config.log_dir = ("/opt/rvc/dbg/");
+    #endif //_MSC_VER
+        std::string str;
+        cmb::log4vendor::init(config, str);
+        printf("init after: %s\n", str.c_str());
+    }
+    else
+    {
+        eRt = Error_AlreadyExist;
+    }
+    return eRt;
+}
+
+DEVICEBASE_API ErrorCodeEnum  ReleaseDevComponent(DeviceBaseClass *&pBaseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(pBaseObj == (DeviceBaseClass*)g_pUpsDevice)
+    {
+        delete g_pUpsDevice;
+        g_pUpsDevice = NULL;
+        return Error_Succeed;
+    }
+    return Error_Param;
+}
+

+ 195 - 0
DevAdapter/cw/ups.1.1/upsimpl.cpp

@@ -0,0 +1,195 @@
+#include "upsimpl.h"
+#include "log4vendor.h"
+
+UpsClassImpl::UpsClassImpl()
+{
+    m_pDevice = new DeviceConnect();
+}
+
+UpsClassImpl::~UpsClassImpl()
+{
+    delete m_pDevice;
+}
+
+ErrorCodeEnum UpsClassImpl::DevOpen(DWORD dwPort, DWORD dwBaudRate)
+{
+    LOG4VTM_FUNCTION();
+    char sPort[16],sGet[32];
+    sprintf(sPort, "COM%d", dwPort);
+    SIni ini;
+    if (ini.GetValueFromIniFile("/cashway/setting/cashway.ini", "Serial", sPort, sGet, 30))
+        strcpy(sPort, sGet);
+    int iRet = m_pDevice->Open(sPort, dwBaudRate);
+    if (iRet != 0)
+        return GetErrorInfo(iRet, "DevOpen");
+    bool bUps, bLow;
+    iRet = m_pDevice->GetStatus(bUps, bLow);
+
+    return GetErrorInfo(iRet, "DevOpen");
+}
+
+int getFileVer(char* sFile, short& ch1, short& ch2)
+{
+    ch1 = 0;
+    ch2 = 0;
+    char* pFind = strstr(sFile, ".so");
+    char* pTemp = pFind;
+    while (pTemp)
+    {
+        pFind = pTemp;
+        pTemp = strstr(pFind + 3, ".so");
+    }
+    if (pFind == NULL) return 0;
+
+    pTemp = pFind - 1;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch2 = atoi(pTemp+1);
+    pTemp--;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch1 = atoi(pTemp+1);
+    return 1;
+}
+
+ErrorCodeEnum UpsClassImpl::GetDevCategory(DevCategoryInfo &devCategory)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pDevice->IsOpen())
+        return GetErrorInfo(UPS_NOT_OPEN, "GetDevCategory");
+    ErrorCodeEnum err = Error_Succeed;
+//    int iRet = _fingerDev->GetVersion(sInfo);
+//    ErrorCodeEnum errcode =  HandleDevError(iRet, "Reset");
+
+    char sSer[256]="11111111";
+    if (m_pDevice->GetVersion(sSer) == 0)
+    {
+        sSer[32] = 0;
+        strcpy(devCategory.szType, sSer);
+    }
+    else
+        strcpy(devCategory.szType, "GetFirmware error");
+    strcpy(devCategory.szModel, "WID=Cashway001");
+    strcpy(devCategory.szVendor, "cw");
+
+    char sPath[256], sFile[128] = {0};
+    GetCurLibsPath(sPath, sFile);
+    short v1,v2;
+    getFileVer(sFile, v1, v2);
+    devCategory.version.wMajor = v1;
+    devCategory.version.wMinor = v2;
+
+    devCategory.version.wRevision = 0xffff;
+    devCategory.version.wBuild = FILE_VERSION;
+    char szRet[512] = {0};
+    sprintf(szRet, "szType:%s,szModel:%s,szVendor:%s,version.wMajor:%d,version.wMinor:%d,version.wBuild:%d,version.wRevision:%d,eState:%d(0:故障1:正常)",
+            devCategory.szType,devCategory.szModel,devCategory.szVendor,devCategory.version.wMajor,devCategory.version.wMinor,devCategory.version.wBuild,devCategory.version.wRevision,devCategory.eState);
+    LOG4VTM(INFO, szRet);
+    return err;
+}
+
+ErrorCodeEnum UpsClassImpl::GetDevStatus(UpsStatusEnum& eStatus)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pDevice->IsOpen())
+        return GetErrorInfo(UPS_NOT_OPEN, "GetDevStatus");
+    bool bUps, bLow;
+    int iRet = m_pDevice->GetStatus(bUps, bLow);
+    if (iRet == 0)
+        eStatus = bUps ? UPS_STATUS_NO_ELECTOR : UPS_STATUS_NORMAL;
+    else
+        eStatus = UPS_STATUS_ERROR_TO_GET_STATUS;
+    return GetErrorInfo(iRet, "GetDevStatus");
+}
+
+ErrorCodeEnum UpsClassImpl::Reset()
+{
+    LOG4VTM_FUNCTION();
+
+    if (!m_pDevice->IsOpen())
+        return GetErrorInfo(UPS_NOT_OPEN, "Reset");
+    int iRet = m_pDevice->ShutDown(0xffff);
+    return GetErrorInfo(iRet, "Reset");;
+}
+
+ErrorCodeEnum UpsClassImpl::DevClose()
+{
+    LOG4VTM_FUNCTION();
+    m_pDevice->Close();
+    return Error_Succeed;
+}
+
+//	Shutdown ups and restart it in minutes.
+//	Arguments:
+//	- dwShutTime:time to shutdown (in minutes)
+// 	- dwRestartTime:time to restart (in minutes)
+//
+ErrorCodeEnum UpsClassImpl::Shutdown(DWORD dwShutTime, DWORD dwRestartTime)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_pDevice->IsOpen())
+        return GetErrorInfo(UPS_NOT_OPEN, "Shutdown");
+    int iRet = m_pDevice->ShutDown(dwShutTime);
+    if (iRet != 0)
+        return GetErrorInfo(iRet, "Shutdown");
+    iRet = m_pDevice->ReStart(dwRestartTime);
+    return GetErrorInfo(iRet, "Shutdown ReStart");;
+}
+
+ErrorCodeEnum UpsClassImpl::GetLastErr(DevErrorInfo &devErrInfo)
+{
+    memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
+    return Error_Succeed;
+}
+
+//  DEC_SUCCESS DEC_HARDWARE DEC_TIMEOUT DEC_INVALID_PARAMETER DEC_INVALID_MASTER_KEY
+const static CmbErrorDef UpsErrorDat[] = {
+    {0,    "成功", Error_Succeed, DEC_SUCCESS},
+    {UPS_NOT_OPEN,   "设备没有打开", Error_Hardware, DEC_DEV_NOT_OPENED},
+    {UPS_HARDWARE_ERROR,   "设备硬件故障", Error_Hardware, DEC_HARDWARE},
+    {UPS_TIMEOUT,   "设备响应超时", Error_DevCommFailed, DEC_TIMEOUT},
+    {UPS_PARA_ERR,   "传入参数错误", Error_Param, DEC_INVALID_PARAMETER},
+};
+
+ErrorCodeEnum UpsClassImpl::GetErrorInfo(int iCode, char* sErr, ...)
+{
+    size_t iLenOne = sizeof(CmbErrorDef);
+    size_t iLenAll = sizeof(UpsErrorDat);
+    int iCount = iLenAll / iLenOne;
+    char sErrInfo[256]="";
+    DWORD dSta = 0;
+    int iErr = -1;
+    for (int ia = 0; ia < iCount; ia++)
+    {
+        if (UpsErrorDat[ia].iCode == iCode)
+        {
+            dSta = UpsErrorDat[ia].iInf;
+            strcpy(sErrInfo, UpsErrorDat[ia].sInf);
+            iErr = UpsErrorDat[ia].iRet;
+            break;
+        }
+    }
+
+    char sErrAll[300];
+    va_list arglist;
+    va_start(arglist, sErr);
+    _vsnprintf(sErrAll, 128, sErr, arglist);
+    va_end(arglist);
+
+    if (sErrInfo[0])
+    {
+        strcat(sErrAll, " ");
+        strcat(sErrAll, sErrInfo);
+    }
+    sErrAll[200] = 0;
+    iLenOne = strlen(sErrAll);
+    sprintf(m_DevErrInfo.szErrMsg, "{\"ErrCode\":\"%04x\",\"Description\":\"%s\"}", iErr, sErrAll);
+//    strcpy(m_DevErrInfo.szErrMsg, sErrAll);
+    m_DevErrInfo.dwErrMsgLen = ((dSta << 16) & 0xffff0000) + iLenOne;
+    if (iErr != Error_Succeed)
+        LOG4VTM(WARN, m_DevErrInfo.szErrMsg);
+    else
+        LOG4VTM(INFO, m_DevErrInfo.szErrMsg);
+    return (ErrorCodeEnum)iErr;
+}
+

+ 49 - 0
DevAdapter/cw/ups.1.1/upsimpl.h

@@ -0,0 +1,49 @@
+#ifndef LIBFRAMEWORK_UPS_IMPL_H
+#define LIBFRAMEWORK_UPS_IMPL_H
+
+#include "UpsClass.h"
+#include "deviceconnect.h"
+
+#define FILE_VERSION    1
+
+
+class UpsClassImpl : public UpsClass
+{
+public:
+    UpsClassImpl();
+    ~UpsClassImpl();
+
+
+    //DeviceBaseClass
+    ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
+    ErrorCodeEnum Reset();
+    ErrorCodeEnum DevClose();
+    ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+
+    //
+    //	Device open.
+    //	Arguments:
+    //	- dwPort[in]		com port number
+    //	- dwBaudRate[in]	Baud rate
+    //
+    virtual ErrorCodeEnum DevOpen(DWORD dwPort, DWORD dwBaudRate);
+    //
+    //	Get device status
+    //
+    virtual ErrorCodeEnum GetDevStatus(UpsStatusEnum& eStatus);
+    //
+    //	Shutdown ups and restart it in minutes.
+    //	Arguments:
+    //	- dwShutTime:time to shutdown (in minutes)
+    // 	- dwRestartTime:time to restart (in minutes)
+    //
+    virtual ErrorCodeEnum Shutdown(DWORD dwShutTime, DWORD dwRestartTime);
+
+private:
+    ErrorCodeEnum       GetErrorInfo(int iCode, char* sErr, ...);
+    DevErrorInfo        m_DevErrInfo;
+    DeviceConnect*      m_pDevice;
+};
+
+
+#endif //LIBFRAMEWORK_UPS_IMPL_H

+ 26 - 0
DevAdapter/cw/watchdog.1.1/CMakeLists.txt

@@ -0,0 +1,26 @@
+
+# 声明模块名称的前缀和名称
+rvc_dev_define_module("WatchDog")
+
+# rvc_dev_config_library 内需要使用这三个参数,用于拼接输出的适配器文件名称
+set(${MODULE_PREFIX}_VENDOR "cw")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+# 包含要编译的实现文件,rvc_dev_config_library 内使用
+set(${MODULE_PREFIX}_SRCS SHARED
+    watchdogimpl.cpp watchdogdev.cpp
+        )
+
+# 适配器工程需要通过此宏替代 add_library
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+# ${MODULE_FULL_NAME} 是 TAGET 名称,在 rvc_dev_config_library 中定义
+target_include_directories(${MODULE_FULL_NAME} PRIVATE ${VENDOR_CURRENT_INCLUDE_DIR})
+target_link_libraries(${MODULE_FULL_NAME} baseio ${VENDOR_LOG_LIB_NAME})
+
+SET(LIBRARY_OUTPUT_PATH ${VENDOR_CURRENT_LIB_DIR})
+
+#  =-=-=-=-=-=-=-=-=-= {适配器工程}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
+rvc_dev_target_install(${MODULE_FULL_NAME})
+

+ 60 - 0
DevAdapter/cw/watchdog.1.1/watchdogdev.cpp

@@ -0,0 +1,60 @@
+#include "watchdogimpl.h"
+#include "log4vendor.h"
+
+
+WatchDogClassImpl*     g_pWatchDog = NULL;
+
+void __attribute__((destructor)) uninit()
+{
+    if (g_pWatchDog)
+    {
+        delete g_pWatchDog;
+        g_pWatchDog = NULL;
+    }
+}
+
+void __attribute__((constructor)) init()
+{
+}
+
+
+
+DEVICEBASE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(NULL == g_pWatchDog)
+    {
+        g_pWatchDog = new WatchDogClassImpl();
+        baseObj = (DeviceBaseClass *)g_pWatchDog;
+
+        cmb::log_init_config config;
+        config.log_level=CMB_LOG_LEVEL_ALL;
+        config.dev_name = "WatchDog";
+    #if defined(_MSC_VER)
+        config.log_dir = ("C:\\rvc\\dbg\\");
+    #else
+        config.log_dir = ("/opt/rvc/dbg/");
+    #endif //_MSC_VER
+        std::string str;
+        cmb::log4vendor::init(config, str);
+        printf("init after: %s\n", str.c_str());
+    }
+    else
+    {
+        eRt = Error_AlreadyExist;
+    }
+    return eRt;
+}
+
+DEVICEBASE_API ErrorCodeEnum  ReleaseDevComponent(DeviceBaseClass *&pBaseObj)
+{
+    ErrorCodeEnum eRt = Error_Succeed;
+    if(pBaseObj == (DeviceBaseClass*)g_pWatchDog)
+    {
+        delete g_pWatchDog;
+        g_pWatchDog = NULL;
+        return Error_Succeed;
+    }
+    return Error_Param;
+}
+

+ 224 - 0
DevAdapter/cw/watchdog.1.1/watchdogimpl.cpp

@@ -0,0 +1,224 @@
+#include "watchdogimpl.h"
+#include "cmb.h"
+#include <sys/reboot.h>
+
+WatchDogClassImpl::WatchDogClassImpl()
+{
+    m_hThreadID = 0;
+    m_iStartTime = 0;
+    m_bIsOpen = false;
+}
+
+WatchDogClassImpl::~WatchDogClassImpl()
+{
+    if (m_hThreadID)     pthread_cancel(m_hThreadID);
+}
+
+int getFileVer(char* sFile, short& ch1, short& ch2)
+{
+    ch1 = 0;
+    ch2 = 0;
+    char* pFind = strstr(sFile, ".so");
+    char* pTemp = pFind;
+    while (pTemp)
+    {
+        pFind = pTemp;
+        pTemp = strstr(pFind + 3, ".so");
+    }
+    if (pFind == NULL) return 0;
+
+    pTemp = pFind - 1;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch2 = atoi(pTemp+1);
+    pTemp--;
+    while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
+    if (*pTemp == '.')
+        ch1 = atoi(pTemp+1);
+    return 1;
+}
+
+ErrorCodeEnum WatchDogClassImpl::GetDevCategory(DevCategoryInfo &devCategory)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_bIsOpen)
+        return GetErrorInfo(-1, "GetDevCategory");
+    ErrorCodeEnum err = Error_Succeed;
+    strcpy(devCategory.szType, "soft WatchDogClass");
+    strcpy(devCategory.szModel, "WID=Cashway001");
+    strcpy(devCategory.szVendor, "cw");
+
+    char sPath[256], sFile[128] = {0};
+    GetCurLibsPath(sPath, sFile);
+    short v1,v2;
+    getFileVer(sFile, v1, v2);
+    devCategory.version.wMajor = v1;
+    devCategory.version.wMinor = v2;
+
+    devCategory.version.wRevision = 0xffff;
+    devCategory.version.wBuild = FILE_VERSION;
+    char szRet[512] = {0};
+    sprintf(szRet, "szType:%s,szModel:%s,szVendor:%s,version.wMajor:%d,version.wMinor:%d,version.wBuild:%d,version.wRevision:%d,eState:%d(0:故障1:正常)",
+            devCategory.szType,devCategory.szModel,devCategory.szVendor,devCategory.version.wMajor,devCategory.version.wMinor,devCategory.version.wBuild,devCategory.version.wRevision,devCategory.eState);
+    LOG4VTM(INFO, szRet);
+    return err;
+}
+
+ErrorCodeEnum WatchDogClassImpl::Reset()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_bIsOpen)
+        return GetErrorInfo(-1, "Reset");
+    m_iStartTime = 0;
+    return GetErrorInfo(0, "Reset");
+}
+
+
+ErrorCodeEnum WatchDogClassImpl::DevClose()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_bIsOpen)
+        return GetErrorInfo(-1, "Reset");
+    m_iStartTime = 0;
+    m_bIsOpen = false;
+    ErrorCodeEnum err = Error_Succeed;
+    return err;
+}
+
+ErrorCodeEnum WatchDogClassImpl::GetLastErr(DevErrorInfo &devErrInfo)
+{
+    memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
+    return Error_Succeed;
+}
+
+//
+//	Device initialization.
+//	Configure port input/output direction.
+//
+ErrorCodeEnum WatchDogClassImpl::DevOpen()
+{
+    LOG4VTM_FUNCTION();
+    if (m_hThreadID)     pthread_cancel(m_hThreadID);
+    m_hThreadID = 0;
+    StartThread();
+    m_bIsOpen = true;
+    return GetErrorInfo(0, "DevOpen");
+}
+
+//  DEC_SUCCESS DEC_HARDWARE DEC_TIMEOUT DEC_INVALID_PARAMETER DEC_INVALID_MASTER_KEY
+const static CmbErrorDef GpioErrorDat[] = {
+    {0,    "成功", Error_Succeed, DEC_SUCCESS},
+    {-1,   "设备没有打开", Error_Hardware, DEC_DEV_NOT_OPENED},
+    {-2,   "设备硬件故障", Error_Hardware, DEC_HARDWARE},
+    {-3,   "设备响应超时", Error_DevCommFailed, DEC_TIMEOUT},
+    {-4,   "传入参数错误", Error_Param, DEC_INVALID_PARAMETER},
+};
+
+ErrorCodeEnum WatchDogClassImpl::GetErrorInfo(int iCode, char* sErr, ...)
+{
+    size_t iLenOne = sizeof(CmbErrorDef);
+    size_t iLenAll = sizeof(GpioErrorDat);
+    int iCount = iLenAll / iLenOne;
+    char sErrInfo[256]="";
+    DWORD dSta = 0;
+    int iErr = -1;
+    for (int ia = 0; ia < iCount; ia++)
+    {
+        if (GpioErrorDat[ia].iCode == iCode)
+        {
+            dSta = GpioErrorDat[ia].iInf;
+            strcpy(sErrInfo, GpioErrorDat[ia].sInf);
+            iErr = GpioErrorDat[ia].iRet;
+            break;
+        }
+    }
+
+    char sErrAll[300];
+    va_list arglist;
+    va_start(arglist, sErr);
+    _vsnprintf(sErrAll, 128, sErr, arglist);
+    va_end(arglist);
+
+    if (sErrInfo[0])
+    {
+        strcat(sErrAll, " ");
+        strcat(sErrAll, sErrInfo);
+    }
+    sErrAll[200] = 0;
+    iLenOne = strlen(sErrAll);
+    sprintf(m_DevErrInfo.szErrMsg, "{\"ErrCode\":\"%04x\",\"Description\":\"%s\"}", iErr, sErrAll);
+//    strcpy(m_DevErrInfo.szErrMsg, sErrAll);
+    m_DevErrInfo.dwErrMsgLen = ((dSta << 16) & 0xffff0000) + iLenOne;
+    if (iErr != Error_Succeed)
+        LOG4VTM(WARN, m_DevErrInfo.szErrMsg);
+    else
+        LOG4VTM(INFO, m_DevErrInfo.szErrMsg);
+    return (ErrorCodeEnum)iErr;
+}
+
+void WatchDogClassImpl::StartThread()
+{
+    pthread_attr_t	attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
+    pthread_create(&m_hThreadID, &attr, ThreadProc, (void*) this);
+    pthread_attr_destroy(&attr);
+
+}
+
+void* WatchDogClassImpl::ThreadProc(void* inPara)
+{
+    WatchDogClassImpl*	pCtrl = (WatchDogClassImpl*)inPara;
+    return pCtrl->ThreadRun();
+}
+
+void*	WatchDogClassImpl::ThreadRun()
+{
+    time_t tNow=0;
+    while (1)
+    {
+        Sleep(500);
+        time(&tNow);
+        if (!m_bIsOpen || m_iStartTime < 1 || tNow < m_iStartTime)   continue;   //监控未开始
+        if (tNow <= m_iRebootTime)   continue;   //监控未开始
+        char sTemp[256];
+        sprintf(sTemp, "WatchDogClassImpl timeout");
+        LOG4VTM(INFO, sTemp);
+        sync(); // 同步磁盘数据,将缓存数据回写到硬盘,以防数据丢失[luther.gliethttp]
+        system("reboot");
+    }
+    return 0;
+}
+
+ErrorCodeEnum WatchDogClassImpl::StartWatch(DWORD dwDelay, DWORD dwTimeout)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_bIsOpen)
+        return GetErrorInfo(-1, "StartWatch");
+    time_t tNow=0;
+    time(&tNow);
+    m_iStartTime = tNow + dwDelay;
+    m_iTimeout = dwTimeout + 1;
+    return Error_Succeed;
+}
+
+ErrorCodeEnum WatchDogClassImpl::StopWatch()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_bIsOpen)
+        return GetErrorInfo(-1, "StopWatch");
+    m_iStartTime = 0;
+    return Error_Succeed;
+}
+
+//	Feed watchdog.
+ErrorCodeEnum WatchDogClassImpl::RefreshDog()
+{
+    LOG4VTM_FUNCTION();
+    if (!m_bIsOpen)
+        return GetErrorInfo(-1, "RefreshDog");
+    time_t tNow=0;
+    time(&tNow);
+    m_iRebootTime = tNow + m_iTimeout;
+    return Error_Succeed;
+}

+ 59 - 0
DevAdapter/cw/watchdog.1.1/watchdogimpl.h

@@ -0,0 +1,59 @@
+#ifndef LIBFRAMEWORK_WATCHDOG_IMPL_H
+#define LIBFRAMEWORK_WATCHDOG_IMPL_H
+
+#include "WatchDogClass.h"
+#include "pthread.h"
+
+#define FILE_VERSION    1
+
+class WatchDogClassImpl : public WatchDogClass
+{
+public:
+    WatchDogClassImpl();
+    ~WatchDogClassImpl();
+
+
+    //DeviceBaseClass
+    ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
+    ErrorCodeEnum Reset();
+    ErrorCodeEnum DevClose();
+    ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+
+    //
+    //	Initialization,make preparation for working.
+    //
+    virtual ErrorCodeEnum DevOpen();
+    //
+    //	Conifgure watchdog.
+    //	Watchdog start to work in [dwDelay] second.It must be feed in every [dwTimeout]
+    //	period or it will restart the computer.
+    //	Arguments:
+    //	- dwDelay:time to start watching(in second)
+    // 	- dwTimeout:max time period to feed dog(in second)
+    //
+    virtual ErrorCodeEnum StartWatch(DWORD dwDelay, DWORD dwTimeout);
+    //
+    //	Stop watchdog.
+    //
+    virtual ErrorCodeEnum StopWatch();
+    //
+    //	Feed watchdog.
+    //
+    virtual ErrorCodeEnum RefreshDog();
+
+    static void*        ThreadProc(void* inPara);
+    void*               ThreadRun();
+
+private:
+    ErrorCodeEnum       GetErrorInfo(int iCode, char* sErr, ...);
+    DevErrorInfo        m_DevErrInfo;
+    pthread_t           m_hThreadID;
+    void                StartThread();
+    time_t              m_iStartTime;
+    time_t              m_iRebootTime;
+    int                 m_iTimeout;
+    bool                m_bIsOpen;
+};
+
+
+#endif //LIBFRAMEWORK_WATCHDOG_IMPL_H