Bugfix: switching brokers with self signed certs. (#1007)
* Fixes BLE scanning being disabled after switching server fails. * Fixes crash caused by BLE scan results arriving while switching servers. * Adds documentation to use the server switching command.
This commit is contained in:
1 parent
05dddf42de
commit
3f13984f44
4 files changed
+105
-77
No files matched your search
+3
-3
@@ -198,7 +198,7 @@ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
||||
# endif
|
||||
|
||||
# ifndef MQTT_SECURE_SELF_SIGNED_CLIENT
|
||||
# define MQTT_SECURE_SELF_SIGNED_CLIENT 1
|
||||
# define MQTT_SECURE_SELF_SIGNED_CLIENT 1 // If using a self signed certificate for the broker and not using client certificates set this to false or 0
|
||||
# endif
|
||||
|
||||
# ifndef MQTT_SECURE_SELF_SIGNED_INDEX_DEFAULT
|
||||
@@ -219,9 +219,9 @@ const char* ss_client_cert PROGMEM = R"EOF("
|
||||
")EOF";
|
||||
|
||||
const char* ss_client_key PROGMEM = R"EOF("
|
||||
-----BEGIN CERTIFICATE-----
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
...
|
||||
-----END CERTIFICATE-----
|
||||
-----END RSA PRIVATE KEY-----
|
||||
")EOF";
|
||||
|
||||
struct ss_certs {
|
||||
|
||||
+67
-65
@@ -623,85 +623,87 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
|
||||
}
|
||||
|
||||
void onResult(BLEAdvertisedDevice* advertisedDevice) {
|
||||
Log.trace(F("Creating BLE buffer" CR));
|
||||
JsonObject& BLEdata = getBTJsonObject();
|
||||
String mac_adress = advertisedDevice->getAddress().toString().c_str();
|
||||
mac_adress.toUpperCase();
|
||||
BLEdata.set("id", (char*)mac_adress.c_str());
|
||||
Log.notice(F("Device detected: %s" CR), (char*)mac_adress.c_str());
|
||||
BLEdevice* device = getDeviceByMac(BLEdata["id"].as<const char*>());
|
||||
if (!ProcessLock) {
|
||||
Log.trace(F("Creating BLE buffer" CR));
|
||||
JsonObject& BLEdata = getBTJsonObject();
|
||||
String mac_adress = advertisedDevice->getAddress().toString().c_str();
|
||||
mac_adress.toUpperCase();
|
||||
BLEdata.set("id", (char*)mac_adress.c_str());
|
||||
Log.notice(F("Device detected: %s" CR), (char*)mac_adress.c_str());
|
||||
BLEdevice* device = getDeviceByMac(BLEdata["id"].as<const char*>());
|
||||
|
||||
# if BLE_FILTER_CONNECTABLE
|
||||
if (device->connect) {
|
||||
Log.notice(F("Filtered connectable device" CR));
|
||||
return;
|
||||
}
|
||||
if (device->connect) {
|
||||
Log.notice(F("Filtered connectable device" CR));
|
||||
return;
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((!oneWhite || isWhite(device)) && !isBlack(device)) { //if not black listed mac we go AND if we have no white mac or this mac is white we go out
|
||||
if (advertisedDevice->haveName())
|
||||
BLEdata.set("name", (char*)advertisedDevice->getName().c_str());
|
||||
if (advertisedDevice->haveManufacturerData()) {
|
||||
char* manufacturerdata = BLEUtils::buildHexData(NULL, (uint8_t*)advertisedDevice->getManufacturerData().data(), advertisedDevice->getManufacturerData().length());
|
||||
Log.trace(F("Manufacturer Data: %s" CR), manufacturerdata);
|
||||
BLEdata.set("manufacturerdata", manufacturerdata);
|
||||
free(manufacturerdata);
|
||||
}
|
||||
if (advertisedDevice->haveRSSI())
|
||||
BLEdata.set("rssi", (int)advertisedDevice->getRSSI());
|
||||
if (advertisedDevice->haveTXPower())
|
||||
BLEdata.set("txpower", (int8_t)advertisedDevice->getTXPower());
|
||||
if (advertisedDevice->haveRSSI() && !publishOnlySensors && hassPresence) {
|
||||
hass_presence(BLEdata); // this device has an rssi and we don't want only sensors so in consequence we can use it for home assistant room presence component
|
||||
}
|
||||
if (advertisedDevice->haveServiceData()) {
|
||||
int serviceDataCount = advertisedDevice->getServiceDataCount();
|
||||
Log.trace(F("Get services data number: %d" CR), serviceDataCount);
|
||||
for (int j = 0; j < serviceDataCount; j++) {
|
||||
std::string service_data = convertServiceData(advertisedDevice->getServiceData(j));
|
||||
Log.trace(F("Service data: %s" CR), service_data.c_str());
|
||||
BLEdata.set("servicedata", (char*)service_data.c_str());
|
||||
std::string serviceDatauuid = advertisedDevice->getServiceDataUUID(j).toString();
|
||||
Log.trace(F("Service data UUID: %s" CR), (char*)serviceDatauuid.c_str());
|
||||
BLEdata.set("servicedatauuid", (char*)serviceDatauuid.c_str());
|
||||
process_bledata(BLEdata); // this will force to resolve all the service data
|
||||
if ((!oneWhite || isWhite(device)) && !isBlack(device)) { //if not black listed mac we go AND if we have no white mac or this mac is white we go out
|
||||
if (advertisedDevice->haveName())
|
||||
BLEdata.set("name", (char*)advertisedDevice->getName().c_str());
|
||||
if (advertisedDevice->haveManufacturerData()) {
|
||||
char* manufacturerdata = BLEUtils::buildHexData(NULL, (uint8_t*)advertisedDevice->getManufacturerData().data(), advertisedDevice->getManufacturerData().length());
|
||||
Log.trace(F("Manufacturer Data: %s" CR), manufacturerdata);
|
||||
BLEdata.set("manufacturerdata", manufacturerdata);
|
||||
free(manufacturerdata);
|
||||
}
|
||||
|
||||
if (serviceDataCount > 1) {
|
||||
BLEdata.remove("servicedata");
|
||||
BLEdata.remove("servicedatauuid");
|
||||
|
||||
int msglen = BLEdata.measureLength() + 1;
|
||||
char jsonmsg[msglen];
|
||||
char jsonmsgb[msglen];
|
||||
BLEdata.printTo(jsonmsgb, sizeof(jsonmsgb));
|
||||
if (advertisedDevice->haveRSSI())
|
||||
BLEdata.set("rssi", (int)advertisedDevice->getRSSI());
|
||||
if (advertisedDevice->haveTXPower())
|
||||
BLEdata.set("txpower", (int8_t)advertisedDevice->getTXPower());
|
||||
if (advertisedDevice->haveRSSI() && !publishOnlySensors && hassPresence) {
|
||||
hass_presence(BLEdata); // this device has an rssi and we don't want only sensors so in consequence we can use it for home assistant room presence component
|
||||
}
|
||||
if (advertisedDevice->haveServiceData()) {
|
||||
int serviceDataCount = advertisedDevice->getServiceDataCount();
|
||||
Log.trace(F("Get services data number: %d" CR), serviceDataCount);
|
||||
for (int j = 0; j < serviceDataCount; j++) {
|
||||
strcpy(jsonmsg, jsonmsgb); // the parse _destroys_ the message buffer
|
||||
JsonObject& BLEdataLocal = getBTJsonObject(jsonmsg, j == 0); // note, that first time we will get here the BLEdata itself; haPresence for the first msg
|
||||
if (!BLEdataLocal.containsKey("id")) { // would crash without id
|
||||
Log.trace("Json parsing error for %s" CR, jsonmsgb);
|
||||
break;
|
||||
}
|
||||
std::string service_data = convertServiceData(advertisedDevice->getServiceData(j));
|
||||
Log.trace(F("Service data: %s" CR), service_data.c_str());
|
||||
BLEdata.set("servicedata", (char*)service_data.c_str());
|
||||
std::string serviceDatauuid = advertisedDevice->getServiceDataUUID(j).toString();
|
||||
Log.trace(F("Service data UUID: %s" CR), (char*)serviceDatauuid.c_str());
|
||||
BLEdata.set("servicedatauuid", (char*)serviceDatauuid.c_str());
|
||||
process_bledata(BLEdata); // this will force to resolve all the service data
|
||||
}
|
||||
|
||||
int last = atomic_load_explicit(&jsonBTBufferQueueLast, ::memory_order_seq_cst) % BTQueueSize;
|
||||
int size1 = jsonBTBufferQueue[last].buffer.size();
|
||||
BLEdataLocal.set("servicedata", (char*)service_data.c_str());
|
||||
int size2 = jsonBTBufferQueue[last].buffer.size();
|
||||
BLEdataLocal.set("servicedatauuid", (char*)serviceDatauuid.c_str());
|
||||
int size3 = jsonBTBufferQueue[last].buffer.size();
|
||||
Log.trace("Buffersize for %d : %d -> %d -> %d" CR, j, size1, size2, size3);
|
||||
PublishDeviceData(BLEdataLocal);
|
||||
if (serviceDataCount > 1) {
|
||||
BLEdata.remove("servicedata");
|
||||
BLEdata.remove("servicedatauuid");
|
||||
|
||||
int msglen = BLEdata.measureLength() + 1;
|
||||
char jsonmsg[msglen];
|
||||
char jsonmsgb[msglen];
|
||||
BLEdata.printTo(jsonmsgb, sizeof(jsonmsgb));
|
||||
for (int j = 0; j < serviceDataCount; j++) {
|
||||
strcpy(jsonmsg, jsonmsgb); // the parse _destroys_ the message buffer
|
||||
JsonObject& BLEdataLocal = getBTJsonObject(jsonmsg, j == 0); // note, that first time we will get here the BLEdata itself; haPresence for the first msg
|
||||
if (!BLEdataLocal.containsKey("id")) { // would crash without id
|
||||
Log.trace("Json parsing error for %s" CR, jsonmsgb);
|
||||
break;
|
||||
}
|
||||
std::string service_data = convertServiceData(advertisedDevice->getServiceData(j));
|
||||
std::string serviceDatauuid = advertisedDevice->getServiceDataUUID(j).toString();
|
||||
|
||||
int last = atomic_load_explicit(&jsonBTBufferQueueLast, ::memory_order_seq_cst) % BTQueueSize;
|
||||
int size1 = jsonBTBufferQueue[last].buffer.size();
|
||||
BLEdataLocal.set("servicedata", (char*)service_data.c_str());
|
||||
int size2 = jsonBTBufferQueue[last].buffer.size();
|
||||
BLEdataLocal.set("servicedatauuid", (char*)serviceDatauuid.c_str());
|
||||
int size3 = jsonBTBufferQueue[last].buffer.size();
|
||||
Log.trace("Buffersize for %d : %d -> %d -> %d" CR, j, size1, size2, size3);
|
||||
PublishDeviceData(BLEdataLocal);
|
||||
}
|
||||
} else {
|
||||
PublishDeviceData(BLEdata, false); // easy case
|
||||
}
|
||||
} else {
|
||||
PublishDeviceData(BLEdata, false); // easy case
|
||||
PublishDeviceData(BLEdata); // PublishDeviceData has its own logic whether it needs to publish the json or not
|
||||
}
|
||||
} else {
|
||||
PublishDeviceData(BLEdata); // PublishDeviceData has its own logic whether it needs to publish the json or not
|
||||
Log.trace(F("Filtered mac device" CR));
|
||||
}
|
||||
} else {
|
||||
Log.trace(F("Filtered mac device" CR));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+14
-9
@@ -868,6 +868,7 @@ void setupTLS(bool self_signed, uint8_t index) {
|
||||
WiFiClientSecure* sClient = (WiFiClientSecure*)eClient;
|
||||
# if MQTT_SECURE_SELF_SIGNED
|
||||
if (self_signed) {
|
||||
Log.notice(F("Using self signed cert index %u" CR), index);
|
||||
# if defined(ESP32)
|
||||
sClient->setCACert(certs_array[index].server_cert);
|
||||
# if MQTT_SECURE_SELF_SIGNED_CLIENT
|
||||
@@ -1881,33 +1882,32 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
|
||||
}
|
||||
|
||||
if (SYSdata.containsKey("mqtt_user") && SYSdata.containsKey("mqtt_pass")) {
|
||||
# if defined(ZgatewayBT) && defined(ESP32)
|
||||
stopProcessing();
|
||||
# endif
|
||||
client.disconnect();
|
||||
bool update_server = false;
|
||||
bool secure_connect = SYSdata.get<bool>("mqtt_secure");
|
||||
void* prev_client = nullptr;
|
||||
bool use_ss_cert = SYSdata.containsKey("mqtt_ss_cert");
|
||||
bool use_ss_cert = SYSdata.containsKey("mqtt_cert_index");
|
||||
uint8_t cert_index = mqtt_ss_index;
|
||||
|
||||
if (SYSdata.containsKey("mqtt_server") && SYSdata.containsKey("mqtt_port")) {
|
||||
if (!SYSdata.containsKey("mqtt_secure")) {
|
||||
Log.warning(F("mqtt_server provided without mqtt_secure defined - ignoring command" CR));
|
||||
Log.error(F("mqtt_server provided without mqtt_secure defined - ignoring command" CR));
|
||||
return;
|
||||
}
|
||||
# if MQTT_SECURE_SELF_SIGNED
|
||||
if (use_ss_cert) {
|
||||
cert_index = SYSdata.get<uint8_t>("mqtt_ss_cert");
|
||||
cert_index = SYSdata.get<uint8_t>("mqtt_cert_index");
|
||||
if (cert_index >= sizeof(certs_array) / sizeof(ss_certs)) {
|
||||
Log.warning(F("mqtt_ss_cert index invalid - ignoring command" CR));
|
||||
Log.error(F("mqtt_cert_index invalid - ignoring command" CR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
# if defined(ZgatewayBT) && defined(ESP32)
|
||||
stopProcessing();
|
||||
# endif
|
||||
client.disconnect();
|
||||
update_server = true;
|
||||
|
||||
if (secure_connect != mqtt_secure) {
|
||||
prev_client = eClient;
|
||||
if (!mqtt_secure) {
|
||||
@@ -1925,6 +1925,11 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
|
||||
}
|
||||
|
||||
client.setServer(SYSdata.get<const char*>("mqtt_server"), SYSdata.get<unsigned int>("mqtt_port"));
|
||||
} else {
|
||||
# if defined(ZgatewayBT) && defined(ESP32)
|
||||
stopProcessing();
|
||||
# endif
|
||||
client.disconnect();
|
||||
}
|
||||
|
||||
String prev_user = mqtt_user;
|
||||
|
||||
Reference in new issue
Block a user