Use references & flash strings where approperate (#110)

* pass originId as const reference
* store strings for serial logging in flash
* Use string references where approperate.
This commit is contained in:
rjwats 2020-05-21 08:42:21 +01:00 committed by GitHub
parent 4e6823ceec
commit 0e2124062f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 85 additions and 90 deletions

View File

@ -365,7 +365,7 @@ You may listen for changes to state by registering an update handler callback. I
```cpp
// register an update handler
update_handler_id_t myUpdateHandler = lightStateService.addUpdateHandler(
[&](String originId) {
[&](const String& originId) {
Serial.println("The light's state has been updated");
}
);
@ -588,7 +588,7 @@ Observe changes to the WiFiSettings:
```cpp
esp8266React.getWiFiSettingsService()->addUpdateHandler(
[&](String originId) {
[&](const String& originId) {
Serial.println("The WiFi Settings were updated!");
}
);

View File

@ -8,9 +8,8 @@ APSettingsService::APSettingsService(AsyncWebServer* server, FS* fs, SecurityMan
AP_SETTINGS_SERVICE_PATH,
securityManager),
_fsPersistence(APSettings::serialize, APSettings::deserialize, this, fs, AP_SETTINGS_FILE),
_lastManaged(0),
_dnsServer(nullptr) {
addUpdateHandler([&](String originId) { reconfigureAP(); }, false);
addUpdateHandler([&](const String& originId) { reconfigureAP(); }, false);
}
void APSettingsService::begin() {
@ -47,11 +46,11 @@ void APSettingsService::manageAP() {
}
void APSettingsService::startAP() {
Serial.println("Starting software access point");
Serial.println(F("Starting software access point"));
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str());
if (!_dnsServer) {
IPAddress apIp = WiFi.softAPIP();
Serial.print("Starting captive portal on ");
Serial.print(F("Starting captive portal on "));
Serial.println(apIp);
_dnsServer = new DNSServer;
_dnsServer->start(DNS_PORT, "*", apIp);
@ -60,12 +59,12 @@ void APSettingsService::startAP() {
void APSettingsService::stopAP() {
if (_dnsServer) {
Serial.println("Stopping captive portal");
Serial.println(F("Stopping captive portal"));
_dnsServer->stop();
delete _dnsServer;
_dnsServer = nullptr;
}
Serial.println("Stopping software access point");
Serial.println(F("Stopping software access point"));
WiFi.softAPdisconnect(true);
}

View File

@ -32,7 +32,8 @@ class FSPersistence {
DynamicJsonDocument jsonDocument = DynamicJsonDocument(MAX_FILE_SIZE);
DeserializationError error = deserializeJson(jsonDocument, settingsFile);
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
updateSettings(jsonDocument.as<JsonObject>());
JsonObject jsonObject = jsonDocument.as<JsonObject>();
_statefulService->updateWithoutPropagation(jsonObject, _jsonDeserializer);
settingsFile.close();
return;
}
@ -74,7 +75,7 @@ class FSPersistence {
void enableUpdateHandler() {
if (!_updateHandlerId) {
_updateHandlerId = _statefulService->addUpdateHandler([&](String originId) { writeToFS(); });
_updateHandlerId = _statefulService->addUpdateHandler([&](const String& originId) { writeToFS(); });
}
}
@ -86,17 +87,13 @@ class FSPersistence {
char const* _filePath;
update_handler_id_t _updateHandlerId = 0;
// update the settings, but do not call propogate
void updateSettings(JsonObject root) {
_statefulService->updateWithoutPropagation(root, _jsonDeserializer);
}
protected:
// We assume the deserializer supplies sensible defaults if an empty object
// is supplied, this virtual function allows that to be changed.
virtual void applyDefaults() {
DynamicJsonDocument jsonDocument = DynamicJsonDocument(MAX_FILE_SIZE);
updateSettings(jsonDocument.to<JsonObject>());
JsonObject jsonObject = jsonDocument.as<JsonObject>();
_statefulService->updateWithoutPropagation(jsonObject, _jsonDeserializer);
}
};

View File

@ -7,14 +7,14 @@
class JsonUtils {
public:
static void readIP(JsonObject& root, String key, IPAddress& _ip) {
if (!root[key].is<String>() || !_ip.fromString(root[key].as<String>())) {
_ip = INADDR_NONE;
static void readIP(JsonObject& root, const String& key, IPAddress& ip) {
if (!root[key].is<String>() || !ip.fromString(root[key].as<String>())) {
ip = INADDR_NONE;
}
}
static void writeIP(JsonObject& root, String key, IPAddress& _ip) {
if (_ip != INADDR_NONE) {
root[key] = _ip.toString();
static void writeIP(JsonObject& root, const String& key, const IPAddress& ip) {
if (ip != INADDR_NONE) {
root[key] = ip.toString();
}
}
};

View File

@ -34,12 +34,12 @@ class MqttPub : virtual public MqttConnector<T> {
MqttPub(JsonSerializer<T> jsonSerializer,
StatefulService<T>* statefulService,
AsyncMqttClient* mqttClient,
String pubTopic = "") :
const String& pubTopic = "") :
MqttConnector<T>(statefulService, mqttClient), _jsonSerializer(jsonSerializer), _pubTopic(pubTopic) {
MqttConnector<T>::_statefulService->addUpdateHandler([&](String originId) { publish(); }, false);
MqttConnector<T>::_statefulService->addUpdateHandler([&](const String& originId) { publish(); }, false);
}
void setPubTopic(String pubTopic) {
void setPubTopic(const String& pubTopic) {
_pubTopic = pubTopic;
publish();
}
@ -76,7 +76,7 @@ class MqttSub : virtual public MqttConnector<T> {
MqttSub(JsonDeserializer<T> jsonDeserializer,
StatefulService<T>* statefulService,
AsyncMqttClient* mqttClient,
String subTopic = "") :
const String& subTopic = "") :
MqttConnector<T>(statefulService, mqttClient), _jsonDeserializer(jsonDeserializer), _subTopic(subTopic) {
MqttConnector<T>::_mqttClient->onMessage(std::bind(&MqttSub::onMqttMessage,
this,
@ -88,7 +88,7 @@ class MqttSub : virtual public MqttConnector<T> {
std::placeholders::_6));
}
void setSubTopic(String subTopic) {
void setSubTopic(const String& subTopic) {
if (!_subTopic.equals(subTopic)) {
// unsubscribe from the existing topic if one was set
if (_subTopic.length() > 0) {
@ -143,15 +143,15 @@ class MqttPubSub : public MqttPub<T>, public MqttSub<T> {
JsonDeserializer<T> jsonDeserializer,
StatefulService<T>* statefulService,
AsyncMqttClient* mqttClient,
String pubTopic = "",
String subTopic = "") :
const String& pubTopic = "",
const String& subTopic = "") :
MqttConnector<T>(statefulService, mqttClient),
MqttPub<T>(jsonSerializer, statefulService, mqttClient, pubTopic),
MqttSub<T>(jsonDeserializer, statefulService, mqttClient, subTopic) {
}
public:
void configureTopics(String pubTopic, String subTopic) {
void configureTopics(const String& pubTopic, const String& subTopic) {
MqttSub<T>::setSubTopic(subTopic);
MqttPub<T>::setPubTopic(pubTopic);
}

View File

@ -42,7 +42,7 @@ MqttSettingsService::MqttSettingsService(AsyncWebServer* server, FS* fs, Securit
#endif
_mqttClient.onConnect(std::bind(&MqttSettingsService::onMqttConnect, this, std::placeholders::_1));
_mqttClient.onDisconnect(std::bind(&MqttSettingsService::onMqttDisconnect, this, std::placeholders::_1));
addUpdateHandler([&](String originId) { onConfigUpdated(); }, false);
addUpdateHandler([&](const String& originId) { onConfigUpdated(); }, false);
}
MqttSettingsService::~MqttSettingsService() {
@ -84,13 +84,16 @@ AsyncMqttClient* MqttSettingsService::getMqttClient() {
}
void MqttSettingsService::onMqttConnect(bool sessionPresent) {
Serial.print("Connected to MQTT, ");
Serial.print(sessionPresent ? "with" : "without");
Serial.println(" persistent session");
Serial.print(F("Connected to MQTT, "));
if (sessionPresent) {
Serial.println(F("with persistent session"));
} else {
Serial.println(F("without persistent session"));
}
}
void MqttSettingsService::onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.print("Disconnected from MQTT reason: ");
Serial.print(F("Disconnected from MQTT reason: "));
Serial.println((uint8_t)reason);
_disconnectReason = reason;
_disconnectedAt = millis();
@ -104,28 +107,28 @@ void MqttSettingsService::onConfigUpdated() {
#ifdef ESP32
void MqttSettingsService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
if (_state.enabled) {
Serial.println("WiFi connection dropped, starting MQTT client.");
Serial.println(F("WiFi connection dropped, starting MQTT client."));
onConfigUpdated();
}
}
void MqttSettingsService::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
if (_state.enabled) {
Serial.println("WiFi connection dropped, stopping MQTT client.");
Serial.println(F("WiFi connection dropped, stopping MQTT client."));
onConfigUpdated();
}
}
#elif defined(ESP8266)
void MqttSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
if (_state.enabled) {
Serial.println("WiFi connection dropped, starting MQTT client.");
Serial.println(F("WiFi connection dropped, starting MQTT client."));
onConfigUpdated();
}
}
void MqttSettingsService::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) {
if (_state.enabled) {
Serial.println("WiFi connection dropped, stopping MQTT client.");
Serial.println(F("WiFi connection dropped, stopping MQTT client."));
onConfigUpdated();
}
}
@ -137,7 +140,7 @@ void MqttSettingsService::configureMqtt() {
// only connect if WiFi is connected and MQTT is enabled
if (_state.enabled && WiFi.isConnected()) {
Serial.println("Connecting to MQTT...");
Serial.println(F("Connecting to MQTT..."));
_mqttClient.setServer(retainCstr(_state.host.c_str(), &_retainedHost), _state.port);
if (_state.username.length() > 0) {
_mqttClient.setCredentials(

View File

@ -20,7 +20,7 @@ NTPSettingsService::NTPSettingsService(AsyncWebServer* server, FS* fs, SecurityM
_onStationModeGotIPHandler =
WiFi.onStationModeGotIP(std::bind(&NTPSettingsService::onStationModeGotIP, this, std::placeholders::_1));
#endif
addUpdateHandler([&](String originId) { configureNTP(); }, false);
addUpdateHandler([&](const String& originId) { configureNTP(); }, false);
}
void NTPSettingsService::begin() {
@ -30,29 +30,29 @@ void NTPSettingsService::begin() {
#ifdef ESP32
void NTPSettingsService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.println("Got IP address, starting NTP Synchronization");
Serial.println(F("Got IP address, starting NTP Synchronization"));
configureNTP();
}
void NTPSettingsService::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.println("WiFi connection dropped, stopping NTP.");
Serial.println(F("WiFi connection dropped, stopping NTP."));
configureNTP();
}
#elif defined(ESP8266)
void NTPSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
Serial.println("Got IP address, starting NTP Synchronization");
Serial.println(F("Got IP address, starting NTP Synchronization"));
configureNTP();
}
void NTPSettingsService::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) {
Serial.println("WiFi connection dropped, stopping NTP.");
Serial.println(F("WiFi connection dropped, stopping NTP."));
configureNTP();
}
#endif
void NTPSettingsService::configureNTP() {
if (WiFi.isConnected() && _state.enabled) {
Serial.println("Starting NTP...");
Serial.println(F("Starting NTP..."));
#ifdef ESP32
configTzTime(_state.tzFormat.c_str(), _state.server.c_str());
#elif defined(ESP8266)

View File

@ -16,7 +16,7 @@ OTASettingsService::OTASettingsService(AsyncWebServer* server, FS* fs, SecurityM
_onStationModeGotIPHandler =
WiFi.onStationModeGotIP(std::bind(&OTASettingsService::onStationModeGotIP, this, std::placeholders::_1));
#endif
addUpdateHandler([&](String originId) { configureArduinoOTA(); }, false);
addUpdateHandler([&](const String& originId) { configureArduinoOTA(); }, false);
}
void OTASettingsService::begin() {
@ -39,27 +39,27 @@ void OTASettingsService::configureArduinoOTA() {
_arduinoOTA = nullptr;
}
if (_state.enabled) {
Serial.println("Starting OTA Update Service...");
Serial.println(F("Starting OTA Update Service..."));
_arduinoOTA = new ArduinoOTAClass;
_arduinoOTA->setPort(_state.port);
_arduinoOTA->setPassword(_state.password.c_str());
_arduinoOTA->onStart([]() { Serial.println("Starting"); });
_arduinoOTA->onEnd([]() { Serial.println("\nEnd"); });
_arduinoOTA->onStart([]() { Serial.println(F("Starting")); });
_arduinoOTA->onEnd([]() { Serial.println(F("\r\nEnd")); });
_arduinoOTA->onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
Serial.printf_P(PSTR("Progress: %u%%\r\n"), (progress / (total / 100)));
});
_arduinoOTA->onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR)
Serial.println("Auth Failed");
Serial.println(F("Auth Failed"));
else if (error == OTA_BEGIN_ERROR)
Serial.println("Begin Failed");
Serial.println(F("Begin Failed"));
else if (error == OTA_CONNECT_ERROR)
Serial.println("Connect Failed");
Serial.println(F("Connect Failed"));
else if (error == OTA_RECEIVE_ERROR)
Serial.println("Receive Failed");
Serial.println(F("Receive Failed"));
else if (error == OTA_END_ERROR)
Serial.println("End Failed");
Serial.println(F("End Failed"));
});
_arduinoOTA->begin();
}

View File

@ -65,7 +65,7 @@ class SecurityManager {
/*
* Authenticate, returning the user if found
*/
virtual Authentication authenticate(String& username, String& password) = 0;
virtual Authentication authenticate(const String& username, const String& password) = 0;
/*
* Check the request header for the Authorization token

View File

@ -8,7 +8,7 @@ SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs)
SECURITY_SETTINGS_PATH,
this),
_fsPersistence(SecuritySettings::serialize, SecuritySettings::deserialize, this, fs, SECURITY_SETTINGS_FILE) {
addUpdateHandler([&](String originId) { configureJWTHandler(); }, false);
addUpdateHandler([&](const String& originId) { configureJWTHandler(); }, false);
}
void SecuritySettingsService::begin() {
@ -51,7 +51,7 @@ Authentication SecuritySettingsService::authenticateJWT(String& jwt) {
return Authentication();
}
Authentication SecuritySettingsService::authenticate(String& username, String& password) {
Authentication SecuritySettingsService::authenticate(const String& username, const String& password) {
for (User _user : _state.users) {
if (_user.username == username && _user.password == password) {
return Authentication(_user);

View File

@ -67,7 +67,7 @@ class SecuritySettingsService : public StatefulService<SecuritySettings>, public
void begin();
// Functions to implement SecurityManager
Authentication authenticate(String& username, String& password);
Authentication authenticate(const String& username, const String& password);
Authentication authenticateRequest(AsyncWebServerRequest* request);
String generateJWT(User* user);
ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate);

View File

@ -13,7 +13,7 @@
#endif
typedef size_t update_handler_id_t;
typedef std::function<void(String originId)> StateUpdateCallback;
typedef std::function<void(const String& originId)> StateUpdateCallback;
static update_handler_id_t currentUpdatedHandlerId;
typedef struct StateUpdateHandlerInfo {
@ -76,7 +76,7 @@ class StatefulService {
#endif
}
void update(std::function<void(T&)> callback, String originId) {
void update(std::function<void(T&)> callback, const String& originId) {
#ifdef ESP32
xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY);
#endif
@ -87,7 +87,7 @@ class StatefulService {
#endif
}
void update(JsonObject& jsonObject, JsonDeserializer<T> deserializer, String originId) {
void update(JsonObject& jsonObject, JsonDeserializer<T> deserializer, const String& originId) {
#ifdef ESP32
xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY);
#endif
@ -118,7 +118,7 @@ class StatefulService {
#endif
}
void callUpdateHandlers(String originId) {
void callUpdateHandlers(const String& originId) {
for (const StateUpdateHandlerInfo_t& updateHandler : _updateHandlers) {
updateHandler._cb(originId);
}

View File

@ -79,8 +79,8 @@ class WebSocketTx : virtual public WebSocketConnector<T> {
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN) :
WebSocketConnector<T>(statefulService, server, webSocketPath, securityManager, authenticationPredicate),
_jsonSerializer(jsonSerializer) {
WebSocketConnector<T>::_statefulService->addUpdateHandler([&](String originId) { transmitData(nullptr, originId); },
false);
WebSocketConnector<T>::_statefulService->addUpdateHandler(
[&](const String& originId) { transmitData(nullptr, originId); }, false);
}
WebSocketTx(JsonSerializer<T> jsonSerializer,
@ -88,8 +88,8 @@ class WebSocketTx : virtual public WebSocketConnector<T> {
AsyncWebServer* server,
char const* webSocketPath) :
WebSocketConnector<T>(statefulService, server, webSocketPath), _jsonSerializer(jsonSerializer) {
WebSocketConnector<T>::_statefulService->addUpdateHandler([&](String originId) { transmitData(nullptr, originId); },
false);
WebSocketConnector<T>::_statefulService->addUpdateHandler(
[&](const String& originId) { transmitData(nullptr, originId); }, false);
}
protected:
@ -129,7 +129,7 @@ class WebSocketTx : virtual public WebSocketConnector<T> {
* Original implementation sent clients their own IDs so they could ignore updates they initiated. This approach
* simplifies the client and the server implementation but may not be sufficent for all use-cases.
*/
void transmitData(AsyncWebSocketClient* client, String originId) {
void transmitData(AsyncWebSocketClient* client, const String& originId) {
DynamicJsonDocument jsonDocument = DynamicJsonDocument(WEB_SOCKET_MSG_SIZE);
JsonObject root = jsonDocument.to<JsonObject>();
root["type"] = "payload";

View File

@ -31,7 +31,7 @@ WiFiSettingsService::WiFiSettingsService(AsyncWebServer* server, FS* fs, Securit
std::bind(&WiFiSettingsService::onStationModeDisconnected, this, std::placeholders::_1));
#endif
addUpdateHandler([&](String originId) { reconfigureWiFiConnection(); }, false);
addUpdateHandler([&](const String& originId) { reconfigureWiFiConnection(); }, false);
}
void WiFiSettingsService::begin() {
@ -68,7 +68,7 @@ void WiFiSettingsService::manageSTA() {
}
// Connect or reconnect as required
if ((WiFi.getMode() & WIFI_STA) == 0) {
Serial.println("Connecting to WiFi.");
Serial.println(F("Connecting to WiFi."));
if (_state.staticIPConfig) {
// configure for static IP
WiFi.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2);

View File

@ -18,36 +18,32 @@ WiFiStatus::WiFiStatus(AsyncWebServer* server, SecurityManager* securityManager)
#ifdef ESP32
void WiFiStatus::onStationModeConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.println("WiFi Connected.");
Serial.println(F("WiFi Connected."));
}
void WiFiStatus::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("WiFi Disconnected. Reason code=");
Serial.print(F("WiFi Disconnected. Reason code="));
Serial.println(info.disconnected.reason);
}
void WiFiStatus::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("WiFi Got IP. localIP=");
Serial.print(WiFi.localIP().toString());
Serial.print(", hostName=");
Serial.println(WiFi.getHostname());
Serial.printf_P(
PSTR("WiFi Got IP. localIP=%s, hostName=%s\r\n"), WiFi.localIP().toString().c_str(), WiFi.getHostname());
}
#elif defined(ESP8266)
void WiFiStatus::onStationModeConnected(const WiFiEventStationModeConnected& event) {
Serial.print("WiFi Connected. SSID=");
Serial.print(F("WiFi Connected. SSID="));
Serial.println(event.ssid);
}
void WiFiStatus::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) {
Serial.print("WiFi Disconnected. Reason code=");
Serial.print(F("WiFi Disconnected. Reason code="));
Serial.println(event.reason);
}
void WiFiStatus::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
Serial.print("WiFi Got IP. localIP=");
Serial.print(event.ip);
Serial.print(", hostName=");
Serial.println(WiFi.hostname());
Serial.printf_P(
PSTR("WiFi Got IP. localIP=%s, hostName=%s\r\n"), event.ip.toString().c_str(), WiFi.hostname().c_str());
}
#endif

View File

@ -28,10 +28,10 @@ LightStateService::LightStateService(AsyncWebServer* server,
_mqttClient->onConnect(std::bind(&LightStateService::registerConfig, this));
// configure update handler for when the light settings change
_lightMqttSettingsService->addUpdateHandler([&](String originId) { registerConfig(); }, false);
_lightMqttSettingsService->addUpdateHandler([&](const String& originId) { registerConfig(); }, false);
// configure settings service update handler to update LED state
addUpdateHandler([&](String originId) { onConfigUpdated(); }, false);
addUpdateHandler([&](const String& originId) { onConfigUpdated(); }, false);
}
void LightStateService::begin() {
@ -48,14 +48,14 @@ void LightStateService::registerConfig() {
return;
}
String configTopic;
String setTopic;
String stateTopic;
String subTopic;
String pubTopic;
DynamicJsonDocument doc(256);
_lightMqttSettingsService->read([&](LightMqttSettings& settings) {
configTopic = settings.mqttPath + "/config";
setTopic = settings.mqttPath + "/set";
stateTopic = settings.mqttPath + "/state";
subTopic = settings.mqttPath + "/set";
pubTopic = settings.mqttPath + "/state";
doc["~"] = settings.mqttPath;
doc["name"] = settings.name;
doc["unique_id"] = settings.uniqueId;
@ -69,5 +69,5 @@ void LightStateService::registerConfig() {
serializeJson(doc, payload);
_mqttClient->publish(configTopic.c_str(), 0, false, payload.c_str());
_mqttPubSub.configureTopics(stateTopic, setTopic);
_mqttPubSub.configureTopics(pubTopic, subTopic);
}