allow to set config values
This commit is contained in:
31
Network.cpp
31
Network.cpp
@@ -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];
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user