Minimize decompose, remove calls to extract_char, check data length before parsing (#724)

This commit is contained in:
Jon authored and GitHub committed 2020-08-15 08:12:27 -05:00
1 parent a53f8b4339
commit 418c1d0c81
3 files changed
+82 -78

No files matched your search

+71 -64
View File
@@ -61,11 +61,9 @@ struct BLEdevice {
# define device_flags_isBlackL 1 << 2
struct decompose {
char subject[4];
int start;
int len;
bool reverse;
char extract[60];
};
vector<BLEdevice> devices;
@@ -402,9 +400,9 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
for (int i = 0; i < serviceDataLength; i++) {
int a = serviceData[i];
if (a < 16) {
returnedString = returnedString + "0";
returnedString += F("0");
}
returnedString = returnedString + String(a, HEX);
returnedString += String(a, HEX);
}
char service_data[returnedString.length() + 1];
returnedString.toCharArray(service_data, returnedString.length() + 1);
@@ -552,11 +550,12 @@ bool BTtoMQTT() { // for on demand BLE scans
SoftwareSerial softserial(BT_RX, BT_TX);
String returnedString = "";
String returnedString((char*)0);
unsigned long timebt = 0;
// this struct define which parts of the hexadecimal chain we extract and what to do with these parts
struct decompose d[6] = {{"mac", 16, 12, true}, {"typ", 28, 2, false}, {"rsi", 30, 2, false}, {"rdl", 32, 2, false}, {"sty", 44, 4, true}, {"rda", 48, 60, false}};
// {"mac"}, {"typ"}, {"rsi"}, {"rdl"}, {"sty"}, {"rda"}
struct decompose d[6] = {{0, 12, true}, {12, 2, false}, {14, 2, false}, {16, 2, false}, {28, 4, true}, {32, 60, false}};
void setupBT() {
BLEinterval = TimeBtw_Read;
@@ -573,6 +572,9 @@ void setupBT() {
softserial.print(F("AT+PIO11" CR)); // When not connected (as in BLE mode) the LED is off. When connected the LED is solid on.
# endif
delay(100);
# if defined(ESP8266)
returnedString.reserve(512); //reserve memory space for BT Serial. (size should depend on available RAM)
# endif
Log.trace(F("ZgatewayBT HM1X setup done " CR));
}
@@ -581,73 +583,78 @@ bool BTtoMQTT() {
while (softserial.available() > 0) {
int a = softserial.read();
if (a < 16) {
returnedString = returnedString + "0";
returnedString += "0";
}
returnedString = returnedString + String(a, HEX);
returnedString += String(a, HEX);
}
if (millis() > (timebt + BLEinterval)) { //retrieving data
timebt = millis();
# if defined(ESP8266)
yield();
# endif
if (returnedString != "") {
Log.verbose(F("returnedString: %s" CR), (char*)returnedString.c_str());
size_t pos = 0;
while ((pos = returnedString.lastIndexOf(BLEdelimiter)) != -1) {
# if defined(ESP8266)
yield();
# endif
String token = returnedString.substring(pos);
returnedString.remove(pos, returnedString.length());
char token_char[token.length() + 1];
token.toCharArray(token_char, token.length() + 1);
Log.trace(F("Token: %s" CR), token_char);
if (token.length() > 60) { // we extract data only if we have infos (BLEdelimiter length + 4)
for (int i = 0; i < 6; i++) {
extract_char(token_char, d[i].extract, d[i].start, d[i].len, d[i].reverse, false);
if (i == 3)
d[5].len = (int)strtol(d[i].extract, NULL, 16) * 2; // extracting the length of the rest data
}
returnedString.remove(0); //init data string
softserial.print(F(QUESTION_MSG)); //start new discovery
return false;
}
if ((strlen(d[0].extract)) == 12) // if a BLE device is detected we analyse it
{
Log.trace(F("Creating BLE buffer" CR));
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
JsonObject& BLEdata = jsonBuffer.createObject();
strupp(d[0].extract);
String Id;
for (int i = 0; i < 12; i = i + 2) {
Id += String(d[0].extract[i]);
Id += String(d[0].extract[i + 1]);
if (i != 10)
Id += ":";
}
Log.trace(F("Id %s" CR), (char*)Id.c_str());
BLEdata.set("id", (char*)Id.c_str());
BLEdevice* device = getDeviceByMac((char*)Id.c_str());
if (isBlack(device))
return false; //if black listed mac we go out
if (oneWhite && !isWhite(device))
return false; //if we have at least one white mac and this mac is not white we go out
int rssi = (int)strtol(d[2].extract, NULL, 16) - 256;
BLEdata.set("rssi", (int)rssi);
# ifdef subjectHomePresence
haRoomPresence(BLEdata); // this device has an rssi in consequence we can use it for home assistant room presence component
# if defined(ESP8266)
yield();
# endif
Log.trace(F("Service data: %s" CR), d[5].extract);
BLEdata.set("servicedata", d[5].extract);
PublishDeviceData(BLEdata);
}
}
}
returnedString = ""; //init data string
if (returnedString.length() > (BLEdelimiterLength + CRLR_Length)) { //packet has to be at least the (BLEdelimiter + 'CR LF') length
Log.verbose(F("returnedString: %s" CR), (char*)returnedString.c_str());
if (returnedString.equals(F(BLEEndOfDiscovery))) //OK+DISCE
{
returnedString.remove(0); //clear data string
return false;
}
softserial.print(F(QUESTION_MSG));
return false;
} else {
size_t pos = 0, eolPos = 0;
while ((pos = returnedString.indexOf(F(BLEdelimiter))) != -1 && (eolPos = returnedString.indexOf(F(CRLR))) != -1) {
# if defined(ESP8266)
yield();
# endif
String token = returnedString.substring(pos + BLEdelimiterLength, eolPos); //capture a BT device frame
returnedString.remove(0, eolPos + CRLR_Length); //remove frame from main buffer (including 'CR LF' chars)
Log.trace(F("Token: %s" CR), token.c_str());
if (token.length() > 32) { // we extract data only if we have size is at least the size of (MAC, TYPE, RSSI, and Rest Data Length)
String mac = F("");
mac.reserve(17);
for (int i = d[0].start; i < (d[0].start + d[0].len); i += 2) {
mac += token.substring((d[0].start + d[0].len) - i - 2, (d[0].start + d[0].len) - i);
if (i < (d[0].start + d[0].len) - 2)
mac += ":";
}
mac.toUpperCase();
String rssiStr = token.substring(d[2].start, (d[2].start + d[2].len));
int rssi = (int)strtol(rssiStr.c_str(), NULL, 16) - 256;
String restDataLengthStr = token.substring(d[3].start, (d[3].start + d[3].len));
int restDataLength = (int)strtol(restDataLengthStr.c_str(), NULL, 16) * 2;
String restData = F("");
if (restDataLength <= 60)
restData = token.substring(d[5].start, (d[5].start + restDataLength));
Log.trace(F("Creating BLE buffer" CR));
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
JsonObject& BLEdata = jsonBuffer.createObject();
Log.trace(F("Id %s" CR), (char*)mac.c_str());
BLEdata.set("id", (char*)mac.c_str());
BLEdevice* device = getDeviceByMac((char*)mac.c_str());
if (isBlack(device))
return false; //if black listed mac we go out
if (oneWhite && !isWhite(device))
return false; //if we have at least one white mac and this mac is not white we go out
BLEdata.set("rssi", (int)rssi);
# ifdef subjectHomePresence
haRoomPresence(BLEdata); // this device has an rssi in consequence we can use it for home assistant room presence component
# endif
Log.trace(F("Service data: %s" CR), restData.c_str());
BLEdata.set("servicedata", restData.c_str());
PublishDeviceData(BLEdata);
}
}
return false;
}
}
+4
View File
@@ -39,6 +39,10 @@ extern void MQTTtoBT(char* topicOri, JsonObject& RFdata);
//#define HM-11 // uncomment this line if you use HM-11 and comment the line above
//#define HM_BLUE_LED_STOP true //uncomment to stop the blue led light of HM1X
#define BLEdelimiter "4f4b2b444953413a" // OK+DISA:
#define BLEEndOfDiscovery "4f4b2b4449534345" // OK+DISCE
#define BLEdelimiterLength 16
#define CRLR "0d0a"
#define CRLR_Length 4
#define ServicedataMinLength 29
#ifndef TimeBtw_Read
+7 -14
View File
@@ -193,7 +193,7 @@ PubSubClient client(eClient);
//MQTT last attemps reconnection date
unsigned long lastMQTTReconnectAttempt = 0;
void revert_hex_data(char* in, char* out, int l) {
void revert_hex_data(const char* in, char* out, int l) {
//reverting array 2 by 2 to get the data in good order
int i = l - 2, j = 0;
while (i != -2) {
@@ -207,24 +207,17 @@ void revert_hex_data(char* in, char* out, int l) {
out[l - 1] = '\0';
}
void extract_char(char* token_char, char* subset, int start, int l, bool reverse, bool isNumber) {
char tmp_subset[l + 1];
memcpy(tmp_subset, &token_char[start], l);
tmp_subset[l] = '\0';
void extract_char(const char* token_char, char* subset, int start, int l, bool reverse, bool isNumber) {
if (isNumber) {
char tmp_subset2[l + 1];
if (reverse)
revert_hex_data(tmp_subset, tmp_subset2, l + 1);
else
strncpy(tmp_subset2, tmp_subset, l + 1);
long long_value = strtoul(tmp_subset2, NULL, 16);
sprintf(tmp_subset2, "%ld", long_value);
strncpy(subset, tmp_subset2, l + 1);
revert_hex_data(token_char + start, subset, l + 1);
long long_value = strtoul(subset, NULL, 16);
sprintf(subset, "%ld", long_value);
} else {
if (reverse)
revert_hex_data(tmp_subset, subset, l + 1);
revert_hex_data(token_char + start, subset, l + 1);
else
strncpy(subset, tmp_subset, l + 1);
strncpy(subset, token_char + start, l + 1);
}
subset[l] = '\0';
}