weather_station_history.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #include "weather_station_history.h"
  2. #include <flipper_format/flipper_format_i.h>
  3. #include <lib/toolbox/stream/stream.h>
  4. #include <lib/subghz/receiver.h>
  5. #include "protocols/ws_generic.h"
  6. #include <furi.h>
  7. #define WS_HISTORY_MAX 50
  8. #define TAG "WSHistory"
  9. typedef struct {
  10. FuriString* item_str;
  11. FlipperFormat* flipper_string;
  12. uint8_t type;
  13. uint32_t id;
  14. SubGhzRadioPreset* preset;
  15. } WSHistoryItem;
  16. ARRAY_DEF(WSHistoryItemArray, WSHistoryItem, M_POD_OPLIST)
  17. #define M_OPL_WSHistoryItemArray_t() ARRAY_OPLIST(WSHistoryItemArray, M_POD_OPLIST)
  18. typedef struct {
  19. WSHistoryItemArray_t data;
  20. } WSHistoryStruct;
  21. struct WSHistory {
  22. uint32_t last_update_timestamp;
  23. uint16_t last_index_write;
  24. uint8_t code_last_hash_data;
  25. FuriString* tmp_string;
  26. WSHistoryStruct* history;
  27. };
  28. WSHistory* ws_history_alloc(void) {
  29. WSHistory* instance = malloc(sizeof(WSHistory));
  30. instance->tmp_string = furi_string_alloc();
  31. instance->history = malloc(sizeof(WSHistoryStruct));
  32. WSHistoryItemArray_init(instance->history->data);
  33. return instance;
  34. }
  35. void ws_history_free(WSHistory* instance) {
  36. furi_assert(instance);
  37. furi_string_free(instance->tmp_string);
  38. for
  39. M_EACH(item, instance->history->data, WSHistoryItemArray_t) {
  40. furi_string_free(item->item_str);
  41. furi_string_free(item->preset->name);
  42. free(item->preset);
  43. flipper_format_free(item->flipper_string);
  44. item->type = 0;
  45. }
  46. WSHistoryItemArray_clear(instance->history->data);
  47. free(instance->history);
  48. free(instance);
  49. }
  50. uint32_t ws_history_get_frequency(WSHistory* instance, uint16_t idx) {
  51. furi_assert(instance);
  52. WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx);
  53. return item->preset->frequency;
  54. }
  55. SubGhzRadioPreset* ws_history_get_radio_preset(WSHistory* instance, uint16_t idx) {
  56. furi_assert(instance);
  57. WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx);
  58. return item->preset;
  59. }
  60. const char* ws_history_get_preset(WSHistory* instance, uint16_t idx) {
  61. furi_assert(instance);
  62. WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx);
  63. return furi_string_get_cstr(item->preset->name);
  64. }
  65. void ws_history_reset(WSHistory* instance) {
  66. furi_assert(instance);
  67. furi_string_reset(instance->tmp_string);
  68. for
  69. M_EACH(item, instance->history->data, WSHistoryItemArray_t) {
  70. furi_string_free(item->item_str);
  71. furi_string_free(item->preset->name);
  72. free(item->preset);
  73. flipper_format_free(item->flipper_string);
  74. item->type = 0;
  75. }
  76. WSHistoryItemArray_reset(instance->history->data);
  77. instance->last_index_write = 0;
  78. instance->code_last_hash_data = 0;
  79. }
  80. uint16_t ws_history_get_item(WSHistory* instance) {
  81. furi_assert(instance);
  82. return instance->last_index_write;
  83. }
  84. uint8_t ws_history_get_type_protocol(WSHistory* instance, uint16_t idx) {
  85. furi_assert(instance);
  86. WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx);
  87. return item->type;
  88. }
  89. const char* ws_history_get_protocol_name(WSHistory* instance, uint16_t idx) {
  90. furi_assert(instance);
  91. WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx);
  92. flipper_format_rewind(item->flipper_string);
  93. if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) {
  94. FURI_LOG_E(TAG, "Missing Protocol");
  95. furi_string_reset(instance->tmp_string);
  96. }
  97. return furi_string_get_cstr(instance->tmp_string);
  98. }
  99. FlipperFormat* ws_history_get_raw_data(WSHistory* instance, uint16_t idx) {
  100. furi_assert(instance);
  101. WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx);
  102. if(item->flipper_string) {
  103. return item->flipper_string;
  104. } else {
  105. return NULL;
  106. }
  107. }
  108. bool ws_history_get_text_space_left(WSHistory* instance, FuriString* output) {
  109. furi_assert(instance);
  110. if(instance->last_index_write == WS_HISTORY_MAX) {
  111. if(output != NULL) furi_string_printf(output, "Memory is FULL");
  112. return true;
  113. }
  114. if(output != NULL)
  115. furi_string_printf(output, "%02u/%02u", instance->last_index_write, WS_HISTORY_MAX);
  116. return false;
  117. }
  118. void ws_history_get_text_item_menu(WSHistory* instance, FuriString* output, uint16_t idx) {
  119. WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx);
  120. furi_string_set(output, item->item_str);
  121. }
  122. WSHistoryStateAddKey
  123. ws_history_add_to_history(WSHistory* instance, void* context, SubGhzRadioPreset* preset) {
  124. furi_assert(instance);
  125. furi_assert(context);
  126. if(instance->last_index_write >= WS_HISTORY_MAX) return WSHistoryStateAddKeyOverflow;
  127. SubGhzProtocolDecoderBase* decoder_base = context;
  128. if((instance->code_last_hash_data ==
  129. subghz_protocol_decoder_base_get_hash_data(decoder_base)) &&
  130. ((furi_get_tick() - instance->last_update_timestamp) < 500)) {
  131. instance->last_update_timestamp = furi_get_tick();
  132. return WSHistoryStateAddKeyTimeOut;
  133. }
  134. instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base);
  135. instance->last_update_timestamp = furi_get_tick();
  136. FlipperFormat* fff = flipper_format_string_alloc();
  137. uint32_t id = 0;
  138. subghz_protocol_decoder_base_serialize(decoder_base, fff, preset);
  139. do {
  140. if(!flipper_format_rewind(fff)) {
  141. FURI_LOG_E(TAG, "Rewind error");
  142. break;
  143. }
  144. if(!flipper_format_read_uint32(fff, "Id", (uint32_t*)&id, 1)) {
  145. FURI_LOG_E(TAG, "Missing Id");
  146. break;
  147. }
  148. } while(false);
  149. flipper_format_free(fff);
  150. //Update record if found
  151. bool sensor_found = false;
  152. for(size_t i = 0; i < WSHistoryItemArray_size(instance->history->data); i++) {
  153. WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, i);
  154. if(item->id == id) {
  155. sensor_found = true;
  156. Stream* flipper_string_stream = flipper_format_get_raw_stream(item->flipper_string);
  157. stream_clean(flipper_string_stream);
  158. subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset);
  159. return WSHistoryStateAddKeyUpdateData;
  160. }
  161. }
  162. // or add new record
  163. if(!sensor_found) { //-V547
  164. WSHistoryItem* item = WSHistoryItemArray_push_raw(instance->history->data);
  165. item->preset = malloc(sizeof(SubGhzRadioPreset));
  166. item->type = decoder_base->protocol->type;
  167. item->preset->frequency = preset->frequency;
  168. item->preset->name = furi_string_alloc();
  169. furi_string_set(item->preset->name, preset->name);
  170. item->preset->data = preset->data;
  171. item->preset->data_size = preset->data_size;
  172. item->id = id;
  173. item->item_str = furi_string_alloc();
  174. item->flipper_string = flipper_format_string_alloc();
  175. subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset);
  176. do {
  177. if(!flipper_format_rewind(item->flipper_string)) {
  178. FURI_LOG_E(TAG, "Rewind error");
  179. break;
  180. }
  181. if(!flipper_format_read_string(
  182. item->flipper_string, "Protocol", instance->tmp_string)) {
  183. FURI_LOG_E(TAG, "Missing Protocol");
  184. break;
  185. }
  186. if(!flipper_format_rewind(item->flipper_string)) {
  187. FURI_LOG_E(TAG, "Rewind error");
  188. break;
  189. }
  190. uint8_t key_data[sizeof(uint64_t)] = {0};
  191. if(!flipper_format_read_hex(item->flipper_string, "Data", key_data, sizeof(uint64_t))) {
  192. FURI_LOG_E(TAG, "Missing Data");
  193. break;
  194. }
  195. uint64_t data = 0;
  196. for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
  197. data = (data << 8) | key_data[i];
  198. }
  199. uint32_t temp_data = 0;
  200. if(!flipper_format_read_uint32(item->flipper_string, "Ch", (uint32_t*)&temp_data, 1)) {
  201. FURI_LOG_E(TAG, "Missing Channel");
  202. break;
  203. }
  204. if(temp_data != WS_NO_CHANNEL) {
  205. furi_string_cat_printf(instance->tmp_string, " Ch:%X", (uint8_t)temp_data);
  206. }
  207. furi_string_printf(
  208. item->item_str, "%s %llX", furi_string_get_cstr(instance->tmp_string), data);
  209. } while(false);
  210. instance->last_index_write++;
  211. return WSHistoryStateAddKeyNewDada;
  212. }
  213. return WSHistoryStateAddKeyUnknown;
  214. }