acurite_592txr.c 12 KB

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