diff --git a/src/devices/emax.c b/src/devices/emax.c index b41bf1948..c38650351 100644 --- a/src/devices/emax.c +++ b/src/devices/emax.c @@ -16,7 +16,7 @@ /** Fuzhou Emax Electronic W6 Professional Weather Station. Rebrand and devices decoded : -- Emax W6 / WEC-W6 / 3390TX W6 / EM3390W6 +- Emax W6 / WEC-W6 / 3390TX W6 / EM3390W6 / EM3551H - Altronics x7063/4 - Optex 990040 / 990050 / 990051 / SM-040 - Infactory FWS-1200 @@ -26,7 +26,7 @@ Rebrand and devices decoded : - Protmex PT3390A - Jula Marquant 014331 weather station /014332 temp hum sensor -S.a. issue #2000 #2299 #2326 PR #2300 +S.a. issue #2000 #2299 #2326 #2373 PR #2300 #2346 #2374 - Likely a rebranded device, sold by Altronics - Data length is 32 bytes with a preamble of 10 bytes (33 bytes for Rain/Wind Station) @@ -64,10 +64,14 @@ Decoded example: aaa CH:1 ID:6e9 FLAGS:0101 TEMP:6b5 HUM:059 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa CHKSUM:d4 000 -Emax EM3390W6 Rain / Wind speed / Wind Direction / Temp / Hum / UV / Lux +Emax Rain / Wind speed / Wind Direction / Temp / Hum / UV / Lux + +Weather Rain/Wind station : humidity not at same byte position as temp/hum sensor. +- With UV Lux without Wind Gust + AA 04 II IB 0T TT HH 0W WW 0D DD RR RR UU LL LL 04 05 06 07 08 09 10 11 12 13 14 15 16 17 xx SS yy +- Without UV / Lux , with Wind Gust + AA 04 II IB 0T TT HH 0W WW 0D DD RR RR ?0 01 01 GG 04 05 06 07 08 09 10 11 12 13 14 15 16 xx SS yy -Weather Rain/Wind station : hummidity not at same byte position. - AA 04 II IB 0T TT HH 0W WW 0D DD RR RR 0U LL LL 04 05 06 07 08 09 10 11 12 13 14 15 16 17 xx SS yy default empty/null = 0x01 => value = 0 @@ -82,6 +86,8 @@ default empty/null = 0x01 => value = 0 - D: (9 bit) Wind Direction - U: (5 bit) UV index - L: (1 + 15 bit) Lux value, if first bit = 1 , then x 10 the rest. +- G: (8 bit) Wind Gust +- ?: unknown - A: (4 bit) fixed values of 0xA - 0: (4 bit) fixed values of 0x0 - xx: incremental value each tx @@ -184,36 +190,60 @@ static int emax_decode(r_device *decoder, bitbuffer_t *bitbuffer) int direction_deg = (((b[9] - 1) & 0x0f) << 8) | (b[10] - 1); int rain_raw = ((b[11] - 1) << 8 ) | (b[12] -1); float rain_mm = rain_raw * 0.2f; - int uv_index = (b[13] - 1) & 0x1f; - int lux_14 = (b[14] - 1) & 0xFF; - int lux_15 = (b[15] - 1) & 0xFF; - int lux_multi = ((lux_14 & 0x80) >> 7); - int light_lux = ((lux_14 & 0x7f) << 8) | (lux_15); - if (lux_multi == 1) { - light_lux = light_lux * 10; - } - - /* clang-format off */ - data_t *data = data_make( - "model", "", DATA_STRING, "Emax-W6", - "id", "", DATA_FORMAT, "%03x", DATA_INT, id, - "channel", "Channel", DATA_INT, channel, - "battery_ok", "Battery_OK", DATA_INT, !battery_low, - "temperature_F", "Temperature", DATA_FORMAT, "%.1f F", DATA_DOUBLE, temp_f, - "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity, - "wind_avg_km_h", "Wind avg speed", DATA_FORMAT, "%.1f km/h", DATA_DOUBLE, speed_kmh, - "wind_dir_deg", "Wind Direction", DATA_INT, direction_deg, - "rain_mm", "Total rainfall", DATA_FORMAT, "%.1f mm", DATA_DOUBLE, rain_mm, - "uv", "UV Index", DATA_FORMAT, "%u", DATA_INT, uv_index, - "light_lux", "Lux", DATA_FORMAT, "%u", DATA_INT, light_lux, - "pairing", "Pairing?", DATA_COND, pairing, DATA_INT, !!pairing, - "mic", "Integrity", DATA_STRING, "CHECKSUM", - NULL); - /* clang-format on */ - - decoder_output_data(decoder, data); - return 1; + if (b[29] == 0x17) { // with UV/Lux, without Wind Gust + int uv_index = (b[13] - 1) & 0x1f; + int lux_14 = (b[14] - 1) & 0xFF; + int lux_15 = (b[15] - 1) & 0xFF; + int lux_multi = ((lux_14 & 0x80) >> 7); + int light_lux = ((lux_14 & 0x7f) << 8) | (lux_15); + if (lux_multi == 1) { + light_lux = light_lux * 10; + } + + /* clang-format off */ + data_t *data = data_make( + "model", "", DATA_STRING, "Emax-W6", + "id", "", DATA_FORMAT, "%03x", DATA_INT, id, + "channel", "Channel", DATA_INT, channel, + "battery_ok", "Battery_OK", DATA_INT, !battery_low, + "temperature_F", "Temperature", DATA_FORMAT, "%.1f F", DATA_DOUBLE, temp_f, + "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity, + "wind_avg_km_h", "Wind avg speed", DATA_FORMAT, "%.1f km/h", DATA_DOUBLE, speed_kmh, + "wind_dir_deg", "Wind Direction", DATA_INT, direction_deg, + "rain_mm", "Total rainfall", DATA_FORMAT, "%.1f mm", DATA_DOUBLE, rain_mm, + "uv", "UV Index", DATA_FORMAT, "%u", DATA_INT, uv_index, + "light_lux", "Lux", DATA_FORMAT, "%u", DATA_INT, light_lux, + "pairing", "Pairing?", DATA_COND, pairing, DATA_INT, !!pairing, + "mic", "Integrity", DATA_STRING, "CHECKSUM", + NULL); + /* clang-format on */ + + decoder_output_data(decoder, data); + return 1; + } + if (b[29] == 0x16) { //without UV/Lux with Wind Gust + float gust_kmh = b[16] / 1.5f; + /* clang-format off */ + data_t *data = data_make( + "model", "", DATA_STRING, "Emax-EM3551H", + "id", "", DATA_FORMAT, "%03x", DATA_INT, id, + "channel", "Channel", DATA_INT, channel, + "battery_ok", "Battery_OK", DATA_INT, !battery_low, + "temperature_F", "Temperature", DATA_FORMAT, "%.1f F", DATA_DOUBLE, temp_f, + "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity, + "wind_avg_km_h", "Wind avg speed", DATA_FORMAT, "%.1f km/h", DATA_DOUBLE, speed_kmh, + "wind_max_km_h", "Wind max speed", DATA_FORMAT, "%.1f km/h", DATA_DOUBLE, gust_kmh, + "wind_dir_deg", "Wind Direction", DATA_INT, direction_deg, + "rain_mm", "Total rainfall", DATA_FORMAT, "%.1f mm", DATA_DOUBLE, rain_mm, + "pairing", "Pairing?", DATA_COND, pairing, DATA_INT, !!pairing, + "mic", "Integrity", DATA_STRING, "CHECKSUM", + NULL); + /* clang-format on */ + + decoder_output_data(decoder, data); + return 1; + } } pos += EMAX_MESSAGE_BITLEN; } @@ -228,6 +258,7 @@ static char *output_fields[] = { "temperature_F", "humidity", "wind_avg_km_h", + "wind_max_km_h", "rain_mm", "wind_dir_deg", "uv",