Skip to content

Commit

Permalink
SmartDry initial (#165)
Browse files Browse the repository at this point in the history
  • Loading branch information
DigiH authored Jul 28, 2022
1 parent 4fd0a25 commit dba99b1
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ module.exports = {
'devices/RDL52832',
'devices/RuuviTag_RAWv1',
'devices/RuuviTag_RAWv2',
'devices/SDLS',
'devices/SBCS',
'devices/SBCU',
'devices/SBMS',
Expand Down
12 changes: 12 additions & 0 deletions docs/devices/SDLS.md
Original file line number Diff line number Diff line change
@@ -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|
1 change: 1 addition & 0 deletions docs/participate/adding-decoders.md
Original file line number Diff line number Diff line change
Expand Up @@ -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":{
Expand Down
27 changes: 18 additions & 9 deletions src/decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -447,7 +455,8 @@ int TheengsDecoder::decodeBLEJson(JsonObject& jsondata) {
temp_val = (this->*dec_fun)(src, decoder[2].as<int>(),
decoder[3].as<int>(),
decoder[4].as<bool>(),
decoder[5].isNull() ? true : decoder[5].as<bool>());
decoder[5].isNull() ? true : decoder[5].as<bool>(),
decoder[6].isNull() ? false : decoder[6].as<bool>());

} else {
break;
Expand Down
5 changes: 3 additions & 2 deletions src/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class TheengsDecoder {
SBMS,
SBMT,
SBS1,
SMARTDRY,
BM_V23,
MS_CDP,
GAEN,
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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},
Expand Down
61 changes: 61 additions & 0 deletions src/devices/SmartDry_json.h
Original file line number Diff line number Diff line change
@@ -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"
}
}
})"""";*/
18 changes: 18 additions & 0 deletions tests/BLE/test_ble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand Down Expand Up @@ -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[]{
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit dba99b1

Please sign in to comment.