log.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. #include "log.h"
  2. #include "rtc.h"
  3. #include "ringfs.h"
  4. #include "spi_flash.h"
  5. #include "FreeRTOS.h"
  6. #include "task.h"
  7. #include "semphr.h"
  8. #include <string.h>
  9. char logFileBuf[FILE_BUF_MAX_LEN];
  10. char name_login[50];
  11. const char* logsStrShortRu[] =
  12. {
  13. "Перезагрузка контроллера",
  14. "Сброс настроек",
  15. "Обновление ПО",
  16. "Включение",
  17. "Смена пароля",
  18. "Сохранение настроек",
  19. "Авторизация",
  20. "Тест ИБП",
  21. "Откл. нагрузки ИБП",
  22. "Авария дискр. входа 1",
  23. "Состояние выхода 1",
  24. "Состояние выхода 2",
  25. "Авария температуры",
  26. "Авария вх. напряжения",
  27. "Низкий заряд АКБ",
  28. "Авария нагрузки",
  29. "Авария связи с ИБП",
  30. "Авария отключения АКБ",
  31. };
  32. bool flUpdateLog = false;
  33. static bool fLogInit = false; // Флаг инициализации журнала
  34. #define LOG_TIME 1000*60*10
  35. #define LOG_FLASH_SECTOR_OFFSET 4
  36. #define ALARM_LOG_FLASH_SECTOR_OFFSET 258
  37. static int op_sector_erase(struct ringfs_flash_partition *flash, int address) {
  38. (void)flash;
  39. int ret;
  40. ret = spi_flash_erase_sector(address, 0);
  41. return ret;
  42. }
  43. static ssize_t op_program(struct ringfs_flash_partition *flash, int address, const void *data, size_t size) {
  44. (void)flash;
  45. int ret;
  46. ret = spi_flash_write(address, data, size, 0);
  47. return ret;
  48. }
  49. static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *data, size_t size) {
  50. (void)flash;
  51. int ret;
  52. ret = spi_flash_read(address, data, size, 0);
  53. return ret;
  54. }
  55. static struct ringfs_flash_partition ringfs_flash = {
  56. .sector_offset = LOG_FLASH_SECTOR_OFFSET,
  57. .sector_erase = op_sector_erase,
  58. .program = op_program,
  59. .read = op_read,
  60. };
  61. static struct ringfs fs;
  62. static struct ringfs_flash_partition ringfs_flash2 = {
  63. .sector_offset = ALARM_LOG_FLASH_SECTOR_OFFSET,
  64. .sector_erase = op_sector_erase,
  65. .program = op_program,
  66. .read = op_read,
  67. };
  68. static struct ringfs fs2;
  69. static SemaphoreHandle_t log_mutex;
  70. /**
  71. * @brief Отключает журнал для безопасной перезагрузки
  72. */
  73. bool LOG_Disable(void)
  74. {
  75. if (fLogInit) {
  76. /* Ожидаем завершения работы с журнал */
  77. if ( xSemaphoreTake(log_mutex, 10000) == pdTRUE ) {
  78. //fLogInit = false;
  79. //xSemaphoreGive(logMutex);
  80. return true;
  81. }
  82. else {
  83. return false;
  84. }
  85. }
  86. else {
  87. return true;
  88. }
  89. }
  90. void log_task(void* params)
  91. {
  92. for(;;){
  93. flUpdateLog = true;
  94. vTaskDelay(LOG_TIME);
  95. /* vTaskDelay(50);
  96. log_event_data(LOG_SYSTEM_BOOT, "Администратор");
  97. log_add(")215.7;215.7;220.5;000;50.1;2.30;25.0;00000001;");*/
  98. }
  99. }
  100. void log_init(bool format) {
  101. DBG printf(">>> Event log\n");
  102. if (!spi_flash_desc.present)
  103. return;
  104. ringfs_flash.sector_size = spi_flash_desc.sector_size;
  105. ringfs_flash.sector_count = spi_flash_desc.sector_count/2 - LOG_FLASH_SECTOR_OFFSET;
  106. ringfs_init(&fs, &ringfs_flash, LOG_ENTRY_VERSION, sizeof(log_entry_t));
  107. if (format || ringfs_scan(&fs) != 0)
  108. ringfs_format(&fs);
  109. ringfs_flash2.sector_size = spi_flash_desc.sector_size;
  110. ringfs_flash2.sector_count = spi_flash_desc.sector_count/2 - LOG_FLASH_SECTOR_OFFSET;
  111. ringfs_init(&fs2, &ringfs_flash2, LOG_ENTRY_VERSION, sizeof(log_entry_t));
  112. if (format || ringfs_scan(&fs2) != 0)
  113. ringfs_format(&fs2);
  114. fLogInit = true;
  115. log_mutex = xSemaphoreCreateMutex();
  116. xTaskCreate(log_task, ( char * ) "log_task", configMINIMAL_STACK_SIZE * 2, NULL, tskIDLE_PRIORITY, NULL);
  117. }
  118. int capacity_flash = 0;
  119. int count_flash = 0;
  120. int log_test(void) {
  121. int ret;
  122. log_entry_t entry;
  123. log_init(false);
  124. capacity_flash = ringfs_capacity(&fs);
  125. count_flash = ringfs_count_exact(&fs);
  126. DBG printf("\tCapacity: %d\n", capacity_flash);
  127. DBG printf("\tCount: %d\n", count_flash);
  128. DBG printf("\tAppending ");
  129. // ret = log_event(LOG_SYSTEM_DEFCONFIG, 0, 0);
  130. DBG printf("%s\n", ret == 0 ? "ok" : "error");
  131. if (ret == 0)
  132. return -1;
  133. // ret = log_event(LOG_SYSTEM_DEFCONFIG, 0, 512);
  134. entry.timestamp = 0;
  135. entry.type = 0;
  136. DBG printf("\tFetching ");
  137. if (log_fetch(&entry, portMAX_DELAY) == 0){
  138. DBG printf("ok, time=%d, type=%d\n", entry.timestamp, entry.type);
  139. log_fetch(&entry, portMAX_DELAY);
  140. entry.timestamp = 0;
  141. entry.type = 0;
  142. log_fetch(&entry, portMAX_DELAY);
  143. entry.timestamp = 0;
  144. entry.type = 0;
  145. log_fetch(&entry, portMAX_DELAY);
  146. entry.timestamp = 0;
  147. entry.type = 0;
  148. log_fetch(&entry, portMAX_DELAY);
  149. return 0;
  150. }
  151. else {
  152. DBG printf("fail\n");
  153. return -1;
  154. }
  155. DBG printf("\tDiscarding ");
  156. if (log_discard(&entry,portMAX_DELAY) == 0)
  157. DBG printf("ok\n");
  158. else {
  159. DBG printf("fail\n");
  160. return -1;
  161. }
  162. return 0;
  163. }
  164. int log_append(log_entry_t *entry) {
  165. int ret;
  166. TM_RTC_t data;
  167. ret = xSemaphoreTake( log_mutex, portMAX_DELAY );
  168. if (ret == pdFALSE)
  169. return ret;
  170. if (!entry->timestamp){
  171. TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);
  172. entry->timestamp = data.unix;
  173. }
  174. if(entry->type == LOG_VALUE)
  175. ringfs_append(&fs, entry);
  176. else
  177. ringfs_append(&fs2, entry);
  178. xSemaphoreGive(log_mutex);
  179. return ret;
  180. }
  181. int log_fetch(log_entry_t *entry, uint32_t timeout) {
  182. int ret;
  183. ret = xSemaphoreTake( log_mutex, (TickType_t)timeout );
  184. if (ret == pdFALSE)
  185. return ret;
  186. if(entry->type == LOG_VALUE)
  187. ret = ringfs_fetch(&fs, entry);
  188. else
  189. ret = ringfs_fetch(&fs2, entry);
  190. xSemaphoreGive(log_mutex);
  191. return ret;
  192. }
  193. int log_rewind(log_entry_t *entry, uint32_t timeout) {
  194. int ret;
  195. ret = xSemaphoreTake( log_mutex, (TickType_t)timeout );
  196. if (ret == pdFALSE)
  197. return ret;
  198. if(entry->type == LOG_VALUE)
  199. ret = ringfs_rewind(&fs);
  200. else
  201. ret = ringfs_rewind(&fs2);
  202. xSemaphoreGive(log_mutex);
  203. return ret;
  204. }
  205. int log_discard(log_entry_t *entry, uint32_t timeout) {
  206. int ret;
  207. ret = xSemaphoreTake( log_mutex, (TickType_t)timeout );
  208. if (ret == pdFALSE)
  209. return ret;
  210. if(entry->type == LOG_VALUE)
  211. ret = ringfs_discard(&fs);
  212. else
  213. ret = ringfs_discard(&fs2);
  214. xSemaphoreGive(log_mutex);
  215. return ret;
  216. }
  217. void log_event_data(log_type_t type, char *data)
  218. {
  219. log_entry_t entry_data;
  220. entry_data.timestamp = 0;
  221. entry_data.type = type;
  222. strncpy(entry_data.data, data, 49);
  223. if (fLogInit)
  224. log_append(&entry_data);
  225. }
  226. void log_add(char *log_data)
  227. {
  228. char buf_value[50];
  229. uint8_t i, len;
  230. memset(buf_value, 0, 50);
  231. len = strlen(log_data);
  232. strncpy(buf_value, log_data, len);
  233. buf_value[0] = '\"';
  234. for(i = 0; i < len; i++)
  235. {
  236. if(buf_value[i] == ' ')
  237. buf_value[i] = ';';
  238. }
  239. buf_value[len - 1] = ';';
  240. if(fLogInit){
  241. if(fs.write.slot>67)
  242. {
  243. log_entry_t entry_data;
  244. entry_data.timestamp = 0;
  245. log_event_data(LOG_VALUE, buf_value);
  246. }
  247. else
  248. log_event_data(LOG_VALUE, buf_value);
  249. }
  250. }
  251. /**
  252. * @brief Возвращает true если журнал проинициализирован
  253. */
  254. bool LOG_IsInit()
  255. {
  256. return fLogInit;
  257. }
  258. /**
  259. * @brief Возвращает общее количество страниц
  260. */
  261. uint32_t LOG_GetPageCount(void)
  262. {
  263. return (((ringfs_count_estimate(&fs)) / 10) + 1);
  264. }
  265. uint32_t LOG_GetTotalSTRCount(void)
  266. {
  267. return ringfs_count_estimate(&fs);
  268. }
  269. void LOG_GetPage(char *str, uint32_t page)
  270. {
  271. TM_RTC_t rtc_data;
  272. log_entry_t entry;
  273. char buf[20];
  274. uint8_t i;
  275. int start =LOG_GetTotalSTRCount();//(fs.write.sector*fs.slots_per_sector + fs.write.slot);
  276. memset(buf, 0, 20);
  277. for(i=0; i < 10; i++){
  278. fs.cursor_position = start - 10*(page-1) - 1 - i;
  279. if(fs.cursor_position < 0)
  280. break;
  281. else{
  282. fs.cursor.sector = (fs.read.sector + fs.cursor_position/fs.slots_per_sector)%fs.flash->sector_count;
  283. fs.cursor.slot = fs.cursor_position%fs.slots_per_sector;
  284. }
  285. entry.type = LOG_VALUE;
  286. log_fetch(&entry, portMAX_DELAY);
  287. entry.data[49] = 0;
  288. strncat(str, entry.data, strlen(entry.data));
  289. TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp);
  290. sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month,
  291. rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds);
  292. strcat(str, buf);
  293. strcat(str, "\",");
  294. }
  295. }
  296. uint32_t LOG_GetData(int ptr, char *str, uint32_t size, bool start)
  297. {
  298. TM_RTC_t rtc_data;
  299. log_entry_t entry;
  300. char buf[20];
  301. uint8_t i;
  302. entry.type = LOG_VALUE;
  303. if(start)
  304. log_rewind(&entry, portMAX_DELAY);
  305. fs.cursor_position = ptr/STRING_SIZE;
  306. fs.cursor.sector = (fs.read.sector + fs.cursor_position/fs.slots_per_sector)%fs.flash->sector_count;
  307. fs.cursor.slot = fs.cursor_position%fs.slots_per_sector;
  308. for(i = 0; i < size/STRING_SIZE; i++)
  309. {
  310. entry.type = LOG_VALUE;
  311. log_fetch(&entry, portMAX_DELAY);
  312. entry.data[49] = 0;
  313. strncat(str, &entry.data[1], (strlen(entry.data) - 1));
  314. TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp);
  315. sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month,
  316. rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds);
  317. strcat(str, buf);
  318. strcat(str, "\n");
  319. }
  320. return strlen(str);
  321. }
  322. /**
  323. * @brief Возвращает общее количество страниц
  324. */
  325. uint32_t History_GetPageCount(void)
  326. {
  327. return (((ringfs_count_estimate(&fs2)) / 10) + 1);
  328. }
  329. uint32_t History_GetTotalSTRCount(void)
  330. {
  331. return ringfs_count_estimate(&fs2);
  332. }
  333. void History_GetPage(char *str, uint32_t page)
  334. {
  335. TM_RTC_t rtc_data;
  336. log_entry_t entry;
  337. char buf[20];
  338. uint8_t i;
  339. int start =History_GetTotalSTRCount();//(fs.write.sector*fs.slots_per_sector + fs.write.slot);
  340. memset(buf, 0, 20);
  341. for(i=0; i < 10; i++){
  342. fs2.cursor_position = start - 10*(page-1) - 1 - i;
  343. if(fs2.cursor_position < 0)
  344. break;
  345. else{
  346. fs2.cursor.sector = (fs2.read.sector + fs2.cursor_position/fs.slots_per_sector)%fs2.flash->sector_count;
  347. fs2.cursor.slot = fs2.cursor_position%fs2.slots_per_sector;
  348. }
  349. entry.type = LOG_LOGIN;
  350. log_fetch(&entry, portMAX_DELAY);
  351. strcat(str, "\"");
  352. strncat(str, logsStrShortRu[entry.type], (strlen(logsStrShortRu[entry.type]) ));
  353. strcat(str, ";");
  354. entry.data[49] = 0;
  355. strncat(str, entry.data, (strlen(entry.data) ));
  356. strcat(str, ";");
  357. TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp);
  358. sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month,
  359. rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds);
  360. strcat(str, buf);
  361. strcat(str, "\",");
  362. }
  363. }
  364. uint32_t History_GetData(int ptr, char *str, uint32_t size, bool start)
  365. {
  366. TM_RTC_t rtc_data;
  367. log_entry_t entry;
  368. char buf[20];
  369. char temp_str[FILE_BUF_MAX_LEN];
  370. uint8_t i;
  371. uint16_t len;
  372. entry.type = LOG_LOGIN;
  373. if(start)
  374. log_rewind(&entry, portMAX_DELAY);
  375. fs2.cursor_position = ptr/STRING_SIZE_HISTORY;
  376. fs2.cursor.sector = (fs2.read.sector + fs2.cursor_position/fs2.slots_per_sector)%fs2.flash->sector_count;
  377. fs2.cursor.slot = fs2.cursor_position%fs2.slots_per_sector;
  378. for(i = 0; i < size/STRING_SIZE_HISTORY; i++)
  379. {
  380. memset(temp_str, 0, 100);
  381. log_fetch(&entry, portMAX_DELAY);
  382. strncat(temp_str, logsStrShortRu[entry.type], (strlen(logsStrShortRu[entry.type])));
  383. strcat(temp_str, ";");
  384. entry.data[49] = 0;
  385. strncat(temp_str, entry.data, (strlen(entry.data)));
  386. strcat(temp_str, ";");
  387. TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp);
  388. sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i", rtc_data.date, rtc_data.month,
  389. rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds);
  390. strcat(temp_str, buf);
  391. len = strlen(temp_str);
  392. if (len <= STRING_SIZE_HISTORY - 1)
  393. {
  394. memset(&temp_str[len], ' ', STRING_SIZE_HISTORY - len - 1);
  395. strcat(temp_str, "\n");
  396. }
  397. else
  398. {
  399. temp_str[STRING_SIZE - 1] = 0xa;
  400. }
  401. strncat(str, temp_str, STRING_SIZE_HISTORY);
  402. }
  403. return strlen(str);
  404. }