Commit 676a9683 by guanghui.cui

添加小票打印接口

parent 059ca4d4
...@@ -97,4 +97,18 @@ struct SetMenuItem ...@@ -97,4 +97,18 @@ struct SetMenuItem
int num; //数量 int num; //数量
}; };
//小票打印
struct LableItem
{
std::string strText; //打印内容
int type; //字体类型
};
struct LableObj
{
std::string strDevice; //设备
int iBaud; //波特率
std::vector<LableItem> vecItem; //打印内容
};
#endif #endif
\ No newline at end of file
...@@ -53,6 +53,7 @@ public: ...@@ -53,6 +53,7 @@ public:
//获取套餐信息(套餐包含项目) //获取套餐信息(套餐包含项目)
virtual std::map<std::string, std::vector<SetMenuItem>>& GetSetMenu()=0; virtual std::map<std::string, std::vector<SetMenuItem>>& GetSetMenu()=0;
virtual int PrintLable(LableObj &print)=0;
}; };
#ifdef WIN32 #ifdef WIN32
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "../base/FM_ErrorCode.h" #include "../base/FM_ErrorCode.h"
#include "../utility/utility.h" #include "../utility/utility.h"
#include "../utility/zini.h" #include "../utility/zini.h"
#include "pos_print.h"
#define SQL_BUFFER_SIZE 1024 #define SQL_BUFFER_SIZE 1024
...@@ -185,6 +186,7 @@ int COrderInfo::SetTakeawayOrder(TakeawayOrder &order) ...@@ -185,6 +186,7 @@ int COrderInfo::SetTakeawayOrder(TakeawayOrder &order)
orderId+=1; //orderid加1 orderId+=1; //orderid加1
char orderIdStr[10]={0}; char orderIdStr[10]={0};
sprintf(orderIdStr,"%d",orderId); sprintf(orderIdStr,"%d",orderId);
LOG(INFO)<<"order id:"<<orderId;
snprintf(mysql->sqlStr,SQL_BUFFER_SIZE*2, snprintf(mysql->sqlStr,SQL_BUFFER_SIZE*2,
"insert into fmTakeaway(orderid, fm_cmd,fm_ver,customer_address,customer_name,customer_phone,delivery_time,dis_platform_fee,dis_shop_fee,discount_fee,\ "insert into fmTakeaway(orderid, fm_cmd,fm_ver,customer_address,customer_name,customer_phone,delivery_time,dis_platform_fee,dis_shop_fee,discount_fee,\
...@@ -305,6 +307,7 @@ int COrderInfo::SetTakeawayOrder(TakeawayOrder &order) ...@@ -305,6 +307,7 @@ int COrderInfo::SetTakeawayOrder(TakeawayOrder &order)
info.childCount=childCount; info.childCount=childCount;
vecDish.push_back(info); vecDish.push_back(info);
} }
//订单商品写入“订单详情表” //订单商品写入“订单详情表”
int itemIndex=0; int itemIndex=0;
for(auto dish:vecDish){ for(auto dish:vecDish){
...@@ -352,39 +355,6 @@ int COrderInfo::SetTakeawayOrder(TakeawayOrder &order) ...@@ -352,39 +355,6 @@ int COrderInfo::SetTakeawayOrder(TakeawayOrder &order)
} }
} }
// //订单商品写入“订单详情表”
// for(std::vector<TakeawayProduct>::size_type i=0;i<order.vecProducts.size();i++){
// float discount_product=0.00; //折扣金额
// float price_product=order.vecProducts[i].original_price/100.00; //商品单价
// float tot_product=order.vecProducts[i].original_price*order.vecProducts[i].consume_num/100.00; //商品总额
// std::string dish_name="";
// int print1=0,print2=0,print3=0,print4=0,print5=0,cat=0,dept=0;
// //查询商品详细信息
// snprintf(mysql->sqlStr,SQL_BUFFER_SIZE,"SELECT Name3,PrintQ1,PrintQ2,PrintQ3,PrintQ4,PrintQ5,Category,Dept FROM tbl_Menu WHERE Item='%s';",order.vecProducts[i].pid.data());
// nErrCode = mysql->query();
// if (NULL != (mysql->_row = mysql_fetch_row(mysql->_result))){
// dish_name=mysql->_row[0];
// print1=atoi(mysql->_row[1]);
// print2=atoi(mysql->_row[2]);
// print3=atoi(mysql->_row[3]);
// print4=atoi(mysql->_row[4]);
// print5=atoi(mysql->_row[5]);
// cat=atoi(mysql->_row[6]);
// dept=atoi(mysql->_row[7]);
// }
// mysql_free_result(mysql->_result);
// snprintf(mysql->sqlStr,SQL_BUFFER_SIZE, "INSERT INTO tbl_Item(`Date`,`Check`,Outlet,ItemIdx,Item,Name3,NameS3,`Type`,OrderTime,OrderStation,OrderEmp,\
// PrintQ1,PrintQ2,PrintQ3,PrintQ4,PrintQ5,IsPrintOnCheck,PrintStatus,PrintCheckStatus,PrintedOnCheck,OgnPrice,Price,PriceLevel,ModiMethod,\
// DiscBefore,UnitQty,Qty,ItemTot,RvDiscBefore,RvItemTot,Dept,Category,IsItemModified,LastModifiedTime)\
// VALUES('%s',%d,%d,%d,'%s','%s','%s',1,'%s',99,4,%d,%d,%d,%d,%d,'1',4,'1',1,%.2f,%.2f,1,-1,%.2f,1,%d,%.2f,%.2f,%.2f,%d,%d,1,'%s')", \
// strDate.data(),orderId,iOutlet,i+1,order.vecProducts[i].pid.data(),dish_name.data(),dish_name.data(),chTime,print1,print2,print3,print4,\
// print5,price_product,price_product,discount_product,\
// order.vecProducts[i].consume_num,tot_product,discount_product,tot_product,dept,cat,chTime);
// nErrCode = mysql->insert();
// }
//支付信息吸入“支付详情表” //支付信息吸入“支付详情表”
snprintf(mysql->sqlStr,SQL_BUFFER_SIZE, "INSERT INTO tbl_Payment(`Date`,`Check`,Outlet,PayIdx,PayNo,Name3,PayEmp,PayTime,PayStation,PayTot,PayClass,Member,\ snprintf(mysql->sqlStr,SQL_BUFFER_SIZE, "INSERT INTO tbl_Payment(`Date`,`Check`,Outlet,PayIdx,PayNo,Name3,PayEmp,PayTime,PayStation,PayTot,PayClass,Member,\
IsModified,LastModifiedTime)\ IsModified,LastModifiedTime)\
...@@ -406,6 +376,7 @@ int COrderInfo::SetTakeawayOrder(TakeawayOrder &order) ...@@ -406,6 +376,7 @@ int COrderInfo::SetTakeawayOrder(TakeawayOrder &order)
ApplyStation,ApplyEmp,IsDiscBefore,Rate,DiscTot)\ ApplyStation,ApplyEmp,IsDiscBefore,Rate,DiscTot)\
VALUES('%s',%d,%d,1,0,'takeout discount','takeout discount','ÍâÂôÕÛ¿Û',%d,0,15,'%s',99,2,'1',%.2f,%.2f)", \ VALUES('%s',%d,%d,1,0,'takeout discount','takeout discount','ÍâÂôÕÛ¿Û',%d,0,15,'%s',99,2,'1',%.2f,%.2f)", \
strDate.data(),orderId,iOutlet,itemIndex,chTime,-disRate,-discount); strDate.data(),orderId,iOutlet,itemIndex,chTime,-disRate,-discount);
LOG(INFO)<<"======disc info insert:"<<mysql->sqlStr;
nErrCode = mysql->insert(); nErrCode = mysql->insert();
if(nErrCode != EC_OK) if(nErrCode != EC_OK)
{ {
...@@ -731,6 +702,73 @@ void COrderInfo::rollbackData(std::string orderid) ...@@ -731,6 +702,73 @@ void COrderInfo::rollbackData(std::string orderid)
mysql->remove(); mysql->remove();
} }
int COrderInfo::PrintLable(LableObj &printObj)
{
int fd=-1;
fd = open_port(printObj.strDevice.data());
if(-1==fd){
LOG(ERROR) << "printCook failed";
return EC_EXIST_ORDER;
}
if(!set_port(printObj.iBaud)){
LOG(ERROR) << "printCook device error";
return EC_EXIST_ORDER;
}
for(auto item:printObj.vecItem){
std::string str=item.strText;
print(charset_u2g(str).data(),item.type);
}
cut_paper();
close_port();
return EC_OK;
}
int COrderInfo::charset_convert(const char* charset_from, const char* charset_to
, const std::string& string_from, std::string& string_to)
{
iconv_t cd = iconv_open(charset_to, charset_from);
if (!cd)
{
return -1;
}
string_to = "";
int ret = 0;
size_t inbytes = string_from.size();
char* inbuf = const_cast<char*>(string_from.c_str());
while (inbytes > 0)
{
char buffer[1024] = {0};
char *outbuf = buffer;
size_t outbytes = sizeof(buffer) - 1;
ret = iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes);
if (ret == 0 || errno == E2BIG)
{
string_to.append(buffer);
}
else
{
break;
}
}
ret = iconv_close(cd);
if (inbytes != 0 || ret != 0)
{
return -1;
}
return 0;
}
std::string COrderInfo::charset_u2g(const std::string& utf8)
{
std::string gbk;
charset_convert("UTF-8", "GB18030//IGNORE", utf8, gbk);
//std::cout<<"convert res:"<<i<<std::endl;
return gbk;
}
//需要导出的函数,即用户在外部可以调用的接口 //需要导出的函数,即用户在外部可以调用的接口
bool GetOperationObject(void** _RtObject) bool GetOperationObject(void** _RtObject)
{ {
......
...@@ -71,6 +71,9 @@ public: ...@@ -71,6 +71,9 @@ public:
//获取套餐信息 //获取套餐信息
std::map<std::string, std::vector<SetMenuItem>>& GetSetMenu(); std::map<std::string, std::vector<SetMenuItem>>& GetSetMenu();
//小票打印
int PrintLable(LableObj &print);
std::string m_FMPay; std::string m_FMPay;
std::string m_LastPayId; std::string m_LastPayId;
...@@ -89,6 +92,15 @@ private: ...@@ -89,6 +92,15 @@ private:
char* UTF8ToLatin1(const char *str); char* UTF8ToLatin1(const char *str);
void CleanOldData(); //清理超过六个月数据 void CleanOldData(); //清理超过六个月数据
int charset_convert(const char* charset_from, const char* charset_to
, const std::string& string_from, std::string& string_to);
/* 功能:utf8转GB18030
* 参数:[1]utf8字符
* 返回:GB18030字符
* */
std::string charset_u2g(const std::string& utf8);
//获取菜品对应打印机及打印设备 //获取菜品对应打印机及打印设备
bool GetMenuPrinter(); bool GetMenuPrinter();
......
#ifndef _FMSPOSDLL_H_
#define _FMSPOSDLL_H_
int open_port(const char* szPort);
void close_port();
bool set_port(int Baudrate);
void cut_paper();
//---------------------------------------------
// print函数说明
// data:要打印的数据
// type:打印类型(如下)
// 1、标准字体
// 2、标准加粗
// 3、两倍宽高
// 4、两倍宽高,加粗
// 5、两倍高
// 6、两倍高,加粗
// 7、三倍宽高
// 8、三倍宽高,加粗,红色
//---------------------------------------------
void print(const char *data,int type);
#endif
...@@ -221,6 +221,10 @@ void Init() ...@@ -221,6 +221,10 @@ void Init()
//启动外卖监控线程 //启动外卖监控线程
pthread_t takewayId; pthread_t takewayId;
ret = pthread_create(&takewayId, NULL, FunTakeaway, NULL); ret = pthread_create(&takewayId, NULL, FunTakeaway, NULL);
//启动打印线程
pthread_t printId;
ret = pthread_create(&printId, NULL, FunPrintLable, NULL);
} }
void app_stopped(int sig) void app_stopped(int sig)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define SOCKET_ERROR (-1) #define SOCKET_ERROR (-1)
#define PAY_BACK_PORT 23771 #define PAY_BACK_PORT 23771
#define TAKEWAY_PORT 23772 #define TAKEWAY_PORT 23772
#define PRINT_PORT 23775
#define BUFFER_SIZE 1024*10 //接收数据缓冲区大小 #define BUFFER_SIZE 1024*10 //接收数据缓冲区大小
int pay_server_fd; int pay_server_fd;
...@@ -152,65 +153,93 @@ DWORD WINAPI FunPayRecv(LPVOID lpParamter) ...@@ -152,65 +153,93 @@ DWORD WINAPI FunPayRecv(LPVOID lpParamter)
return 0; return 0;
} }
*/ */
//外卖线程 //小票打印线程
#define CHINA_CHAR_START 0x80 void *FunPrintLable(void* lpParamter)
#define LATIN_CTRL_START 0x80
#define LATIN_CTRL_END 0x9F
#define C_MASK 0x7F
//转换前后长度不变
void utf8_to_latin1(char * pcSrcStr, char *pcDstStr)
{ {
int strLen = strlen(pcSrcStr); int socket_fd, connect_fd;
struct sockaddr_in servaddr;
char* printLableRecvBuf = new char[BUFFER_SIZE]; //打印数据接收区
int nRecvLen = 0;
for(int idx = 0; idx < strLen; idx++) LableObj printObj;
{ int nErrCode = EC_OK;
unsigned char cc = (unsigned char)pcSrcStr[idx];
if (LATIN_CTRL_START <= cc && LATIN_CTRL_END >= cc)
{
cc &= C_MASK;
cc += 1;
}
pcDstStr[idx] = cc; //初始化Socket
if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
LOG(ERROR)<<"create printLable socket error:"<<strerror(errno)<<" errno:"<<errno;
exit(0);
} }
//初始化
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。
servaddr.sin_port = htons(PRINT_PORT);//设置的端口为DEFAULT_PORT
pcDstStr[strLen] = 0; // 设置套接字选项避免地址使用错误
} int flag = 1;
if ((setsockopt(pay_server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)))<0)
//转换前后长度不变,pcSrcStr从数据库里读出来后,要在最后一字符后面一个字节置0,即字符结束符
void latin1_to_utf8(char * pcSrcStr, char *pcDstStr)
{
int strLen = strlen(pcSrcStr);
int cFlag = 0;
for(int idx = 0; idx < strLen; idx++)
{ {
unsigned char cc = (unsigned char)pcSrcStr[idx]; LOG(ERROR)<<"setsockopt printLable failed";
exit(0);
}
if (cFlag) //将本地地址绑定到所创建的套接字上
{ if( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
if (CHINA_CHAR_START > cc) LOG(ERROR)<<"bind printLable socket error:"<<strerror(errno)<<" errno:"<<errno;
{ exit(0);
cc--;
cc |= (~C_MASK);
} }
//开始监听是否有客户端连接
if( listen(socket_fd, 10) == -1){
LOG(ERROR)<<"listen printLable socket error:"<<strerror(errno)<<" errno:"<<errno;
exit(0);
}
LOG(INFO)<<"======waiting for printLable client's request======";
cFlag = 0; while(!g_exit){
//阻塞直到有客户端连接,不然多浪费CPU资源。
if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1){
LOG(ERROR)<<"accept socket error:"<<strerror(errno)<<" errno:"<<errno;
continue;
} }
else //接受客户端传过来的数据
int rlt = socketRecvData(printLableRecvBuf, BUFFER_SIZE, connect_fd);
if (rlt > 0)
{ {
if (CHINA_CHAR_START <= cc) printLableRecvBuf[rlt] = '\0';
//
LOG(INFO)<<"打印请求:"<<printLableRecvBuf;
printObj.vecItem.clear();
//GetTakeawayOrder(printLableRecvBuf,order);
GetTakeawayPrintInfo(printLableRecvBuf, printObj);
//根据请求类型进行不同操作
int statusCode;
std::string msg;
nErrCode = dbOperation->PrintLable(printObj);
LOG(INFO)<<"---------------print result:"<<nErrCode;
if(nErrCode == EC_OK)
{ {
cFlag = 1; statusCode = 100;
msg = "";
} }
else{
statusCode=101;
msg = "print failed";
} }
pcDstStr[idx] = cc; std::string strReturnJson = GetTakeawayResultJson(statusCode,msg.data());
//发送返回数据
int result = socketSendData(strReturnJson.data(), connect_fd);
LOG(INFO)<<"外卖发送处理结果:"<<strReturnJson.c_str();
close(connect_fd);
} }
pcDstStr[strLen] = 0; }
close(socket_fd);
delete[] printLableRecvBuf;
} }
//外卖线程
void *FunTakeaway(void* lpParamter) void *FunTakeaway(void* lpParamter)
{ {
int socket_fd, connect_fd; int socket_fd, connect_fd;
...@@ -263,21 +292,6 @@ void *FunTakeaway(void* lpParamter) ...@@ -263,21 +292,6 @@ void *FunTakeaway(void* lpParamter)
if (rlt > 0) if (rlt > 0)
{ {
takeWayRecvBuf[rlt] = '\0'; takeWayRecvBuf[rlt] = '\0';
//int lenGBK = CCodeConv::UTF8ToGBK(takeWayRecvBuf,NULL,NULL);
//char* strGBK = new char[lenGBK];
//CCodeConv::UTF8ToGBK(takeWayRecvBuf,strGBK,lenGBK);
//--------------------test
// char* latinbuf = new char[rlt+1];
// utf8_to_latin1(takeWayRecvBuf,latinbuf);
// LOG(INFO)<<"++++++++utf8转latin:"<<latinbuf;
// char* utf8buf = new char[rlt+1];
// latin1_to_utf8(latinbuf,utf8buf);
// LOG(INFO)<<"++++++++latin转utf8:"<<utf8buf;
// delete[] utf8buf;
// delete[] latinbuf;
//---------------test end
// //
LOG(INFO)<<"外卖请求:"<<takeWayRecvBuf; LOG(INFO)<<"外卖请求:"<<takeWayRecvBuf;
order.vecProducts.clear(); order.vecProducts.clear();
......
...@@ -17,6 +17,9 @@ void *PayRecv(void *ptr); //支付返回线程函数 ...@@ -17,6 +17,9 @@ void *PayRecv(void *ptr); //支付返回线程函数
////外卖线程 ////外卖线程
void *FunTakeaway(void* lpParamter); void *FunTakeaway(void* lpParamter);
//小票打印线程
void *FunPrintLable(void* lpParamter);
//socket 数据接收 //socket 数据接收
//返回值 成功:接收长度 //返回值 成功:接收长度
// 失败: -1 // 失败: -1
......
...@@ -257,3 +257,41 @@ std::string GetPOSMenuJson(std::vector<PrinterMenu> &vecMenu,std::map<std::strin ...@@ -257,3 +257,41 @@ std::string GetPOSMenuJson(std::vector<PrinterMenu> &vecMenu,std::map<std::strin
document.Accept(writer); document.Accept(writer);
return buffer.GetString(); return buffer.GetString();
} }
bool GetTakeawayPrintInfo(const char* json, LableObj &print)
{
rapidjson::Document document; // 定义一个Document对象
document.Parse(json); // 解析,Parse()无返回值,也不会抛异常
if (document.HasParseError()) // 通过HasParseError()来判断解析是否成功
{
// 可通过GetParseError()取得出错代码,
// 注意GetParseError()返回的是一个rapidjson::ParseErrorCode类型的枚举值
// 使用函数rapidjson::GetParseError_En()得到错误码的字符串说明,这里的En为English简写
// 函数GetErrorOffset()返回出错发生的位置
//LOG_ERROR("GetTakeawayPrintInfo JSON parse error: (%d:%d)", document.GetParseError(), document.GetErrorOffset())
return false;
}
else
{
rapidjson::Value& strDevice = document["device"];
rapidjson::Value& iBaud = document["baud"];
print.strDevice=strDevice.GetString();
print.iBaud=iBaud.GetInt();
rapidjson::Value& printObjs= document["print"];
if(printObjs.IsArray()){
for(unsigned int i=0;i<printObjs.Size();i++){
LableItem obj;
rapidjson::Value& printValue = printObjs[i];
rapidjson::Value& vText = printValue["text"];
rapidjson::Value& vType = printValue["type"];
obj.strText =vText.GetString();
obj.type=vType.GetInt();
print.vecItem.push_back(obj);
}
}
}
return true;
}
\ No newline at end of file
...@@ -17,4 +17,7 @@ std::string GetTakeawayResultJson(const int statuscode,const char* msg); ...@@ -17,4 +17,7 @@ std::string GetTakeawayResultJson(const int statuscode,const char* msg);
std::string GetPOSMenuJson(std::vector<PrinterMenu> &vecMenu,std::map<std::string, std::vector<SetMenuItem>> &mapSetMenu); std::string GetPOSMenuJson(std::vector<PrinterMenu> &vecMenu,std::map<std::string, std::vector<SetMenuItem>> &mapSetMenu);
//通过json字串获取打印信息
bool GetTakeawayPrintInfo(const char* json, LableObj &print);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment