subghz_protocol_raw.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #include "subghz_protocol_raw.h"
  2. #include "../subghz_file_encoder_worker.h"
  3. #define TAG "SubGhzRaw"
  4. #define SUBGHZ_DOWNLOAD_MAX_SIZE 512
  5. struct SubGhzProtocolRAW {
  6. SubGhzProtocolCommon common;
  7. int32_t* upload_raw;
  8. uint16_t ind_write;
  9. Storage* storage;
  10. FlipperFile* flipper_file;
  11. SubGhzFileEncoderWorker* file_worker_encoder;
  12. uint32_t file_is_open;
  13. string_t file_name;
  14. size_t sample_write;
  15. bool last_level;
  16. };
  17. typedef enum {
  18. RAWFileIsOpenClose = 0,
  19. RAWFileIsOpenWrite,
  20. RAWFileIsOpenRead,
  21. } RAWFilIsOpen;
  22. SubGhzProtocolRAW* subghz_protocol_raw_alloc(void) {
  23. SubGhzProtocolRAW* instance = furi_alloc(sizeof(SubGhzProtocolRAW));
  24. instance->upload_raw = NULL;
  25. instance->ind_write = 0;
  26. instance->last_level = false;
  27. instance->storage = furi_record_open("storage");
  28. instance->flipper_file = flipper_file_alloc(instance->storage);
  29. instance->file_is_open = RAWFileIsOpenClose;
  30. string_init(instance->file_name);
  31. instance->common.name = "RAW";
  32. instance->common.code_min_count_bit_for_found = 0;
  33. instance->common.te_short = 80;
  34. instance->common.te_long = 32700;
  35. instance->common.te_delta = 0;
  36. instance->common.type_protocol = SubGhzProtocolCommonTypeRAW;
  37. instance->common.to_load_protocol_from_file =
  38. (SubGhzProtocolCommonLoadFromFile)subghz_protocol_raw_to_load_protocol_from_file;
  39. instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_raw_to_str;
  40. //instance->common.to_load_protocol =
  41. // (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_raw_to_load_protocol;
  42. instance->common.get_upload_protocol =
  43. (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_raw_send_key;
  44. return instance;
  45. }
  46. void subghz_protocol_raw_free(SubGhzProtocolRAW* instance) {
  47. furi_assert(instance);
  48. string_clear(instance->file_name);
  49. flipper_file_free(instance->flipper_file);
  50. furi_record_close("storage");
  51. free(instance);
  52. }
  53. void subghz_protocol_raw_file_encoder_worker_stop(void* context) {
  54. furi_assert(context);
  55. SubGhzProtocolRAW* instance = context;
  56. if(subghz_file_encoder_worker_is_running(instance->file_worker_encoder)) {
  57. subghz_file_encoder_worker_stop(instance->file_worker_encoder);
  58. subghz_file_encoder_worker_free(instance->file_worker_encoder);
  59. instance->file_is_open = RAWFileIsOpenClose;
  60. }
  61. }
  62. bool subghz_protocol_raw_send_key(
  63. SubGhzProtocolRAW* instance,
  64. SubGhzProtocolCommonEncoder* encoder) {
  65. furi_assert(instance);
  66. furi_assert(encoder);
  67. bool loaded = false;
  68. instance->file_worker_encoder = subghz_file_encoder_worker_alloc();
  69. if(subghz_file_encoder_worker_start(
  70. instance->file_worker_encoder, string_get_cstr(instance->file_name))) {
  71. //the worker needs a file in order to open and read part of the file
  72. osDelay(100);
  73. instance->file_is_open = RAWFileIsOpenRead;
  74. subghz_protocol_encoder_common_set_callback(
  75. encoder, subghz_file_encoder_worker_get_level_duration, instance->file_worker_encoder);
  76. subghz_protocol_encoder_common_set_callback_end(
  77. encoder, subghz_protocol_raw_file_encoder_worker_stop, instance);
  78. loaded = true;
  79. } else {
  80. subghz_protocol_raw_file_encoder_worker_stop(instance);
  81. }
  82. return loaded;
  83. }
  84. void subghz_protocol_raw_reset(SubGhzProtocolRAW* instance) {
  85. instance->ind_write = 0;
  86. }
  87. void subghz_protocol_raw_parse(SubGhzProtocolRAW* instance, bool level, uint32_t duration) {
  88. if(instance->upload_raw != NULL) {
  89. if(duration > instance->common.te_short) {
  90. if(duration > instance->common.te_long) duration = instance->common.te_long;
  91. if(instance->last_level != level) {
  92. instance->last_level = (level ? true : false);
  93. instance->upload_raw[instance->ind_write++] = (level ? duration : -duration);
  94. }
  95. }
  96. if(instance->ind_write == SUBGHZ_DOWNLOAD_MAX_SIZE) {
  97. subghz_protocol_raw_save_to_file_write(instance);
  98. }
  99. }
  100. }
  101. void subghz_protocol_raw_to_str(SubGhzProtocolRAW* instance, string_t output) {
  102. string_cat_printf(output, "RAW Date");
  103. }
  104. const char* subghz_protocol_raw_get_last_file_name(SubGhzProtocolRAW* instance) {
  105. return string_get_cstr(instance->file_name);
  106. }
  107. void subghz_protocol_raw_set_last_file_name(SubGhzProtocolRAW* instance, const char* name) {
  108. string_printf(instance->file_name, "%s", name);
  109. }
  110. bool subghz_protocol_raw_save_to_file_init(
  111. SubGhzProtocolRAW* instance,
  112. const char* dev_name,
  113. uint32_t frequency,
  114. const char* preset) {
  115. furi_assert(instance);
  116. //instance->flipper_file = flipper_file_alloc(instance->storage);
  117. string_t dev_file_name;
  118. string_init(dev_file_name);
  119. bool init = false;
  120. do {
  121. // Create subghz folder directory if necessary
  122. if(!storage_simply_mkdir(instance->storage, SUBGHZ_RAW_FOLDER)) {
  123. break;
  124. }
  125. // Create saved directory if necessary
  126. if(!storage_simply_mkdir(instance->storage, SUBGHZ_RAW_PATH_FOLDER)) {
  127. break;
  128. }
  129. string_set(instance->file_name, dev_name);
  130. // First remove subghz device file if it was saved
  131. string_printf(
  132. dev_file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, dev_name, SUBGHZ_APP_EXTENSION);
  133. if(!storage_simply_remove(instance->storage, string_get_cstr(dev_file_name))) {
  134. break;
  135. }
  136. // Open file
  137. if(!flipper_file_open_always(instance->flipper_file, string_get_cstr(dev_file_name))) {
  138. FURI_LOG_E(TAG, "Unable to open file for write: %s", dev_file_name);
  139. break;
  140. }
  141. if(!flipper_file_write_header_cstr(
  142. instance->flipper_file, SUBGHZ_RAW_FILE_TYPE, SUBGHZ_RAW_FILE_VERSION)) {
  143. FURI_LOG_E(TAG, "Unable to add header");
  144. break;
  145. }
  146. if(!flipper_file_write_uint32(instance->flipper_file, "Frequency", &frequency, 1)) {
  147. FURI_LOG_E(TAG, "Unable to add Frequency");
  148. break;
  149. }
  150. if(!flipper_file_write_string_cstr(instance->flipper_file, "Preset", preset)) {
  151. FURI_LOG_E(TAG, "Unable to add Preset");
  152. break;
  153. }
  154. if(!flipper_file_write_string_cstr(instance->flipper_file, "Protocol", instance->common.name)) {
  155. FURI_LOG_E(TAG, "Unable to add Protocol");
  156. break;
  157. }
  158. instance->upload_raw = furi_alloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(int32_t));
  159. instance->file_is_open = RAWFileIsOpenWrite;
  160. instance->sample_write = 0;
  161. init = true;
  162. } while(0);
  163. string_clear(dev_file_name);
  164. return init;
  165. }
  166. void subghz_protocol_raw_save_to_file_stop(SubGhzProtocolRAW* instance) {
  167. furi_assert(instance);
  168. if(instance->file_is_open == RAWFileIsOpenWrite && instance->ind_write)
  169. subghz_protocol_raw_save_to_file_write(instance);
  170. if(instance->file_is_open != RAWFileIsOpenClose) {
  171. free(instance->upload_raw);
  172. instance->upload_raw = NULL;
  173. }
  174. flipper_file_close(instance->flipper_file);
  175. instance->file_is_open = RAWFileIsOpenClose;
  176. }
  177. bool subghz_protocol_raw_save_to_file_write(SubGhzProtocolRAW* instance) {
  178. furi_assert(instance);
  179. bool is_write = false;
  180. if(instance->file_is_open == RAWFileIsOpenWrite) {
  181. if(!flipper_file_write_int32(
  182. instance->flipper_file, "RAW_Data", instance->upload_raw, instance->ind_write)) {
  183. FURI_LOG_E(TAG, "Unable to add RAW_Data");
  184. } else {
  185. instance->sample_write += instance->ind_write;
  186. instance->ind_write = 0;
  187. is_write = true;
  188. }
  189. }
  190. return is_write;
  191. }
  192. size_t subghz_protocol_raw_get_sample_write(SubGhzProtocolRAW* instance) {
  193. return instance->sample_write + instance->ind_write;
  194. }
  195. bool subghz_protocol_raw_to_load_protocol_from_file(
  196. FlipperFile* flipper_file,
  197. SubGhzProtocolRAW* instance,
  198. const char* file_path) {
  199. furi_assert(file_path);
  200. subghz_protocol_raw_set_last_file_name(instance, file_path);
  201. return true;
  202. }