From 87361a86a9c1e1e9f0cc83f6fd49acae4e23c0a3 Mon Sep 17 00:00:00 2001 From: Matthias Prinke Date: Sun, 19 Nov 2023 21:21:49 +0100 Subject: [PATCH 1/4] Restructured data generation and encoding --- SensorTransmitter.ino | 524 +++++++++++++++++++++++------------------- 1 file changed, 285 insertions(+), 239 deletions(-) diff --git a/SensorTransmitter.ino b/SensorTransmitter.ino index 823e77c..46f5d10 100644 --- a/SensorTransmitter.ino +++ b/SensorTransmitter.ino @@ -119,74 +119,159 @@ int count = 0; WeatherSensor ws; -// -// From from rtl_433 project - https://github.com/merbanan/rtl_433/blob/master/src/devices/bresser_5in1.c (20220212) -// -// Example input data: -// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 -// EA EC 7F EB 5F EE EF FA FE 76 BB FA FF 15 13 80 14 A0 11 10 05 01 89 44 05 00 -// CC CC CC CC CC CC CC CC CC CC CC CC CC uu II sS GG DG WW W TT T HH RR RR Bt -// - C = Check, inverted data of 13 byte further -// - uu = checksum (number/count of set bits within bytes 14-25) -// - I = station ID (maybe) -// - G = wind gust in 1/10 m/s, normal binary coded, GGxG = 0x76D1 => 0x0176 = 256 + 118 = 374 => 37.4 m/s. MSB is out of sequence. -// - D = wind direction 0..F = N..NNE..E..S..W..NNW -// - W = wind speed in 1/10 m/s, BCD coded, WWxW = 0x7512 => 0x0275 = 275 => 27.5 m/s. MSB is out of sequence. -// - T = temperature in 1/10 °C, BCD coded, TTxT = 1203 => 31.2 °C -// - t = temperature sign, minus if unequal 0 -// - H = humidity in percent, BCD coded, HH = 23 => 23 % -// - R = rain in mm, BCD coded, RRRR = 1203 => 031.2 mm -// - B = Battery. 0=Ok, 8=Low. -// - s = startup, 0 after power-on/reset / 8 after 1 hour -// - S = sensor type, only low nibble used, 0x9 for Bresser Professional Rain Gauge -uint8_t encodeBresser5In1Payload(String msg_str, uint8_t *msg) +int msgBegin(uint8_t *msg) { uint8_t preamble[] = {0xAA, 0xAA, 0xAA, 0xAA}; uint8_t syncword[] = {0x2D, 0xD4}; - char buf[7]; - memcpy(msg, preamble, 4); - memcpy(&msg[4], syncword, 2); + memcpy(msg, preamble, sizeof(preamble)); + memcpy(&msg[sizeof(preamble)], syncword, sizeof(syncword)); + + return sizeof(preamble) + sizeof(syncword); +} #if defined(DATA_RAW) - uint8_t payload[] = {0xEA, 0xEC, 0x7F, 0xEB, 0x5F, 0xEE, 0xEF, 0xFA, 0xFE, 0x76, 0xBB, 0xFA, 0xFF, - 0x15, 0x13, 0x80, 0x14, 0xA0, 0x11, 0x10, 0x05, 0x01, 0x89, 0x44, 0x05, 0x00}; +uint8_t rawPayload(Encoders encoder, uint8_t *msg) +{ + uint8_t payload_5in1[] = {0xEA, 0xEC, 0x7F, 0xEB, 0x5F, 0xEE, 0xEF, 0xFA, 0xFE, 0x76, 0xBB, 0xFA, 0xFF, + 0x15, 0x13, 0x80, 0x14, 0xA0, 0x11, 0x10, 0x05, 0x01, 0x89, 0x44, 0x05, 0x00}; + uint8_t payload_6in1[] = {0x2A, 0xAF, 0x21, 0x10, 0x34, 0x27, 0x18, 0xFF, 0xAA, 0xFF, 0x29, 0x28, 0xFF, + 0xBB, 0x89, 0xFF, 0x01, 0x1F}; + uint8_t payload_7in1[] = {0xC4, 0xD6, 0x3A, 0xC5, 0xBD, 0xFA, 0x18, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFC, + 0xAA, 0x98, 0xDA, 0x89, 0xA3, 0x2F, 0xEC, 0xAF, 0x9A, 0xAA, 0xAA, 0xAA, 0x00}; + uint8_t payload_lightning[] = {0x73, 0x69, 0xB5, 0x08, 0xAA, 0xA2, 0x90, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t payload_leakage[] = {0xB3, 0xDA, 0x55, 0x57, 0x17, 0x40, 0x53, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB}; + if (encoder == ENC_BRESSER_5IN1) + { + memcpy(msg, payload_5in1, 26); + return 26; + } + else if (encoder == ENC_BRESSER_6IN1) + { + memcpy(msg, payload_6in1, 18); + return 18; + } + else if (encoder == ENC_BRESSER_7IN1) + { + memcpy(msg, payload_7in1, 26); + return 26; + } + else if (encoder == ENC_BRESSER_LIGHTNING) + { + memcpy(msg, payload_lightning, 26); + return 26; + } + else if (encoder == ENC_BRESSER_LEAKAGE) + { + memcpy(msg, payload_leakage, 26); + return 26; + } + else + { + log_e("Encoder not supported!"); + } +} +#endif -#elif defined(DATA_GEN) - uint8_t payload[26]; - ws.genMessage(0 /* slot */, 0xff /* id */, SENSOR_TYPE_WEATHER0 /* s_type */); +#if defined(GEN_DATA) +void genData(Encoders encoder) +{ + if (encoder == ENC_BRESSER_5IN1) + { + ws.genMessage(0 /* slot */, 0xff /* id */, SENSOR_TYPE_WEATHER0 /* s_type */); + } + else if (encoder == ENC_BRESSER_6IN1) + { + ws.genMessage(0 /* slot */, 0xFFFFFFFF /* id */, SENSOR_TYPE_WEATHER1 /* s_type */); + } + else if (encoder == ENC_BRESSER_7IN1) + { + ws.genMessage(0 /* slot */, 0xFFFF /* id */, SENSOR_TYPE_WEATHER1 /* s_type */); + } + else if (encoder == ENC_BRESSER_LIGHTNING) + { + ws.genMessage(0 /* slot */, 0xFFFF /* id */, SENSOR_TYPE_LIGHTNING /* s_type */); + } + else if (encoder == ENC_BRESSER_LEAKAGE) + { + ws.genMessage(0 /* slot */, 0xFFFFFFFF /* id */, SENSOR_TYPE_LEAKAGE /* s_type */); + } + else + { + log_e("Encoder not supported!"); + } +} +#endif -#elif defined(DATA_JSON_CONST) - uint8_t payload[26]; - StaticJsonDocument<512> doc; - const char json[] = +#if defined(DATA_JSON_CONST) +void genJson(Encoders encoder, String &json_str) +{ + const String json_5in1 = "{\"sensor_id\":255,\"s_type\":1,\"chan\":0,\"startup\":0,\"battery_ok\":1,\"temp_c\":12.3,\ - \"humidity\":44,\"wind_gust_meter_sec\":3.3,\"wind_avg_meter_sec\":2.2,\"wind_direction_deg\":111.1,\ - \"rain_mm\":123.4}"; + \"humidity\":44,\"wind_gust_meter_sec\":3.3,\"wind_avg_meter_sec\":2.2,\"wind_direction_deg\":111.1,\ + \"rain_mm\":123.4}"; - // Deserialize the JSON document - DeserializationError error = deserializeJson(doc, json); + const String json_6in1 = + "{\"sensor_id\":4294967295,\"s_type\":1,\"chan\":0,\"startup\":0,\"battery_ok\":1,\"temp_c\":12.3,\ + \"humidity\":44,\"wind_gust_meter_sec\":3.3,\"wind_avg_meter_sec\":2.2,\"wind_direction_deg\":111.1,\ + \"rain_mm\":12345.6,\"uv\":7.8}"; + + const String json_7in1 = + "{\"sensor_id\":65535,\"s_type\":1,\"chan\":0,\"startup\":0,\"battery_ok\":1,\"temp_c\":12.3,\ + \"humidity\":44,\"wind_gust_meter_sec\":3.3,\"wind_avg_meter_sec\":2.2,\"wind_direction_deg\":111.1,\ + \"rain_mm\":12345.6}"; -#elif defined(DATA_JSON_INPUT) - if (!msg_str.length()) + const String json_lightning = + "{\"sensor_id\":65535,\"s_type\":9,\"chan\":0,\"startup\":0,\"battery_ok\":1,\"strike_count\":22,\ + \"distance_km\":44}"; + + // TBD + const String json_leakage = "{}"; + + if (encoder == ENC_BRESSER_5IN1) + { + json_str = json_5in1; + } + else if (encoder == ENC_BRESSER_6IN1) + { + json_str = json_6in1; + } + else if (encoder == ENC_BRESSER_7IN1) + { + json_str = json_7in1; + } + else if (encoder == ENC_BRESSER_LIGHTNING) + { + json_str = json_lightning; + } + // else if (encoder == ENC_BRESSER_LEAKAGE) + // { + + // } + else { - return 0; + log_e("Encoder not supported!"); } +} +#endif + +#if defined(DATA_JSON_INPUT) || defined(DATA_JSON_CONST) +bool deSerialize(Encoders encoder, String json_str) +{ uint8_t payload[26]; StaticJsonDocument<512> doc; // Deserialize the JSON document - DeserializationError error = deserializeJson(doc, msg_str.c_str()); - -#endif + DeserializationError error = deserializeJson(doc, json_str.c_str()); -#if defined(DATA_JSON_INPUT) || defined(DATA_JSON_CONST) // Test if parsing succeeded if (error) { log_e("DeserializeJson() failed: %s", error.f_str()); - return 0; + return false; } ws.sensor[0].sensor_id = doc["sensor_id"]; @@ -194,15 +279,87 @@ uint8_t encodeBresser5In1Payload(String msg_str, uint8_t *msg) ws.sensor[0].chan = doc["chan"]; ws.sensor[0].startup = doc["startup"]; ws.sensor[0].battery_ok = doc["battery_ok"]; - ws.sensor[0].w.temp_c = doc["temp_c"]; - ws.sensor[0].w.humidity = doc["humidity"]; - ws.sensor[0].w.wind_gust_meter_sec = doc["wind_gust_meter_sec"]; - ws.sensor[0].w.wind_avg_meter_sec = doc["wind_avg_meter_sec"]; - ws.sensor[0].w.wind_direction_deg = doc["wind_direction_deg"]; - ws.sensor[0].w.rain_mm = doc["rain_mm"]; + + if (encoder == ENC_BRESSER_5IN1) + { + ws.sensor[0].w.temp_c = doc["temp_c"]; + ws.sensor[0].w.humidity = doc["humidity"]; + ws.sensor[0].w.wind_gust_meter_sec = doc["wind_gust_meter_sec"]; + ws.sensor[0].w.wind_avg_meter_sec = doc["wind_avg_meter_sec"]; + ws.sensor[0].w.wind_direction_deg = doc["wind_direction_deg"]; + ws.sensor[0].w.rain_mm = doc["rain_mm"]; + } + else if (encoder == ENC_BRESSER_6IN1) + { + if (ws.sensor[0].s_type == SENSOR_TYPE_SOIL) + { + ws.sensor[0].soil.temp_c = doc["temp_c"]; + ws.sensor[0].soil.moisture = doc["moisture"]; + } + else + { + ws.sensor[0].w.temp_c = doc["temp_c"]; + ws.sensor[0].w.humidity = doc["humidity"]; + ws.sensor[0].w.wind_gust_meter_sec = doc["wind_gust_meter_sec"]; + ws.sensor[0].w.wind_avg_meter_sec = doc["wind_avg_meter_sec"]; + ws.sensor[0].w.wind_direction_deg = doc["wind_direction_deg"]; + ws.sensor[0].w.rain_mm = doc["rain_mm"]; + ws.sensor[0].w.uv = doc["uv"]; + } + } + else if (encoder == ENC_BRESSER_7IN1) + { + ws.sensor[0].w.temp_c = doc["temp_c"]; + ws.sensor[0].w.humidity = doc["humidity"]; + ws.sensor[0].w.wind_gust_meter_sec = doc["wind_gust_meter_sec"]; + ws.sensor[0].w.wind_avg_meter_sec = doc["wind_avg_meter_sec"]; + ws.sensor[0].w.wind_direction_deg = doc["wind_direction_deg"]; + ws.sensor[0].w.rain_mm = doc["rain_mm"]; + ws.sensor[0].w.uv = doc["uv"]; + ws.sensor[0].w.light_klx = doc["light_klx"]; + } + else if (ENC_BRESSER_LIGHTNING) + { + ws.sensor[0].lgt.strike_count = doc["strike_count"]; + ws.sensor[0].lgt.distance_km = doc["distance_km"]; + } + // else if (ENC_BRESSER_LEAKAGE) + // { + //} + else + { + log_e("Encoder not supported!"); + return false; + } + return true; +} #endif -#if !defined(DATA_RAW) +// +// From from rtl_433 project - https://github.com/merbanan/rtl_433/blob/master/src/devices/bresser_5in1.c (20220212) +// +// Example input data: +// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 +// EA EC 7F EB 5F EE EF FA FE 76 BB FA FF 15 13 80 14 A0 11 10 05 01 89 44 05 00 +// CC CC CC CC CC CC CC CC CC CC CC CC CC uu II sS GG DG WW W TT T HH RR RR Bt +// - C = Check, inverted data of 13 byte further +// - uu = checksum (number/count of set bits within bytes 14-25) +// - I = station ID (maybe) +// - G = wind gust in 1/10 m/s, normal binary coded, GGxG = 0x76D1 => 0x0176 = 256 + 118 = 374 => 37.4 m/s. MSB is out of sequence. +// - D = wind direction 0..F = N..NNE..E..S..W..NNW +// - W = wind speed in 1/10 m/s, BCD coded, WWxW = 0x7512 => 0x0275 = 275 => 27.5 m/s. MSB is out of sequence. +// - T = temperature in 1/10 °C, BCD coded, TTxT = 1203 => 31.2 °C +// - t = temperature sign, minus if unequal 0 +// - H = humidity in percent, BCD coded, HH = 23 => 23 % +// - R = rain in mm, BCD coded, RRRR = 1203 => 031.2 mm +// - B = Battery. 0=Ok, 8=Low. +// - s = startup, 0 after power-on/reset / 8 after 1 hour +// - S = sensor type, only low nibble used, 0x9 for Bresser Professional Rain Gauge +uint8_t encodeBresser5In1Payload(uint8_t *msg) +{ + uint8_t payload[26] = {0}; + char buf[7]; + payload[14] = (uint8_t)(ws.sensor[0].sensor_id & 0xFF); payload[15] = ((ws.sensor[0].startup ? 0 : 8) << 4) | ws.sensor[0].s_type; @@ -261,12 +418,11 @@ uint8_t encodeBresser5In1Payload(String msg_str, uint8_t *msg) { payload[col] = ~payload[col + 13]; } -#endif - memcpy(&msg[6], payload, 26); + memcpy(msg, payload, 26); // Return message size - return 4 + 2 + 26; + return 26; } // @@ -342,80 +498,12 @@ uint8_t encodeBresser5In1Payload(String msg_str, uint8_t *msg) // - 18c0 0f10 18 : rege245 BRESSER-PC-Weather-station-with-6-in-1-outdoor-sensor // - 1880 02c3 18 : f4gqk 6-in-1 // - 18b0 0887 18 : npkap -uint8_t encodeBresser6In1Payload(String msg_str, uint8_t *msg) +uint8_t encodeBresser6In1Payload(uint8_t *msg) { - uint8_t preamble[] = {0xAA, 0xAA, 0xAA, 0xAA}; - uint8_t syncword[] = {0x2D, 0xD4}; static int msg_type; char buf[8]; + uint8_t payload[18] = {0}; - memcpy(msg, preamble, 4); - memcpy(&msg[4], syncword, 2); - -#if defined(DATA_RAW) - uint8_t payload[] = {0x2A, 0xAF, 0x21, 0x10, 0x34, 0x27, 0x18, 0xFF, 0xAA, 0xFF, 0x29, 0x28, 0xFF, - 0xBB, 0x89, 0xFF, 0x01, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -#elif defined(DATA_GEN) - uint8_t payload[18]; - ws.genMessage(0 /* slot */, 0xFFFFFFFF /* id */, SENSOR_TYPE_WEATHER1 /* s_type */, 7 /* channel */); - -#elif defined(DATA_JSON_CONST) - uint8_t payload[18]; - StaticJsonDocument<512> doc; - const char json[] = - "{\"sensor_id\":4294967295,\"s_type\":1,\"chan\":0,\"startup\":0,\"battery_ok\":1,\"temp_c\":12.3,\ - \"humidity\":44,\"wind_gust_meter_sec\":3.3,\"wind_avg_meter_sec\":2.2,\"wind_direction_deg\":111.1,\ - \"rain_mm\":12345.6}"; - - // Deserialize the JSON document - DeserializationError error = deserializeJson(doc, json); - -#elif defined(DATA_JSON_INPUT) - if (!msg_str.length()) - { - return 0; - } - - uint8_t payload[18]; - StaticJsonDocument<512> doc; - - // Deserialize the JSON document - DeserializationError error = deserializeJson(doc, msg_str.c_str()); - -#endif - -#if defined(DATA_JSON_INPUT) || defined(DATA_JSON_CONST) - // Test if parsing succeeded - if (error) - { - log_e("DeserializeJson() failed: %s", error.f_str()); - return 0; - } - - ws.sensor[0].sensor_id = doc["sensor_id"]; - ws.sensor[0].s_type = doc["s_type"]; - ws.sensor[0].chan = doc["chan"]; - ws.sensor[0].startup = doc["startup"]; - ws.sensor[0].battery_ok = doc["battery_ok"]; - if (ws.sensor[0].s_type == SENSOR_TYPE_SOIL) - { - ws.sensor[0].soil.temp_c = doc["temp_c"]; - ws.sensor[0].soil.moisture = doc["moisture"]; - } - else - { - ws.sensor[0].w.temp_c = doc["temp_c"]; - ws.sensor[0].w.humidity = doc["humidity"]; - ws.sensor[0].w.wind_gust_meter_sec = doc["wind_gust_meter_sec"]; - ws.sensor[0].w.wind_avg_meter_sec = doc["wind_avg_meter_sec"]; - ws.sensor[0].w.wind_direction_deg = doc["wind_direction_deg"]; - ws.sensor[0].w.rain_mm = doc["rain_mm"]; - ws.sensor[0].w.uv = doc["uv"]; - } -#endif - -#if !defined(DATA_RAW) payload[2] = ws.sensor[0].sensor_id >> 24; payload[3] = (ws.sensor[0].sensor_id >> 16) & 0xFF; payload[4] = (ws.sensor[0].sensor_id >> 8) & 0xFF; @@ -485,14 +573,16 @@ uint8_t encodeBresser6In1Payload(String msg_str, uint8_t *msg) if (ws.sensor[0].s_type == SENSOR_TYPE_SOIL) { int const moisture_map[] = {0, 7, 13, 20, 27, 33, 40, 47, 53, 60, 67, 73, 80, 87, 93, 99}; // scale is 20/3 - for (int i=0; i<16; i++) { - if (moisture_map[i] > ws.sensor[0].soil.moisture) { + for (int i = 0; i < 16; i++) + { + if (moisture_map[i] > ws.sensor[0].soil.moisture) + { log_d("Moisture: %d Index: %d", ws.sensor[0].soil.moisture, i); payload[14] = i; break; } } - //payload[14] = (int)(ws.sensor[0].soil.moisture / 20.0f * 3.0f); + // payload[14] = (int)(ws.sensor[0].soil.moisture / 20.0f * 3.0f); } if (ws.sensor[0].s_type == SENSOR_TYPE_WEATHER1) @@ -533,12 +623,11 @@ uint8_t encodeBresser6In1Payload(String msg_str, uint8_t *msg) int digest = lfsr_digest16(&payload[2], 15, 0x8810, 0x5412); payload[0] = digest >> 8; payload[1] = digest & 0xFF; -#endif - memcpy(&msg[6], payload, 18); + memcpy(msg, payload, 18); // Return message size - return 4 + 2 + 18; + return 18; } // @@ -571,33 +660,28 @@ DIGEST:8h8h ID?8h8h ?8h8h STYPE:4h STARTUP:1b CH:3b ?8h 4h ?4h8h4h PM_2_5:4h8h4h STYPE, STARTUP and CH are not covered by whitening. Probably also ID. First two bytes are an LFSR-16 digest, generator 0x8810 key 0xba95 with a final xor 0x6df1, which likely means we got that wrong. */ -uint8_t encodeBresser7In1Payload(String msg_str, uint8_t *msg) +uint8_t encodeBresser7In1Payload(uint8_t *msg) { - uint8_t preamble[] = {0xAA, 0xAA, 0xAA, 0xAA}; - uint8_t syncword[] = {0x2D, 0xD4}; - - memcpy(msg, preamble, 4); - memcpy(&msg[4], syncword, 2); - - uint8_t payload[] = {0xC4, 0xD6, 0x3A, 0xC5, 0xBD, 0xFA, 0x18, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFC, - 0xAA, 0x98, 0xDA, 0x89, 0xA3, 0x2F, 0xEC, 0xAF, 0x9A, 0xAA, 0xAA, 0xAA, 0x00}; + uint8_t payload[26] = {0}; // LFSR-16 digest, generator 0x8810 key 0xba95 final xor 0x6df1 - //int chkdgst = (msgw[0] << 8) | msgw[1]; - for (int i=2; i < 26; i++) { + // int chkdgst = (msgw[0] << 8) | msgw[1]; + for (int i = 2; i < 26; i++) + { payload[i] ^= 0xAA; } - int digest = lfsr_digest16(&payload[2], 23, 0x8810, 0xba95); // bresser_7in1 - - for (int i=0; i < 26; i++) { + int digest = lfsr_digest16(&payload[2], 23, 0x8810, 0xba95); // bresser_7in1 + + for (int i = 0; i < 26; i++) + { payload[i] ^= 0xAA; } log_d("Digest: 0x%04X", digest ^ 0xAAAA ^ 0x6df1); - memcpy(&msg[6], payload, 26); + memcpy(msg, payload, 26); // Return message size - return 4 + 2 + 26; + return 26; } /** @@ -618,65 +702,9 @@ The data has a whitening of 0xaa. First two bytes are an LFSR-16 digest, generator 0x8810 key 0xabf9 with a final xor 0x899e */ -uint8_t encodeBresserLightningPayload(String msg_str, uint8_t *msg) +uint8_t encodeBresserLightningPayload(uint8_t *msg) { - uint8_t preamble[] = {0xAA, 0xAA, 0xAA, 0xAA}; - uint8_t syncword[] = {0x2D, 0xD4}; - - memcpy(msg, preamble, 4); - memcpy(&msg[4], syncword, 2); - -#if defined(DATA_RAW) - uint8_t payload[] = {0x73, 0x69, 0xB5, 0x08, 0xAA, 0xA2, 0x90, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - -#elif defined(DATA_GEN) - uint8_t payload[26]; - ws.genMessage(0 /* slot */, 0xffff /* id */, SENSOR_TYPE_LIGHTNING /* s_type */); - -#elif defined(DATA_JSON_CONST) - uint8_t payload[26]; - StaticJsonDocument<256> doc; - const char json[] = - "{\"sensor_id\":65535,\"s_type\":9,\"chan\":0,\"startup\":0,\"battery_ok\":1,\"strike_count\":22,\ - \"distance_km\":44}"; - - // Deserialize the JSON document - DeserializationError error = deserializeJson(doc, json); - -#elif defined(DATA_JSON_INPUT) - if (!msg_str.length()) - { - return 0; - } - - uint8_t payload[26]; - StaticJsonDocument<256> doc; - - // Deserialize the JSON document - DeserializationError error = deserializeJson(doc, msg_str.c_str()); - -#endif - -#if defined(DATA_JSON_INPUT) || defined(DATA_JSON_CONST) - // Test if parsing succeeded - if (error) - { - log_e("DeserializeJson() failed: %s", error.f_str()); - return 0; - } - - ws.sensor[0].sensor_id = doc["sensor_id"]; - ws.sensor[0].s_type = doc["s_type"]; - ws.sensor[0].chan = doc["chan"]; - ws.sensor[0].startup = doc["startup"]; - ws.sensor[0].battery_ok = doc["battery_ok"]; - ws.sensor[0].lgt.strike_count = doc["strike_count"]; - ws.sensor[0].lgt.distance_km = doc["distance_km"]; - -#endif - -#if !defined(DATA_RAW) + uint8_t payload[10] = {0}; payload[2] = (ws.sensor[0].sensor_id >> 8) & 0xFF; payload[3] = ws.sensor[0].sensor_id & 0xFF; @@ -703,8 +731,6 @@ uint8_t encodeBresserLightningPayload(String msg_str, uint8_t *msg) payload[8] = 0; payload[9] = 0; -#endif - int crc = crc16(&payload[2], 7, 0x1021 /* polynomial */, 0 /* init */); log_d("CRC: 0x%04X", crc); crc ^= 0x899e; @@ -717,10 +743,10 @@ uint8_t encodeBresserLightningPayload(String msg_str, uint8_t *msg) payload[i] ^= 0xAA; } - memcpy(&msg[6], payload, 10); + memcpy(msg, payload, 10); // Return message size - return 4 + 2 + 10; + return 10; } /** @@ -765,28 +791,21 @@ uint8_t encodeBresserLightningPayload(String msg_str, uint8_t *msg) * - The ID changes on power-up/reset * - NSTARTUP changes from 0 to 1 approx. one hour after power-on/reset */ -uint8_t encodeBresserLeakagePayload(String msg_str, uint8_t *msg) +uint8_t encodeBresserLeakagePayload(uint8_t *msg) { - uint8_t preamble[] = {0xAA, 0xAA, 0xAA, 0xAA}; - uint8_t syncword[] = {0x2D, 0xD4}; - - memcpy(msg, preamble, 4); - memcpy(&msg[4], syncword, 2); + uint8_t payload[26] = {0}; - uint8_t payload[] = {0xB3, 0xDA, 0x55, 0x57, 0x17, 0x40, 0x53, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB}; - - memcpy(&msg[6], payload, 26); + memcpy(msg, payload, 26); // Return message size - return 4 + 2 + 26; + return 26; } void loop() { String input_str; static String json_str; - static Encoders encoder = ENC_BRESSER_7IN1; + static Encoders encoder = ENC_BRESSER_6IN1; static unsigned tx_interval = TX_INTERVAL; if (Serial.available()) @@ -857,31 +876,58 @@ void loop() uint8_t msg_buf[40]; uint8_t msg_size; + bool valid = true; + + msg_size = msgBegin(msg_buf); + +#if defined(DATA_RAW) + msg_size += rawPayload(encoder, &msg_buf[msg_size]); +#elif defined(GEN_DATA) + genData(encoder); +#elif defined(DATA_JSON_CONST) + genJson(encoder, json_str); +#endif - switch (encoder) +#if defined(DATA_JSON_CONST) || defined(DATA_JSON_INPUT) + if (json_str.length() > 0) { - case ENC_BRESSER_5IN1: - msg_size = encodeBresser5In1Payload(json_str, msg_buf); - break; + valid = deSerialize(encoder, json_str); + } + else + { + valid = false; + } +#endif - case ENC_BRESSER_6IN1: - msg_size = encodeBresser6In1Payload(json_str, msg_buf); - break; + if (valid) + { + switch (encoder) + { + case ENC_BRESSER_5IN1: + msg_size += encodeBresser5In1Payload(&msg_buf[msg_size]); + break; + + case ENC_BRESSER_6IN1: + msg_size += encodeBresser6In1Payload(&msg_buf[msg_size]); + break; - case ENC_BRESSER_7IN1: - msg_size = encodeBresser7In1Payload(json_str, msg_buf); - break; + case ENC_BRESSER_7IN1: + msg_size += encodeBresser7In1Payload(&msg_buf[msg_size]); + break; - case ENC_BRESSER_LIGHTNING: - msg_size = encodeBresserLightningPayload(json_str, msg_buf); - break; + case ENC_BRESSER_LIGHTNING: + msg_size = encodeBresserLightningPayload(&msg_buf[msg_size]); + break; - case ENC_BRESSER_LEAKAGE: - msg_size = encodeBresserLeakagePayload(json_str, msg_buf); - break; + case ENC_BRESSER_LEAKAGE: + msg_size = encodeBresserLeakagePayload(&msg_buf[msg_size]); + break; - default: - log_e("Encoder not implemented!"); + default: + log_e("Encoder not implemented!"); + msg_size = 0; + } + } else { msg_size = 0; } From bd19ab5135d805d245ff6d16c3ec41c8d7f686c7 Mon Sep 17 00:00:00 2001 From: Matthias Prinke Date: Sun, 19 Nov 2023 22:31:57 +0100 Subject: [PATCH 2/4] Fixes --- SensorTransmitter.h | 2 +- SensorTransmitter.ino | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/SensorTransmitter.h b/SensorTransmitter.h index 6707de8..6ebbd08 100644 --- a/SensorTransmitter.h +++ b/SensorTransmitter.h @@ -53,7 +53,7 @@ #define NUM_SENSORS 1 //!< WeatherSensor - no. of sensors #define WIND_DATA_FLOATINGPOINT //!< WeatherSensor - wind data type -//!< Select one of the followind data sources +//!< Select one of the following data sources //#define DATA_RAW //!< payload from raw data //#define DATA_GEN //!< payload from WeatherSensor::genMessage() //#define DATA_JSON_CONST //!< payload from JSON constant string diff --git a/SensorTransmitter.ino b/SensorTransmitter.ino index 46f5d10..ad186f0 100644 --- a/SensorTransmitter.ino +++ b/SensorTransmitter.ino @@ -175,7 +175,7 @@ uint8_t rawPayload(Encoders encoder, uint8_t *msg) } #endif -#if defined(GEN_DATA) +#if defined(DATA_GEN) void genData(Encoders encoder) { if (encoder == ENC_BRESSER_5IN1) @@ -582,14 +582,13 @@ uint8_t encodeBresser6In1Payload(uint8_t *msg) break; } } - // payload[14] = (int)(ws.sensor[0].soil.moisture / 20.0f * 3.0f); } if (ws.sensor[0].s_type == SENSOR_TYPE_WEATHER1) { msg_type = 1; } - } + } // msg_type == 0 else { snprintf(buf, 8, "%07.1f", ws.sensor[0].w.rain_mm); @@ -608,7 +607,7 @@ uint8_t encodeBresser6In1Payload(uint8_t *msg) snprintf(buf, 8, "%04.1f", ws.sensor[0].w.uv); log_d("UV: %04.1f", ws.sensor[0].w.uv); payload[15] = ((buf[0] - '0') << 4) | (buf[1] - '0'); - payload[16] = ((buf[3] - '0') << 4); + payload[16] |= ((buf[3] - '0') << 4); payload[15] ^= 0xFF; payload[16] ^= 0xF0; @@ -882,7 +881,7 @@ void loop() #if defined(DATA_RAW) msg_size += rawPayload(encoder, &msg_buf[msg_size]); -#elif defined(GEN_DATA) +#elif defined(DATA_GEN) genData(encoder); #elif defined(DATA_JSON_CONST) genJson(encoder, json_str); @@ -899,6 +898,7 @@ void loop() } #endif +#if !defined(DATA_RAW) if (valid) { switch (encoder) @@ -916,11 +916,11 @@ void loop() break; case ENC_BRESSER_LIGHTNING: - msg_size = encodeBresserLightningPayload(&msg_buf[msg_size]); + msg_size += encodeBresserLightningPayload(&msg_buf[msg_size]); break; case ENC_BRESSER_LEAKAGE: - msg_size = encodeBresserLeakagePayload(&msg_buf[msg_size]); + msg_size += encodeBresserLeakagePayload(&msg_buf[msg_size]); break; default: @@ -930,6 +930,7 @@ void loop() } else { msg_size = 0; } +#endif log_i("%s Transmitting packet (%d bytes)... ", TRANSCEIVER_CHIP, msg_size); int state = radio.transmit(msg_buf, msg_size); From f5a08ceb10c2a1cd66dca667667b7915779427d8 Mon Sep 17 00:00:00 2001 From: Matthias Prinke Date: Sun, 19 Nov 2023 22:34:50 +0100 Subject: [PATCH 3/4] Added comment --- SensorTransmitter.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/SensorTransmitter.ino b/SensorTransmitter.ino index ad186f0..67a3104 100644 --- a/SensorTransmitter.ino +++ b/SensorTransmitter.ino @@ -49,6 +49,7 @@ // Added encodeBresser<6In1|7In1|Leakage>Payload() - only raw data input! // 20231117 Implemented encodeBresser6In1Payload() (basic functionality) // 20231118 encodeBresser6In1Payload(): Added UV index and remaining (known) sensors +// 20231119 Restructured data generation and encoding // // ToDo: // - From dcdc5f371955ae664853f6007e4bee8e53857f75 Mon Sep 17 00:00:00 2001 From: Matthias Prinke Date: Sun, 19 Nov 2023 22:42:56 +0100 Subject: [PATCH 4/4] Fixes --- SensorTransmitter.ino | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/SensorTransmitter.ino b/SensorTransmitter.ino index 67a3104..1bf2125 100644 --- a/SensorTransmitter.ino +++ b/SensorTransmitter.ino @@ -261,8 +261,6 @@ void genJson(Encoders encoder, String &json_str) #if defined(DATA_JSON_INPUT) || defined(DATA_JSON_CONST) bool deSerialize(Encoders encoder, String json_str) { - - uint8_t payload[26]; StaticJsonDocument<512> doc; // Deserialize the JSON document @@ -319,7 +317,7 @@ bool deSerialize(Encoders encoder, String json_str) ws.sensor[0].w.uv = doc["uv"]; ws.sensor[0].w.light_klx = doc["light_klx"]; } - else if (ENC_BRESSER_LIGHTNING) + else if (encoder == ENC_BRESSER_LIGHTNING) { ws.sensor[0].lgt.strike_count = doc["strike_count"]; ws.sensor[0].lgt.distance_km = doc["distance_km"]; @@ -662,26 +660,27 @@ First two bytes are an LFSR-16 digest, generator 0x8810 key 0xba95 with a final */ uint8_t encodeBresser7In1Payload(uint8_t *msg) { - uint8_t payload[26] = {0}; + // uint8_t payload[26] = {0}; - // LFSR-16 digest, generator 0x8810 key 0xba95 final xor 0x6df1 - // int chkdgst = (msgw[0] << 8) | msgw[1]; - for (int i = 2; i < 26; i++) - { - payload[i] ^= 0xAA; - } - int digest = lfsr_digest16(&payload[2], 23, 0x8810, 0xba95); // bresser_7in1 + // // LFSR-16 digest, generator 0x8810 key 0xba95 final xor 0x6df1 + // // int chkdgst = (msgw[0] << 8) | msgw[1]; + // for (int i = 2; i < 26; i++) + // { + // payload[i] ^= 0xAA; + // } + // int digest = lfsr_digest16(&payload[2], 23, 0x8810, 0xba95); // bresser_7in1 - for (int i = 0; i < 26; i++) - { - payload[i] ^= 0xAA; - } - log_d("Digest: 0x%04X", digest ^ 0xAAAA ^ 0x6df1); + // for (int i = 0; i < 26; i++) + // { + // payload[i] ^= 0xAA; + // } + // log_d("Digest: 0x%04X", digest ^ 0xAAAA ^ 0x6df1); - memcpy(msg, payload, 26); + // memcpy(msg, payload, 26); - // Return message size - return 26; + // // Return message size + // return 26; + return 0; } /**