termalprintimpl.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. #include "termalprintimpl.h"
  2. #include "SUcs.h"
  3. ThermalPrintClassImpl::ThermalPrintClassImpl()
  4. {
  5. m_pPrint = new ReceiptSnbc();
  6. m_bStartup = false;
  7. }
  8. ThermalPrintClassImpl::~ThermalPrintClassImpl()
  9. {
  10. delete m_pPrint;
  11. }
  12. // 打开打印机
  13. ErrorCodeEnum ThermalPrintClassImpl::DevOpen(BYTE btPort,DWORD dwBaudRate)
  14. {
  15. int iRet = m_pPrint->Open(0x154f, 0x154f);
  16. if (iRet != 0) return GetErrorInfo(iRet, "DevOpen");
  17. iRet = m_pPrint->GetState();
  18. return GetErrorInfo(iRet, "DevOpen");
  19. }
  20. int getFileVer(char* sFile, short& ch1, short& ch2)
  21. {
  22. ch1 = 0;
  23. ch2 = 0;
  24. char* pFind = strstr(sFile, ".so");
  25. char* pTemp = pFind;
  26. while (pTemp)
  27. {
  28. pFind = pTemp;
  29. pTemp = strstr(pFind + 3, ".so");
  30. }
  31. if (pFind == NULL) return 0;
  32. pTemp = pFind - 1;
  33. while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
  34. if (*pTemp == '.')
  35. ch2 = atoi(pTemp+1);
  36. pTemp--;
  37. while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
  38. if (*pTemp == '.')
  39. ch1 = atoi(pTemp+1);
  40. return 1;
  41. }
  42. ErrorCodeEnum ThermalPrintClassImpl::GetDevCategory(DevCategoryInfo &devCategory)
  43. {
  44. LOG4VTM_FUNCTION();
  45. if (!m_pPrint->Isopen())
  46. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "GetDevCategory");
  47. char sSVer[256];
  48. char szType[] = {"PVER=SNBC#MID=BT-NH80"};
  49. char szModel[] = "FWID=%s";
  50. strcpy(devCategory.szType, szType);
  51. if (m_pPrint->GetFirmware(sSVer) == 0)
  52. sprintf(devCategory.szModel, szModel, sSVer + 1);
  53. else
  54. sprintf(devCategory.szModel, szModel, "00000000");
  55. strcpy(devCategory.szVendor, "cw");
  56. char cFilePath[300] = {0};
  57. GetCurLibsPath(m_sLibPath, cFilePath);
  58. short v1,v2;
  59. getFileVer(cFilePath, v1, v2);
  60. devCategory.version.wMajor = v1;
  61. devCategory.version.wMinor = v2;
  62. devCategory.version.wRevision = 0xffff;
  63. devCategory.version.wBuild = FILE_VERSION;
  64. char szRet[512] = {0};
  65. sprintf(szRet, "szType:%s,szModel:%s,szVendor:%s,version.wMajor:%d,version.wMinor:%d,version.wBuild:%d,version.wRevision:%d,eState:%d(0:故障1:正常)",
  66. devCategory.szType,devCategory.szModel,devCategory.szVendor,devCategory.version.wMajor,devCategory.version.wMinor,devCategory.version.wBuild,devCategory.version.wRevision,devCategory.eState);
  67. LOG4VTM(INFO, szRet);
  68. return Error_Succeed;
  69. }
  70. ErrorCodeEnum ThermalPrintClassImpl::Reset()
  71. {
  72. LOG4VTM_FUNCTION();
  73. if (!m_pPrint->Isopen())
  74. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "Reset");
  75. m_pPrint->Init();
  76. int iRet = m_pPrint->GetState();
  77. return GetErrorInfo(iRet, "Reset");
  78. }
  79. ErrorCodeEnum ThermalPrintClassImpl::DevClose()
  80. {
  81. LOG4VTM_FUNCTION();
  82. if (!m_pPrint->Isopen())
  83. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "DevClose");
  84. int iRet = m_pPrint->Close();
  85. return GetErrorInfo(iRet, "DevClose");
  86. }
  87. ErrorCodeEnum ThermalPrintClassImpl::GetLastErr(DevErrorInfo &devErrInfo)
  88. {
  89. memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
  90. return Error_Succeed;
  91. }
  92. // 获取打印机实时状态
  93. ErrorCodeEnum ThermalPrintClassImpl::GetDevState(ThermalState& devState)
  94. {
  95. LOG4VTM_FUNCTION();
  96. if (!m_pPrint->Isopen())
  97. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "GetDevCategory");
  98. int iRet = m_pPrint->GetState();
  99. if (iRet < 0)
  100. return GetErrorInfo(iRet, "Reset");
  101. devState.hardwareState = STATE_OK;
  102. switch(iRet)
  103. {
  104. case RECEIPT_SUCCESS:
  105. devState.paperState = PAPER_FULL;
  106. break;
  107. case RECEIPT_WARN_NO_MEDIA:
  108. devState.paperState = PAPER_EMPTY;
  109. break;
  110. case RECEIPT_WARN_PAP_LOW:
  111. devState.paperState = PAPER_LOW;
  112. break;
  113. case RECEIPT_WARN_HEAD_UP:
  114. devState.hardwareState = STATE_OTHER_ERROR;
  115. break;
  116. case RECEIPT_WARN_JAMMED:
  117. devState.paperState = PAPER_JAMMED;
  118. break;
  119. }
  120. return Error_Succeed;
  121. }
  122. //开始打印初始设置:paperWidth一般为80mm和57mm
  123. ErrorCodeEnum ThermalPrintClassImpl::BeginPrint(ThermalPaperType eType, int paperWidth)
  124. {
  125. LOG4VTM_FUNCTION();
  126. if (!m_pPrint->Isopen())
  127. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "BeginPrint");
  128. int iRet = m_pPrint->Init();
  129. if (iRet != 0)
  130. return GetErrorInfo(iRet, "BeginPrint");
  131. m_bStartup = true;
  132. return Error_Succeed;
  133. }
  134. //打印控制指令函数:主要是打印,切纸和控制打印光标指令函数
  135. //第三个参数是预留参数 暂时无用到
  136. ErrorCodeEnum ThermalPrintClassImpl::ControlAction(PrintAction eAction, DWORD dwValue1, DWORD dwValue2)
  137. {
  138. LOG4VTM_FUNCTION();
  139. if (!m_pPrint->Isopen())
  140. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "ControlAction");
  141. char sAnsi[256];
  142. sprintf(sAnsi, "ControlAction PrintAction=%d val=%d,%d", eAction, dwValue1, dwValue2);
  143. LOG4VTM(INFO, sAnsi);
  144. int iRet = 0;
  145. switch(eAction)
  146. {
  147. case ACTION_PRINT_ONE_LINE:
  148. iRet = m_pPrint->FeedLines(1);
  149. break;
  150. case ACTION_PRINT_MOVEFORWRAD_LINES:
  151. iRet = m_pPrint->FeedLines(dwValue1);
  152. break;
  153. // case ACTION_PRINT_MOVEBACKWRAD_LINES: //回纸n行(单位:字符行)
  154. // iRet = m_pPrint->FeedLines(-dwValue1);
  155. // break;
  156. case ACTION_CUT_ALL:
  157. iRet = m_pPrint->Cut(0);
  158. break;
  159. case ACTION_CUT_HALF:
  160. iRet = m_pPrint->Cut(1);
  161. break;
  162. case ACTION_MOVE_TO_POSITION_RELATIVE: //把打印光标移动相对当前位置一段距离(横向),单位mm
  163. iRet = m_pPrint->MoveX(dwValue1 * 8);
  164. break;
  165. case ACTION_MOVE_TO_FORWRAD_LENGTH:
  166. iRet = m_pPrint->FeedPaper(0, dwValue1 * 8);
  167. break;
  168. // case ACTION_MOVE_TO_BLACKMARK: //移动到黑标位置,把打印位置设置在行首(标记纸有效)
  169. // iRet = m_pPrint->mo
  170. // break;
  171. // case ACTION_PRINT_MOVEBACK_TO_LINE: //设置起始位置在行首,取值(0:打印内容返回行首,1:清空要打印的内容返回行首)
  172. // iRet = m_pPrint->FeedPaper(0, dwValue1 * 8);
  173. // break;
  174. }
  175. return GetErrorInfo(iRet, "ControlAction");
  176. }
  177. //打印参数指令函数:
  178. //第三个参数是预留参数 暂时无用到
  179. ErrorCodeEnum ThermalPrintClassImpl::SetParam(CommandType eType, DWORD dwValue1, DWORD dwValue2)
  180. {
  181. LOG4VTM_FUNCTION();
  182. if (!m_pPrint->Isopen())
  183. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "SetParam");
  184. char sAnsi[1024];
  185. sprintf(sAnsi, "SetParam CommandType=%d val=%d,%d", eType, dwValue1, dwValue2);
  186. LOG4VTM(INFO, sAnsi);
  187. int iRet = 0;
  188. switch(eType)
  189. {
  190. case COMMON_ROW_SPACE:
  191. iRet = m_pPrint->SetRowDistance(dwValue1 * 8);
  192. break;
  193. case COMMON_ALIGN:
  194. iRet = m_pPrint->SetAlign(dwValue1);
  195. break;
  196. // case COMMON_REVERSE:
  197. // iRet = m_pPrint->SetInverse(dwValue1);
  198. // break;
  199. case COMMON_LEFT_MARGIN:
  200. iRet = m_pPrint->SetLeftDistance(dwValue1 * 8);
  201. break;
  202. case COMMON_PRINTABLE_AREA:
  203. iRet = m_pPrint->SetPrintArea(dwValue1 * 8);
  204. break;
  205. }
  206. return GetErrorInfo(iRet, "SetParam");
  207. }
  208. //打印字体指令函数:主要是字体相关饿指令函数
  209. //第三个参数是预留参数 设置FONT_CUSTOM_SIZE用到,dwValue1表示宽,dwValue2表示长
  210. // 设置FONT_LEFT_RIGHT_SPACE用到 dwValue1表示左边距 dwValue2表示右边距
  211. ErrorCodeEnum ThermalPrintClassImpl::SetFont(FontStyle eType, DWORD dwValue1, DWORD dwValue2)
  212. {
  213. LOG4VTM_FUNCTION();
  214. if (!m_pPrint->Isopen())
  215. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "SetFont");
  216. char sAnsi[1024];
  217. sprintf(sAnsi, "SetFont FontStyle=%d val=%d,%d", eType, dwValue1, dwValue2);
  218. LOG4VTM(INFO, sAnsi);
  219. int iRet = 0;
  220. switch(eType)
  221. {
  222. case FONT_UNDERLINE:
  223. m_FontParam.bUL = dwValue1;
  224. m_bFontChanged = true;
  225. break;
  226. case FONT_BOLD:
  227. m_FontParam.bold = dwValue1;
  228. m_bFontChanged = true;
  229. break;
  230. case FONT_DOUBLEHEIGHT:
  231. m_FontParam.bDH = dwValue1;
  232. m_bFontChanged = true;
  233. break;
  234. case FONT_DOUBLEWIDE:
  235. m_FontParam.bDW = dwValue1;
  236. m_FontParam.iXScale = dwValue1 ? 2 : 1;
  237. m_bFontChanged = true;
  238. break;
  239. case FONT_INVERSE:
  240. iRet = m_pPrint->SetInverse(dwValue1);
  241. break;
  242. case FONT_CUSTOM_SIZE:
  243. m_FontParam.iXScale = dwValue1;
  244. iRet = m_pPrint->SetScale(dwValue1, dwValue2);
  245. break;
  246. case FONT_ROTATE:
  247. iRet = m_pPrint->SetRotate(dwValue1);
  248. break;
  249. case FONT_LEFT_RIGHT_SPACE:
  250. iRet = m_pPrint->SetCharSpace(dwValue1*8 / m_FontParam.iXScale, dwValue2*8 / m_FontParam.iXScale);
  251. break;
  252. }
  253. return GetErrorInfo(iRet, "SetParam");
  254. }
  255. //打印文本数据函数
  256. ErrorCodeEnum ThermalPrintClassImpl::PrintText(BYTE* pData, DWORD dwDataLen)
  257. {
  258. LOG4VTM_FUNCTION();
  259. if (!m_pPrint->Isopen())
  260. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintText");
  261. int iRet = 0;
  262. char sAnsi[64];
  263. sprintf(sAnsi, "send leng=%d", dwDataLen);
  264. LOG4VTM(INFO, sAnsi);
  265. if (m_bFontChanged)
  266. {
  267. iRet = m_pPrint->SetFont(m_FontParam.bDH, m_FontParam.bDW, m_FontParam.bold, m_FontParam.bUL, false);
  268. m_bFontChanged = false;
  269. if (iRet != 0)
  270. return GetErrorInfo(iRet, "PrintText");
  271. }
  272. int iLen = dwDataLen > 0 ? dwDataLen : strlen((char*)pData);
  273. char* pGB = new char[iLen+1];
  274. iLen = SUcs::UTF8ToGB18030((char*)pData, iLen, pGB);
  275. iRet = m_pPrint->GetState();
  276. if (iRet < 0)
  277. GetErrorInfo(iRet, "PrintText");
  278. iRet = m_pPrint->PrintData(pGB);
  279. if (iRet < 0)
  280. return GetErrorInfo(iRet, "PrintText");
  281. return GetErrorInfo(0, "PrintText");
  282. }
  283. //打印条形码函数
  284. //dwUnitWidth 条形码基本模块宽度 取值{2..6} 默认2
  285. //dwHeight 条形码高度 单位mm
  286. //iHRIPosition hri字符打印位置 见枚举类型HriPosition
  287. ErrorCodeEnum ThermalPrintClassImpl::PrintBarCode(BarCodeType eType, BYTE* pData,
  288. DWORD dwDataLen, DWORD dwUnitWidth,
  289. DWORD dwHeight, HriPosition eHRIPosition)
  290. {
  291. LOG4VTM_FUNCTION();
  292. if (!m_pPrint->Isopen())
  293. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintBarCode");
  294. return Error_Succeed;
  295. }
  296. //打印二维码QRCode函数
  297. //dwUnitWidth 二维码基本元素宽度 取值{1..255} 默认3
  298. ErrorCodeEnum ThermalPrintClassImpl::PrintQRCode(BYTE* pData, DWORD dwDataLen, DWORD dwUnitWidth)
  299. {
  300. LOG4VTM_FUNCTION();
  301. if (!m_pPrint->Isopen())
  302. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintQRCode");
  303. return Error_Succeed;
  304. }
  305. //打印二维码QRCode函数
  306. //dwWidth 二维码长度 ,单位mm
  307. ErrorCodeEnum ThermalPrintClassImpl::PrintQRCodeByArea(BYTE* pData, DWORD dwDataLen, DWORD dwUnitWidth, DWORD dwWidth)
  308. {
  309. LOG4VTM_FUNCTION();
  310. if (!m_pPrint->Isopen())
  311. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintQRCodeByArea");
  312. return Error_Succeed;
  313. }
  314. //打印二维码PDF417函数
  315. //errorLevel pdf417纠错级别 取值{0..8}
  316. //dwUnitWidth 基本元素宽度 取值{3..90}
  317. //dwUnitHeight 基本元素长度 取值{1..30}
  318. //row pdf417 行数 取值{1..7}
  319. //lines pdf417 列数 取值{2..25}
  320. ErrorCodeEnum ThermalPrintClassImpl::PrintPDF417code(BYTE* pData, DWORD dwDataLen, int errorLevel,
  321. DWORD dwUnitWidth, DWORD dwUnitHeight, int rows, int lines)
  322. {
  323. LOG4VTM_FUNCTION();
  324. if (!m_pPrint->Isopen())
  325. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintPDF417code");
  326. return Error_Succeed;
  327. }
  328. //打印二维码PDF417函数
  329. //errorLevel pdf417纠错级别 取值{0..8}
  330. //dwWidth pdf417宽度 单位mm
  331. //dwHeight pdf417长度 单位mm
  332. ErrorCodeEnum ThermalPrintClassImpl::PrintPDF417codeByArea(BYTE* pData, DWORD dwDataLen,
  333. int errorLevel, DWORD dwWidth, DWORD dwHeight)
  334. {
  335. LOG4VTM_FUNCTION();
  336. if (!m_pPrint->Isopen())
  337. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintPDF417codeByArea");
  338. return Error_Succeed;
  339. }
  340. //打印图像函数:pData是base64编码的数据
  341. ErrorCodeEnum ThermalPrintClassImpl::PrintImage(BYTE* pData, DWORD dwDataLen)
  342. {
  343. LOG4VTM_FUNCTION();
  344. if (!m_pPrint->Isopen())
  345. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "PrintImage");
  346. int iRet = m_pPrint->PrintMemBmp((char*)pData, true);
  347. return GetErrorInfo(iRet, "PrintImage");
  348. }
  349. //获取打印失败后错误信息和错误状态
  350. ErrorCodeEnum ThermalPrintClassImpl::GetLastErrState(ThermalState& devState, DevErrorInfo& devErrInfo)
  351. {
  352. LOG4VTM_FUNCTION();
  353. if (!m_pPrint->Isopen())
  354. return GetErrorInfo(RECEIPT_ERR_NO_OPEN, "GetLastErrState");
  355. int iRet = m_pPrint->GetState();
  356. if (iRet < 0)
  357. return GetErrorInfo(iRet, "Reset");
  358. devState.hardwareState = STATE_OK;
  359. switch(iRet)
  360. {
  361. case RECEIPT_SUCCESS:
  362. devState.paperState = PAPER_FULL;
  363. break;
  364. case RECEIPT_WARN_NO_MEDIA:
  365. devState.paperState = PAPER_EMPTY;
  366. break;
  367. case RECEIPT_WARN_PAP_LOW:
  368. devState.paperState = PAPER_LOW;
  369. break;
  370. case RECEIPT_WARN_HEAD_UP:
  371. devState.hardwareState = STATE_OTHER_ERROR;
  372. break;
  373. case RECEIPT_WARN_JAMMED:
  374. devState.paperState = PAPER_JAMMED;
  375. break;
  376. }
  377. memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
  378. return Error_Succeed;
  379. }
  380. /////////////////////////////////////////////////////////////////////////////
  381. // DEC_SUCCESS DEC_HARDWARE DEC_TIMEOUT DEC_INVALID_PARAMETER DEC_INVALID_MASTER_KEY
  382. const static CmbErrorDef PrintErrInfo[] = {
  383. {RECEIPT_SUCCESS, "命令执行成功", Error_Succeed, DEC_SUCCESS},
  384. {RECEIPT_ERR_NO_FOND, "设备未找到", Error_Hardware, DEC_DEV_NOT_FOUND},
  385. {RECEIPT_ERR_NO_OPEN, "设备尚未打开", Error_Param, DEC_DEV_NOT_OPENED},
  386. {RECEIPT_ERR_RCV_ERR, "数据接收错误", Error_IO, DEC_COMMUNICATION_FAILED},
  387. {RECEIPT_ERR_IN_ERR, "输入参数错误", Error_Param, DEC_INVALID_PARAMETER},
  388. {RECEIPT_ERR_DEV_ERR, "设备硬件故障", Error_Hardware, DEC_HARDWARE},
  389. {RECEIPT_WARN_NO_MEDIA, "缺纸", Error_DevMedia, DEC_HARDWARE},
  390. {RECEIPT_WARN_HEAD_UP, "机头未闭合", Error_Hardware, DEC_HARDWARE},
  391. {RECEIPT_WARN_JAMMED, "卡纸", Error_Hardware, DEC_HARDWARE},
  392. {RECEIPT_WARN_PAP_LOW, "纸少", Error_Succeed, DEC_SUCCESS},
  393. };
  394. ErrorCodeEnum ThermalPrintClassImpl::GetErrorInfo(int iCode, char* sErr, ...)
  395. {
  396. size_t iLenOne = sizeof(CmbErrorDef);
  397. size_t iLenAll = sizeof(PrintErrInfo);
  398. int iCount = iLenAll / iLenOne;
  399. char sErrInfo[256]="";
  400. DWORD dSta = 0;
  401. int iErr = -1;
  402. for (int ia = 0; ia < iCount; ia++)
  403. {
  404. if (PrintErrInfo[ia].iCode == iCode)
  405. {
  406. dSta = PrintErrInfo[ia].iInf;
  407. strcpy(sErrInfo, PrintErrInfo[ia].sInf);
  408. iErr = PrintErrInfo[ia].iRet;
  409. break;
  410. }
  411. }
  412. char sErrAll[300];
  413. va_list arglist;
  414. va_start(arglist, sErr);
  415. _vsnprintf(sErrAll, 128, sErr, arglist);
  416. va_end(arglist);
  417. if (sErrInfo[0])
  418. {
  419. strcat(sErrAll, " ");
  420. strcat(sErrAll, sErrInfo);
  421. }
  422. sErrAll[200] = 0;
  423. iLenOne = strlen(sErrAll);
  424. sprintf(m_DevErrInfo.szErrMsg, "{\"ErrCode\":\"%04x\",\"Description\":\"%s\"}", iErr, sErrAll);
  425. // strcpy(m_DevErrInfo.szErrMsg, sErrAll);
  426. m_DevErrInfo.dwErrMsgLen = ((dSta << 16) & 0xffff0000) + iLenOne;
  427. if (iErr != Error_Succeed)
  428. LOG4VTM(WARN, m_DevErrInfo.szErrMsg);
  429. else
  430. LOG4VTM(INFO, m_DevErrInfo.szErrMsg);
  431. return (ErrorCodeEnum)iErr;
  432. }