subghz_protocol_raw.c 8.9 KB

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