#include "log.h" #include "rtc.h" #include "ringfs.h" #include "spi_flash.h" #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include char logFileBuf[FILE_BUF_MAX_LEN]; char name_login[50]; extern const char* logsStrShortRu[]; bool flUpdateLog = false; static bool fLogInit = false; // Флаг инициализации журнала #define LOG_TIME 1000*60*10 static int op_sector_erase(struct ringfs_flash_partition *flash, int address) { (void)flash; int ret; ret = spi_flash_erase_sector(address, 0); return ret; } static ssize_t op_program(struct ringfs_flash_partition *flash, int address, const void *data, size_t size) { (void)flash; int ret; ret = spi_flash_write(address, data, size, 0); return ret; } static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *data, size_t size) { (void)flash; int ret; ret = spi_flash_read(address, data, size, 0); return ret; } static struct ringfs_flash_partition ringfs_flash = { .sector_offset = LOG_FLASH_SECTOR_OFFSET, .sector_erase = op_sector_erase, .program = op_program, .read = op_read, }; static struct ringfs fs; static struct ringfs_flash_partition ringfs_flash2 = { .sector_offset = ALARM_LOG_FLASH_SECTOR_OFFSET, .sector_erase = op_sector_erase, .program = op_program, .read = op_read, }; static struct ringfs fs2; static SemaphoreHandle_t log_mutex; /** * @brief Отключает журнал для безопасной перезагрузки */ bool LOG_Disable(void) { if (fLogInit) { /* Ожидаем завершения работы с журнал */ if ( xSemaphoreTake(log_mutex, 10000) == pdTRUE ) { //fLogInit = false; //xSemaphoreGive(logMutex); return true; } else { return false; } } else { return true; } } void log_task(void* params) { for(;;){ flUpdateLog = true; vTaskDelay(LOG_TIME); /*vTaskDelay(50); log_event_data(LOG_SYSTEM_BOOT, "Администратор"); log_add(")215.7;215.7;220.5;000;50.1;2.30;25.0;00000001;");*/ } } void log_init(bool format) { DBG printf(">>> Event log\n"); if (!spi_flash_desc.present) return; ringfs_flash.sector_size = spi_flash_desc.sector_size; ringfs_flash.sector_count = SECTOR_COUNT; ringfs_init(&fs, &ringfs_flash, LOG_ENTRY_VERSION, sizeof(log_entry_t)); if (format || ringfs_scan(&fs) != 0){ DBG printf("FAT1 false\r\n"); ringfs_format(&fs); } DBG printf("FAT1 true\r\n"); ringfs_flash2.sector_size = spi_flash_desc.sector_size; ringfs_flash2.sector_count = SECTOR_COUNT; ringfs_init(&fs2, &ringfs_flash2, LOG_ENTRY_VERSION, sizeof(log_entry_t)); if (format || ringfs_scan(&fs2) != 0){ DBG printf("FAT2 false\r\n"); ringfs_format(&fs2); } DBG printf("FAT2 true\r\n"); fLogInit = true; log_mutex = xSemaphoreCreateMutex(); xTaskCreate(log_task, ( char * ) "log_task", configMINIMAL_STACK_SIZE * 2, NULL, tskIDLE_PRIORITY, NULL); } int capacity_flash = 0; int count_flash = 0; int log_test(void) { int ret; log_entry_t entry; log_init(false); capacity_flash = ringfs_capacity(&fs); count_flash = ringfs_count_exact(&fs); DBG printf("\tCapacity: %d\n", capacity_flash); DBG printf("\tCount: %d\n", count_flash); DBG printf("\tAppending "); // ret = log_event(LOG_SYSTEM_DEFCONFIG, 0, 0); DBG printf("%s\n", ret == 0 ? "ok" : "error"); if (ret == 0) return -1; // ret = log_event(LOG_SYSTEM_DEFCONFIG, 0, 512); entry.timestamp = 0; entry.type = 0; DBG printf("\tFetching "); if (log_fetch(&entry, portMAX_DELAY) == 0){ DBG printf("ok, time=%d, type=%d\n", entry.timestamp, entry.type); log_fetch(&entry, portMAX_DELAY); entry.timestamp = 0; entry.type = 0; log_fetch(&entry, portMAX_DELAY); entry.timestamp = 0; entry.type = 0; log_fetch(&entry, portMAX_DELAY); entry.timestamp = 0; entry.type = 0; log_fetch(&entry, portMAX_DELAY); return 0; } else { DBG printf("fail\n"); return -1; } DBG printf("\tDiscarding "); if (log_discard(&entry,portMAX_DELAY) == 0) DBG printf("ok\n"); else { DBG printf("fail\n"); return -1; } return 0; } int log_append(log_entry_t *entry) { int ret; TM_RTC_t data; ret = xSemaphoreTake( log_mutex, portMAX_DELAY ); if (ret == pdFALSE) return ret; if (!entry->timestamp){ TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN); entry->timestamp = data.unix; } if(entry->type == LOG_VALUE) ringfs_append(&fs, entry); else ringfs_append(&fs2, entry); xSemaphoreGive(log_mutex); return ret; } int log_fetch(log_entry_t *entry, uint32_t timeout) { int ret; ret = xSemaphoreTake( log_mutex, (TickType_t)timeout ); if (ret == pdFALSE) return ret; if(entry->type == LOG_VALUE) ret = ringfs_fetch(&fs, entry); else ret = ringfs_fetch(&fs2, entry); xSemaphoreGive(log_mutex); return ret; } int log_rewind(log_entry_t *entry, uint32_t timeout) { int ret; ret = xSemaphoreTake( log_mutex, (TickType_t)timeout ); if (ret == pdFALSE) return ret; if(entry->type == LOG_VALUE) ret = ringfs_rewind(&fs); else ret = ringfs_rewind(&fs2); xSemaphoreGive(log_mutex); return ret; } int log_discard(log_entry_t *entry, uint32_t timeout) { int ret; ret = xSemaphoreTake( log_mutex, (TickType_t)timeout ); if (ret == pdFALSE) return ret; if(entry->type == LOG_VALUE) ret = ringfs_discard(&fs); else ret = ringfs_discard(&fs2); xSemaphoreGive(log_mutex); return ret; } void log_event_data(log_type_t type, char *data) { log_entry_t entry_data; entry_data.timestamp = 0; entry_data.type = type; strncpy(entry_data.data, data, 49); if (fLogInit) log_append(&entry_data); } void log_add(char *log_data) { char buf_value[50]; uint8_t i, len; memset(buf_value, 0, 50); len = strlen(log_data); if (len != UPS_DATA_STRING_SIZE) { //len = UPS_DATA_STRING_SIZE; return; } strncpy(buf_value, log_data, len); DBG printf("UPS log data: %s\r\n", log_data); buf_value[0] = '\"'; for(i = 0; i < len; i++) { if(buf_value[i] == ' ') buf_value[i] = ';'; } buf_value[len - 1] = ';'; if(fLogInit){ if(fs.write.slot>67) { log_entry_t entry_data; entry_data.timestamp = 0; log_event_data(LOG_VALUE, buf_value); } else log_event_data(LOG_VALUE, buf_value); } } /** * @brief Возвращает true если журнал проинициализирован */ bool LOG_IsInit() { return fLogInit; } /** * @brief Возвращает общее количество страниц */ uint32_t LOG_GetPageCount(void) { return (((ringfs_count_estimate(&fs)) / 10) + 1); } uint32_t LOG_GetTotalSTRCount(void) { return ringfs_count_estimate(&fs); } void LOG_GetPage_tabs(char *str, uint32_t page) { TM_RTC_t rtc_data; log_entry_t entry; char buf[20]; uint8_t i; int start =LOG_GetTotalSTRCount();//(fs.write.sector*fs.slots_per_sector + fs.write.slot); memset(buf, 0, 20); for(i=0; i < 10; i++){ fs.cursor_position = start - 10*(page-1) - 1 - i; if(fs.cursor_position < 0) break; else{ fs.cursor.sector = (fs.read.sector + fs.cursor_position/fs.slots_per_sector)%fs.flash->sector_count; fs.cursor.slot = fs.cursor_position%fs.slots_per_sector; } entry.type = LOG_VALUE; log_fetch(&entry, portMAX_DELAY); entry.data[49] = 0; strncat(str, entry.data, strlen(entry.data)); TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp); sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month, rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds); strcat(str, buf); strcat(str, "\","); strcat(str, "\r\n"); } } void LOG_GetPage(char *str, uint32_t page) { TM_RTC_t rtc_data; log_entry_t entry; char buf[20]; uint8_t i; int start =LOG_GetTotalSTRCount();//(fs.write.sector*fs.slots_per_sector + fs.write.slot); memset(buf, 0, 20); for(i=0; i < 10; i++){ fs.cursor_position = start - 10*(page-1) - 1 - i; if(fs.cursor_position < 0) break; else{ fs.cursor.sector = (fs.read.sector + fs.cursor_position/fs.slots_per_sector)%fs.flash->sector_count; fs.cursor.slot = fs.cursor_position%fs.slots_per_sector; } entry.type = LOG_VALUE; log_fetch(&entry, portMAX_DELAY); entry.data[49] = 0; strncat(str, entry.data, strlen(entry.data)); TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp); sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month, rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds); strcat(str, buf); strcat(str, "\","); } } uint32_t LOG_GetData(int ptr, char *str, uint32_t size, bool start) { TM_RTC_t rtc_data; log_entry_t entry; char buf[20]; uint8_t i; entry.type = LOG_VALUE; if(start) log_rewind(&entry, portMAX_DELAY); fs.cursor_position = ptr/STRING_SIZE; fs.cursor.sector = (fs.read.sector + fs.cursor_position/fs.slots_per_sector)%fs.flash->sector_count; fs.cursor.slot = fs.cursor_position%fs.slots_per_sector; for(i = 0; i < size/STRING_SIZE; i++) { entry.type = LOG_VALUE; log_fetch(&entry, portMAX_DELAY); entry.data[49] = 0; strncat(str, &entry.data[1], (strlen(entry.data) - 1)); TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp); sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month, rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds); strcat(str, buf); strcat(str, "\n"); } return strlen(str); } /** * @brief Возвращает общее количество страниц */ uint32_t History_GetPageCount(void) { return (((ringfs_count_estimate(&fs2)) / 10) + 1); } uint32_t History_GetTotalSTRCount(void) { return ringfs_count_estimate(&fs2); } void History_GetPage(char *str, uint32_t page) { TM_RTC_t rtc_data; log_entry_t entry; char buf[20]; uint8_t i; int start =History_GetTotalSTRCount();//(fs.write.sector*fs.slots_per_sector + fs.write.slot); memset(buf, 0, 20); for(i=0; i < 10; i++){ fs2.cursor_position = start - 10*(page-1) - 1 - i; if(fs2.cursor_position < 0) break; else{ fs2.cursor.sector = (fs2.read.sector + fs2.cursor_position/fs.slots_per_sector)%fs2.flash->sector_count; fs2.cursor.slot = fs2.cursor_position%fs2.slots_per_sector; } entry.type = LOG_LOGIN; log_fetch(&entry, portMAX_DELAY); strcat(str, "\""); strncat(str, logsStrShortRu[entry.type], (strlen(logsStrShortRu[entry.type]) )); strcat(str, ";"); entry.data[49] = 0; strncat(str, entry.data, (strlen(entry.data) )); strcat(str, ";"); TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp); sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month, rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds); strcat(str, buf); strcat(str, "\","); } } void History_GetPage_tabs(char *str, uint32_t page) { TM_RTC_t rtc_data; log_entry_t entry; char buf[50]; uint8_t i; int start =History_GetTotalSTRCount();//(fs.write.sector*fs.slots_per_sector + fs.write.slot); memset(buf, 0, 50); for(i=0; i < 10; i++){ fs2.cursor_position = start - 10*(page-1) - 1 - i; if(fs2.cursor_position < 0) break; else{ fs2.cursor.sector = (fs2.read.sector + fs2.cursor_position/fs.slots_per_sector)%fs2.flash->sector_count; fs2.cursor.slot = fs2.cursor_position%fs2.slots_per_sector; } entry.type = LOG_LOGIN; log_fetch(&entry, portMAX_DELAY); //sprintf(buf, "%-50s", logsStrShortRu[entry.type]); strncat(str, logsStrShortRu[entry.type], (strlen(logsStrShortRu[entry.type]) )); for(uint8_t j = 0; j < (25 - strlen(logsStrShortRu[entry.type])/2); j ++) strcat(str, " "); strcat(str, "\t"); memset(buf, 0, 50); entry.data[49] = 0; strncat(str, entry.data, (strlen(entry.data) )); for(uint8_t j = 0; j < (25 - strlen(entry.data)/2); j ++) strcat(str, " "); strcat(str, "\t"); memset(buf, 0, 50); TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp); sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month, rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds); strcat(str, buf); strcat(str, "\r\n"); } } uint32_t History_GetData(int ptr, char *str, uint32_t size, bool start) { TM_RTC_t rtc_data; log_entry_t entry; char buf[20]; char temp_str[FILE_BUF_MAX_LEN]; uint8_t i; uint16_t len; entry.type = LOG_LOGIN; if(start) log_rewind(&entry, portMAX_DELAY); fs2.cursor_position = ptr/STRING_SIZE_HISTORY; fs2.cursor.sector = (fs2.read.sector + fs2.cursor_position/fs2.slots_per_sector)%fs2.flash->sector_count; fs2.cursor.slot = fs2.cursor_position%fs2.slots_per_sector; for(i = 0; i < size/STRING_SIZE_HISTORY; i++) { memset(temp_str, 0, 100); log_fetch(&entry, portMAX_DELAY); strncat(temp_str, logsStrShortRu[entry.type], (strlen(logsStrShortRu[entry.type]))); strcat(temp_str, ";"); entry.data[49] = 0; strncat(temp_str, entry.data, (strlen(entry.data))); strcat(temp_str, ";"); TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp); sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month, rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds); strcat(temp_str, buf); len = strlen(temp_str); if (len <= STRING_SIZE_HISTORY - 1) { memset(&temp_str[len], ' ', STRING_SIZE_HISTORY - len - 1); strcat(temp_str, "\n"); } else { temp_str[STRING_SIZE - 1] = 0xa; } strncat(str, temp_str, STRING_SIZE_HISTORY); } return strlen(str); }