log.c 15 KB

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