#include #include #include "journal.h" #include "fram.h" #include "fram_map.h" #include "time.h" #include "fr.h" #include "crc16.h" #include "mode.h" #ifdef CONFIG_FTP_CLIENT_ENABLE #include "ftp_app.h" #endif static CPU_INT32U GlobalErrorsFlags[JOURNAL_EVENTS_COUNT / 32 + 1] = {0}; static CPU_INT32U PrevFlags[JOURNAL_EVENTS_COUNT / 32 + 1] = {0}; CPU_INT32U journal_rec_index; OS_EVENT *JournalLock = NULL; void journal_getSem() { CPU_INT08U err; do{ OSSemPend(JournalLock, 1, &err); if (!err) break; OSTimeDly(1); }while (err); } void journal_freeSem() { OSSemPost(JournalLock); } void SetErrorFlag(CPU_INT08U error) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0; #endif OS_ENTER_CRITICAL(); GlobalErrorsFlags[error/32] |= (1L << (error%32)); OS_EXIT_CRITICAL(); } void ClrErrorFlag(CPU_INT08U error) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0; #endif OS_ENTER_CRITICAL(); GlobalErrorsFlags[error/32] &= ~(1L << (error%32)); OS_EXIT_CRITICAL(); } int TstErrorFlag(CPU_INT08U error) { CPU_INT32U temp = 0; #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0; #endif OS_ENTER_CRITICAL(); temp = GlobalErrorsFlags[error/32] & (1L << (error%32)); OS_EXIT_CRITICAL(); return temp; } int TstCriticalErrors(void) { CPU_INT32U errors = 0; #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0; #endif CPU_INT32U ignore_fiscal = 0; GetData(&DisableFiscalErrorsDesc, &ignore_fiscal, 0, DATA_FLAG_SYSTEM_INDEX); OS_ENTER_CRITICAL(); if (!ignore_fiscal) { errors |= TstCriticalFiscalError(); errors |= TstErrorFlag(ERROR_FR_CONN); /* if (!FReportTest()) { // ФР недоступен для любой печати errors |= 0x1; } */ } errors |= TstErrorFlag(ERROR_VALIDATOR_CONN); OS_EXIT_CRITICAL(); if (errors) return 1; return 0; } int TstCriticalValidatorErrors(void) { return 0; } void ClrValidatorErrors(void) { for (CPU_INT08U i=ERROR_VALIDATOR_FAILURE; i= EVENT_RECORDS_COUNT) return -1; journal_getSem(); ReadArrayFram(offsetof(TFramMap, EventRecords[0])+index*sizeof(TEventRecord), sizeof(TEventRecord), (unsigned char*)record); journal_freeSem(); return 0; } void SaveEventAbonementRecord(CPU_INT08U event, CPU_INT16U money, CPU_INT16U bonus, CPU_INT08U type_abonement, CPU_INT32U time_before, CPU_INT32U number_abonement) { TEventRecord record; journal_getSem(); record.time = GetTimeSec(); record.type_abonement = type_abonement; record.event = event; record.money = money; record.bonus = bonus; record.time_before = time_before; record.number_abonement = number_abonement; WriteArrayFram(offsetof(TFramMap, EventRecords[0])+journal_rec_index*sizeof(TEventRecord), sizeof(TEventRecord), (unsigned char*)&record); journal_rec_index = (journal_rec_index + 1) % EVENT_RECORDS_COUNT; #ifdef CONFIG_FTP_CLIENT_ENABLE if ((journal_rec_index == 0) || (journal_rec_index == EVENT_RECORDS_COUNT / 2)) { time_to_ftp = FTP_FLAG_SEND_COUNTERS | FTP_FLAG_SEND_LOGS; } #endif journal_freeSem(); } // запись в журнал записи о событии void SaveEventRecord(CPU_INT08U channel, CPU_INT08U event, CPU_INT16U data) { TEventRecord record; journal_getSem(); record.time = GetTimeSec(); record.channel = channel; record.event = event; record.data = data; WriteArrayFram(offsetof(TFramMap, EventRecords[0])+journal_rec_index*sizeof(TEventRecord), sizeof(TEventRecord), (unsigned char*)&record); journal_rec_index = (journal_rec_index + 1) % EVENT_RECORDS_COUNT; #ifdef CONFIG_FTP_CLIENT_ENABLE if ((journal_rec_index == 0) || (journal_rec_index == EVENT_RECORDS_COUNT / 2)) { time_to_ftp = FTP_FLAG_SEND_COUNTERS | FTP_FLAG_SEND_LOGS; } #endif journal_freeSem(); } void ClearEventJournal(void) { journal_getSem(); SetArrayFram(offsetof(TFramMap, EventRecords), sizeof(TEventRecord)*EVENT_RECORDS_COUNT, 0x00); journal_freeSem(); } void GetEventStr(char* str, char event) { switch (event){ case JOURNAL_CANSEL_BILL: strcpy(str, "Отмена чека"); break; case JOURNAL_EVENT_FTP_SEND: strcpy(str, "Отправка на FTP"); break; case JOURNAL_EVENT_SOLARIUM_CLEANING_START: sprintf(str, "Начало уборки "); break; case JOURNAL_EVENT_SOLARIUM_CLEANING_END: sprintf(str, "Конец уборки "); break; case JOURNAL_EVENT_SOLARIUM_SERVICE_START: sprintf(str, "Начало серв."); break; case JOURNAL_EVENT_SOLARIUM_SERVICE_END: sprintf(str, "Конец серв."); break; case JOURNAL_EVENT_SOLARIUM_TESTMODE_START: sprintf(str, "Начало теста "); break; case JOURNAL_EVENT_SOLARIUM_TESTMODE_END: sprintf(str, "Конец теста "); break; case JOURNAL_EVENT_POST_UNAVIABLE: sprintf(str, "Недоступен пост"); break; case JOURNAL_EVENT_MONEY_NOTE: sprintf(str, "Вн.купюра "); break; case JOURNAL_EVENT_MONEY_COIN: sprintf(str, "Вн.монеты "); break; case JOURNAL_EVENT_CARD_ACCEPTED: sprintf(str, "Банк.оплата "); break; case JOURNAL_EVENT_CARD_REJECTED: sprintf(str, "Банк.оплата "); break; case JOURNAL_EVENT_ABONEMENT_ACCEPTED: sprintf(str, "БКЗ.оплата "); break; case JOURNAL_EVENT_ABONEMENT_REJECTED: sprintf(str, "БКЗ.оплата "); break; case JOURNAL_EVENT_ABONEMENT_PAY_ACCEPTED: sprintf(str, "БКЗ.пополнение "); break; case JOURNAL_EVENT_ABONEMENT_PAY_REJECTED: sprintf(str, "БКЗ.пополнение "); break; case JOURNAL_EVENT_ABONEMENT_BALANCE: sprintf(str, "БКЗ.баланс "); break; case JOURNAL_EVENT_ABONEMENT_WRONG: sprintf(str, "БКЗ.карта "); break; case JOURNAL_EVENT_START_SESSION: #if defined(BOARD_CENTRAL_CARWASH) sprintf(str, "Нач.работы "); #elif defined(BOARD_SOLARIUM_WEB) || defined(BOARD_SOLARIUM_VLAD) sprintf(str, "Нач.сеанса "); #endif break; case JOURNAL_EVENT_END_SESSION: #if defined(BOARD_CENTRAL_CARWASH) sprintf(str, "Кон.блок. "); #elif defined(BOARD_SOLARIUM_WEB) || defined(BOARD_SOLARIUM_VLAD) sprintf(str, "Конец сеанса "); #endif break; case JOURNAL_EVENT_DEVICE_ON: #if defined(BOARD_CENTRAL_CARWASH) sprintf(str, "Включение"); #elif defined(BOARD_SOLARIUM_WEB) sprintf(str, "ВКЛЮЧЕНИЕ"); #endif break; case JOURNAL_EVENT_PRINT_BILL: sprintf(str, "Печать чека"); break; case JOURNAL_EVENT_PRINT_Z: sprintf(str, "Печать Z-отчета"); break; case JOURNAL_EVENT_PRINT_X: sprintf(str, "Печать X-отчета"); break; case JOURNAL_EVENT_PRINT_BUF: sprintf(str, "Печать отч.из буф."); break; case JOURNAL_EVENT_CHANGE_MODE: sprintf(str, "Смена режима"); break; case JOURNAL_EVENT_INCASSATION: sprintf(str, "Инкассация"); break; case JOURNAL_EVENT_PASS_FAIL: sprintf(str, "Неверный пароль"); break; case JOURNAL_EVENT_EMAIL_FAIL: sprintf(str, "Ошибка отпр.e-mail"); break; case JOURNAL_EVENT_EMAIL_OK: sprintf(str, "E-mail отпр.успешно"); break; default: sprintf(str, "нет"); break; } } void GetEventStrEng(char* str, char event) { switch (event){ case JOURNAL_EVENT_MONEY_NOTE: sprintf(str, " | Vnesena kupura "); break; case JOURNAL_EVENT_MONEY_COIN: sprintf(str, " | Vneseny monety "); break; case JOURNAL_EVENT_START_SESSION: sprintf(str, " | Nachalo seansa "); break; case JOURNAL_EVENT_END_SESSION: sprintf(str, " | Koneс seansa "); break; case JOURNAL_EVENT_DEVICE_ON: sprintf(str, " | Vkluchenie "); break; case JOURNAL_EVENT_PRINT_BILL: sprintf(str, " | Pechat' checka "); break; case JOURNAL_EVENT_PRINT_Z: sprintf(str, " | Pechat' Z-otcheta "); break; case JOURNAL_EVENT_PRINT_X: sprintf(str, " | Pechat' X-otcheta "); break; case JOURNAL_EVENT_PRINT_BUF: sprintf(str, " | Pechat' otcheta iz bufera "); break; case JOURNAL_EVENT_CHANGE_MODE: sprintf(str, " | Smena rejima "); break; case JOURNAL_EVENT_INCASSATION: sprintf(str, " | Incassaciya "); break; case JOURNAL_EVENT_PASS_FAIL: sprintf(str, " | Neverniy parol' "); break; case JOURNAL_EVENT_EMAIL_FAIL: sprintf(str, " | Oshibka otpravki e-mail "); break; case JOURNAL_EVENT_EMAIL_OK: sprintf(str, " | E-mail otpravleno uspeshno "); break; default: sprintf(str, " | Net sobytiya "); break; } } void PrintEventJournalRecordEng(char* str, TEventRecord *record) { if (record->event) { TRTC_Data rtc_data; // напечатаем время Sec2Date(&rtc_data, record->time); sprintf(str, "| "); PrintRTCDateTimeString(&str[strlen(str)], &rtc_data); // напечатаем событие GetEventStrEng(&str[strlen(str)], record->event); // напечатаем дополнительные поля if ((record->event == JOURNAL_EVENT_MONEY_NOTE) || (record->event == JOURNAL_EVENT_MONEY_COIN)) { sprintf(&str[strlen(str)], "kanal %d ", record->channel+1); sprintf(&str[strlen(str)], "%d rub.", record->data); } else if (record->event == JOURNAL_EVENT_START_SESSION) { sprintf(&str[strlen(str)], "kanal %d ", record->channel+1); PrintSecToHourMinSec(&str[strlen(str)], record->data); } else if (record->event == JOURNAL_EVENT_END_SESSION) { sprintf(&str[strlen(str)], "kanal %d ", record->channel+1); sprintf(&str[strlen(str)], ""); } else if (record->event == JOURNAL_EVENT_DEVICE_ON) { sprintf(&str[strlen(str)], ""); } else if (record->event == JOURNAL_EVENT_PRINT_BILL) { sprintf(&str[strlen(str)], "kanal %d ", record->channel+1); } else if (record->event == JOURNAL_EVENT_PRINT_Z) { sprintf(&str[strlen(str)], ""); } else if (record->event == JOURNAL_EVENT_PRINT_X) { sprintf(&str[strlen(str)], ""); } else if (record->event == JOURNAL_EVENT_PRINT_BUF) { sprintf(&str[strlen(str)], ""); } else if (record->event == JOURNAL_EVENT_CHANGE_MODE) { if (record->data == MODE_WORK) sprintf(&str[strlen(str)], "rabota"); else sprintf(&str[strlen(str)], "nastroika"); } else if (record->event == JOURNAL_EVENT_INCASSATION) { sprintf(&str[strlen(str)], "%u rub.", record->data); } else if (record->event == JOURNAL_EVENT_PASS_FAIL) { sprintf(&str[strlen(str)], "%u", record->data); } else if ((record->event == JOURNAL_EVENT_EMAIL_OK) || (record->event == JOURNAL_EVENT_EMAIL_FAIL)) { sprintf(&str[strlen(str)], ""); } sprintf(&str[strlen(str)], "\r\n"); } else { // пустая запись sprintf(str, "net zapisi\r\n"); } } void IncCounter(CPU_INT08U ch, CPU_INT32U time, CPU_INT32U money, CPU_INT08U card) { CPU_INT32U r, t, m; TCountersLong long_ctrs; journal_getSem(); // увеличим канальные счетчики ReadArrayFram(offsetof(TFramMap, Counters.CounterChannelRun)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&r); ReadArrayFram(offsetof(TFramMap, Counters.CounterChannelTime)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&t); r++; t+=time; WriteArrayFram(offsetof(TFramMap, Counters.CounterChannelRun)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&r); WriteArrayFram(offsetof(TFramMap, Counters.CounterChannelTime)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&t); if (card == 2) { ReadArrayFram(offsetof(TFramMap, Counters.CounterChannelAbonement)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&m); m+=money; WriteArrayFram(offsetof(TFramMap, Counters.CounterChannelAbonement)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&m); } else if (card) { ReadArrayFram(offsetof(TFramMap, Counters.CounterChannelCard)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&m); m+=money; WriteArrayFram(offsetof(TFramMap, Counters.CounterChannelCard)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&m); } else { ReadArrayFram(offsetof(TFramMap, Counters.CounterChannelMoney)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&m); m+=money; WriteArrayFram(offsetof(TFramMap, Counters.CounterChannelMoney)+sizeof(CPU_INT32U)*ch, sizeof(CPU_INT32U), (unsigned char*)&m); } // увеличим общие счетчики ReadArrayFram(offsetof(TFramMap, Counters.CounterRun), sizeof(CPU_INT32U), (unsigned char*)&r); ReadArrayFram(offsetof(TFramMap, Counters.CounterTime), sizeof(CPU_INT32U), (unsigned char*)&t); r++; t+=time; WriteArrayFram(offsetof(TFramMap, Counters.CounterRun), sizeof(CPU_INT32U), (unsigned char*)&r); WriteArrayFram(offsetof(TFramMap, Counters.CounterTime), sizeof(CPU_INT32U), (unsigned char*)&t); if (card == 2) { ReadArrayFram(offsetof(TFramMap, Counters.CounterAbonement), sizeof(CPU_INT32U), (unsigned char*)&m); m+=money; WriteArrayFram(offsetof(TFramMap, Counters.CounterAbonement), sizeof(CPU_INT32U), (unsigned char*)&m); } else if (card) { ReadArrayFram(offsetof(TFramMap, Counters.CounterCard), sizeof(CPU_INT32U), (unsigned char*)&m); m+=money; WriteArrayFram(offsetof(TFramMap, Counters.CounterCard), sizeof(CPU_INT32U), (unsigned char*)&m); } else { ReadArrayFram(offsetof(TFramMap, Counters.CounterMoney), sizeof(CPU_INT32U), (unsigned char*)&m); m+=money; WriteArrayFram(offsetof(TFramMap, Counters.CounterMoney), sizeof(CPU_INT32U), (unsigned char*)&m); } // увеличим длинные счетчики ReadArrayFram(offsetof(TFramMap, CountersLong), sizeof(TCountersLong), (unsigned char*)&long_ctrs); long_ctrs.CounterChannelRunLong[ch]++; long_ctrs.CounterChannelTimeLong[ch] += time; long_ctrs.CounterRunLong++; long_ctrs.CounterTimeLong += time; if (card == 2) { long_ctrs.CounterChannelAbonementLong[ch] += money; long_ctrs.CounterAbonementLong += money; } else if (card) { long_ctrs.CounterChannelCardLong[ch] += money; long_ctrs.CounterCardLong += money; } else { long_ctrs.CounterChannelMoneyLong[ch] += money; long_ctrs.CounterMoneyLong += money; } long_ctrs.crc = CRC16((unsigned char*)&long_ctrs, offsetof(TCountersLong, crc)); WriteArrayFram(offsetof(TFramMap, CountersLong), sizeof(TCountersLong), (unsigned char*)&long_ctrs); journal_freeSem(); } void CheckLongCounters(void) { TCountersLong long_ctrs; CPU_INT16U crc; ReadArrayFram(offsetof(TFramMap, CountersLong), sizeof(TCountersLong), (unsigned char*)&long_ctrs); crc = CRC16((unsigned char*)&long_ctrs, offsetof(TCountersLong, crc)); if (crc != long_ctrs.crc) { memset(&long_ctrs, 0, sizeof(TCountersLong)); long_ctrs.crc = CRC16((unsigned char*)&long_ctrs, offsetof(TCountersLong, crc)); WriteArrayFram(offsetof(TFramMap, CountersLong), sizeof(TCountersLong), (unsigned char*)&long_ctrs); /// обычные счетчики тоже очистим ClearCounters(); ClearBillnomCounter(); } } void ClearCounters(void) { journal_getSem(); SetArrayFram(offsetof(TFramMap, Counters), sizeof(CPU_INT32U)*(CHANNELS_NUM+1)*4, 0x00); journal_freeSem(); } /// инкремент счетчика купюр по номиналам void IncBillnomCounter(CPU_INT32U index) { CPU_INT32U counter; if (index >= 24) return; journal_getSem(); ReadArrayFram(offsetof(TFramMap, Counters.CounterBillNominals)+sizeof(CPU_INT32U)*index, sizeof(CPU_INT32U), (unsigned char*)&counter); counter++; WriteArrayFram(offsetof(TFramMap, Counters.CounterBillNominals)+sizeof(CPU_INT32U)*index, sizeof(CPU_INT32U), (unsigned char*)&counter); ReadArrayFram(offsetof(TFramMap, Counters.BillsCount), sizeof(CPU_INT32U), (unsigned char*)&counter); counter++; WriteArrayFram(offsetof(TFramMap, Counters.BillsCount), sizeof(CPU_INT32U), (unsigned char*)&counter); journal_freeSem(); } /// очистка счетчиков купюр void ClearBillnomCounter(void) { CPU_INT32U counter = 0; CPU_INT32U i; journal_getSem(); for (i = 0; i < 24; i++) { WriteArrayFram(offsetof(TFramMap, Counters.CounterBillNominals)+sizeof(CPU_INT32U)*i, sizeof(CPU_INT32U), (unsigned char*)&counter); } WriteArrayFram(offsetof(TFramMap, Counters.BillsCount), sizeof(CPU_INT32U), (unsigned char*)&counter); journal_freeSem(); } // сервер ошибок (занесение ошибок в журнал) void ErrorServer(void) { for (int i = ERROR_VALIDATOR_CONN; i < JOURNAL_EVENTS_COUNT; i++) { if (!(PrevFlags[i/32] & (1L<<(i%32))) && (TstErrorFlag(i))) { // запишем в журнал SaveEventRecord(0, i, 0); } } memcpy(PrevFlags, GlobalErrorsFlags, sizeof(CPU_INT32U) * (JOURNAL_EVENTS_COUNT / 32 + 1)); } void JournalInit(void) { if (!JournalLock) JournalLock = OSSemCreate(1); journal_getSem(); TEventRecord record; // найти самую старую по времени запись и добавить новую после неё CPU_INT32U i, ind=0, indm = 0, maxtime = 0; for (i = 0; i < EVENT_RECORDS_COUNT; i++) { ReadArrayFram(offsetof(TFramMap, EventRecords[0])+i*sizeof(TEventRecord), sizeof(TEventRecord), (unsigned char*)&record); if ((record.time == 0) || (record.time == 0xffffffff)) {ind = i; break;} if (record.time >= maxtime) {maxtime = record.time; indm = i;} } if (i >= EVENT_RECORDS_COUNT) { // все записи заполены - записываем на место самой старой ind = (indm + 1) % EVENT_RECORDS_COUNT; } journal_rec_index = ind; journal_freeSem(); }