acurite_5n1.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #include "acurite_5n1.h"
  2. #define TAG "WSProtocolAcurite_5n1"
  3. /*
  4. * Help
  5. * https://github.com/merbanan/rtl_433/blob/master/src/devices/acurite.c
  6. *
  7. * Acurite 5n1 Wind Speed Temperature Humidity sensor decoder
  8. * Message Type 0x38, 8 bytes
  9. * | Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
  10. * | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- |
  11. * | CCII IIII | IIII IIII | pB11 1000 | p??W WWWW | pWWW TTTT | pTTT TTTT | pHHH HHHH | KKKK KKKK |
  12. * - C: Channel 00: C, 10: B, 11: A, (01 is invalid)
  13. * - I: Device ID (14 bits)
  14. * - B: Battery, 1 is battery OK, 0 is battery low
  15. * - M: Message type (6 bits), 0x38
  16. * - W: Wind Speed (8 bits)
  17. * - T: Temperature Fahrenheit (11 bits), + 400 * 10
  18. * - H: Relative Humidity (%) (7 bits)
  19. * - K: Checksum (8 bits)
  20. * - p: Parity bit
  21. * Notes:
  22. * - Temperature
  23. * - Encoded as Fahrenheit + 400 * 10
  24. * - only 11 bits needed for specified range -40 F - 158 F (-40 C to 70 C)
  25. *
  26. */
  27. static const SubGhzBlockConst ws_protocol_acurite_5n1_const = {
  28. .te_short = 200,
  29. .te_long = 400,
  30. .te_delta = 90,
  31. .min_count_bit_for_found = 64,
  32. };
  33. struct WSProtocolDecoderAcurite_5n1 {
  34. SubGhzProtocolDecoderBase base;
  35. SubGhzBlockDecoder decoder;
  36. WSBlockGeneric generic;
  37. uint16_t header_count;
  38. };
  39. struct WSProtocolEncoderAcurite_5n1 {
  40. SubGhzProtocolEncoderBase base;
  41. SubGhzProtocolBlockEncoder encoder;
  42. WSBlockGeneric generic;
  43. };
  44. typedef enum {
  45. Acurite_5n1DecoderStepReset = 0,
  46. Acurite_5n1DecoderStepCheckPreambule,
  47. Acurite_5n1DecoderStepSaveDuration,
  48. Acurite_5n1DecoderStepCheckDuration,
  49. } Acurite_5n1DecoderStep;
  50. const SubGhzProtocolDecoder ws_protocol_acurite_5n1_decoder = {
  51. .alloc = ws_protocol_decoder_acurite_5n1_alloc,
  52. .free = ws_protocol_decoder_acurite_5n1_free,
  53. .feed = ws_protocol_decoder_acurite_5n1_feed,
  54. .reset = ws_protocol_decoder_acurite_5n1_reset,
  55. .get_hash_data = ws_protocol_decoder_acurite_5n1_get_hash_data,
  56. .serialize = ws_protocol_decoder_acurite_5n1_serialize,
  57. .deserialize = ws_protocol_decoder_acurite_5n1_deserialize,
  58. .get_string = ws_protocol_decoder_acurite_5n1_get_string,
  59. };
  60. const SubGhzProtocolEncoder ws_protocol_acurite_5n1_encoder = {
  61. .alloc = NULL,
  62. .free = NULL,
  63. .deserialize = NULL,
  64. .stop = NULL,
  65. .yield = NULL,
  66. };
  67. const SubGhzProtocol ws_protocol_acurite_5n1 = {
  68. .name = WS_PROTOCOL_ACURITE_5N1_NAME,
  69. .type = SubGhzProtocolWeatherStation,
  70. .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
  71. SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
  72. .decoder = &ws_protocol_acurite_5n1_decoder,
  73. .encoder = &ws_protocol_acurite_5n1_encoder,
  74. };
  75. void* ws_protocol_decoder_acurite_5n1_alloc(SubGhzEnvironment* environment) {
  76. UNUSED(environment);
  77. WSProtocolDecoderAcurite_5n1* instance = malloc(sizeof(WSProtocolDecoderAcurite_5n1));
  78. instance->base.protocol = &ws_protocol_acurite_5n1;
  79. instance->generic.protocol_name = instance->base.protocol->name;
  80. return instance;
  81. }
  82. void ws_protocol_decoder_acurite_5n1_free(void* context) {
  83. furi_assert(context);
  84. WSProtocolDecoderAcurite_5n1* instance = context;
  85. free(instance);
  86. }
  87. void ws_protocol_decoder_acurite_5n1_reset(void* context) {
  88. furi_assert(context);
  89. WSProtocolDecoderAcurite_5n1* instance = context;
  90. instance->decoder.parser_step = Acurite_5n1DecoderStepReset;
  91. }
  92. static bool ws_protocol_acurite_5n1_check_crc(WSProtocolDecoderAcurite_5n1* instance) {
  93. uint8_t msg[] = {
  94. instance->decoder.decode_data >> 56,
  95. instance->decoder.decode_data >> 48,
  96. instance->decoder.decode_data >> 40,
  97. instance->decoder.decode_data >> 32,
  98. instance->decoder.decode_data >> 24,
  99. instance->decoder.decode_data >> 16,
  100. instance->decoder.decode_data >> 8};
  101. if((subghz_protocol_blocks_add_bytes(msg, 7) ==
  102. (uint8_t)(instance->decoder.decode_data & 0xFF)) &&
  103. (!subghz_protocol_blocks_parity_bytes(&msg[2], 5))) {
  104. return true;
  105. } else {
  106. return false;
  107. }
  108. }
  109. static bool ws_protocol_acurite_5n1_check_message_type(WSProtocolDecoderAcurite_5n1* instance) {
  110. if(((instance->decoder.decode_data >> 40) & 0x3F) == 0x38) {
  111. return true;
  112. } else {
  113. return false;
  114. }
  115. }
  116. /**
  117. * Analysis of received data
  118. * @param instance Pointer to a WSBlockGeneric* instance
  119. */
  120. static void ws_protocol_acurite_5n1_remote_controller(WSBlockGeneric* instance) {
  121. uint8_t channel[] = {3, 0, 2, 1};
  122. uint8_t channel_raw = ((instance->data >> 62) & 0x03);
  123. instance->channel = channel[channel_raw];
  124. instance->id = (instance->data >> 48) & 0x3FFF;
  125. instance->battery_low = !((instance->data >> 46) & 1);
  126. instance->humidity = (instance->data >> 8) & 0x7F;
  127. uint16_t temp_raw = ((instance->data >> (24 - 7)) & 0x780) | ((instance->data >> 16) & 0x7F);
  128. instance->temp = locale_fahrenheit_to_celsius(((float)(temp_raw)-400) / 10.0f);
  129. instance->btn = WS_NO_BTN;
  130. }
  131. void ws_protocol_decoder_acurite_5n1_feed(void* context, bool level, uint32_t duration) {
  132. furi_assert(context);
  133. WSProtocolDecoderAcurite_5n1* instance = context;
  134. switch(instance->decoder.parser_step) {
  135. case Acurite_5n1DecoderStepReset:
  136. if((level) && (DURATION_DIFF(duration, ws_protocol_acurite_5n1_const.te_short * 3) <
  137. ws_protocol_acurite_5n1_const.te_delta * 2)) {
  138. instance->decoder.parser_step = Acurite_5n1DecoderStepCheckPreambule;
  139. instance->decoder.te_last = duration;
  140. instance->header_count = 0;
  141. }
  142. break;
  143. case Acurite_5n1DecoderStepCheckPreambule:
  144. if(level) {
  145. instance->decoder.te_last = duration;
  146. } else {
  147. if((DURATION_DIFF(
  148. instance->decoder.te_last, ws_protocol_acurite_5n1_const.te_short * 3) <
  149. ws_protocol_acurite_5n1_const.te_delta * 2) &&
  150. (DURATION_DIFF(duration, ws_protocol_acurite_5n1_const.te_short * 3) <
  151. ws_protocol_acurite_5n1_const.te_delta * 2)) {
  152. //Found preambule
  153. instance->header_count++;
  154. } else if((instance->header_count > 2) && (instance->header_count < 5)) {
  155. if((DURATION_DIFF(
  156. instance->decoder.te_last, ws_protocol_acurite_5n1_const.te_short) <
  157. ws_protocol_acurite_5n1_const.te_delta) &&
  158. (DURATION_DIFF(duration, ws_protocol_acurite_5n1_const.te_long) <
  159. ws_protocol_acurite_5n1_const.te_delta)) {
  160. instance->decoder.decode_data = 0;
  161. instance->decoder.decode_count_bit = 0;
  162. subghz_protocol_blocks_add_bit(&instance->decoder, 0);
  163. instance->decoder.parser_step = Acurite_5n1DecoderStepSaveDuration;
  164. } else if(
  165. (DURATION_DIFF(
  166. instance->decoder.te_last, ws_protocol_acurite_5n1_const.te_long) <
  167. ws_protocol_acurite_5n1_const.te_delta) &&
  168. (DURATION_DIFF(duration, ws_protocol_acurite_5n1_const.te_short) <
  169. ws_protocol_acurite_5n1_const.te_delta)) {
  170. instance->decoder.decode_data = 0;
  171. instance->decoder.decode_count_bit = 0;
  172. subghz_protocol_blocks_add_bit(&instance->decoder, 1);
  173. instance->decoder.parser_step = Acurite_5n1DecoderStepSaveDuration;
  174. } else {
  175. instance->decoder.parser_step = Acurite_5n1DecoderStepReset;
  176. }
  177. } else {
  178. instance->decoder.parser_step = Acurite_5n1DecoderStepReset;
  179. }
  180. }
  181. break;
  182. case Acurite_5n1DecoderStepSaveDuration:
  183. if(level) {
  184. instance->decoder.te_last = duration;
  185. instance->decoder.parser_step = Acurite_5n1DecoderStepCheckDuration;
  186. } else {
  187. instance->decoder.parser_step = Acurite_5n1DecoderStepReset;
  188. }
  189. break;
  190. case Acurite_5n1DecoderStepCheckDuration:
  191. if(!level) {
  192. if(duration >= ((uint32_t)ws_protocol_acurite_5n1_const.te_short * 5)) {
  193. if((instance->decoder.decode_count_bit ==
  194. ws_protocol_acurite_5n1_const.min_count_bit_for_found) &&
  195. ws_protocol_acurite_5n1_check_crc(instance) &&
  196. ws_protocol_acurite_5n1_check_message_type(instance)) {
  197. instance->generic.data = instance->decoder.decode_data;
  198. instance->generic.data_count_bit = instance->decoder.decode_count_bit;
  199. ws_protocol_acurite_5n1_remote_controller(&instance->generic);
  200. if(instance->base.callback)
  201. instance->base.callback(&instance->base, instance->base.context);
  202. }
  203. instance->decoder.decode_data = 0;
  204. instance->decoder.decode_count_bit = 0;
  205. instance->decoder.parser_step = Acurite_5n1DecoderStepReset;
  206. break;
  207. } else if(
  208. (DURATION_DIFF(instance->decoder.te_last, ws_protocol_acurite_5n1_const.te_short) <
  209. ws_protocol_acurite_5n1_const.te_delta) &&
  210. (DURATION_DIFF(duration, ws_protocol_acurite_5n1_const.te_long) <
  211. ws_protocol_acurite_5n1_const.te_delta)) {
  212. subghz_protocol_blocks_add_bit(&instance->decoder, 0);
  213. instance->decoder.parser_step = Acurite_5n1DecoderStepSaveDuration;
  214. } else if(
  215. (DURATION_DIFF(instance->decoder.te_last, ws_protocol_acurite_5n1_const.te_long) <
  216. ws_protocol_acurite_5n1_const.te_delta) &&
  217. (DURATION_DIFF(duration, ws_protocol_acurite_5n1_const.te_short) <
  218. ws_protocol_acurite_5n1_const.te_delta)) {
  219. subghz_protocol_blocks_add_bit(&instance->decoder, 1);
  220. instance->decoder.parser_step = Acurite_5n1DecoderStepSaveDuration;
  221. } else {
  222. instance->decoder.parser_step = Acurite_5n1DecoderStepReset;
  223. }
  224. } else {
  225. instance->decoder.parser_step = Acurite_5n1DecoderStepReset;
  226. }
  227. break;
  228. }
  229. }
  230. uint8_t ws_protocol_decoder_acurite_5n1_get_hash_data(void* context) {
  231. furi_assert(context);
  232. WSProtocolDecoderAcurite_5n1* instance = context;
  233. return subghz_protocol_blocks_get_hash_data(
  234. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  235. }
  236. SubGhzProtocolStatus ws_protocol_decoder_acurite_5n1_serialize(
  237. void* context,
  238. FlipperFormat* flipper_format,
  239. SubGhzRadioPreset* preset) {
  240. furi_assert(context);
  241. WSProtocolDecoderAcurite_5n1* instance = context;
  242. return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
  243. }
  244. SubGhzProtocolStatus
  245. ws_protocol_decoder_acurite_5n1_deserialize(void* context, FlipperFormat* flipper_format) {
  246. furi_assert(context);
  247. WSProtocolDecoderAcurite_5n1* instance = context;
  248. return ws_block_generic_deserialize_check_count_bit(
  249. &instance->generic, flipper_format, ws_protocol_acurite_5n1_const.min_count_bit_for_found);
  250. }
  251. void ws_protocol_decoder_acurite_5n1_get_string(void* context, FuriString* output) {
  252. furi_assert(context);
  253. WSProtocolDecoderAcurite_5n1* instance = context;
  254. furi_string_printf(
  255. output,
  256. "%s %dbit\r\n"
  257. "Key:0x%lX%08lX\r\n"
  258. "Sn:0x%lX Ch:%d Bat:%d\r\n"
  259. "Temp:%3.1f C Hum:%d%%",
  260. instance->generic.protocol_name,
  261. instance->generic.data_count_bit,
  262. (uint32_t)(instance->generic.data >> 32),
  263. (uint32_t)(instance->generic.data),
  264. instance->generic.id,
  265. instance->generic.channel,
  266. instance->generic.battery_low,
  267. (double)instance->generic.temp,
  268. instance->generic.humidity);
  269. }