From 3bfafacd504bba5a18f125902d446f332e4af0a5 Mon Sep 17 00:00:00 2001 From: DigiH Date: Wed, 20 Jul 2022 17:37:31 +0200 Subject: [PATCH] SmartDry initial --- docs/.vuepress/config.js | 1 + docs/devices/SDLS.md | 12 ++++++ docs/participate/adding-decoders.md | 1 + src/decoder.cpp | 27 ++++++++----- src/decoder.h | 5 ++- src/devices.h | 2 + src/devices/SmartDry_json.h | 61 +++++++++++++++++++++++++++++ tests/BLE/test_ble.cpp | 18 +++++++++ 8 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 docs/devices/SDLS.md create mode 100644 src/devices/SmartDry_json.h diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 75abd30b..9e539577 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -63,6 +63,7 @@ module.exports = { 'devices/RDL52832', 'devices/RuuviTag_RAWv1', 'devices/RuuviTag_RAWv2', + 'devices/SDLS', 'devices/SBCS', 'devices/SBCU', 'devices/SBMS', diff --git a/docs/devices/SDLS.md b/docs/devices/SDLS.md new file mode 100644 index 00000000..d66c4253 --- /dev/null +++ b/docs/devices/SDLS.md @@ -0,0 +1,12 @@ +# SmartDry Laundry Sensor + +|Model Id|[SDLS](https://github.com/theengs/decoder/blob/development/src/devices/SmartDry_json.h)| +|-|-| +|Brand|SmartDry| +|Model|Laundry Sensor| +|Short Description|Wireless Laundry Sensor| +|Communication|BLE broadcast| +|Frequency|2.4Ghz| +|Power source|CR2032| +|Exchanged data|temperature, humidity, shake, voltage, wake| +|Encrypted|No| diff --git a/docs/participate/adding-decoders.md b/docs/participate/adding-decoders.md index 974da412..5e152d61 100644 --- a/docs/participate/adding-decoders.md +++ b/docs/participate/adding-decoders.md @@ -155,6 +155,7 @@ The other parameters for the first three functions are: - 4, The length of the data in bytes (characters in the string). - true/false, If the value in the data source should have it's endianness reversed before converting. - (optional)true/false, Sets if the resulting value can be a negative number. Defaults to true when omitted. +- (optional)false/true, Sets if the "value_from_hex_data" decoding result is a `float` instead of an `integer` type. Defaults to false when omitted. ``` "properties":{ diff --git a/src/decoder.cpp b/src/decoder.cpp index bc3c5730..a53b4497 100644 --- a/src/decoder.cpp +++ b/src/decoder.cpp @@ -44,7 +44,7 @@ static size_t peakDocSize = 0; typedef double (TheengsDecoder::*decoder_function)(const char* data_str, int offset, int data_length, - bool reverse, bool canBeNegative); + bool reverse, bool canBeNegative, bool isFloat); typedef double (TheengsDecoder::*staticbitdecoder_function)(const char* data_str, const char* source_str, int offset, int bitindex, @@ -66,10 +66,10 @@ void TheengsDecoder::reverse_hex_data(const char* in, char* out, int l) { double TheengsDecoder::bf_value_from_hex_string(const char* data_str, int offset, int data_length, - bool reverse, bool canBeNegative) { + bool reverse, bool canBeNegative, bool isFloat) { DEBUG_PRINT("extracting BCF data\n"); - long value = (long)value_from_hex_string(data_str, offset, data_length, reverse, false); + long value = (long)value_from_hex_string(data_str, offset, data_length, reverse, false, false); double d_value = ((((value >> 8) * 100) + (uint8_t)value)) / 100.0; if (canBeNegative) { @@ -86,17 +86,25 @@ double TheengsDecoder::bf_value_from_hex_string(const char* data_str, */ double TheengsDecoder::value_from_hex_string(const char* data_str, int offset, int data_length, - bool reverse, bool canBeNegative) { - DEBUG_PRINT("offset: %d, len %d, rev %u, neg, %u\n", - offset, data_length, reverse, canBeNegative); + bool reverse, bool canBeNegative, bool isFloat) { + DEBUG_PRINT("offset: %d, len %d, rev %u, neg, %u, flo, %u\n", + offset, data_length, reverse, canBeNegative, isFloat); std::string data(&data_str[offset], data_length); if (reverse) { reverse_hex_data(&data_str[offset], &data[0], data_length); } - double value = strtol(data.c_str(), NULL, 16); - DEBUG_PRINT("extracted value from %s = 0x%08lx\n", data.c_str(), (long)value); + double value = 0; + if (!isFloat) { + value = strtol(data.c_str(), NULL, 16); + DEBUG_PRINT("extracted value from %s = 0x%08lx\n", data.c_str(), (long)value); + } else { + long longV = strtol(data.c_str(), NULL, 16); + float floatV = *((float *) &longV); + DEBUG_PRINT("extracted float value from %s = %f\n", data.c_str(), floatV); + value = floatV; + } if (canBeNegative) { if (data_length <= 2 && value > SCHAR_MAX) { @@ -447,7 +455,8 @@ int TheengsDecoder::decodeBLEJson(JsonObject& jsondata) { temp_val = (this->*dec_fun)(src, decoder[2].as(), decoder[3].as(), decoder[4].as(), - decoder[5].isNull() ? true : decoder[5].as()); + decoder[5].isNull() ? true : decoder[5].as(), + decoder[6].isNull() ? false : decoder[6].as()); } else { break; diff --git a/src/decoder.h b/src/decoder.h index 994d0393..c596fefe 100644 --- a/src/decoder.h +++ b/src/decoder.h @@ -85,6 +85,7 @@ class TheengsDecoder { SBMS, SBMT, SBS1, + SMARTDRY, BM_V23, MS_CDP, GAEN, @@ -98,8 +99,8 @@ class TheengsDecoder { private: void reverse_hex_data(const char* in, char* out, int l); - double value_from_hex_string(const char* data_str, int offset, int data_length, bool reverse, bool canBeNegative = true); - double bf_value_from_hex_string(const char* data_str, int offset, int data_length, bool reverse, bool canBeNegative = true); + double value_from_hex_string(const char* data_str, int offset, int data_length, bool reverse, bool canBeNegative = true, bool isFloat = false); + double bf_value_from_hex_string(const char* data_str, int offset, int data_length, bool reverse, bool canBeNegative = true, bool isFloat = false); bool data_index_is_valid(const char* str, size_t index, size_t len); int data_length_is_valid(size_t data_len, size_t default_min, const JsonArray& condition, int idx); uint8_t getBinaryData(char ch); diff --git a/src/devices.h b/src/devices.h index dd63ac15..96a0f569 100644 --- a/src/devices.h +++ b/src/devices.h @@ -55,6 +55,7 @@ #include "devices/SBMS_json.h" #include "devices/SBMT_json.h" #include "devices/SBS1_json.h" +#include "devices/SmartDry_json.h" #include "devices/TPMS_json.h" #include "devices/WS02_json.h" #include "devices/WS08_json.h" @@ -106,6 +107,7 @@ const char* _devices[][2] = { {_SBMS_json, _SBMS_json_props}, {_SBMT_json, _SBMT_json_props}, {_SBS1_json, _SBS1_json_props}, + {_SmartDry_json, _SmartDry_json_props}, {_BM_V23_json, _BM_V23_json_props}, {_MS_CDP_json, _MS_CDP_json_props}, {_GAEN_json, _GAEN_json_props}, diff --git a/src/devices/SmartDry_json.h b/src/devices/SmartDry_json.h new file mode 100644 index 00000000..097ac4b6 --- /dev/null +++ b/src/devices/SmartDry_json.h @@ -0,0 +1,61 @@ +const char* _SmartDry_json = "{\"brand\":\"SmartDry\",\"model\":\"Laundry Sensor\",\"model_id\":\"SDLS\",\"condition\":[\"manufacturerdata\",\"=\",28,\"index\",0,\"ae01\"],\"properties\":{\"tempc\":{\"decoder\":[\"value_from_hex_data\",\"manufacturerdata\",4,8,true,false,true]},\"hum\":{\"decoder\":[\"value_from_hex_data\",\"manufacturerdata\",12,8,true,false,true]},\"shake\":{\"decoder\":[\"bit_static_value\",\"manufacturerdata\",23,0,false,true]},\"shake_count\":{\"decoder\":[\"value_from_hex_data\",\"manufacturerdata\",20,2,false,false]},\"volt\":{\"decoder\":[\"value_from_hex_data\",\"manufacturerdata\",24,2,false,false],\"post_proc\":[\"+\",\"2847\",\"/\",1000]},\"wake\":{\"decoder\":[\"bit_static_value\",\"manufacturerdata\",27,0,false,true]}}}"; + +/* R""""( +{ + "brand":"SmartDry", + "model":"Laundry Sensor", + "model_id":"SDLS", + "condition":["manufacturerdata", "=", 28, "index", 0, "ae01"], + "properties":{ + "tempc":{ + "decoder":["value_from_hex_data", "manufacturerdata", 4, 8, true, false, true] + }, + "hum":{ + "decoder":["value_from_hex_data", "manufacturerdata", 12, 8, true, false, true] + }, + "shake":{ + "decoder":["bit_static_value", "manufacturerdata", 23, 0, false, true] + }, + "shake_count":{ + "decoder":["value_from_hex_data", "manufacturerdata", 20, 2, false, false] + }, + "volt":{ + "decoder":["value_from_hex_data", "manufacturerdata", 24, 2, false, false], + "post_proc":["+", "2847", "/", 1000] + }, + "wake":{ + "decoder":["bit_static_value", "manufacturerdata", 27, 0, false, true] + } + } +})"""";*/ + +const char* _SmartDry_json_props = "{\"properties\":{\"tempc\":{\"unit\":\"°C\",\"name\":\"temperature\"},\"hum\":{\"unit\":\"%\",\"name\":\"humidity\"},\"shake\":{\"unit\":\"status\",\"name\":\"shake\"},\"shake_count\":{\"unit\":\"int\",\"name\":\"shake count\"},\"volt\":{\"unit\":\"V\",\"name\":\"voltage\"},\"wake\":{\"unit\":\"status\",\"name\":\"wake\"}}}"; +/*R""""( +{ + "properties":{ + "tempc":{ + "unit":"°C", + "name":"temperature" + }, + "hum":{ + "unit":"%", + "name":"humidity" + }, + "shake":{ + "unit":"status", + "name":"shake" + }, + "shake_count":{ + "unit":"int", + "name":"shake count" + }, + "volt":{ + "unit":"V", + "name":"voltage" + }, + "wake":{ + "unit":"status", + "name":"wake" + } + } +})"""";*/ diff --git a/tests/BLE/test_ble.cpp b/tests/BLE/test_ble.cpp index 340b06ff..607eb944 100644 --- a/tests/BLE/test_ble.cpp +++ b/tests/BLE/test_ble.cpp @@ -85,6 +85,12 @@ const char* expected_mfg[] = { "{\"brand\":\"Inkbird/Tenergy\",\"model\":\"iBBQ/SOLIS6\",\"model_id\":\"IBT-6XS/SOLIS-6\",\"tempc\":20,\"tempf\":68,\"tempc2\":20,\"tempf2\":68,\"tempc4\":21,\"tempf4\":69.8}", "{\"brand\":\"GENERIC\",\"model\":\"BM2 Battery Monitor\",\"model_id\":\"BM2\",\"batt\":100}", "{\"brand\":\"GENERIC\",\"model\":\"BM2 Battery Monitor\",\"model_id\":\"BM2\",\"batt\":68}", + "{\"brand\":\"SmartDry\",\"model\":\"Laundry Sensor\",\"model_id\":\"SDLS\",\"tempc\":34.210289,\"tempf\":93.5785202,\"hum\":100,\"shake\":false,\"shake_count\":82,\"volt\":2.952,\"wake\":true}", + "{\"brand\":\"SmartDry\",\"model\":\"Laundry Sensor\",\"model_id\":\"SDLS\",\"tempc\":21.97295189,\"tempf\":71.5513134,\"hum\":97.91998291,\"shake\":true,\"shake_count\":8,\"volt\":2.951,\"wake\":true}", + "{\"brand\":\"SmartDry\",\"model\":\"Laundry Sensor\",\"model_id\":\"SDLS\",\"tempc\":31.79714203,\"tempf\":89.23485565,\"hum\":99.49163818,\"shake\":false,\"shake_count\":51,\"volt\":2.956,\"wake\":true}", + "{\"brand\":\"SmartDry\",\"model\":\"Laundry Sensor\",\"model_id\":\"SDLS\",\"tempc\":29.57704544,\"tempf\":85.23868179,\"hum\":55.99645996,\"shake\":false,\"shake_count\":74,\"volt\":2.929,\"wake\":true}", + "{\"brand\":\"SmartDry\",\"model\":\"Laundry Sensor\",\"model_id\":\"SDLS\",\"tempc\":29.57704544,\"tempf\":85.23868179,\"hum\":55.99645996,\"shake\":false,\"shake_count\":74,\"volt\":2.929,\"wake\":false}", + "{\"brand\":\"SmartDry\",\"model\":\"Laundry Sensor\",\"model_id\":\"SDLS\",\"tempc\":29.57704544,\"tempf\":85.23868179,\"hum\":55.99645996,\"shake\":false,\"shake_count\":74,\"volt\":2.929,\"wake\":false}", }; const char* expected_uuid_mfgsvcdata[] = { @@ -268,6 +274,12 @@ const char* test_mfgdata[][3] = { {"SOLIS_6", "iBBQ", "000000000cb2b71b5b18c800c800f6ffd200f6fff6ff"}, {"BM2", "Battery Monitor", "4c000215655f83caae16a10a702e31f30d58dd82f644000064"}, {"BM2", "Battery Monitor", "4c000215655f83caae16a10a702e31f30d58dd82f441423144"}, + {"SmartDry", "Laundry Sensor", "ae0156d708420000c84252006907"}, + {"SmartDry", "Laundry Sensor", "ae019bc8af4108d7c34208016807"}, + {"SmartDry", "Laundry Sensor", "ae018c60fe41b8fbc64233006d07"}, + {"SmartDry", "Laundry Sensor", "ae01ca9dec4160fc5f424a005207"}, + {"SmartDry", "Laundry Sensor", "ae01ca9dec4160fc5f424a005200"}, + {"SmartDry", "Laundry Sensor", "ae01ca9dec4160fc5f424a005206"}, }; TheengsDecoder::BLE_ID_NUM test_mfgdata_id_num[]{ @@ -315,6 +327,12 @@ TheengsDecoder::BLE_ID_NUM test_mfgdata_id_num[]{ TheengsDecoder::BLE_ID_NUM::IBT6XS_SOLIS, TheengsDecoder::BLE_ID_NUM::BM2, TheengsDecoder::BLE_ID_NUM::BM2, + TheengsDecoder::BLE_ID_NUM::SMARTDRY, + TheengsDecoder::BLE_ID_NUM::SMARTDRY, + TheengsDecoder::BLE_ID_NUM::SMARTDRY, + TheengsDecoder::BLE_ID_NUM::SMARTDRY, + TheengsDecoder::BLE_ID_NUM::SMARTDRY, + TheengsDecoder::BLE_ID_NUM::SMARTDRY, }; // uuid test input [test name] [uuid] [manufacturer data] [service data]