//! AYRA01FRKZ /*! Класс принтера AYRA01FRKZ \author Иванов Игорь М. \file FP300KZ.cpp */ //--------------------------------------------------------------------------- #pragma hdrstop #include "stdafx.h" #include "AYRA01FRKZ.h" #include #include #include #include #include #include //#include #include #include //#include //#include //#include #if defined( __WXMSW__ ) //Если кроссплатформкннное приложение #include #include #include #endif // __WXMSW__ //--------------------------------------------------------------------------- //#pragma package(smart_init) //--------------------------------------------------------------------------- //Сохранить лог в текстовый файл bool saveLog(std::string FileName, std::string Text) { try { for(uint4 i=1;i<=Text.length();i++) if(Text[i]=='\n') Text[i]=' '; //Чтоб в 1 строку было Text="["+getDateTime()+"] "+Text; //Добавляем дату std::string path=getAppPathA()+std::string("logs\\"); //Путь к файлу //#if defined( _VC ) // CreateDirectoryA(path.c_str(), NULL); //Пробуем создать папку //#endif path+=FileName+"_"+getStrDate()+".log"; #if defined( _BORLAND ) std::ofstream file(path.c_str(),std::ios::app); file << Text.c_str() << std::endl; file.close(); #endif #if defined( _VC ) FILE* pfile = fopen ( path.c_str(), "a" ); //Для юникода _wfopen fputs( Text.c_str() , pfile ); fputs( "\n" , pfile ); fclose( pfile ); #endif }catch(...) { return false; } return true; } //--------------------------------------------------------------------------- AYRA01FRKZ::AYRA01FRKZ() { cPort=new ComPort(); m_Password="0000"; } //--------------------------------------------------------------------------- AYRA01FRKZ::~AYRA01FRKZ() { delete cPort; } //--------------------------------------------------------------------------- //Соедениться по COM порту bool AYRA01FRKZ::OpenCOMPort(int ComNumber,int BaudRate) { if(ComNumber>0) cPort->ComNumber=ComNumber; if(BaudRate>0) cPort->BaudRate=BaudRate; cPort->Close(); if(cPort->Open(cPort->ComNumber)) { if(!cPort->Setup(1)) return false; }else return false; return true; } //--------------------------------------------------------------------------- /* //Записываем в файл wxTextFile* TextFile = new wxTextFile(); if(!wxFileExists(L"o:\\WriteReqwest.txt")) TextFile->Create(L"o:\\WriteReqwest.txt"); TextFile->Open(L"o:\\WriteReqwest.txt"); if(TextFile->IsOpened()) { TextFile->AddLine(L"0) "+IntToStr(ch)); TextFile->Write(); TextFile->Close(); } delete TextFile; */ //--------------------------------------------------------------------------- //Записывать запрос //request - Запрос данных обычно 1й байт номер команды а остальные данные bool AYRA01FRKZ::WriteReqwest(std::string request) { /* unsigned char ENQ = 0x05; //Запрос unsigned char ACK = 0x06; //Подтверждение unsigned char STX = 0x02; //Начало текста unsigned char ETX = 0x03; //Конец текста unsigned char EOT = 0x04; //Конец передачи unsigned char NAK = 0x15; //Отрицание unsigned char DLE = 0x10; //Экранирование управляющих символов //В виде строоки std::string sSTX; sSTX+=STX; std::string sDLE; sDLE+=DLE; std::string sETX; sETX+=ETX; //Для маскировки данных std::string sDLEDLE; sDLEDLE+=DLE; sDLEDLE+=DLE; std::string sDLEETX; sDLEETX+=DLE; sDLEETX+=ETX; //Маскируем байты, равные DLE и ETX request=replaceStrings(request,sDLE,sDLEDLE); request=replaceStrings(request,sETX,sDLEETX); //Добавляем в конец ETX request+=ETX; //Подсчитываем CRC unsigned char crc=0; for(size_t i=0;iSetTimeout(500)) //Ожидание готовности T1 и T3 0,5 сек от приёмника (одинаково поэтому в 1 месте) return false; cPort->Write(&ENQ,1); //Запрос сеанса связи cPort->Read(&ch,1); if(ch==ACK) //Подтверждение готовности { for(int i=0;i<10;i++) { cPort->Write(request.c_str(),request.length()); //Передача кадра данных cPort->Read(&ch,1); //Подтверждение приема кадра if(ch==ACK) { cPort->Write(&EOT,1); //Завершение сеанса связи return true; }else if(ch==NAK) //Отрицание (Ошибка) { //Повтор сообщения не больше 10 раз } } } return false; */ //unsigned char t=0x95; //cPort->Write(&t,1); unsigned char ENQ = 0x05; //Запрос unsigned char ACK = 0x06; //Подтверждение unsigned char STX = 0x02; //Начало текста unsigned char ETX = 0x03; //Конец текста unsigned char EOT = 0x04; //Конец передачи unsigned char NAK = 0x15; //Отрицание unsigned char DLE = 0x10; //Экранирование управляющих символов //В виде строоки std::string sSTX; sSTX+=STX; std::string sDLE; sDLE+=DLE; std::string sETX; sETX+=ETX; //Для маскировки данных std::string sDLEDLE; sDLEDLE+=DLE; sDLEDLE+=DLE; std::string sDLEETX; sDLEETX+=DLE; sDLEETX+=ETX; //Маскируем байты, равные DLE и ETX request=replaceStrings(request,sDLE,sDLEDLE); request=replaceStrings(request,sETX,sDLEETX); //Подсчитываем CRC unsigned char CRC=0; CRC=CRC ^ ETX; for(size_t i=0;iSetTimeout(500)) //Ожидание готовности T1 и T3 0,5 сек от приёмника (одинаково поэтому в 1 месте) return false; //По блок схеме for(int frc=0;frc<100;frc++) { for(int rc=0;rc<5;rc++) //При неправильном ответе не больше 5 раз { cPort->Write(&ENQ,1); //Запрос сеанса связи if(cPort->Read(&ch,1)>0) { if(ch==NAK) { Sleep(500); //Ожидаем время T1 0,5 сек continue; }else //Если конфликтная ситуация ответил ENQ if(ch==ENQ) { Sleep(500); //Ожидаем время T7 0,5 сек break; }else if(ch==ACK) //Подтверждение готовности { for(int rc2=0;rc2<10;rc2++) { cPort->Write(request.c_str(),request.length()); //Передача кадра данных if(cPort->Read(&ch,1)>0) //Подтверждение приема кадра { if(ch==ACK) { cPort->Write(&EOT,1); //Завершение сеанса связи return true; }else if(ch==ENQ && rc2>1) { ch=0; //??? переход в опр позицию приёма данных (уродцы) }else if(ch==NAK) //Отрицание (Ошибка) { //Повтор сообщения не больше 10 раз } } } cPort->Write(&EOT,1); return false; }else break; } } cPort->Write(&EOT,1); //Нет ответа или неправильный ответ на запрос установки связи } return false; } //--------------------------------------------------------------------------- //Читать ответ принтера bool AYRA01FRKZ::ReadAnswer(std::string &answer) { unsigned char ENQ = 0x05; //Запрос unsigned char ACK = 0x06; //Подтверждение unsigned char STX = 0x02; //Начало текста unsigned char ETX = 0x03; //Конец текста unsigned char EOT = 0x04; //Конец передачи unsigned char NAK = 0x15; //Отрицание unsigned char DLE = 0x10; //Экранирование управляющих символов unsigned char ch=0; if(!cPort->SetTimeout(500)) //Ожидание готовности T1 и T3 0,5 сек от приёмника (одинаково поэтому в 1 месте) return false; //Получаем ответ answer=""; for(int rc=0; rc<100; rc++) { if(cPort->Read(&ch,1)>0) { if(ch==ENQ) { for(int frc=0;frc<10;frc++) { cPort->Write(&ACK,1); //Подтверждение готовности L_RC: int rc2; for(rc2=0;rc2<10;rc2++) //Повтор кадра данных может происходить до 10 раз { if(!cPort->SetTimeout(2000)) return false; //Ожидание готовности T2 2 сек. if(cPort->Read(&ch,1)>0) { if(ch==STX) //Принимаем сам ответ { answer=""; //Очищяем буфер ответа unsigned char crc=0; //Для подсчёта CRC while(true) { if(cPort->Read(&ch,1)==0) { frc++; if(frc<=10) goto L_RC; else return false; //На метку L_RC либо выйти } crc=crc ^ ch; if(ch==DLE) //Если маскировка символов DLE и ETX { if(cPort->Read(&ch,1)==0) { frc++; if(frc<=10) goto L_RC; else return false; //На метку L_RC либо выйти } crc=crc ^ ch; answer+=ch; }else if(ch==ETX) { answer+=ch; break; }else answer+=ch; if(answer.length()>2048) //Защита от переполнения буфера { frc++; if(frc<=10) goto L_RC; else return false; //На метку L_RC либо выйти } } if(cPort->Read(&ch,1)==0) //Читаем CRC { frc++; if(frc<=10) goto L_RC; else return false; //На метку L_RC либо выйти } if(ch==crc) { cPort->Write(&ACK,1); //Отвечаем что с CRC всё в порядке if(!cPort->SetTimeout(500)) //Ожидание готовности Т4 0,5 сек. return false; if(cPort->Read(&ch,1)>0) { if(ch==STX) { frc++; if(frc<=10) goto L_RC; else return false; //На метку L_RC либо выйти }else if(ch==EOT) //Получили признак конца пакета { return true; }else { if(cPort->Read(&ch,1)>0) { frc++; if(frc<=10) goto L_RC; else return false; //На метку L_RC либо выйти }else return true; } }else return true; //Хоть и недождались последнего байта всёравно true break; } else { cPort->Write(&NAK,1); //Отрицание неправильные данные frc++; if(frc<=10) goto L_RC; else return false; //На метку L_RC либо выйти } }else if(ch==ENQ) { break; } }else return false; //Вернуть "Нет ответа" } if(rc2==10) return false; //Вернуть "Нет ответа" } } }else return false; //Вернуть "Нет ответа" } return false; //Вернуть "Нет ответа" } //--------------------------------------------------------------------------- //Звуковой сигнал bool AYRA01FRKZ::Beep(int Hz,int mSec) { std::string req; req=CodeBSD(m_Password); req+=fcBeep; m_ErrorCode=200; if(!WriteReqwest(req)) return false; m_ErrorCode=0;//Ответа на команду гудок нет return true; } //--------------------------------------------------------------------------- //Отрезать бумагу bool AYRA01FRKZ::CutPaper(bool full) { std::string req; req=CodeBSD(m_Password); req+=fc75; if(full) req+="0"; else req+="1"; if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; return true; } //--------------------------------------------------------------------------- //Протянуть бумагу //lines - количество срок bool AYRA01FRKZ::FeedPaper(int lines) { std::string req; req=CodeBSD(m_Password); req+=fc75; if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; return true; } //--------------------------------------------------------------------------- //Открытие денежного ящика bool AYRA01FRKZ::OpenCashDrawer(int mSec) { std::string req; req=CodeBSD(m_Password); req+=(char)fcOpenCashDrawer; m_ErrorCode=200; if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Печатать дневной отчёт с гашением bool AYRA01FRKZ::PrintZReport() { std::string req; req=CodeBSD(m_Password); req+=fcDailyFinancialReport; m_ErrorCode=200; if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Печатать дневной отчёт без гашения bool AYRA01FRKZ::PrintXReport() { return PrintReport(1); } //--------------------------------------------------------------------------- //Начало снятия отчета без гашения ///\param type - Тип отчёта 1 - Суточный отчет (X-отчет) 2 - Отчет по секциям 3 - Отчет по кассирам 4 - Отчет по товарам 5 - Почасовой отчет 7 - Отчет количеств bool AYRA01FRKZ::PrintReport(unsigned char type) { std::string req; req=CodeBSD(m_Password); req+=fc67; req+=type; //Суточный отчёт без гашеня m_ErrorCode=200; if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Печатает строку текста bool AYRA01FRKZ::PrintLine(std::wstring line) { std::string req; req=CodeBSD(m_Password); req+=fc4C; //req+=WStringToString(line, std::locale("rus_rus.866"),'?'); //Каз символы не преобразует req+=UnicodeToDOS886(line); //Самодельное преобразование в DOS m_ErrorCode=200; if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } return true; } //--------------------------------------------------------------------------- //Готов ли к работе принтер (должна быстро выполнятся) bool AYRA01FRKZ::isOk() { return true; } //--------------------------------------------------------------------------- //Инициализация принтера. bool AYRA01FRKZ::PrinterInit() { //Получить кол-во точек после запятой std::string state; return GetStateKKM(state); } //--------------------------------------------------------------------------- //Получить тип устройства bool AYRA01FRKZ::GetDeviseType() { std::string req; req=CodeBSD(m_Password); req+=fcA5; m_ErrorCode=200; //200 C8h Нет устройства, обрабатывающего данную команду if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { m_ErrorCode=(unsigned char)ans[0]; //Код_ошибки (1) unsigned char v=(unsigned char)ans[0]; //Версия_протокола (1) unsigned char t=(unsigned char)ans[0]; //Тип (1) unsigned char m=(unsigned char)ans[0]; //Модель (1) //<Режим (2)>, <Версия_устройства (5)>, <Название (N)>. } return true; } //--------------------------------------------------------------------------- //Внесение +, выемка - bool AYRA01FRKZ::CashInOut(bool test, double sum) { std::string req; req=CodeBSD(m_Password); if(sum>0) req+=fc49; //Вннесение else req+=fc4F; //Выплата req+=(char)test; //Тестовый либо реальны взнос req+=CodeBSD(ceil(fabs(sum)*M()),5); //Сумма целая m_ErrorCode=200; //200 C8h Нет устройства, обрабатывающего данную команду if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; //Код ошибки if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } return true; } //--------------------------------------------------------------------------- //Получить сумму наличности в кассе. bool AYRA01FRKZ::GetCashSum(double& sum) { return true; } //--------------------------------------------------------------------------- //Запрос состояния ККМ ответ в виде строки (Формат не придумал наверно как в ini файле сделать...) bool AYRA01FRKZ::GetStateKKM(std::string& state) { std::string req; req=CodeBSD(m_Password); req+=fc3F; m_ErrorCode=200; if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; m_ErrorCode=0; state=ans; if(ans[0]='D') { //Формат ответа: //"D"<Кассир(1)> <Номер_в_зале(1)> <Дата_YMD(3)><Время_HMS(3)> <Флаги(1)> <Заводской_номер(4)> <Модель(1)> //<Версия_ККМ(2)> <Режим_работы(1)> <Номер_чека(2)> <Номер_смены(2)><Состояние_чека(1)> <Сумма_чека(5)> //<Десятичная_точка(1)> <Порт(1)> unsigned char cs1 = BSDToInt(ans[1]); //Кассир(1) 00..30 (было 0) unsigned char cs2 = BSDToInt(ans[2]); //Номер_в_зале(1) 01..99 (было 1) unsigned char year = BSDToInt(ans[3]); //Год 00..99 unsigned char month = BSDToInt(ans[4]); //Месяц 01..12 unsigned char day = BSDToInt(ans[5]); //День 01..31 unsigned char hours = BSDToInt(ans[6]); //Часы 00..23 unsigned char min = BSDToInt(ans[7]); //Минуты 00..59 unsigned char sec = BSDToInt(ans[8]); //Секунды 00..59 unsigned char st = ans[9]; //состояние ККМ (было 26) bool f1=getBitVal(st,0); //ККМ фискализирована (0 - нет, 1 - да) bool f2=getBitVal(st,1); //Смена открыта (0 - нет, 1 - да) bool f3=getBitVal(st,2); //Денежный ящик открыт (0 - да, 1 - нет) bool f4=getBitVal(st,3); //Весовой датчик ЧЛ (0-нет бумаги, 1-есть бумага) bool f5=getBitVal(st,4); //Бит не используется bool f6=getBitVal(st,5); //Cостояние датчика крышки (0 – крышка закрыта, 1 – крышка открыта) bool f7=getBitVal(st,6); //Бит не используется и должен содержать 0 bool f8=getBitVal(st,7); //Равен 1, если напряжение на батарейки меньше допустимого unsigned int num=StdStrToInt(DecodeBSD(ans, 10, 4)); //Заводской_номер(4) (00000000 .. 99999999) unsigned char model = ans[14]; //Модель устройства 42 Аура-01ФР-KZ 43 PayVKP-80KZ //Версия ПО ККМ 2 ASCI символа (У ауры была: "30") unsigned char mod = ans[17]; //Режим работы bool r0=getBitVal(mod,0); //0-й (младший) бит: 0 – бумага есть, 1 – нет бумаги (в принтере чеков). bool r1=getBitVal(mod,1); //1-й бит: 0 – связь с принтером чеков есть, 1 – связи нет. bool r2=getBitVal(mod,2); //2-й бит: 0 – нет ошибок, 1 – механическая ошибка печатающего устройства. bool r3=getBitVal(mod,3); //3-й бит: 0 – нет ошибок отрезчика, 1 – ошибка отрезчика. bool r4=getBitVal(mod,4); //4-й бит: 0 – нет ошибок принтера, 1 – восстановимая ошибка принтера (перегрев). bool r5=getBitVal(mod,5); //5-й бит: 0 – буфер принтера ПД используется, 1 – буфер принтера ПД пустой. bool r6=getBitVal(mod,6); //6-й бит: 0 – буфер принтера ПД не переполнен, 1 – буфер принтера ПД переполнен. unsigned int ns=StdStrToInt(DecodeBSD(ans, 18, 2)); //Номер чека 0000..9999 (было 38) unsigned int nc=StdStrToInt(DecodeBSD(ans, 20, 2)); //Номер смены 0000..9999 (было 0) unsigned char stn = ans[22]; //Состояние чека //0-1 бит: 0 – чек закрыт, 1 – открыт чек регистрации, 2- открыт чек возврата, 3 – открыт чек аннулирования. //2 бит: 0 – чек продажи, 1 – чек покупки (тип чека – биты 0-1). //3 бит: 0 – чек формируется сразу, 1 – формируется отложенный документ. unsigned int sum=StdStrToInt(DecodeBSD(ans, 23, 5)); //Сумма чека 0000000000 .. 9999999999 где. - сумма текущего чека (имеет смысл только в режиме регистрации), формат BCD. //unsigned int dot=ans[28]; //Десятичная точка 0 .. 3 - положение десятичной точки во всех денежных величинах (кол-во разрядов справа от десятичной точки) m_Dots=ans[28]; //Десятичная точка 0 .. 3 - положение десятичной точки во всех денежных величинах (кол-во разрядов справа от десятичной точки) unsigned int port=ans[29]; //Порт Номер порта ККМ, к которому подключен ПК. Формат – двоично-десятичное число из диапазона: 1, 2, 3. О портах более подробно говорится на странице 84. } return true; } //--------------------------------------------------------------------------- //Открытие фискального (клиентского) чека /*Тип чека 1 – чек продажи 2 – чек возврата продажи 3 – чек аннулирования продажи 4 – чек покупки 5 – чек возврата покупки 6 – чек аннулирования покупки. */ bool AYRA01FRKZ::OpenFiscalInv(unsigned char type) { std::string req; req=CodeBSD(m_Password); req+=(char)fc92; req+=(char)0x00; req+=(char)type; m_ErrorCode=200; if(!WriteReqwest(req)) return false; std::string ans; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Установить дату и время bool AYRA01FRKZ::SetDateTime(unsigned char ye,unsigned char mo,unsigned char de,unsigned char ho,unsigned char mi,unsigned char se) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc4B; req+=CodeBSD(ye); //Год req+=CodeBSD(mo); //Месяц req+=CodeBSD(de); //День m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode!=0) return false; req=CodeBSD(m_Password); req+=fc64; req+=CodeBSD(ho); //Часы req+=CodeBSD(mi); //Минуты req+=CodeBSD(se); //Секунды m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode!=0) return false; return true; } //--------------------------------------------------------------------------- //Наличных в денюжном ящике bool AYRA01FRKZ::GetCashSum(double* sum) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc4D; m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { *sum=0; m_ErrorCode=(unsigned char)ans[1]; }else if(ans[0]==fc4D) { *sum=BSDToInt(ans, 1, 7)/M(); m_ErrorCode=0; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Запрос состояния ККМ ///state1 - Состояние из 8 битов смотри докуиентацию bool AYRA01FRKZ::GetStateKKM(unsigned char &state1,unsigned char &state2,unsigned char &flags) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc45; m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { state1=ans[1] & 15; state2=(ans[1] >> 4) & 15; flags=ans[2]; m_ErrorCode=0; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Открытие смены //test - тест операции //text - текст для печати bool AYRA01FRKZ::OpenGang(bool test, std::wstring text) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=(char)fc9A; req+=(char)test; req+=UnicodeToDOS886(text); //Самодельное преобразование в DOS m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Анулирование всего чека bool AYRA01FRKZ::Storno() { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fcCancelFiscalInv; //fc59; m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Печать окончание чека bool AYRA01FRKZ::PrintTail() { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc73; m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Печать контрольной ленты bool AYRA01FRKZ::PrintEJ(bool full,bool clear) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=(char)fcB7; if(full) req+=CodeBSD("01"); else req+=CodeBSD("02"); if(clear) req+=CodeBSD("01"); else req+=CodeBSD("00"); m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Вход в режим //state - режим 1 - Режим регистрации 2 - Режим отчетов без гашения 3 - Режим отчетов с гашением 4 - Режим программирования 5 - Режим доступа к ФП //password - Пароль для входа врежим bool AYRA01FRKZ::EnterInState(int state,int password) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc56; req+=CodeBSD(state,1); req+=CodeBSD(password,4); m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Выход из режима bool AYRA01FRKZ::ExitFromState() { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc48; m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Регистрация продажи (команда режима регистрации) ///\param price - Цена ///\param count - Количество ///\param section - Секция в которую осуществляется регистрация 0..30 bool AYRA01FRKZ::RegisterSale(double price, double count, unsigned char section) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc52; req+=(char)0x00; //Для Ауры-01ФР-KZ всегда 0 req+=CodeBSD(price*100.0f,5); //Цена(5) (В документации скзанно 2 знака после запятой) req+=CodeBSD(count*1000.0f,5); //Количество(5) (В документации скзанно 3 знака после запятой) req+=CodeBSD(section,1); //Секция(1) m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Сторнирование продажи bool AYRA01FRKZ::StornoSale(bool test, double price, double count, unsigned char section) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc4E; req+=(char)test; req+=CodeBSD(price*100.0f,5); //Цена(5) req+=CodeBSD(count*1000.0f,5); //Количество(5) req+=CodeBSD(section,1); //Секция(1) 0..30 m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- bool AYRA01FRKZ::Abort(bool test, bool nal, double price, double count) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc41; unsigned char ch=0; setBit(&ch,7,test); //Тест setBit(&ch,6,nal); //Проверять ли наличность req+=(char)ch; req+=CodeBSD(price*M(),5); req+=CodeBSD(count*1000,5); m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- bool AYRA01FRKZ::Return(bool test, bool nal, double price, double count) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc57; unsigned char ch=0; setBit(&ch,7,test); //Тест setBit(&ch,6,nal); //Проверять ли наличность req+=(char)ch; //req+=(char)test; req+=CodeBSD(price*M(),5); req+=CodeBSD(count*1000,5); m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Отмена последней скидки/надбавки bool AYRA01FRKZ::ReturnDiscount() { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc78; m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Расчёт по чеку //test - Проверка можно ли выполнить данную операцию //type - Тип оплаты 1 - наличными 2,3,4 - остальные типы оплаты //price - Сумма для расчёта bool AYRA01FRKZ::Settle(bool test,int type,double price) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=(char)fc99; req+=(char)test; req+=CodeBSD(type,1); //Тип оплаты (1) req+=CodeBSD(price*M(),5); //Сумма (5) m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Сторно расчёта по чеку //test - Проверка можно ли выполнить данную операцию //type - Тип оплаты (0,1,2,3 - 0 наличными) //price - Сумма для расчёта //remainder - Остаток //deal - Сдача bool AYRA01FRKZ::ReturnSettle(bool test,int type,double price, double* remainder, double* deal) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=(char)fc9B; req+=(char)test; req+=CodeBSD(type,1); //Тип оплаты (1) req+=CodeBSD(price,5); //Сумма (5) m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; if(m_ErrorCode==0) //Если нет ошибки выбираем "Остаток" и "Сдачу" { *remainder=BSDToInt(ans, 2, 5); *deal=BSDToInt(ans, 7, 5); }else { *remainder=0; *deal=0; } } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Закрыть чек со здачей //<Флаги(1)><Тип оплаты(1)><Внесенная сумма(5)>. bool AYRA01FRKZ::CloseFiscalInv(bool test, int type, double price) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc4A; req+=(char)test; req+=CodeBSD(type,1); //Тип оплаты (1) req+=CodeBSD(price*M(),5); //Сумма (5) m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Скидка - либо надбавка + //area - На пооследнюю операцию 0 либо на весь чек 1 //abs - Процентом 0 суммой 1 //price - Значение +- в процентах либо суммой bool AYRA01FRKZ::Discount(bool test, bool area, bool abs, double price) { std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc43; req+=(char)test; req+=(char)area; req+=(char)abs; if(price<0) req+=(char)0x00; else req+=(char)0x01; if(abs) req+=CodeBSD(price*M(),5); //суммой else req+=CodeBSD(price*M(),3); //Процентом m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- //Чтение поля из таблицы bool AYRA01FRKZ::ReadTable(unsigned char table,unsigned short row,unsigned char field, std::string& ans) { //std::string ans; std::string req; req=CodeBSD(m_Password); req+=fc46; req+=table; req+=((unsigned char *)&row)[1]; //С начала старший потом младший байт req+=((unsigned char *)&row)[0]; //С начала старший потом младший байт req+=field; m_ErrorCode=200; if(!WriteReqwest(req)) return false; if(!ReadAnswer(ans)) return false; if(ans.length()>3) { if(ans[0]==0x55) //Пришёл код ошибки { m_ErrorCode=(unsigned char)ans[1]; } } if(m_ErrorCode==0) return true; else return false; } //--------------------------------------------------------------------------- /*Программирование даты Команда: "d" <День(1)><Месяц(1)><Год(1)> Ответ: "U" <Код Ошибки(1)><0>. Код команды ("d", 64h, 100). Допустимые значения (формат BCD) – см. команду Запрос состояния ККМ на стр. 29. Примечание 1: Если вводимая дата меньше даты последней записи ФП, то ККМ блокируется до ввода правильной даты. Примечание 2: Если вводимая дата превышает текущую дату ККМ хотя бы на один день, то ККМ ожидает подтверждения ввода даты. Для подтверждения ввода даты необходимо повторить команду «Программирование даты». Внимание! Команда может быть выполнена только при закрытой смене. Внимание! Не выполнять данную команду, если ККМ заблокирована в результате появления ошибки ЭЖ, т.к. это может вызвать сбой в памяти ККМ. Программирование времени Команда: "K" <Час(1)><Минута(1)><Секунда(1)> Ответ: "U" <Код Ошибки(1)><0>. Код команды ("K", 4Bh, 75). Допустимые значения (формат BCD) – см. команду Запрос состояния ККМ на стр. 29. Примечание: Команда может быть выполнена только в том случае, если текущая дата ККМ меньше 01.01.2090 и больше 31.12.1999. Внимание! Команда может быть выполнена только при закрытой смене. Внимание! Не выполнять данную команду, если ККМ заблокирована в результате появления ошибки ЭЖ, т.к. это может вызвать сбой в памяти ККМ. */ //--------------------------------------------------------------------------- std::wstring AYRA01FRKZ::GetErrorDesc(int ResultCode) { std::wstring result; switch( ResultCode ) { case 0: result=L"Ошибок нет"; break; case 1: result=L"Контрольная лента обработана без ошибок"; break; case 8: result=L"Неверная цена (сумма)"; break; case 10: result=L"Неверное количество"; break; case 11: result=L"Переполнение счетчика наличности"; break; case 12: result=L"Невозможно сторно последней операции"; break; case 13: result=L"Сторно по коду невозможно (в чеке зарегистрировано меньшее количество товаров с указанным кодом)"; break; case 14: result=L"Невозможен повтор последней операции"; break; case 15: result=L"Повторная скидка на операцию невозможна"; break; case 16: result=L"Скидка/надбавка на предыдущую операцию невозможна"; break; case 17: result=L"Неверный код товара"; break; case 18: result=L"Неверный штрих-код товара"; break; case 19: result=L"Неверный формат"; break; case 20: result=L"Неверная длина"; break; case 21: result=L"ККМ заблокирована в режиме ввода даты"; break; case 22: result=L"Требуется подтверждение ввода даты"; break; case 24: result=L"Нет больше данных для передачи ПО ККМ"; break; case 25: result=L"Нет подтверждения или отмены продажи"; break; case 26: result=L"Отчет с гашением прерван. Вход в режим невозможен."; break; case 27: result=L"Отключение контроля наличности невозможно (не настроены необходимые типы оплаты)."; break; case 30: result=L"Вход в режим заблокирован"; break; case 31: result=L"Проверьте дату и время"; break; case 32: result=L"Зарезервировано"; break; case 33: result=L"Невозможно закрыть архив"; break; case 61: result=L"Товар не найден"; break; case 62: result=L"Весовой штрих-код с количеством <>1.000"; break; case 63: result=L"Переполнение буфера чека"; break; case 64: result=L"Недостаточное количество товара"; break; case 65: result=L"Сторнируемое количество больше проданного"; break; case 66: result=L"Заблокированный товар не найден в буфере чека"; break; case 67: result=L"Данный товар не продавался в чеке, сторно невозможно"; break; case 68: result=L"Memo PlusTM 3TM заблокировано с ПК"; break; case 69: result=L"Ошибка контрольной суммы таблицы настроек Memo PlusTM 3TM"; break; case 70: result=L"Неверная команда от ККМ"; break; case 102: result=L"Команда не реализуется в данном режиме ККМ"; break; case 103: result=L"Нет бумаги"; break; case 104: result=L"Нет связи с принтером чеков"; break; case 105: result=L"Механическая ошибка печатающего устройства"; break; case 106: result=L"Неверный тип чека"; break; case 107: result=L"Нет больше строк картинки"; break; case 108: result=L"Неверный номер регистра"; break; case 109: result=L"Недопустимое целевое устройство"; break; case 110: result=L"Нет места в массиве картинок"; break; case 111: result=L"Неверный номер картинки / картинка отсутствует"; break; case 112: result=L"Сумма сторно больше, чем было получено данным типом оплаты"; break; case 113: result=L"Сумма не наличных платежей превышает сумму чека"; break; case 114: result=L"Сумма платежей меньше суммы чека"; break; case 115: result=L"Накопление меньше суммы возврата или аннулирования"; break; case 117: result=L"Переполнение суммы платежей"; break; case 118: result=L"(зарезервировано)"; break; case 122: result=L"Данная модель ККМ не может выполнить команду"; break; case 123: result=L"Неверная величина скидки / надбавки"; break; case 124: result=L"Операция после скидки / надбавки невозможна"; break; case 125: result=L"Неверная секция"; break; case 126: result=L"Неверный вид оплаты"; break; case 127: result=L"Переполнение при умножении"; break; case 128: result=L"Операция запрещена в таблице настроек"; break; case 129: result=L"Переполнение итога чека"; break; case 130: result=L"Открыт чек аннулирования – операция невозможна"; break; case 132: result=L"Переполнение буфера контрольной ленты"; break; case 134: result=L"Вносимая клиентом сумма меньше суммы чека"; break; case 135: result=L"Открыт чек возврата – операция невозможна"; break; case 136: result=L"Смена превысила 24 часа"; break; case 137: result=L"Открыт чек продажи – операция невозможна"; break; case 138: result=L"Переполнение ФП"; break; case 140: result=L"Неверный пароль"; break; case 141: result=L"Буфер контрольной ленты не переполнен"; break; case 142: result=L"Идет обработка контрольной ленты"; break; case 143: result=L"Обнуленная касса (повторное гашение невозможно)"; break; case 145: result=L"Неверный номер таблицы"; break; case 146: result=L"Неверный номер ряда"; break; case 147: result=L"Неверный номер поля"; break; case 148: result=L"Неверная дата"; break; case 149: result=L"Неверное время"; break; case 150: result=L"Сумма чека по секции меньше суммы сторно"; break; case 151: result=L"Подсчет суммы сдачи невозможен"; break; case 152: result=L"В ККМ нет денег для выплаты"; break; case 154: result=L"Чек закрыт – операция невозможна"; break; case 155: result=L"Чек открыт – операция невозможна"; break; case 156: result=L"Смена открыта, операция невозможна"; break; case 157: result=L"ККМ заблокирована, ждет ввода пароля доступа к ФП"; break; case 158: result=L"Заводской номер уже задан"; break; case 159: result=L"Количество перерегистраций не может быть более 4"; break; case 160: result=L"Ошибка Ф.П."; break; case 162: result=L"Неверная смена"; break; case 163: result=L"Неверный тип отчета"; break; case 164: result=L"Недопустимый пароль"; break; case 165: result=L"Недопустимый заводской номер ККМ"; break; case 166: result=L"Недопустимый РНМ"; break; case 167: result=L"Недопустимый ИНН"; break; case 168: result=L"ККМ не фискализирована"; break; case 169: result=L"Не задан заводской номер"; break; case 170: result=L"Нет отчетов"; break; case 171: result=L"Режим не активизирован"; break; case 172: result=L"Нет указанного чека в КЛ"; break; case 173: result=L"Нет больше записей КЛ"; break; case 174: result=L"Некорректный код или номер кода защиты ККМ"; break; case 176: result=L"Требуется выполнение общего гашения"; break; case 177: result=L"Команда не разрешена введенными кодами защиты ККМ"; break; case 178: result=L"Невозможна отмена скидки/надбавки"; break; case 179: result=L"Невозможно закрыть чек данным типом оплаты (в чеке присутствуют операции без контроля наличных)"; break; case 186: result=L"Ошибка обмена с фискальным модулем"; break; case 190: result=L"Необходимо провести профилактические работы"; break; case 200: result=L"Нет устройства, обрабатывающего данную команду"; break; case 201: result=L"Нет связи с внешним устройством"; break; case 202: result=L"Ошибочное состояние ТРК"; break; case 203: result=L"Больше одной регистрации в чеке"; break; case 204: result=L"Ошибочный номер ТРК"; break; case 205: result=L"Неверный делитель"; break; case 207: result=L"В ККМ произведено 20 активизаций"; break; case 208: result=L"Зарезервировано"; break; case 209: result=L"Перегрев головки принтера"; break; case 210: result=L"Зарезервировано"; break; case 211: result=L"Зарезервировано"; break; case 212: result=L"Зарезервировано"; break; case 213: result=L"Зарезервировано"; break; case 214: result=L"Зарезервировано"; break; case 215: result=L"Зарезервировано"; break; case 216: result=L"Зарезервировано"; break; case 217: result=L"Зарезервировано"; break; case 218: result=L"Зарезервировано"; break; case 219: result=L"Зарезервировано"; break; case 220: result=L"Буфер переполнен"; break; case 221: result=L"Невозможно напечатать вторую фискальную копию"; break; case 222: result=L"Требуется гашение ЭЖ"; break; default: result=L"Нет описания ошибки!"; } return result; } //---------------------------------------------------------------------------