#include #include "app_serv.h" #include "fiscal.h" #include "fr.h" #include "uart0.h" #include "data.h" #include "datadesc.h" #include "journal.h" #include "time.h" TFiscDevType FiscDevInfo; static TFiscFullStatus FiscFullStatus; CPU_INT08U FiscalConnState = FISCAL_NOCONN; OS_EVENT *FLock = NULL; //OS_EVENT *FReportLock = NULL; //OS_STK FiscalTaskStk[FISCAL_TASK_STK_SIZE]; // проверка и обработка текущего статуса ФР int CheckFiscalStatus() { CPU_INT08U err; int poll; CPU_INT32U time1, time2; CPU_INT32U enable; GetData(&EnableFiscalDesc, &enable, 0, DATA_FLAG_SYSTEM_INDEX); if (!enable) return 0; time1 = time2 = OSTimeGet(); while (labs(time2 - time1) < WAIT_PRINT_TIMEOUT) { OSTimeDly(100); time2 = OSTimeGet(); // сначала поллим poll = FiscPollExt(); if (poll == FISC_UNDEF) { FiscalConnState = FISCAL_NOCONN; SetErrorFlag(ERROR_FR_CONN); return -1; } else if (poll == FISC_BUSY) { continue; } // теперь запрашиваем статус if (FiscGetFullStatus(DEFAULT_PASS, &FiscFullStatus, &err) != FISC_OK) { if (err) { // есть какая-то глобальная ошибка if (err) SetFiscalErrorByCode(err); FiscalConnState = FISCAL_CONN; ClrErrorFlag(ERROR_FR_CONN); } else { // просто нет соединения ClearFiscalErrors(); FiscalConnState = FISCAL_NOCONN; SetErrorFlag(ERROR_FR_CONN); } return -2; } // далее разбираем статус FiscalConnState = FISCAL_CONN; ClrErrorFlag(ERROR_FR_CONN); CPU_INT16U flags; memcpy(&flags, &FiscFullStatus.Flags, sizeof(CPU_INT16U)); // КРИТИЧНЫЕ ФЛАГИ: ClrFiscalErrorByCode(FR_ERROR_CODE_6B); // ПОДРЕЖИМ switch (FiscFullStatus.SubMode) { case 1: // 1. Пассивное отсутствие бумаги – ФР не в фазе печати операции – не принимает от // хоста команды, связанные с печатью на том документе, датчик которого сообщает об // отсутствии бумаги. SetFiscalErrorByCode(FR_ERROR_CODE_6B); return -4; case 2: // 2. Активное отсутствие бумаги – ФР в фазе печати операции – принимает только // команды, не связанные с печатью. Переход из этого подрежима только в подрежим 3. SetFiscalErrorByCode(FR_ERROR_CODE_6B); return -5; case 3: // 3. После активного отсутствия бумаги – ФР ждет команду продолжения печати. Кроме // этого принимает команды, не связанные с печатью. SetFiscalErrorByCode(FR_ERROR_CODE_6B); // допечатываем чек FiscPrintContinue(DEFAULT_PASS, &err); return -6; case 4: //Фаза печати операции полных фискальных отчетов case 5: //Фаза печати операции continue; default: break; } // РЕЖИМ switch (FiscFullStatus.Mode) { case 0: // 0. Принтер в рабочем режиме. // или печать отчетов из буфера // OK ClearFiscalErrors(); goto check_exit; case 1: // 1. Выдача данных. // OK ClearFiscalErrors(); goto check_exit; case 2: // 2. Открытая смена, 24 часа не кончились. // OK ClearFiscalErrors(); goto check_exit; case 3: // 3. Открытая смена, 24 часа кончились. { CPU_INT32U autoclose; GetData(&EnableFiscalDayClearDesc, &autoclose, 0, DATA_FLAG_SYSTEM_INDEX); if (autoclose==2) { // закрываем смену в буфер FiscPrintDayReportToBuf(30, &err); // как только переполнение буфера, печатаем из буфера if (err == FR_ERROR_CODE_4B) { SetFiscalErrorByCode(err); SaveEventRecord(0, JOURNAL_EVENT_PRINT_BUF, GetTimeSec()); FiscPrintDayReportsFromBuf(30, &err); if (err) { SetFiscalErrorByCode(err); return -8; } } else if (err) { SetFiscalErrorByCode(err); return -9; } } else if (autoclose==1) { // закроем смену Z-отчетом FiscPrintDayReportClear(30, &err); SaveEventRecord(0, JOURNAL_EVENT_PRINT_Z, GetTimeSec()); if (err) { SetFiscalErrorByCode(err); return -10; } } else if (autoclose==0) { // ошибка - должен прийти оператор и закрыть смену SetFiscalErrorByCode(FR_ERROR_CODE_4E); goto check_exit; //return -11; } } goto check_exit; case 4: // 4. Закрытая смена. // открываем смену if (FiscOpenDay(DEFAULT_PASS, &err) != FISC_OK) { if (err) { SetFiscalErrorByCode(err); } else { ClearFiscalErrors(); FiscalConnState = FISCAL_NOCONN; SetErrorFlag(ERROR_FR_CONN); } return -12; } ClearFiscalErrors(); goto check_exit; case 5: // 5. Блокировка по неправильному паролю налогового инспектора. SetFiscalErrorByCode(FR_ERROR_CODE_4F); goto check_exit; case 6: // 6. Ожидание подтверждения ввода даты. SetFiscalErrorByCode(FR_ERROR_CODE_C0); goto check_exit; case 8: // 8. Открытый документ: // 8.0. Продажа. // 8.1. Покупка. // 8.2. Возврат продажи. // 8.3. Возврат покупки. // 8.4. Нефискальный. /* { CPU_INT64U cash = 0; CPU_INT08U tax[4] = {0,0,0,0}; FiscCloseBill(DEFAULT_PASS, &cash, &tax[0], "Спасибо за покупку!!!", &err); if (err) { SetFiscalErrorByCode(err); return -13; } } */ goto check_exit; case 12: // идет печать Z-отчета continue; default: goto check_exit; } } check_exit: if (labs(time2 - time1) < WAIT_PRINT_TIMEOUT) { // OK return 0; } return -1; } #define FISCAL_BAUDS_COUNT 7 static const CPU_INT32U fiscal_bauds[FISCAL_BAUDS_COUNT] = {2400, 4800, 9600, 19200, 38400, 57600, 115200}; // подключение ФР int ConnectFiscal(void) { int i, poll; CPU_INT08U err; CPU_INT32U enable; GetData(&EnableFiscalDesc, &enable, 0, DATA_FLAG_SYSTEM_INDEX); FPend(); if (enable) { int j; // поллим for (j = FISCAL_BAUDS_COUNT-1; j >= 0; j--) { i = 10; do { OSTimeDly(100); Uart0_Init(fiscal_bauds[j]); poll = FiscPollExt(); if ((poll == FISC_READY) || (poll == FISC_BUSY)) break; } while (--i); // не нашли поллингом if (i) { break; } } if (j < 0) { SetErrorFlag(ERROR_FR_CONN); FiscalConnState = FISCAL_NOCONN; FPost(); return -1; } // запросим статус if (FiscGetFullStatus(DEFAULT_PASS, &FiscFullStatus, &err) != FISC_OK) { if (err) { // есть какая-то глобальная ошибка // надо разобрать подробно if (err) SetFiscalErrorByCode(err); } else { // просто нет соединения ClearFiscalErrors(); FiscalConnState = FISCAL_NOCONN; SetErrorFlag(ERROR_FR_CONN); FPost(); return -2; } } // подключиили FiscalConnState = FISCAL_CONN; ClrErrorFlag(ERROR_FR_CONN); } else { // ФР отключен FiscalConnState = FISCAL_NOCONN; ClearFiscalErrors(); ClrErrorFlag(ERROR_FR_CONN); FPost(); return -3; } FPost(); return 0; } // подключение ФР int ConnectFiscalFast(void) { int i, poll; CPU_INT08U err; CPU_INT32U enable; GetData(&EnableFiscalDesc, &enable, 0, DATA_FLAG_SYSTEM_INDEX); FPend(); if (enable) { int j; // поллим for (j = FISCAL_BAUDS_COUNT-1; j >= 0; j--) { i = 2; do { OSTimeDly(100); Uart0_Init(fiscal_bauds[j]); poll = FiscPollExt(); if ((poll == FISC_READY) || (poll == FISC_BUSY)) break; } while (--i); // не нашли поллингом if (i) { break; } } if (j < 0) { SetErrorFlag(ERROR_FR_CONN); FiscalConnState = FISCAL_NOCONN; FPost(); return -1; } // запросим статус if (FiscGetFullStatus(DEFAULT_PASS, &FiscFullStatus, &err) != FISC_OK) { if (err) { // есть какая-то глобальная ошибка // надо разобрать подробно if (err) SetFiscalErrorByCode(err); } else { // просто нет соединения ClearFiscalErrors(); FiscalConnState = FISCAL_NOCONN; SetErrorFlag(ERROR_FR_CONN); FPost(); return -2; } } // подключиили FiscalConnState = FISCAL_CONN; ClrErrorFlag(ERROR_FR_CONN); } else { // ФР отключен FiscalConnState = FISCAL_NOCONN; ClearFiscalErrors(); ClrErrorFlag(ERROR_FR_CONN); FPost(); return -3; } FPost(); return 0; } // инициализация void InitFiscal(void) { if (!FLock) { FLock = OSSemCreate(1); //FReportLock = OSSemCreate(1); //OSTaskCreate(FiscalTask, (void *)0, (OS_STK *)&FiscalTaskStk[FISCAL_TASK_STK_SIZE-1], FISCAL_TASK_PRIO); } if (ConnectFiscal()) return; CheckFiscalStatus(); } int IsFiscalConnected(void) { int retval = 0; CPU_INT32U enable; #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0; #endif GetData(&EnableFiscalDesc, &enable, 0, DATA_FLAG_SYSTEM_INDEX); OS_ENTER_CRITICAL(); if ((enable) && (FiscalConnState == FISCAL_CONN)) retval=1; OS_EXIT_CRITICAL(); return retval; } // занять void FPend(void) { CPU_INT08U err; do{ OSSemPend(FLock, 1, &err); if (!err) break; OSTimeDly(1); }while (err); } // освободить void FPost(void) { OSTimeDly(200); OSSemPost(FLock); } /* // занять void FReportPend(void) { CPU_INT08U err; do{ OSSemPend(FReportLock, 1, &err); if (!err) break; OSTimeDly(1); }while (err); } // занять 2 int FReportGet(void) { CPU_INT08U err; OSSemPend(FReportLock, 1, &err); if (!err) return 1; return 0; } // освободить void FReportPost(void) { if (!FReportTest()) OSSemPost(FReportLock); } // проверить // 0 - недоступен // >0 - доступен CPU_INT16U FReportTest(void) { return OSSemCheck(FReportLock); } */ // очистка всех ошибок ФР void ClearFiscalErrors(void) { for (unsigned char i=ERROR_FR; i