allow to set config values

This commit is contained in:
technyon
2022-04-09 20:20:52 +02:00
parent 3111c59e0b
commit 1db1022819
6 changed files with 125 additions and 23 deletions

View File

@@ -12,6 +12,11 @@ Network::Network(Preferences* preferences)
_preferences(preferences) _preferences(preferences)
{ {
nwInst = this; nwInst = this;
_configTopics.reserve(3);
_configTopics.push_back(mqtt_topic_config_button_enabled);
_configTopics.push_back(mqtt_topic_config_led_enabled);
_configTopics.push_back(mqtt_topic_config_led_brightness);
} }
void Network::initialize() void Network::initialize()
@@ -129,9 +134,11 @@ bool Network::reconnect()
_mqttConnected = true; _mqttConnected = true;
delay(200); delay(200);
subscribe(mqtt_topic_lockstate_action); subscribe(mqtt_topic_lockstate_action);
subscribe(mqtt_topic_config_button_enabled);
subscribe(mqtt_topic_config_led_enabled); for(auto topic : _configTopics)
subscribe(mqtt_topic_config_led_brightness); {
subscribe(topic);
}
} }
else else
{ {
@@ -197,6 +204,17 @@ void Network::onMqttDataReceived(char *&topic, byte *&payload, unsigned int &len
} }
publishString(mqtt_topic_lockstate_action, ""); publishString(mqtt_topic_lockstate_action, "");
} }
for(auto configTopic : _configTopics)
{
if(comparePrefixedPath(topic, configTopic))
{
if(_configUpdateReceivedCallback != nullptr)
{
_configUpdateReceivedCallback(configTopic, value);
}
}
}
} }
void Network::publishKeyTurnerState(const Nuki::KeyTurnerState& keyTurnerState, const Nuki::KeyTurnerState& lastKeyTurnerState) void Network::publishKeyTurnerState(const Nuki::KeyTurnerState& keyTurnerState, const Nuki::KeyTurnerState& lastKeyTurnerState)
@@ -264,11 +282,16 @@ void Network::publishPresenceDetection(char *csv)
_presenceCsv = csv; _presenceCsv = csv;
} }
void Network::setLockActionReceived(void (*lockActionReceivedCallback)(const char *)) void Network::setLockActionReceivedCallback(void (*lockActionReceivedCallback)(const char *))
{ {
_lockActionReceivedCallback = lockActionReceivedCallback; _lockActionReceivedCallback = lockActionReceivedCallback;
} }
void Network::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char *, const char *))
{
_configUpdateReceivedCallback = configUpdateReceivedCallback;
}
void Network::publishFloat(const char* topic, const float value, const uint8_t precision) void Network::publishFloat(const char* topic, const float value, const uint8_t precision)
{ {
char str[30]; char str[30];

View File

@@ -3,6 +3,7 @@
#include <PubSubClient.h> #include <PubSubClient.h>
#include <WiFiClient.h> #include <WiFiClient.h>
#include <Preferences.h> #include <Preferences.h>
#include <vector>
#include "NukiConstants.h" #include "NukiConstants.h"
#include "SpiffsCookie.h" #include "SpiffsCookie.h"
@@ -22,7 +23,8 @@ public:
void publishConfig(const Nuki::Config& config); void publishConfig(const Nuki::Config& config);
void publishPresenceDetection(char* csv); void publishPresenceDetection(char* csv);
void setLockActionReceived(void (*lockActionReceivedCallback)(const char* value)); void setLockActionReceivedCallback(void (*lockActionReceivedCallback)(const char* value));
void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* path, const char* value));
void restartAndConfigureWifi(); void restartAndConfigureWifi();
@@ -56,7 +58,10 @@ private:
char* _presenceCsv = nullptr; char* _presenceCsv = nullptr;
std::vector<char*> _configTopics;
bool _firstTunerStatePublish = true; bool _firstTunerStatePublish = true;
void (*_lockActionReceivedCallback)(const char* value) = NULL; void (*_lockActionReceivedCallback)(const char* value) = nullptr;
void (*_configUpdateReceivedCallback)(const char* path, const char* value) = nullptr;
}; };

View File

@@ -1,6 +1,7 @@
#include "NukiWrapper.h" #include "NukiWrapper.h"
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include "PreferencesKeys.h" #include "PreferencesKeys.h"
#include "MqttTopics.h"
NukiWrapper* nukiInst; NukiWrapper* nukiInst;
@@ -18,7 +19,8 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, Network* ne
memset(&_keyTurnerState, sizeof(Nuki::KeyTurnerState), 0); memset(&_keyTurnerState, sizeof(Nuki::KeyTurnerState), 0);
_keyTurnerState.lockState = Nuki::LockState::Undefined; _keyTurnerState.lockState = Nuki::LockState::Undefined;
network->setLockActionReceived(nukiInst->onLockActionReceived); network->setLockActionReceivedCallback(nukiInst->onLockActionReceivedCallback);
network->setConfigUpdateReceivedCallback(nukiInst->onConfigUpdateReceivedCallback);
} }
@@ -112,6 +114,11 @@ void NukiWrapper::update()
memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(Nuki::KeyTurnerState)); memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(Nuki::KeyTurnerState));
} }
void NukiWrapper::setPin(const uint16_t pin)
{
_nukiBle.saveSecurityPincode(pin);
}
void NukiWrapper::updateKeyTurnerState() void NukiWrapper::updateKeyTurnerState()
{ {
_nukiBle.requestKeyTurnerState(&_keyTurnerState); _nukiBle.requestKeyTurnerState(&_keyTurnerState);
@@ -162,11 +169,42 @@ Nuki::LockAction NukiWrapper::lockActionToEnum(const char *str)
return (Nuki::LockAction)0xff; return (Nuki::LockAction)0xff;
} }
void NukiWrapper::onLockActionReceived(const char *value) void NukiWrapper::onLockActionReceivedCallback(const char *value)
{ {
nukiInst->_nextLockAction = nukiInst->lockActionToEnum(value); nukiInst->_nextLockAction = nukiInst->lockActionToEnum(value);
} }
void NukiWrapper::onConfigUpdateReceivedCallback(const char *topic, const char *value)
{
nukiInst->onConfigUpdateReceived(topic, value);
}
void NukiWrapper::onConfigUpdateReceived(const char *topic, const char *value)
{
if(strcmp(topic, mqtt_topic_config_button_enabled) == 0)
{
bool newValue = atoi(value) > 0;
if(!_nukiConfigValid || _nukiConfig.buttonEnabled == newValue) return;
_nukiBle.enableButton(newValue);
_nextConfigUpdateTs = millis() + 300;
}
if(strcmp(topic, mqtt_topic_config_led_enabled) == 0)
{
bool newValue = atoi(value) > 0;
if(!_nukiConfigValid || _nukiConfig.ledEnabled == newValue) return;
_nukiBle.enableLedFlash(newValue);
_nextConfigUpdateTs = millis() + 300;
}
else if(strcmp(topic, mqtt_topic_config_led_brightness) == 0)
{
int newValue = atoi(value);
if(!_nukiConfigValid || _nukiConfig.ledBrightness == newValue) return;
_nukiBle.setLedBrightness(newValue);
_nextConfigUpdateTs = millis() + 300;
}
}
const Nuki::KeyTurnerState &NukiWrapper::keyTurnerState() const Nuki::KeyTurnerState &NukiWrapper::keyTurnerState()
{ {
return _keyTurnerState; return _keyTurnerState;
@@ -192,8 +230,6 @@ void NukiWrapper::notify(Nuki::EventType eventType)
void NukiWrapper::readConfig() void NukiWrapper::readConfig()
{ {
Serial.print(F("Reading config. Result: "));
Nuki::CmdResult result = _nukiBle.requestConfig(&_nukiConfig); Nuki::CmdResult result = _nukiBle.requestConfig(&_nukiConfig);
_nukiConfigValid = result == Nuki::CmdResult::Success; _nukiConfigValid = result == Nuki::CmdResult::Success;
Serial.println(result);
} }

View File

@@ -14,6 +14,8 @@ public:
void initialize(); void initialize();
void update(); void update();
void setPin(const uint16_t pin);
const Nuki::KeyTurnerState& keyTurnerState(); const Nuki::KeyTurnerState& keyTurnerState();
const bool isPaired(); const bool isPaired();
@@ -22,7 +24,9 @@ public:
void notify(Nuki::EventType eventType) override; void notify(Nuki::EventType eventType) override;
private: private:
static void onLockActionReceived(const char* value); static void onLockActionReceivedCallback(const char* value);
static void onConfigUpdateReceivedCallback(const char* topic, const char* value);
void onConfigUpdateReceived(const char* topic, const char* value);
void updateKeyTurnerState(); void updateKeyTurnerState();
void updateBatteryState(); void updateBatteryState();

View File

@@ -57,30 +57,38 @@ void WebCfgServer::initialize()
String response = ""; String response = "";
buildConfirmHtml(response, "Restarting. Connect to ESP access point to reconfigure WiFi.", 0); buildConfirmHtml(response, "Restarting. Connect to ESP access point to reconfigure WiFi.", 0);
server.send(200, "text/html", response); server.send(200, "text/html", response);
waitAndProcess(2000); waitAndProcess(true, 2000);
_network->restartAndConfigureWifi(); _network->restartAndConfigureWifi();
}); });
server.on("/method=get", [&]() { server.on("/method=get", [&]() {
if (_hasCredentials && !server.authenticate(_credUser, _credPassword)) { if (_hasCredentials && !server.authenticate(_credUser, _credPassword)) {
return server.requestAuthentication(); return server.requestAuthentication();
} }
bool configChanged = processArgs(); String message = "";
if(configChanged) bool restartEsp = processArgs(message);
if(restartEsp)
{ {
String response = ""; String response = "";
buildConfirmHtml(response, "Configuration saved ... restarting."); buildConfirmHtml(response, message);
server.send(200, "text/html", response); server.send(200, "text/html", response);
Serial.println(F("Restarting")); Serial.println(F("Restarting"));
waitAndProcess(1000); waitAndProcess(true, 1000);
ESP.restart(); ESP.restart();
} }
else
{
String response = "";
buildConfirmHtml(response, message, 3);
server.send(200, "text/html", response);
waitAndProcess(false, 1000);
}
}); });
server.begin(); server.begin();
} }
bool WebCfgServer::processArgs() bool WebCfgServer::processArgs(String& message)
{ {
bool configChanged = false; bool configChanged = false;
bool clearMqttCredentials = false; bool clearMqttCredentials = false;
@@ -159,6 +167,19 @@ bool WebCfgServer::processArgs()
_preferences->putString(preference_cred_password, value); _preferences->putString(preference_cred_password, value);
configChanged = true; configChanged = true;
} }
else if(key == "NUKIPIN")
{
if(value == "#")
{
message = "PIN cleared";
_nuki->setPin(0xffff);
}
else
{
message = "PIN saved";
_nuki->setPin(value.toInt());
}
}
} }
if(clearMqttCredentials) if(clearMqttCredentials)
@@ -177,6 +198,7 @@ bool WebCfgServer::processArgs()
if(configChanged) if(configChanged)
{ {
message = "Configuration saved ... restarting.";
_enabled = false; _enabled = false;
_preferences->end(); _preferences->end();
} }
@@ -250,15 +272,20 @@ void WebCfgServer::buildCredHtml(String &response)
buildHtmlHeader(response); buildHtmlHeader(response);
response.concat("<FORM ACTION=method=get >"); response.concat("<FORM ACTION=method=get >");
response.concat("<h3>Credentials</h3>"); response.concat("<h3>Credentials</h3>");
response.concat("<table>"); response.concat("<table>");
printInputField(response, "CREDUSER", "User (# to clear)", _preferences->getString(preference_cred_user).c_str(), 20); printInputField(response, "CREDUSER", "User (# to clear)", _preferences->getString(preference_cred_user).c_str(), 20);
printInputField(response, "CREDPASS", "Password", "*", 30, true); printInputField(response, "CREDPASS", "Password", "*", 30, true);
response.concat("</table>"); response.concat("</table>");
response.concat("<br><INPUT TYPE=SUBMIT NAME=\"submit\" VALUE=\"Save\">"); response.concat("<br><INPUT TYPE=SUBMIT NAME=\"submit\" VALUE=\"Save\">");
response.concat("</FORM>");
response.concat("<br><br><FORM ACTION=method=get >");
response.concat("<h3>NUKI Pin Code</h3>");
response.concat("<table>");
printInputField(response, "NUKIPIN", "PIN Code (# to clear)", "*", 20, true);
response.concat("</table>");
response.concat("<br><INPUT TYPE=SUBMIT NAME=\"submit\" VALUE=\"Save\">");
response.concat("</FORM>"); response.concat("</FORM>");
response.concat("</BODY>\n"); response.concat("</BODY>\n");
@@ -361,12 +388,19 @@ void WebCfgServer::printParameter(String& response, const char *description, con
} }
void WebCfgServer::waitAndProcess(const uint32_t duration) void WebCfgServer::waitAndProcess(const bool blocking, const uint32_t duration)
{ {
unsigned long timeout = millis() + duration; unsigned long timeout = millis() + duration;
while(millis() < timeout) while(millis() < timeout)
{ {
server.handleClient(); server.handleClient();
delay(10); if(blocking)
{
delay(10);
}
else
{
vTaskDelay( 50 / portTICK_PERIOD_MS);
}
} }
} }

View File

@@ -28,7 +28,7 @@ public:
private: private:
bool processArgs(); bool processArgs(String& message);
void buildHtml(String& response); void buildHtml(String& response);
void buildCredHtml(String& response); void buildCredHtml(String& response);
void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5); void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5);
@@ -40,7 +40,7 @@ private:
void printParameter(String& response, const char* description, const char* value); void printParameter(String& response, const char* description, const char* value);
void waitAndProcess(const uint32_t duration); void waitAndProcess(const bool blocking, const uint32_t duration);
WebServer server; WebServer server;
NukiWrapper* _nuki; NukiWrapper* _nuki;