Arduino Core 3 (#407)
* Add and remove libs and components for Arduino Core 3 * Arduino Core 3 * Add back Solo1 * Change ESP32-S3 to 4MB build * Update README.md * Fix retain and number of retries * Fix rolling log * Fix defaults * Fix BleScanner on Solo1 * Export settings * Import settings * Fix HA Battery voltage * Change submodule * Update espMqttClient and AsyncTCP * Webserial and MQTT/Network reconnecting * Update nuki_ble --------- Co-authored-by: iranl <iranl@github.com>
This commit is contained in:
6
src/CMakeLists.txt
Normal file
6
src/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# This file was automatically generated for projects
|
||||
# without default 'CMakeLists.txt' file.
|
||||
|
||||
FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources})
|
||||
27
src/Config.h
27
src/Config.h
@@ -5,30 +5,39 @@
|
||||
#define NUKI_HUB_VERSION "8.35"
|
||||
#define NUKI_HUB_BUILD "unknownbuildnr"
|
||||
|
||||
#define GITHUB_LATEST_RELEASE_URL "https://github.com/technyon/nuki_hub/releases/latest"
|
||||
#define GITHUB_LATEST_RELEASE_API_URL "https://api.github.com/repos/technyon/nuki_hub/releases/latest"
|
||||
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
|
||||
#define GITHUB_LATEST_RELEASE_API_URL (char*)"https://api.github.com/repos/technyon/nuki_hub/releases/latest"
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define GITHUB_LATEST_RELEASE_BINARY_URL "https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_esp32c3.bin"
|
||||
#define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_esp32c3.bin"
|
||||
#define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_updater_esp32c3.bin"
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define GITHUB_LATEST_RELEASE_BINARY_URL "https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_esp32s3.bin"
|
||||
#define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_esp32s3.bin"
|
||||
#define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_updater_esp32s3.bin"
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||
#define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_esp32c6.bin"
|
||||
#define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_updater_esp32c6.bin"
|
||||
#else
|
||||
#if defined(FRAMEWORK_ARDUINO_SOLO1)
|
||||
#define GITHUB_LATEST_RELEASE_BINARY_URL "https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_esp32solo1.bin"
|
||||
#else
|
||||
#define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_esp32solo1.bin"
|
||||
#define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_updater_esp32solo1.bin"
|
||||
#else
|
||||
#define GITHUB_LATEST_RELEASE_BINARY_URL "https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_esp32.bin"
|
||||
#define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://github.com/technyon/nuki_hub/raw/master/ota/nuki_hub_updater_esp32.bin"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#define MQTT_QOS_LEVEL 1
|
||||
#define MQTT_CLEAN_SESSIONS false
|
||||
|
||||
#define MQTT_KEEP_ALIVE 60
|
||||
#define GPIO_DEBOUNCE_TIME 200
|
||||
|
||||
#define CHAR_BUFFER_SIZE 4096
|
||||
#define NETWORK_TASK_SIZE 12288
|
||||
#define NUKI_TASK_SIZE 8192
|
||||
#define PD_TASK_SIZE 1024
|
||||
#define MAX_AUTHLOG 5
|
||||
#define MAX_KEYPAD 10
|
||||
#define MAX_TIMECONTROL 10
|
||||
#endif
|
||||
|
||||
#define NETWORK_TASK_SIZE 12288
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "Logger.h"
|
||||
#include "PreferencesKeys.h"
|
||||
#include "RestartReason.h"
|
||||
#include "../lib/gpio2go/src/Gpio2Go.h"
|
||||
#include "Gpio2Go.h"
|
||||
|
||||
Gpio* Gpio::_inst = nullptr;
|
||||
unsigned long Gpio::_debounceTs = 0;
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#ifndef MQTT_LOGGER_GLOBAL
|
||||
#define MQTT_LOGGER_GLOBAL
|
||||
|
||||
#include "MqttLogger.h"
|
||||
#include "WebSerial.h"
|
||||
extern Print* Log;
|
||||
|
||||
#endif
|
||||
#else
|
||||
#include <Print.h>
|
||||
extern Print* Log;
|
||||
#endif
|
||||
@@ -14,7 +14,7 @@
|
||||
#define mqtt_topic_lock_log "/lock/log"
|
||||
#define mqtt_topic_lock_log_latest "/lock/shortLog"
|
||||
#define mqtt_topic_lock_log_rolling "/lock/rollingLog"
|
||||
#define mqtt_topic_lock_log_rolling_last "lock/lastRollingLog"
|
||||
#define mqtt_topic_lock_log_rolling_last "/lock/lastRollingLog"
|
||||
#define mqtt_topic_lock_auth_id "/lock/authorizationId"
|
||||
#define mqtt_topic_lock_auth_name "/lock/authorizationName"
|
||||
#define mqtt_topic_lock_completionStatus "/lock/completionStatus"
|
||||
@@ -93,6 +93,7 @@
|
||||
#define mqtt_topic_info_nuki_hub_ip "/info/nukiHubIp"
|
||||
|
||||
#define mqtt_topic_reset "/maintenance/reset"
|
||||
#define mqtt_topic_update "/maintenance/update"
|
||||
#define mqtt_topic_webserver_state "/maintenance/webserver/state"
|
||||
#define mqtt_topic_webserver_action "/maintenance/webserver/enable"
|
||||
#define mqtt_topic_uptime "/maintenance/uptime"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <Arduino.h>
|
||||
#include "NukiDeviceId.h"
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
#include "Network.h"
|
||||
#include "NukiNetwork.h"
|
||||
#include "PreferencesKeys.h"
|
||||
#include "networkDevices/W5500Device.h"
|
||||
#include "networkDevices/WifiDevice.h"
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include "RestartReason.h"
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||
#include "networkDevices/EthLan8720Device.h"
|
||||
#endif
|
||||
|
||||
Network* Network::_inst = nullptr;
|
||||
unsigned long Network::_ignoreSubscriptionsTs = 0;
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include <ArduinoJson.h>
|
||||
bool _versionPublished = false;
|
||||
#endif
|
||||
|
||||
NukiNetwork* NukiNetwork::_inst = nullptr;
|
||||
|
||||
RTC_NOINIT_ATTR char WiFi_fallbackDetect[14];
|
||||
|
||||
Network::Network(Preferences *preferences, PresenceDetection* presenceDetection, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize)
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
NukiNetwork::NukiNetwork(Preferences *preferences, PresenceDetection* presenceDetection, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize)
|
||||
: _preferences(preferences),
|
||||
_presenceDetection(presenceDetection),
|
||||
_gpio(gpio),
|
||||
_buffer(buffer),
|
||||
_bufferSize(bufferSize)
|
||||
#else
|
||||
NukiNetwork::NukiNetwork(Preferences *preferences)
|
||||
: _preferences(preferences)
|
||||
#endif
|
||||
{
|
||||
// Remove obsolete W5500 hardware detection configuration
|
||||
if(_preferences->getInt(preference_network_hardware_gpio) != 0)
|
||||
@@ -30,6 +39,7 @@ Network::Network(Preferences *preferences, PresenceDetection* presenceDetection,
|
||||
_inst = this;
|
||||
_hostname = _preferences->getString(preference_hostname);
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
memset(_maintenancePathPrefix, 0, sizeof(_maintenancePathPrefix));
|
||||
size_t len = maintenancePathPrefix.length();
|
||||
for(int i=0; i < len; i++)
|
||||
@@ -46,11 +56,12 @@ Network::Network(Preferences *preferences, PresenceDetection* presenceDetection,
|
||||
{
|
||||
_mqttConnectionStateTopic[i] = connectionStateTopic.charAt(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
setupDevice();
|
||||
}
|
||||
|
||||
void Network::setupDevice()
|
||||
void NukiNetwork::setupDevice()
|
||||
{
|
||||
_ipConfiguration = new IPConfiguration(_preferences);
|
||||
|
||||
@@ -94,6 +105,7 @@ void Network::setupDevice()
|
||||
Log->println(F("W5500 on M5Stack Atom POE"));
|
||||
_networkDeviceType = NetworkDeviceType::W5500;
|
||||
break;
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||
case 4:
|
||||
Log->println(F("Olimex ESP32-POE / ESP-POE-ISO"));
|
||||
_networkDeviceType = NetworkDeviceType::Olimex_LAN8720;
|
||||
@@ -114,6 +126,7 @@ void Network::setupDevice()
|
||||
Log->println(F("GL-S10"));
|
||||
_networkDeviceType = NetworkDeviceType::GL_S10;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
Log->println(F("Unknown hardware selected, falling back to Wi-Fi."));
|
||||
_networkDeviceType = NetworkDeviceType::WiFi;
|
||||
@@ -126,6 +139,7 @@ void Network::setupDevice()
|
||||
case NetworkDeviceType::W5500:
|
||||
_device = new W5500Device(_hostname, _preferences, _ipConfiguration, hardwareDetect);
|
||||
break;
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||
case NetworkDeviceType::Olimex_LAN8720:
|
||||
_device = new EthLan8720Device(_hostname, _preferences, _ipConfiguration, "Olimex (LAN8720)", ETH_PHY_ADDR, 12, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLOCK_GPIO17_OUT);
|
||||
break;
|
||||
@@ -141,6 +155,7 @@ void Network::setupDevice()
|
||||
case NetworkDeviceType::LilyGO_T_ETH_POE:
|
||||
_device = new EthLan8720Device(_hostname, _preferences, _ipConfiguration, "LilyGO T-ETH-POE", 0, -1, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLOCK_GPIO17_OUT);
|
||||
break;
|
||||
#endif
|
||||
case NetworkDeviceType::WiFi:
|
||||
_device = new WifiDevice(_hostname, _preferences, _ipConfiguration);
|
||||
break;
|
||||
@@ -149,6 +164,7 @@ void Network::setupDevice()
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
_device->mqttOnConnect([&](bool sessionPresent)
|
||||
{
|
||||
onMqttConnect(sessionPresent);
|
||||
@@ -157,9 +173,68 @@ void Network::setupDevice()
|
||||
{
|
||||
onMqttDisconnect(reason);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void Network::initialize()
|
||||
void NukiNetwork::reconfigureDevice()
|
||||
{
|
||||
_device->reconfigure();
|
||||
}
|
||||
|
||||
const String NukiNetwork::networkDeviceName() const
|
||||
{
|
||||
return _device->deviceName();
|
||||
}
|
||||
|
||||
const String NukiNetwork::networkBSSID() const
|
||||
{
|
||||
return _device->BSSIDstr();
|
||||
}
|
||||
|
||||
const NetworkDeviceType NukiNetwork::networkDeviceType()
|
||||
{
|
||||
return _networkDeviceType;
|
||||
}
|
||||
|
||||
void NukiNetwork::setKeepAliveCallback(std::function<void()> reconnectTick)
|
||||
{
|
||||
_keepAliveCallback = reconnectTick;
|
||||
}
|
||||
|
||||
void NukiNetwork::clearWifiFallback()
|
||||
{
|
||||
memset(WiFi_fallbackDetect, 0, sizeof(WiFi_fallbackDetect));
|
||||
}
|
||||
|
||||
NetworkDevice *NukiNetwork::device()
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
|
||||
#ifdef NUKI_HUB_UPDATER
|
||||
void NukiNetwork::initialize()
|
||||
{
|
||||
_hostname = _preferences->getString(preference_hostname);
|
||||
|
||||
if(_hostname == "")
|
||||
{
|
||||
_hostname = "nukihub";
|
||||
_preferences->putString(preference_hostname, _hostname);
|
||||
}
|
||||
strcpy(_hostnameArr, _hostname.c_str());
|
||||
_device->initialize();
|
||||
|
||||
Log->print(F("Host name: "));
|
||||
Log->println(_hostname);
|
||||
}
|
||||
|
||||
bool NukiNetwork::update()
|
||||
{
|
||||
_device->update();
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
void NukiNetwork::initialize()
|
||||
{
|
||||
_restartOnDisconnect = _preferences->getBool(preference_restart_on_disconnect, false);
|
||||
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
|
||||
@@ -219,6 +294,7 @@ void Network::initialize()
|
||||
|
||||
_device->mqttSetClientId(_hostnameArr);
|
||||
_device->mqttSetCleanSession(MQTT_CLEAN_SESSIONS);
|
||||
_device->mqttSetKeepAlive(MQTT_KEEP_ALIVE);
|
||||
|
||||
_networkTimeout = _preferences->getInt(preference_network_timeout);
|
||||
if(_networkTimeout == 0)
|
||||
@@ -261,6 +337,8 @@ void Network::initialize()
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state});
|
||||
subscribe(_lockPath.c_str(), gpioPath);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
_gpio->addCallback([this](const GpioAction& action, const int& pin)
|
||||
@@ -269,7 +347,7 @@ void Network::initialize()
|
||||
});
|
||||
}
|
||||
|
||||
bool Network::update()
|
||||
bool NukiNetwork::update()
|
||||
{
|
||||
unsigned long ts = millis();
|
||||
|
||||
@@ -282,6 +360,8 @@ bool Network::update()
|
||||
|
||||
if(!_device->isConnected())
|
||||
{
|
||||
_device->mqttDisconnect(true);
|
||||
|
||||
if(_restartOnDisconnect && millis() > 60000)
|
||||
{
|
||||
restartEsp(RestartReason::RestartOnDisconnectWatchdog);
|
||||
@@ -306,10 +386,9 @@ bool Network::update()
|
||||
Log->println(F("Reconnect failed"));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!_device->mqttConnected())
|
||||
if(!_device->mqttConnected() && _device->isConnected())
|
||||
{
|
||||
if(_networkTimeout > 0 && (ts - _lastConnectedTs > _networkTimeout * 1000) && ts > 60000)
|
||||
{
|
||||
@@ -323,16 +402,17 @@ bool Network::update()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
if(!_device->mqttConnected() || !_device->isConnected()) return false;
|
||||
|
||||
_lastConnectedTs = ts;
|
||||
|
||||
if(_presenceDetection != nullptr && (_lastPresenceTs == 0 || (ts - _lastPresenceTs) > 3000))
|
||||
{
|
||||
char* presenceCsv = _presenceDetection->generateCsv();
|
||||
|
||||
// if(_presenceCsv != nullptr && strlen(_presenceCsv) > 0)
|
||||
bool success = publishString(_mqttPresencePrefix, mqtt_topic_presence, presenceCsv);
|
||||
bool success = publishString(_mqttPresencePrefix, mqtt_topic_presence, presenceCsv, true);
|
||||
if(!success)
|
||||
{
|
||||
Log->println(F("Failed to publish presence CSV data."));
|
||||
@@ -349,25 +429,25 @@ bool Network::update()
|
||||
|
||||
if(rssi != _lastRssi)
|
||||
{
|
||||
publishInt(_maintenancePathPrefix, mqtt_topic_wifi_rssi, _device->signalStrength());
|
||||
publishInt(_maintenancePathPrefix, mqtt_topic_wifi_rssi, _device->signalStrength(), true);
|
||||
_lastRssi = rssi;
|
||||
}
|
||||
}
|
||||
|
||||
if(_lastMaintenanceTs == 0 || (ts - _lastMaintenanceTs) > 30000)
|
||||
{
|
||||
publishULong(_maintenancePathPrefix, mqtt_topic_uptime, ts / 1000 / 60);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online");
|
||||
|
||||
publishULong(_maintenancePathPrefix, mqtt_topic_uptime, ts / 1000 / 60, true);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online", true);
|
||||
|
||||
if(_publishDebugInfo)
|
||||
{
|
||||
publishUInt(_maintenancePathPrefix, mqtt_topic_freeheap, esp_get_free_heap_size());
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_fw, getRestartReason().c_str());
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_esp, getEspRestartReason().c_str());
|
||||
publishUInt(_maintenancePathPrefix, mqtt_topic_freeheap, esp_get_free_heap_size(), true);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_fw, getRestartReason().c_str(), true);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_esp, getEspRestartReason().c_str(), true);
|
||||
}
|
||||
if (!_versionPublished) {
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_version, NUKI_HUB_VERSION);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_build, NUKI_HUB_BUILD);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_version, NUKI_HUB_VERSION, true);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_build, NUKI_HUB_BUILD, true);
|
||||
_versionPublished = true;
|
||||
}
|
||||
_lastMaintenanceTs = ts;
|
||||
@@ -392,7 +472,7 @@ bool Network::update()
|
||||
if (!jsonError)
|
||||
{
|
||||
_latestVersion = doc["tag_name"];
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_latest, _latestVersion);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_latest, _latestVersion, true);
|
||||
|
||||
if (_latestVersion != _preferences->getString(preference_latest_version).c_str())
|
||||
{
|
||||
@@ -429,14 +509,14 @@ bool Network::update()
|
||||
}
|
||||
|
||||
|
||||
void Network::onMqttConnect(const bool &sessionPresent)
|
||||
void NukiNetwork::onMqttConnect(const bool &sessionPresent)
|
||||
{
|
||||
_connectReplyReceived = true;
|
||||
}
|
||||
|
||||
void Network::onMqttDisconnect(const espMqttClientTypes::DisconnectReason &reason)
|
||||
void NukiNetwork::onMqttDisconnect(const espMqttClientTypes::DisconnectReason &reason)
|
||||
{
|
||||
_connectReplyReceived = true;
|
||||
_connectReplyReceived = false;
|
||||
|
||||
Log->print("MQTT disconnected. Reason: ");
|
||||
switch(reason)
|
||||
@@ -471,7 +551,7 @@ void Network::onMqttDisconnect(const espMqttClientTypes::DisconnectReason &reaso
|
||||
}
|
||||
}
|
||||
|
||||
bool Network::reconnect()
|
||||
bool NukiNetwork::reconnect()
|
||||
{
|
||||
_mqttConnectionState = 0;
|
||||
int port = _preferences->getInt(preference_mqtt_broker_port);
|
||||
@@ -521,8 +601,7 @@ bool Network::reconnect()
|
||||
_mqttConnectionState = 1;
|
||||
delay(100);
|
||||
|
||||
_ignoreSubscriptionsTs = millis() + 2000;
|
||||
_device->mqttOnMessage(Network::onMqttDataReceivedCallback);
|
||||
_device->mqttOnMessage(NukiNetwork::onMqttDataReceivedCallback);
|
||||
for(const String& topic : _subscribedTopics)
|
||||
{
|
||||
_device->mqttSubscribe(topic.c_str(), MQTT_QOS_LEVEL);
|
||||
@@ -530,15 +609,15 @@ bool Network::reconnect()
|
||||
if(_firstConnect)
|
||||
{
|
||||
_firstConnect = false;
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_network_device, _device->deviceName().c_str());
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_network_device, _device->deviceName().c_str(), true);
|
||||
for(const auto& it : _initTopics)
|
||||
{
|
||||
_device->mqttPublish(it.first.c_str(), MQTT_QOS_LEVEL, true, it.second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online");
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_ip, _device->localIP().c_str());
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online", true);
|
||||
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_ip, _device->localIP().c_str(), true);
|
||||
|
||||
_mqttConnectionState = 2;
|
||||
for(const auto& callback : _reconnectedCallbacks)
|
||||
@@ -552,20 +631,20 @@ bool Network::reconnect()
|
||||
_device->printError();
|
||||
_mqttConnectionState = 0;
|
||||
_nextReconnect = millis() + 5000;
|
||||
_device->mqttDisconnect(true);
|
||||
//_device->mqttDisconnect(true);
|
||||
}
|
||||
}
|
||||
return _mqttConnectionState > 0;
|
||||
}
|
||||
|
||||
void Network::subscribe(const char* prefix, const char *path)
|
||||
void NukiNetwork::subscribe(const char* prefix, const char *path)
|
||||
{
|
||||
char prefixedPath[500];
|
||||
buildMqttPath(prefixedPath, { prefix, path });
|
||||
_subscribedTopics.push_back(prefixedPath);
|
||||
}
|
||||
|
||||
void Network::initTopic(const char *prefix, const char *path, const char *value)
|
||||
void NukiNetwork::initTopic(const char *prefix, const char *path, const char *value)
|
||||
{
|
||||
char prefixedPath[500];
|
||||
buildMqttPath(prefixedPath, { prefix, path });
|
||||
@@ -574,7 +653,7 @@ void Network::initTopic(const char *prefix, const char *path, const char *value)
|
||||
_initTopics[pathStr] = valueStr;
|
||||
}
|
||||
|
||||
void Network::buildMqttPath(char* outPath, std::initializer_list<const char*> paths)
|
||||
void NukiNetwork::buildMqttPath(char* outPath, std::initializer_list<const char*> paths)
|
||||
{
|
||||
int offset = 0;
|
||||
int pathCount = 0;
|
||||
@@ -600,12 +679,12 @@ void Network::buildMqttPath(char* outPath, std::initializer_list<const char*> pa
|
||||
outPath[offset] = 0x00;
|
||||
}
|
||||
|
||||
void Network::registerMqttReceiver(MqttReceiver* receiver)
|
||||
void NukiNetwork::registerMqttReceiver(MqttReceiver* receiver)
|
||||
{
|
||||
_mqttReceivers.push_back(receiver);
|
||||
}
|
||||
|
||||
void Network::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
|
||||
void NukiNetwork::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
|
||||
{
|
||||
uint8_t value[800] = {0};
|
||||
|
||||
@@ -619,15 +698,10 @@ void Network::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProper
|
||||
_inst->onMqttDataReceived(properties, topic, value, len, index, total);
|
||||
}
|
||||
|
||||
void Network::onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total)
|
||||
void NukiNetwork::onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total)
|
||||
{
|
||||
parseGpioTopics(properties, topic, payload, len, index, total);
|
||||
|
||||
if(millis() < _ignoreSubscriptionsTs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto receiver : _mqttReceivers)
|
||||
{
|
||||
receiver->onMqttDataReceived(topic, (byte*)payload, index);
|
||||
@@ -635,7 +709,7 @@ void Network::onMqttDataReceived(const espMqttClientTypes::MessageProperties& pr
|
||||
}
|
||||
|
||||
|
||||
void Network::parseGpioTopics(const espMqttClientTypes::MessageProperties &properties, const char *topic, const uint8_t *payload, size_t& len, size_t& index, size_t& total)
|
||||
void NukiNetwork::parseGpioTopics(const espMqttClientTypes::MessageProperties &properties, const char *topic, const uint8_t *payload, size_t& len, size_t& index, size_t& total)
|
||||
{
|
||||
char gpioPath[250];
|
||||
buildMqttPath(gpioPath, {_lockPath.c_str(), mqtt_topic_gpio_prefix, mqtt_topic_gpio_pin});
|
||||
@@ -665,49 +739,34 @@ void Network::parseGpioTopics(const espMqttClientTypes::MessageProperties &prope
|
||||
}
|
||||
}
|
||||
|
||||
void Network::gpioActionCallback(const GpioAction &action, const int &pin)
|
||||
void NukiNetwork::gpioActionCallback(const GpioAction &action, const int &pin)
|
||||
{
|
||||
_gpioTs[pin] = millis();
|
||||
}
|
||||
|
||||
void Network::reconfigureDevice()
|
||||
{
|
||||
_device->reconfigure();
|
||||
}
|
||||
|
||||
void Network::setMqttPresencePath(char *path)
|
||||
void NukiNetwork::setMqttPresencePath(char *path)
|
||||
{
|
||||
memset(_mqttPresencePrefix, 0, sizeof(_mqttPresencePrefix));
|
||||
strcpy(_mqttPresencePrefix, path);
|
||||
}
|
||||
|
||||
void Network::disableAutoRestarts()
|
||||
void NukiNetwork::disableAutoRestarts()
|
||||
{
|
||||
_networkTimeout = 0;
|
||||
_restartOnDisconnect = false;
|
||||
}
|
||||
|
||||
int Network::mqttConnectionState()
|
||||
int NukiNetwork::mqttConnectionState()
|
||||
{
|
||||
return _mqttConnectionState;
|
||||
}
|
||||
|
||||
bool Network::encryptionSupported()
|
||||
bool NukiNetwork::encryptionSupported()
|
||||
{
|
||||
return _device->supportsEncryption();
|
||||
}
|
||||
|
||||
const String Network::networkDeviceName() const
|
||||
{
|
||||
return _device->deviceName();
|
||||
}
|
||||
|
||||
const String Network::networkBSSID() const
|
||||
{
|
||||
return _device->BSSIDstr();
|
||||
}
|
||||
|
||||
void Network::publishFloat(const char* prefix, const char* topic, const float value, const uint8_t precision, bool retain)
|
||||
void NukiNetwork::publishFloat(const char* prefix, const char* topic, const float value, const uint8_t precision, bool retain)
|
||||
{
|
||||
char str[30];
|
||||
dtostrf(value, 0, precision, str);
|
||||
@@ -716,7 +775,7 @@ void Network::publishFloat(const char* prefix, const char* topic, const float va
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
|
||||
}
|
||||
|
||||
void Network::publishInt(const char* prefix, const char *topic, const int value, bool retain)
|
||||
void NukiNetwork::publishInt(const char* prefix, const char *topic, const int value, bool retain)
|
||||
{
|
||||
char str[30];
|
||||
itoa(value, str, 10);
|
||||
@@ -725,7 +784,7 @@ void Network::publishInt(const char* prefix, const char *topic, const int value,
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
|
||||
}
|
||||
|
||||
void Network::publishUInt(const char* prefix, const char *topic, const unsigned int value, bool retain)
|
||||
void NukiNetwork::publishUInt(const char* prefix, const char *topic, const unsigned int value, bool retain)
|
||||
{
|
||||
char str[30];
|
||||
utoa(value, str, 10);
|
||||
@@ -734,7 +793,7 @@ void Network::publishUInt(const char* prefix, const char *topic, const unsigned
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
|
||||
}
|
||||
|
||||
void Network::publishULong(const char* prefix, const char *topic, const unsigned long value, bool retain)
|
||||
void NukiNetwork::publishULong(const char* prefix, const char *topic, const unsigned long value, bool retain)
|
||||
{
|
||||
char str[30];
|
||||
utoa(value, str, 10);
|
||||
@@ -743,7 +802,7 @@ void Network::publishULong(const char* prefix, const char *topic, const unsigned
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
|
||||
}
|
||||
|
||||
void Network::publishBool(const char* prefix, const char *topic, const bool value, bool retain)
|
||||
void NukiNetwork::publishBool(const char* prefix, const char *topic, const bool value, bool retain)
|
||||
{
|
||||
char str[2] = {0};
|
||||
str[0] = value ? '1' : '0';
|
||||
@@ -752,14 +811,14 @@ void Network::publishBool(const char* prefix, const char *topic, const bool valu
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
|
||||
}
|
||||
|
||||
bool Network::publishString(const char* prefix, const char *topic, const char *value, bool retain)
|
||||
bool NukiNetwork::publishString(const char* prefix, const char *topic, const char *value, bool retain)
|
||||
{
|
||||
char path[200] = {0};
|
||||
buildMqttPath(path, { prefix, topic });
|
||||
return _device->mqttPublish(path, MQTT_QOS_LEVEL, retain, value) > 0;
|
||||
}
|
||||
|
||||
void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction)
|
||||
void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction)
|
||||
{
|
||||
JsonDocument json;
|
||||
json.clear();
|
||||
@@ -843,7 +902,7 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
|
||||
"diagnostic",
|
||||
"",
|
||||
{ {(char*)"unit_of_meas", (char*)"V"},
|
||||
{(char*)"val_tpl", (char*)"{{value_json.level}}" }});
|
||||
{(char*)"val_tpl", (char*)"{{value_json.batteryVoltage}}" }});
|
||||
|
||||
// Trigger
|
||||
publishHassTopic("sensor",
|
||||
@@ -991,23 +1050,47 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
|
||||
_lockPath.toCharArray(latest_version_topic,_lockPath.length() + 1);
|
||||
strcat(latest_version_topic, mqtt_topic_info_nuki_hub_latest);
|
||||
|
||||
publishHassTopic("update",
|
||||
"nuki_hub_update",
|
||||
uidString,
|
||||
"_nuki_hub_update",
|
||||
"NUKI Hub firmware update",
|
||||
name,
|
||||
baseTopic,
|
||||
_lockPath + mqtt_topic_info_nuki_hub_version,
|
||||
deviceType,
|
||||
"firmware",
|
||||
"",
|
||||
"diagnostic",
|
||||
"",
|
||||
{ { (char*)"en", (char*)"true" },
|
||||
{ (char*)"ent_pic", (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/master/icon/favicon-32x32.png" },
|
||||
{ (char*)"rel_u", (char*)GITHUB_LATEST_RELEASE_URL },
|
||||
{ (char*)"l_ver_t", (char*)latest_version_topic }});
|
||||
if(!_preferences->getBool(preference_update_from_mqtt, false))
|
||||
{
|
||||
publishHassTopic("update",
|
||||
"nuki_hub_update",
|
||||
uidString,
|
||||
"_nuki_hub_update",
|
||||
"NUKI Hub firmware update",
|
||||
name,
|
||||
baseTopic,
|
||||
_lockPath + mqtt_topic_info_nuki_hub_version,
|
||||
deviceType,
|
||||
"firmware",
|
||||
"",
|
||||
"diagnostic",
|
||||
"",
|
||||
{ { (char*)"en", (char*)"true" },
|
||||
{ (char*)"ent_pic", (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/master/icon/favicon-32x32.png" },
|
||||
{ (char*)"rel_u", (char*)GITHUB_LATEST_RELEASE_URL },
|
||||
{ (char*)"l_ver_t", (char*)latest_version_topic }});
|
||||
}
|
||||
else
|
||||
{
|
||||
publishHassTopic("update",
|
||||
"nuki_hub_update",
|
||||
uidString,
|
||||
"_nuki_hub_update",
|
||||
"NUKI Hub firmware update",
|
||||
name,
|
||||
baseTopic,
|
||||
_lockPath + mqtt_topic_info_nuki_hub_version,
|
||||
deviceType,
|
||||
"firmware",
|
||||
"",
|
||||
"diagnostic",
|
||||
_lockPath + mqtt_topic_update,
|
||||
{ { (char*)"en", (char*)"true" },
|
||||
{ (char*)"pl_inst", (char*)"1" },
|
||||
{ (char*)"ent_pic", (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/master/icon/favicon-32x32.png" },
|
||||
{ (char*)"rel_u", (char*)GITHUB_LATEST_RELEASE_URL },
|
||||
{ (char*)"l_ver_t", (char*)latest_version_topic }});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1099,8 +1182,7 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
|
||||
{ {(char*)"unit_of_meas", (char*)"dBm"} });
|
||||
}
|
||||
|
||||
|
||||
void Network::publishHASSConfigAdditionalLockEntities(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
{
|
||||
uint32_t aclPrefs[17];
|
||||
_preferences->getBytes(preference_acl, &aclPrefs, sizeof(aclPrefs));
|
||||
@@ -2150,7 +2232,7 @@ void Network::publishHASSConfigAdditionalLockEntities(char *deviceType, const ch
|
||||
}
|
||||
}
|
||||
|
||||
void Network::publishHASSConfigDoorSensor(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
void NukiNetwork::publishHASSConfigDoorSensor(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
{
|
||||
publishHassTopic("binary_sensor",
|
||||
"door_sensor",
|
||||
@@ -2170,7 +2252,7 @@ void Network::publishHASSConfigDoorSensor(char *deviceType, const char *baseTopi
|
||||
{(char*)"pl_not_avail", (char*)"unavailable"}});
|
||||
}
|
||||
|
||||
void Network::publishHASSConfigAdditionalOpenerEntities(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
{
|
||||
uint32_t aclPrefs[17];
|
||||
_preferences->getBytes(preference_acl, &aclPrefs, sizeof(aclPrefs));
|
||||
@@ -3027,7 +3109,7 @@ void Network::publishHASSConfigAdditionalOpenerEntities(char *deviceType, const
|
||||
}
|
||||
}
|
||||
|
||||
void Network::publishHASSConfigAccessLog(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
void NukiNetwork::publishHASSConfigAccessLog(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
{
|
||||
publishHassTopic("sensor",
|
||||
"last_action_authorization",
|
||||
@@ -3064,10 +3146,10 @@ void Network::publishHASSConfigAccessLog(char *deviceType, const char *baseTopic
|
||||
"",
|
||||
{ { (char*)"ic", (char*)"mdi:format-list-bulleted" },
|
||||
{ (char*)"json_attr_t", (char*)rollingStateChr },
|
||||
{ (char*)"val_tpl", (char*)"{{value_json.authorizationId}}" }});
|
||||
{ (char*)"val_tpl", (char*)"{{value_json.index}}" }});
|
||||
}
|
||||
|
||||
void Network::publishHASSConfigKeypad(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
void NukiNetwork::publishHASSConfigKeypad(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
{
|
||||
// Keypad battery critical
|
||||
publishHassTopic("binary_sensor",
|
||||
@@ -3121,7 +3203,7 @@ void Network::publishHASSConfigKeypad(char *deviceType, const char *baseTopic, c
|
||||
{ (char*)"val_tpl", (char*)"{{ (value_json|selectattr('type', 'eq', 'KeypadAction')|first|default).completionStatus|default }}" }});
|
||||
}
|
||||
|
||||
void Network::publishHASSWifiRssiConfig(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
void NukiNetwork::publishHASSWifiRssiConfig(char *deviceType, const char *baseTopic, char *name, char *uidString)
|
||||
{
|
||||
if(_device->signalStrength() == 127)
|
||||
{
|
||||
@@ -3144,7 +3226,7 @@ void Network::publishHASSWifiRssiConfig(char *deviceType, const char *baseTopic,
|
||||
{ {(char*)"unit_of_meas", (char*)"dBm"} });
|
||||
}
|
||||
|
||||
void Network::publishHassTopic(const String& mqttDeviceType,
|
||||
void NukiNetwork::publishHassTopic(const String& mqttDeviceType,
|
||||
const String& mqttDeviceName,
|
||||
const String& uidString,
|
||||
const String& uidStringPostfix,
|
||||
@@ -3172,7 +3254,7 @@ void Network::publishHassTopic(const String& mqttDeviceType,
|
||||
}
|
||||
}
|
||||
|
||||
String Network::createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString)
|
||||
String NukiNetwork::createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString)
|
||||
{
|
||||
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);
|
||||
String path = discoveryTopic;
|
||||
@@ -3187,7 +3269,7 @@ String Network::createHassTopicPath(const String& mqttDeviceType, const String&
|
||||
return path;
|
||||
}
|
||||
|
||||
void Network::removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString)
|
||||
void NukiNetwork::removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString)
|
||||
{
|
||||
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);
|
||||
|
||||
@@ -3198,7 +3280,7 @@ void Network::removeHassTopic(const String& mqttDeviceType, const String& mqttDe
|
||||
}
|
||||
}
|
||||
|
||||
void Network::removeTopic(const String& mqttPath, const String& mqttTopic)
|
||||
void NukiNetwork::removeTopic(const String& mqttPath, const String& mqttTopic)
|
||||
{
|
||||
String path = mqttPath;
|
||||
path.concat(mqttTopic);
|
||||
@@ -3211,7 +3293,7 @@ void Network::removeTopic(const String& mqttPath, const String& mqttTopic)
|
||||
}
|
||||
|
||||
|
||||
void Network::removeHASSConfig(char* uidString)
|
||||
void NukiNetwork::removeHASSConfig(char* uidString)
|
||||
{
|
||||
removeHassTopic((char*)"lock", (char*)"smartlock", uidString);
|
||||
removeHassTopic((char*)"binary_sensor", (char*)"battery_low", uidString);
|
||||
@@ -3300,12 +3382,12 @@ void Network::removeHASSConfig(char* uidString)
|
||||
removeHassTopic((char*)"switch", (char*)"auto_unlatch", uidString);
|
||||
}
|
||||
|
||||
void Network::removeHASSConfigTopic(char *deviceType, char *name, char *uidString)
|
||||
void NukiNetwork::removeHASSConfigTopic(char *deviceType, char *name, char *uidString)
|
||||
{
|
||||
removeHassTopic(deviceType, name, uidString);
|
||||
}
|
||||
|
||||
JsonDocument Network::createHassJson(const String& uidString,
|
||||
JsonDocument NukiNetwork::createHassJson(const String& uidString,
|
||||
const String& uidStringPostfix,
|
||||
const String& displayName,
|
||||
const String& name,
|
||||
@@ -3377,7 +3459,7 @@ JsonDocument Network::createHassJson(const String& uidString,
|
||||
return json;
|
||||
}
|
||||
|
||||
void Network::batteryTypeToString(const Nuki::BatteryType battype, char* str) {
|
||||
void NukiNetwork::batteryTypeToString(const Nuki::BatteryType battype, char* str) {
|
||||
switch (battype) {
|
||||
case Nuki::BatteryType::Alkali:
|
||||
strcpy(str, "Alkali");
|
||||
@@ -3394,7 +3476,7 @@ void Network::batteryTypeToString(const Nuki::BatteryType battype, char* str) {
|
||||
}
|
||||
}
|
||||
|
||||
void Network::advertisingModeToString(const Nuki::AdvertisingMode advmode, char* str) {
|
||||
void NukiNetwork::advertisingModeToString(const Nuki::AdvertisingMode advmode, char* str) {
|
||||
switch (advmode) {
|
||||
case Nuki::AdvertisingMode::Automatic:
|
||||
strcpy(str, "Automatic");
|
||||
@@ -3414,7 +3496,7 @@ void Network::advertisingModeToString(const Nuki::AdvertisingMode advmode, char*
|
||||
}
|
||||
}
|
||||
|
||||
void Network::timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* str) {
|
||||
void NukiNetwork::timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* str) {
|
||||
switch (timeZoneId) {
|
||||
case Nuki::TimeZoneId::Africa_Cairo:
|
||||
strcpy(str, "Africa/Cairo");
|
||||
@@ -3563,38 +3645,19 @@ void Network::timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* str) {
|
||||
}
|
||||
}
|
||||
|
||||
const NetworkDeviceType Network::networkDeviceType()
|
||||
{
|
||||
return _networkDeviceType;
|
||||
}
|
||||
|
||||
uint16_t Network::subscribe(const char *topic, uint8_t qos)
|
||||
uint16_t NukiNetwork::subscribe(const char *topic, uint8_t qos)
|
||||
{
|
||||
return _device->mqttSubscribe(topic, qos);
|
||||
}
|
||||
|
||||
void Network::setKeepAliveCallback(std::function<void()> reconnectTick)
|
||||
{
|
||||
_keepAliveCallback = reconnectTick;
|
||||
}
|
||||
|
||||
void Network::addReconnectedCallback(std::function<void()> reconnectedCallback)
|
||||
void NukiNetwork::addReconnectedCallback(std::function<void()> reconnectedCallback)
|
||||
{
|
||||
_reconnectedCallbacks.push_back(reconnectedCallback);
|
||||
}
|
||||
|
||||
void Network::clearWifiFallback()
|
||||
{
|
||||
memset(WiFi_fallbackDetect, 0, sizeof(WiFi_fallbackDetect));
|
||||
}
|
||||
|
||||
void Network::disableMqtt()
|
||||
void NukiNetwork::disableMqtt()
|
||||
{
|
||||
_device->disableMqtt();
|
||||
_mqttEnabled = false;
|
||||
}
|
||||
|
||||
NetworkDevice *Network::device()
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
#endif
|
||||
@@ -4,14 +4,17 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "networkDevices/NetworkDevice.h"
|
||||
#include "MqttReceiver.h"
|
||||
#include "networkDevices/IPConfiguration.h"
|
||||
#include <HTTPClient.h>
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "MqttReceiver.h"
|
||||
#include "MqttTopics.h"
|
||||
#include "Gpio.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "NukiConstants.h"
|
||||
#include "PresenceDetection.h"
|
||||
#endif
|
||||
|
||||
enum class NetworkDeviceType
|
||||
{
|
||||
@@ -26,20 +29,27 @@ enum class NetworkDeviceType
|
||||
|
||||
#define JSON_BUFFER_SIZE 1024
|
||||
|
||||
class Network
|
||||
class NukiNetwork
|
||||
{
|
||||
public:
|
||||
explicit Network(Preferences* preferences,
|
||||
PresenceDetection* presenceDetection,
|
||||
Gpio* gpio,
|
||||
const String& maintenancePathPrefix,
|
||||
char* buffer,
|
||||
size_t bufferSize);
|
||||
|
||||
void initialize();
|
||||
bool update();
|
||||
void registerMqttReceiver(MqttReceiver* receiver);
|
||||
void reconfigureDevice();
|
||||
void clearWifiFallback();
|
||||
|
||||
const String networkDeviceName() const;
|
||||
const String networkBSSID() const;
|
||||
const NetworkDeviceType networkDeviceType();
|
||||
void setKeepAliveCallback(std::function<void()> reconnectTick);
|
||||
|
||||
NetworkDevice* device();
|
||||
|
||||
#ifdef NUKI_HUB_UPDATER
|
||||
explicit NukiNetwork(Preferences* preferences);
|
||||
#else
|
||||
explicit NukiNetwork(Preferences* preferences, PresenceDetection* presenceDetection, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize);
|
||||
|
||||
void registerMqttReceiver(MqttReceiver* receiver);
|
||||
void setMqttPresencePath(char* path);
|
||||
void disableAutoRestarts(); // disable on OTA start
|
||||
void disableMqtt();
|
||||
@@ -83,29 +93,38 @@ public:
|
||||
void advertisingModeToString(const Nuki::AdvertisingMode advmode, char* str);
|
||||
void timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* str);
|
||||
|
||||
void clearWifiFallback();
|
||||
|
||||
int mqttConnectionState(); // 0 = not connected; 1 = connected; 2 = connected and mqtt processed
|
||||
bool encryptionSupported();
|
||||
const String networkDeviceName() const;
|
||||
const String networkBSSID() const;
|
||||
|
||||
const NetworkDeviceType networkDeviceType();
|
||||
|
||||
uint16_t subscribe(const char* topic, uint8_t qos);
|
||||
|
||||
void setKeepAliveCallback(std::function<void()> reconnectTick);
|
||||
void addReconnectedCallback(std::function<void()> reconnectedCallback);
|
||||
|
||||
NetworkDevice* device();
|
||||
|
||||
#endif
|
||||
private:
|
||||
void setupDevice();
|
||||
bool reconnect();
|
||||
|
||||
static NukiNetwork* _inst;
|
||||
|
||||
const char* _latestVersion;
|
||||
HTTPClient https;
|
||||
|
||||
Preferences* _preferences;
|
||||
IPConfiguration* _ipConfiguration = nullptr;
|
||||
String _hostname;
|
||||
char _hostnameArr[101] = {0};
|
||||
NetworkDevice* _device = nullptr;
|
||||
|
||||
std::function<void()> _keepAliveCallback = nullptr;
|
||||
std::vector<std::function<void()>> _reconnectedCallbacks;
|
||||
|
||||
NetworkDeviceType _networkDeviceType = (NetworkDeviceType)-1;
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
static void onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
|
||||
void onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
|
||||
void parseGpioTopics(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
|
||||
void gpioActionCallback(const GpioAction& action, const int& pin);
|
||||
void setupDevice();
|
||||
bool reconnect();
|
||||
|
||||
String createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
|
||||
JsonDocument createHassJson(const String& uidString,
|
||||
@@ -127,22 +146,13 @@ private:
|
||||
|
||||
void buildMqttPath(char* outPath, std::initializer_list<const char*> paths);
|
||||
|
||||
static Network* _inst;
|
||||
|
||||
const char* _lastWillPayload = "offline";
|
||||
char _mqttConnectionStateTopic[211] = {0};
|
||||
String _lockPath;
|
||||
|
||||
const char* _latestVersion;
|
||||
HTTPClient https;
|
||||
|
||||
Preferences* _preferences;
|
||||
PresenceDetection* _presenceDetection;
|
||||
Gpio* _gpio;
|
||||
IPConfiguration* _ipConfiguration = nullptr;
|
||||
String _hostname;
|
||||
char _hostnameArr[101] = {0};
|
||||
NetworkDevice* _device = nullptr;
|
||||
|
||||
int _mqttConnectionState = 0;
|
||||
bool _connectReplyReceived = false;
|
||||
|
||||
@@ -166,18 +176,12 @@ private:
|
||||
unsigned long _lastPresenceTs = 0;
|
||||
unsigned long _lastRssiTs = 0;
|
||||
bool _mqttEnabled = true;
|
||||
static unsigned long _ignoreSubscriptionsTs;
|
||||
long _rssiPublishInterval = 0;
|
||||
std::map<uint8_t, unsigned long> _gpioTs;
|
||||
|
||||
char* _buffer;
|
||||
const size_t _bufferSize;
|
||||
|
||||
std::function<void()> _keepAliveCallback = nullptr;
|
||||
std::vector<std::function<void()>> _reconnectedCallbacks;
|
||||
|
||||
NetworkDeviceType _networkDeviceType = (NetworkDeviceType)-1;
|
||||
|
||||
int8_t _lastRssi = 127;
|
||||
|
||||
};
|
||||
#endif
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "NetworkLock.h"
|
||||
#include "NukiNetworkLock.h"
|
||||
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
|
||||
#include "Arduino.h"
|
||||
#include "Config.h"
|
||||
#include "MqttTopics.h"
|
||||
#include "PreferencesKeys.h"
|
||||
#include "Logger.h"
|
||||
@@ -8,7 +9,7 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <ctype.h>
|
||||
|
||||
NetworkLock::NetworkLock(Network* network, Preferences* preferences, char* buffer, size_t bufferSize)
|
||||
NukiNetworkLock::NukiNetworkLock(NukiNetwork* network, Preferences* preferences, char* buffer, size_t bufferSize)
|
||||
: _network(network),
|
||||
_preferences(preferences),
|
||||
_buffer(buffer),
|
||||
@@ -33,11 +34,11 @@ NetworkLock::NetworkLock(Network* network, Preferences* preferences, char* buffe
|
||||
_network->registerMqttReceiver(this);
|
||||
}
|
||||
|
||||
NetworkLock::~NetworkLock()
|
||||
NukiNetworkLock::~NukiNetworkLock()
|
||||
{
|
||||
}
|
||||
|
||||
void NetworkLock::initialize()
|
||||
void NukiNetworkLock::initialize()
|
||||
{
|
||||
String mqttPath = _preferences->getString(preference_mqtt_lock_path);
|
||||
if(mqttPath.length() > 0)
|
||||
@@ -63,8 +64,16 @@ void NetworkLock::initialize()
|
||||
_network->initTopic(_mqttPath, mqtt_topic_config_action, "--");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_config_action);
|
||||
|
||||
_network->subscribe(_mqttPath, mqtt_topic_reset);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_reset, "0");
|
||||
if(_preferences->getBool(preference_update_from_mqtt, false))
|
||||
{
|
||||
_network->subscribe(_mqttPath, mqtt_topic_reset);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_reset, "0");
|
||||
}
|
||||
|
||||
#if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
_network->subscribe(_mqttPath, mqtt_topic_update);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_update, "0");
|
||||
#endif
|
||||
|
||||
_network->subscribe(_mqttPath, mqtt_topic_webserver_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_webserver_action, "--");
|
||||
@@ -167,7 +176,7 @@ void NetworkLock::initialize()
|
||||
});
|
||||
}
|
||||
|
||||
void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const unsigned int length)
|
||||
void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const unsigned int length)
|
||||
{
|
||||
char* value = (char*)payload;
|
||||
|
||||
@@ -178,6 +187,16 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
delay(200);
|
||||
restartEsp(RestartReason::RequestedViaMqtt);
|
||||
}
|
||||
#if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_update) && strcmp(value, "1") == 0 && _preferences->getBool(preference_update_from_mqtt, false))
|
||||
{
|
||||
Log->println(F("Update requested via MQTT."));
|
||||
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
|
||||
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
|
||||
delay(200);
|
||||
restartEsp(RestartReason::OTAReboot);
|
||||
}
|
||||
#endif
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_webserver_action))
|
||||
{
|
||||
if(strcmp(value, "") == 0 ||
|
||||
@@ -197,7 +216,7 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
_preferences->putBool(preference_webserver_enabled, false);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_webserver_action, "--");
|
||||
publishString(mqtt_topic_webserver_action, "--", true);
|
||||
_network->clearWifiFallback();
|
||||
delay(200);
|
||||
restartEsp(RestartReason::RequestedViaMqtt);
|
||||
@@ -275,12 +294,12 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
|
||||
if(strcmp(value, "--") != 0)
|
||||
{
|
||||
publishString(mqtt_topic_keypad_command_action, "--");
|
||||
publishString(mqtt_topic_keypad_command_action, "--", true);
|
||||
}
|
||||
publishInt(mqtt_topic_keypad_command_id, _keypadCommandId);
|
||||
publishString(mqtt_topic_keypad_command_name, _keypadCommandName);
|
||||
publishString(mqtt_topic_keypad_command_code, _keypadCommandCode);
|
||||
publishInt(mqtt_topic_keypad_command_enabled, _keypadCommandEnabled);
|
||||
publishInt(mqtt_topic_keypad_command_id, _keypadCommandId, true);
|
||||
publishString(mqtt_topic_keypad_command_name, _keypadCommandName, true);
|
||||
publishString(mqtt_topic_keypad_command_code, _keypadCommandCode, true);
|
||||
publishInt(mqtt_topic_keypad_command_enabled, _keypadCommandEnabled, true);
|
||||
}
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_id))
|
||||
@@ -304,22 +323,22 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(value, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_CONFIG;
|
||||
publishString(mqtt_topic_query_config, "0");
|
||||
publishString(mqtt_topic_query_config, "0", true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_lockstate) && strcmp(value, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_LOCKSTATE;
|
||||
publishString(mqtt_topic_query_lockstate, "0");
|
||||
publishString(mqtt_topic_query_lockstate, "0", true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_keypad) && strcmp(value, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_KEYPAD;
|
||||
publishString(mqtt_topic_query_keypad, "0");
|
||||
publishString(mqtt_topic_query_keypad, "0", true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_battery) && strcmp(value, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_BATTERY;
|
||||
publishString(mqtt_topic_query_battery, "0");
|
||||
publishString(mqtt_topic_query_battery, "0", true);
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_config_action))
|
||||
@@ -331,7 +350,7 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
_configUpdateReceivedCallback(value);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_config_action, "--");
|
||||
publishString(mqtt_topic_config_action, "--", true);
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_keypad_json_action))
|
||||
@@ -343,7 +362,7 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
_keypadJsonCommandReceivedReceivedCallback(value);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_keypad_json_action, "--");
|
||||
publishString(mqtt_topic_keypad_json_action, "--", true);
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_timecontrol_action))
|
||||
@@ -355,11 +374,11 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
_timeControlCommandReceivedReceivedCallback(value);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_timecontrol_action, "--");
|
||||
publishString(mqtt_topic_timecontrol_action, "--", true);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState)
|
||||
void NukiNetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState)
|
||||
{
|
||||
char str[50];
|
||||
memset(&str, 0, sizeof(str));
|
||||
@@ -374,7 +393,7 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
|
||||
if(keyTurnerState.lockState != NukiLock::LockState::Undefined)
|
||||
{
|
||||
|
||||
publishString(mqtt_topic_lock_state, str);
|
||||
publishString(mqtt_topic_lock_state, str, true);
|
||||
|
||||
if(_haEnabled)
|
||||
{
|
||||
@@ -400,7 +419,7 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
|
||||
|
||||
if(_firstTunerStatePublish || keyTurnerState.trigger != lastKeyTurnerState.trigger)
|
||||
{
|
||||
publishString(mqtt_topic_lock_trigger, str);
|
||||
publishString(mqtt_topic_lock_trigger, str, true);
|
||||
}
|
||||
|
||||
json["trigger"] = str;
|
||||
@@ -425,7 +444,7 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
|
||||
|
||||
if(_firstTunerStatePublish || keyTurnerState.lastLockAction != lastKeyTurnerState.lastLockAction)
|
||||
{
|
||||
publishString(mqtt_topic_lock_last_lock_action, str);
|
||||
publishString(mqtt_topic_lock_last_lock_action, str, true);
|
||||
}
|
||||
|
||||
json["last_lock_action"] = str;
|
||||
@@ -445,7 +464,7 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
|
||||
|
||||
if(_firstTunerStatePublish || keyTurnerState.lastLockActionCompletionStatus != lastKeyTurnerState.lastLockActionCompletionStatus)
|
||||
{
|
||||
publishString(mqtt_topic_lock_completionStatus, str);
|
||||
publishString(mqtt_topic_lock_completionStatus, str, true);
|
||||
}
|
||||
|
||||
json["lock_completion_status"] = str;
|
||||
@@ -457,7 +476,7 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
|
||||
|
||||
if(_firstTunerStatePublish || keyTurnerState.doorSensorState != lastKeyTurnerState.doorSensorState)
|
||||
{
|
||||
publishString(mqtt_topic_lock_door_sensor_state, str);
|
||||
publishString(mqtt_topic_lock_door_sensor_state, str, true);
|
||||
}
|
||||
|
||||
json["door_sensor_state"] = str;
|
||||
@@ -474,14 +493,14 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
|
||||
|
||||
if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishBool(mqtt_topic_battery_critical, critical);
|
||||
publishBool(mqtt_topic_battery_charging, charging);
|
||||
publishInt(mqtt_topic_battery_level, level);
|
||||
publishBool(mqtt_topic_battery_critical, critical, true);
|
||||
publishBool(mqtt_topic_battery_charging, charging, true);
|
||||
publishInt(mqtt_topic_battery_level, level, true);
|
||||
}
|
||||
|
||||
if((_firstTunerStatePublish || keyTurnerState.accessoryBatteryState != lastKeyTurnerState.accessoryBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishBool(mqtt_topic_battery_keypad_critical, keypadCritical);
|
||||
publishBool(mqtt_topic_battery_keypad_critical, keypadCritical, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -494,55 +513,55 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
|
||||
json["auth_name"] = _authName;
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_lock_json, _buffer);
|
||||
publishString(mqtt_topic_lock_json, _buffer, true);
|
||||
|
||||
serializeJson(jsonBattery, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_battery_basic_json, _buffer);
|
||||
publishString(mqtt_topic_battery_basic_json, _buffer, true);
|
||||
|
||||
_firstTunerStatePublish = false;
|
||||
}
|
||||
|
||||
void NetworkLock::publishState(NukiLock::LockState lockState)
|
||||
void NukiNetworkLock::publishState(NukiLock::LockState lockState)
|
||||
{
|
||||
switch(lockState)
|
||||
{
|
||||
case NukiLock::LockState::Locked:
|
||||
publishString(mqtt_topic_lock_ha_state, "locked");
|
||||
publishString(mqtt_topic_lock_binary_state, "locked");
|
||||
publishString(mqtt_topic_lock_ha_state, "locked", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "locked", true);
|
||||
break;
|
||||
case NukiLock::LockState::Locking:
|
||||
publishString(mqtt_topic_lock_ha_state, "locking");
|
||||
publishString(mqtt_topic_lock_binary_state, "locked");
|
||||
publishString(mqtt_topic_lock_ha_state, "locking", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "locked", true);
|
||||
break;
|
||||
case NukiLock::LockState::Unlocking:
|
||||
publishString(mqtt_topic_lock_ha_state, "unlocking");
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_ha_state, "unlocking", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked", true);
|
||||
break;
|
||||
case NukiLock::LockState::Unlocked:
|
||||
case NukiLock::LockState::UnlockedLnga:
|
||||
publishString(mqtt_topic_lock_ha_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_ha_state, "unlocked", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked", true);
|
||||
break;
|
||||
case NukiLock::LockState::Unlatched:
|
||||
publishString(mqtt_topic_lock_ha_state, "open");
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_ha_state, "open", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked", true);
|
||||
break;
|
||||
case NukiLock::LockState::Unlatching:
|
||||
publishString(mqtt_topic_lock_ha_state, "opening");
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_ha_state, "opening", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked", true);
|
||||
break;
|
||||
case NukiLock::LockState::Uncalibrated:
|
||||
case NukiLock::LockState::Calibration:
|
||||
case NukiLock::LockState::BootRun:
|
||||
case NukiLock::LockState::MotorBlocked:
|
||||
publishString(mqtt_topic_lock_ha_state, "jammed");
|
||||
publishString(mqtt_topic_lock_ha_state, "jammed", true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>& logEntries, bool latest)
|
||||
void NukiNetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>& logEntries, bool latest)
|
||||
{
|
||||
char str[50];
|
||||
char authName[33];
|
||||
@@ -659,46 +678,47 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
|
||||
_lastRollingLog = log.index;
|
||||
serializeJson(entry, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_lock_log_rolling, _buffer);
|
||||
publishInt(mqtt_topic_lock_log_rolling_last, log.index);
|
||||
publishInt(mqtt_topic_lock_log_rolling_last, log.index, true);
|
||||
}
|
||||
}
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
|
||||
if(latest) publishString(mqtt_topic_lock_log_latest, _buffer);
|
||||
else publishString(mqtt_topic_lock_log, _buffer);
|
||||
if(latest) publishString(mqtt_topic_lock_log_latest, _buffer, true);
|
||||
else publishString(mqtt_topic_lock_log, _buffer, true);
|
||||
|
||||
if(authIndex > 0)
|
||||
{
|
||||
publishUInt(mqtt_topic_lock_auth_id, _authId);
|
||||
publishString(mqtt_topic_lock_auth_name, _authName);
|
||||
publishUInt(mqtt_topic_lock_auth_id, _authId, true);
|
||||
publishString(mqtt_topic_lock_auth_name, _authName, true);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::clearAuthorizationInfo()
|
||||
void NukiNetworkLock::clearAuthorizationInfo()
|
||||
{
|
||||
publishString(mqtt_topic_lock_log, "--");
|
||||
publishUInt(mqtt_topic_lock_auth_id, 0);
|
||||
publishString(mqtt_topic_lock_auth_name, "--");}
|
||||
|
||||
void NetworkLock::publishCommandResult(const char *resultStr)
|
||||
{
|
||||
publishString(mqtt_topic_lock_action_command_result, resultStr);
|
||||
publishString(mqtt_topic_lock_log, "--", true);
|
||||
publishUInt(mqtt_topic_lock_auth_id, 0, true);
|
||||
publishString(mqtt_topic_lock_auth_name, "--", true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishLockstateCommandResult(const char *resultStr)
|
||||
void NukiNetworkLock::publishCommandResult(const char *resultStr)
|
||||
{
|
||||
publishString(mqtt_topic_query_lockstate_command_result, resultStr);
|
||||
publishString(mqtt_topic_lock_action_command_result, resultStr, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishBatteryReport(const NukiLock::BatteryReport& batteryReport)
|
||||
void NukiNetworkLock::publishLockstateCommandResult(const char *resultStr)
|
||||
{
|
||||
publishString(mqtt_topic_query_lockstate_command_result, resultStr, true);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::publishBatteryReport(const NukiLock::BatteryReport& batteryReport)
|
||||
{
|
||||
if(!_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0);
|
||||
publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain); // milliwatt seconds
|
||||
publishFloat(mqtt_topic_battery_max_turn_current, (float)batteryReport.maxTurnCurrent / 1000.0);
|
||||
publishInt(mqtt_topic_battery_lock_distance, batteryReport.lockDistance); // degrees
|
||||
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0, true);
|
||||
publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain, true); // milliwatt seconds
|
||||
publishFloat(mqtt_topic_battery_max_turn_current, (float)batteryReport.maxTurnCurrent / 1000.0, true);
|
||||
publishInt(mqtt_topic_battery_lock_distance, batteryReport.lockDistance, true); // degrees
|
||||
}
|
||||
|
||||
char str[50];
|
||||
@@ -719,10 +739,10 @@ void NetworkLock::publishBatteryReport(const NukiLock::BatteryReport& batteryRep
|
||||
json["batteryResistance"] = (float)batteryReport.batteryResistance / 1000.0;
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_battery_advanced_json, _buffer);
|
||||
publishString(mqtt_topic_battery_advanced_json, _buffer, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishConfig(const NukiLock::Config &config)
|
||||
void NukiNetworkLock::publishConfig(const NukiLock::Config &config)
|
||||
{
|
||||
char str[50];
|
||||
char curTime[20];
|
||||
@@ -773,21 +793,21 @@ void NetworkLock::publishConfig(const NukiLock::Config &config)
|
||||
json["timeZone"] = str;
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_config_basic_json, _buffer);
|
||||
publishString(mqtt_topic_config_basic_json, _buffer, true);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1);
|
||||
publishBool(mqtt_topic_config_led_enabled, config.ledEnabled == 1);
|
||||
publishInt(mqtt_topic_config_led_brightness, config.ledBrightness);
|
||||
publishBool(mqtt_topic_config_single_lock, config.singleLock == 1);
|
||||
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1, true);
|
||||
publishBool(mqtt_topic_config_led_enabled, config.ledEnabled == 1, true);
|
||||
publishInt(mqtt_topic_config_led_brightness, config.ledBrightness, true);
|
||||
publishBool(mqtt_topic_config_single_lock, config.singleLock == 1, true);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_info_firmware_version, std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]));
|
||||
publishString(mqtt_topic_info_hardware_version, std::to_string(config.hardwareRevision[0]) + "." + std::to_string(config.hardwareRevision[1]));
|
||||
publishString(mqtt_topic_info_firmware_version, std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]), true);
|
||||
publishString(mqtt_topic_info_hardware_version, std::to_string(config.hardwareRevision[0]) + "." + std::to_string(config.hardwareRevision[1]), true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishAdvancedConfig(const NukiLock::AdvancedConfig &config)
|
||||
void NukiNetworkLock::publishAdvancedConfig(const NukiLock::AdvancedConfig &config)
|
||||
{
|
||||
char str[50];
|
||||
char nmst[6];
|
||||
@@ -828,31 +848,31 @@ void NetworkLock::publishAdvancedConfig(const NukiLock::AdvancedConfig &config)
|
||||
json["autoUpdateEnabled"] = config.autoUpdateEnabled;
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_config_advanced_json, _buffer);
|
||||
publishString(mqtt_topic_config_advanced_json, _buffer, true);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0);
|
||||
publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1);
|
||||
publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0, true);
|
||||
publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::publishRssi(const int& rssi)
|
||||
void NukiNetworkLock::publishRssi(const int& rssi)
|
||||
{
|
||||
publishInt(mqtt_topic_lock_rssi, rssi);
|
||||
publishInt(mqtt_topic_lock_rssi, rssi, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishRetry(const std::string& message)
|
||||
void NukiNetworkLock::publishRetry(const std::string& message)
|
||||
{
|
||||
publishString(mqtt_topic_lock_retry, message);
|
||||
publishString(mqtt_topic_lock_retry, message, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishBleAddress(const std::string &address)
|
||||
void NukiNetworkLock::publishBleAddress(const std::string &address)
|
||||
{
|
||||
publishString(mqtt_topic_lock_address, address);
|
||||
publishString(mqtt_topic_lock_address, address, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
|
||||
void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
|
||||
{
|
||||
uint index = 0;
|
||||
char uidString[20];
|
||||
@@ -956,7 +976,7 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
|
||||
jsonEntry["name_ha"] = entry.name;
|
||||
jsonEntry["index"] = index;
|
||||
serializeJson(jsonEntry, _buffer, _bufferSize);
|
||||
publishString(basePath.c_str(), _buffer);
|
||||
publishString(basePath.c_str(), _buffer, true);
|
||||
|
||||
String basePathPrefix = "~";
|
||||
basePathPrefix.concat(basePath);
|
||||
@@ -997,7 +1017,7 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
|
||||
}
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_keypad_json, _buffer);
|
||||
publishString(mqtt_topic_keypad_json, _buffer, true);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
@@ -1047,7 +1067,7 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
|
||||
_network->removeTopic(codeTopic, "createdSec");
|
||||
_network->removeTopic(codeTopic, "lockCount");
|
||||
}
|
||||
|
||||
|
||||
for(int j=entries.size(); j<maxKeypadCodeCount; j++)
|
||||
{
|
||||
String codesTopic = _mqttPath;
|
||||
@@ -1062,7 +1082,7 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry)
|
||||
void NukiNetworkLock::publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry)
|
||||
{
|
||||
if(_preferences->getBool(preference_disable_non_json, false)) return;
|
||||
|
||||
@@ -1070,25 +1090,25 @@ void NetworkLock::publishKeypadEntry(const String topic, NukiLock::KeypadEntry e
|
||||
memset(codeName, 0, sizeof(codeName));
|
||||
memcpy(codeName, entry.name, sizeof(entry.name));
|
||||
|
||||
publishInt(concat(topic, "/id").c_str(), entry.codeId);
|
||||
publishBool(concat(topic, "/enabled").c_str(), entry.enabled);
|
||||
publishString(concat(topic, "/name").c_str(), codeName);
|
||||
publishInt(concat(topic, "/id").c_str(), entry.codeId, true);
|
||||
publishBool(concat(topic, "/enabled").c_str(), entry.enabled, true);
|
||||
publishString(concat(topic, "/name").c_str(), codeName, true);
|
||||
|
||||
if(_preferences->getBool(preference_keypad_publish_code, false))
|
||||
{
|
||||
publishInt(concat(topic, "/code").c_str(), entry.code);
|
||||
publishInt(concat(topic, "/code").c_str(), entry.code, true);
|
||||
}
|
||||
|
||||
publishInt(concat(topic, "/createdYear").c_str(), entry.dateCreatedYear);
|
||||
publishInt(concat(topic, "/createdMonth").c_str(), entry.dateCreatedMonth);
|
||||
publishInt(concat(topic, "/createdDay").c_str(), entry.dateCreatedDay);
|
||||
publishInt(concat(topic, "/createdHour").c_str(), entry.dateCreatedHour);
|
||||
publishInt(concat(topic, "/createdMin").c_str(), entry.dateCreatedMin);
|
||||
publishInt(concat(topic, "/createdSec").c_str(), entry.dateCreatedSec);
|
||||
publishInt(concat(topic, "/lockCount").c_str(), entry.lockCount);
|
||||
publishInt(concat(topic, "/createdYear").c_str(), entry.dateCreatedYear, true);
|
||||
publishInt(concat(topic, "/createdMonth").c_str(), entry.dateCreatedMonth, true);
|
||||
publishInt(concat(topic, "/createdDay").c_str(), entry.dateCreatedDay, true);
|
||||
publishInt(concat(topic, "/createdHour").c_str(), entry.dateCreatedHour, true);
|
||||
publishInt(concat(topic, "/createdMin").c_str(), entry.dateCreatedMin, true);
|
||||
publishInt(concat(topic, "/createdSec").c_str(), entry.dateCreatedSec, true);
|
||||
publishInt(concat(topic, "/lockCount").c_str(), entry.lockCount, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount)
|
||||
void NukiNetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount)
|
||||
{
|
||||
uint index = 0;
|
||||
char str[50];
|
||||
@@ -1166,7 +1186,7 @@ void NetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEntry>
|
||||
basePath.concat(std::to_string(index).c_str());
|
||||
jsonEntry["index"] = index;
|
||||
serializeJson(jsonEntry, _buffer, _bufferSize);
|
||||
publishString(basePath.c_str(), _buffer);
|
||||
publishString(basePath.c_str(), _buffer, true);
|
||||
|
||||
String basePathPrefix = "~";
|
||||
basePathPrefix.concat(basePath);
|
||||
@@ -1199,13 +1219,13 @@ void NetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEntry>
|
||||
{ (char*)"stat_on", (char*)"1" },
|
||||
{ (char*)"stat_off", (char*)"0" }});
|
||||
}
|
||||
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_timecontrol_json, _buffer);
|
||||
|
||||
publishString(mqtt_topic_timecontrol_json, _buffer, true);
|
||||
|
||||
for(int j=timeControlEntries.size(); j<maxTimeControlEntryCount; j++)
|
||||
{
|
||||
String entriesTopic = _mqttPath;
|
||||
@@ -1217,64 +1237,64 @@ void NetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEntry>
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::publishConfigCommandResult(const char* result)
|
||||
void NukiNetworkLock::publishConfigCommandResult(const char* result)
|
||||
{
|
||||
publishString(mqtt_topic_config_action_command_result, result);
|
||||
publishString(mqtt_topic_config_action_command_result, result, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishKeypadCommandResult(const char* result)
|
||||
void NukiNetworkLock::publishKeypadCommandResult(const char* result)
|
||||
{
|
||||
if(_preferences->getBool(preference_disable_non_json, false)) return;
|
||||
publishString(mqtt_topic_keypad_command_result, result);
|
||||
publishString(mqtt_topic_keypad_command_result, result, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishKeypadJsonCommandResult(const char* result)
|
||||
void NukiNetworkLock::publishKeypadJsonCommandResult(const char* result)
|
||||
{
|
||||
publishString(mqtt_topic_keypad_json_command_result, result);
|
||||
publishString(mqtt_topic_keypad_json_command_result, result, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishTimeControlCommandResult(const char* result)
|
||||
void NukiNetworkLock::publishTimeControlCommandResult(const char* result)
|
||||
{
|
||||
publishString(mqtt_topic_timecontrol_command_result, result);
|
||||
publishString(mqtt_topic_timecontrol_command_result, result, true);
|
||||
}
|
||||
|
||||
void NetworkLock::publishStatusUpdated(const bool statusUpdated)
|
||||
void NukiNetworkLock::publishStatusUpdated(const bool statusUpdated)
|
||||
{
|
||||
publishBool(mqtt_topic_lock_status_updated, statusUpdated);
|
||||
}
|
||||
|
||||
void NetworkLock::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *))
|
||||
{
|
||||
_lockActionReceivedCallback = lockActionReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkLock::setOfficialUpdateReceivedCallback(void (*officialUpdateReceivedCallback)(const char *, const char *))
|
||||
void NukiNetworkLock::setOfficialUpdateReceivedCallback(void (*officialUpdateReceivedCallback)(const char *, const char *))
|
||||
{
|
||||
_officialUpdateReceivedCallback = officialUpdateReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkLock::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char *))
|
||||
{
|
||||
_configUpdateReceivedCallback = configUpdateReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkLock::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
|
||||
void NukiNetworkLock::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
|
||||
{
|
||||
if(_preferences->getBool(preference_disable_non_json, false)) return;
|
||||
_keypadCommandReceivedReceivedCallback = keypadCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkLock::setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char *))
|
||||
{
|
||||
_keypadJsonCommandReceivedReceivedCallback = keypadJsonCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkLock::setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char *))
|
||||
{
|
||||
_timeControlCommandReceivedReceivedCallback = timeControlCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkLock::buildMqttPath(const char* path, char* outPath, bool offPath)
|
||||
void NukiNetworkLock::buildMqttPath(const char* path, char* outPath, bool offPath)
|
||||
{
|
||||
int offset = 0;
|
||||
char inPath[181] = {0};
|
||||
@@ -1301,14 +1321,14 @@ void NetworkLock::buildMqttPath(const char* path, char* outPath, bool offPath)
|
||||
outPath[i+1] = 0x00;
|
||||
}
|
||||
|
||||
bool NetworkLock::comparePrefixedPath(const char *fullPath, const char *subPath, bool offPath)
|
||||
bool NukiNetworkLock::comparePrefixedPath(const char *fullPath, const char *subPath, bool offPath)
|
||||
{
|
||||
char prefixedPath[500];
|
||||
buildMqttPath(subPath, prefixedPath, offPath);
|
||||
return strcmp(fullPath, prefixedPath) == 0;
|
||||
}
|
||||
|
||||
void NetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, char *name, char *uidString, const char *softwareVersion, const char *hardwareVersion, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char *lockAction,
|
||||
void NukiNetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, char *name, char *uidString, const char *softwareVersion, const char *hardwareVersion, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char *lockAction,
|
||||
char *unlockAction, char *openAction)
|
||||
{
|
||||
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, softwareVersion, hardwareVersion, "~/maintenance/mqttConnectionState", hasKeypad, lockAction, unlockAction, openAction);
|
||||
@@ -1345,37 +1365,37 @@ void NetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, cha
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::removeHASSConfig(char *uidString)
|
||||
void NukiNetworkLock::removeHASSConfig(char *uidString)
|
||||
{
|
||||
_network->removeHASSConfig(uidString);
|
||||
}
|
||||
|
||||
void NetworkLock::publishOffAction(const int value)
|
||||
void NukiNetworkLock::publishOffAction(const int value)
|
||||
{
|
||||
_network->publishInt(_offMqttPath, mqtt_topic_official_lock_action, value, false);
|
||||
}
|
||||
|
||||
void NetworkLock::publishFloat(const char *topic, const float value, const uint8_t precision, bool retain)
|
||||
void NukiNetworkLock::publishFloat(const char *topic, const float value, const uint8_t precision, bool retain)
|
||||
{
|
||||
_network->publishFloat(_mqttPath, topic, value, precision, retain);
|
||||
}
|
||||
|
||||
void NetworkLock::publishInt(const char *topic, const int value, bool retain)
|
||||
void NukiNetworkLock::publishInt(const char *topic, const int value, bool retain)
|
||||
{
|
||||
_network->publishInt(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NetworkLock::publishUInt(const char *topic, const unsigned int value, bool retain)
|
||||
void NukiNetworkLock::publishUInt(const char *topic, const unsigned int value, bool retain)
|
||||
{
|
||||
_network->publishUInt(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NetworkLock::publishBool(const char *topic, const bool value, bool retain)
|
||||
void NukiNetworkLock::publishBool(const char *topic, const bool value, bool retain)
|
||||
{
|
||||
_network->publishBool(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
bool NetworkLock::publishString(const char *topic, const String &value, bool retain)
|
||||
bool NukiNetworkLock::publishString(const char *topic, const String &value, bool retain)
|
||||
{
|
||||
char str[value.length() + 1];
|
||||
memset(str, 0, sizeof(str));
|
||||
@@ -1383,7 +1403,7 @@ bool NetworkLock::publishString(const char *topic, const String &value, bool ret
|
||||
return publishString(topic, str, retain);
|
||||
}
|
||||
|
||||
bool NetworkLock::publishString(const char *topic, const std::string &value, bool retain)
|
||||
bool NukiNetworkLock::publishString(const char *topic, const std::string &value, bool retain)
|
||||
{
|
||||
char str[value.size() + 1];
|
||||
memset(str, 0, sizeof(str));
|
||||
@@ -1391,38 +1411,38 @@ bool NetworkLock::publishString(const char *topic, const std::string &value, boo
|
||||
return publishString(topic, str, retain);
|
||||
}
|
||||
|
||||
bool NetworkLock::publishString(const char *topic, const char *value, bool retain)
|
||||
bool NukiNetworkLock::publishString(const char *topic, const char *value, bool retain)
|
||||
{
|
||||
return _network->publishString(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NetworkLock::publishULong(const char *topic, const unsigned long value, bool retain)
|
||||
void NukiNetworkLock::publishULong(const char *topic, const unsigned long value, bool retain)
|
||||
{
|
||||
return _network->publishULong(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
String NetworkLock::concat(String a, String b)
|
||||
String NukiNetworkLock::concat(String a, String b)
|
||||
{
|
||||
String c = a;
|
||||
c.concat(b);
|
||||
return c;
|
||||
}
|
||||
|
||||
bool NetworkLock::reconnected()
|
||||
bool NukiNetworkLock::reconnected()
|
||||
{
|
||||
bool r = _reconnected;
|
||||
_reconnected = false;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8_t NetworkLock::queryCommands()
|
||||
uint8_t NukiNetworkLock::queryCommands()
|
||||
{
|
||||
uint8_t qc = _queryCommands;
|
||||
_queryCommands = 0;
|
||||
return qc;
|
||||
}
|
||||
|
||||
void NetworkLock::buttonPressActionToString(const NukiLock::ButtonPressAction btnPressAction, char* str) {
|
||||
void NukiNetworkLock::buttonPressActionToString(const NukiLock::ButtonPressAction btnPressAction, char* str) {
|
||||
switch (btnPressAction) {
|
||||
case NukiLock::ButtonPressAction::NoAction:
|
||||
strcpy(str, "No Action");
|
||||
@@ -1451,7 +1471,7 @@ void NetworkLock::buttonPressActionToString(const NukiLock::ButtonPressAction bt
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::homeKitStatusToString(const int hkstatus, char* str) {
|
||||
void NukiNetworkLock::homeKitStatusToString(const int hkstatus, char* str) {
|
||||
switch (hkstatus) {
|
||||
case 0:
|
||||
strcpy(str, "Not Available");
|
||||
@@ -1471,7 +1491,7 @@ void NetworkLock::homeKitStatusToString(const int hkstatus, char* str) {
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkLock::fobActionToString(const int fobact, char* str) {
|
||||
void NukiNetworkLock::fobActionToString(const int fobact, char* str) {
|
||||
switch (fobact) {
|
||||
case 0:
|
||||
strcpy(str, "No Action");
|
||||
@@ -8,17 +8,17 @@
|
||||
#include <list>
|
||||
#include "NukiConstants.h"
|
||||
#include "NukiLockConstants.h"
|
||||
#include "Network.h"
|
||||
#include "NukiNetwork.h"
|
||||
#include "QueryCommand.h"
|
||||
#include "LockActionResult.h"
|
||||
|
||||
#define LOCK_LOG_JSON_BUFFER_SIZE 2048
|
||||
|
||||
class NetworkLock : public MqttReceiver
|
||||
class NukiNetworkLock : public MqttReceiver
|
||||
{
|
||||
public:
|
||||
explicit NetworkLock(Network* network, Preferences* preferences, char* buffer, size_t bufferSize);
|
||||
virtual ~NetworkLock();
|
||||
explicit NukiNetworkLock(NukiNetwork* network, Preferences* preferences, char* buffer, size_t bufferSize);
|
||||
virtual ~NukiNetworkLock();
|
||||
|
||||
void initialize();
|
||||
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
|
||||
void buildMqttPath(const char* path, char* outPath, bool offPath = false);
|
||||
|
||||
Network* _network;
|
||||
NukiNetwork* _network;
|
||||
Preferences* _preferences;
|
||||
|
||||
std::vector<char*> _offTopics;
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "NetworkOpener.h"
|
||||
#include "NukiNetworkOpener.h"
|
||||
#include "Arduino.h"
|
||||
#include "MqttTopics.h"
|
||||
#include "PreferencesKeys.h"
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "Config.h"
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
NetworkOpener::NetworkOpener(Network* network, Preferences* preferences, char* buffer, size_t bufferSize)
|
||||
NukiNetworkOpener::NukiNetworkOpener(NukiNetwork* network, Preferences* preferences, char* buffer, size_t bufferSize)
|
||||
: _preferences(preferences),
|
||||
_network(network),
|
||||
_buffer(buffer),
|
||||
@@ -18,7 +18,7 @@ NetworkOpener::NetworkOpener(Network* network, Preferences* preferences, char* b
|
||||
_network->registerMqttReceiver(this);
|
||||
}
|
||||
|
||||
void NetworkOpener::initialize()
|
||||
void NukiNetworkOpener::initialize()
|
||||
{
|
||||
String mqttPath = _preferences->getString(preference_mqtt_opener_path);
|
||||
if(mqttPath.length() > 0)
|
||||
@@ -120,16 +120,16 @@ void NetworkOpener::initialize()
|
||||
});
|
||||
}
|
||||
|
||||
void NetworkOpener::update()
|
||||
void NukiNetworkOpener::update()
|
||||
{
|
||||
if(_resetRingStateTs != 0 && millis() >= _resetRingStateTs)
|
||||
{
|
||||
_resetRingStateTs = 0;
|
||||
publishString(mqtt_topic_lock_binary_ring, "standby");
|
||||
publishString(mqtt_topic_lock_binary_ring, "standby", true);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const unsigned int length)
|
||||
void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const unsigned int length)
|
||||
{
|
||||
char* value = (char*)payload;
|
||||
|
||||
@@ -192,12 +192,12 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u
|
||||
|
||||
if(strcmp(value, "--") != 0)
|
||||
{
|
||||
publishString(mqtt_topic_keypad_command_action, "--");
|
||||
publishString(mqtt_topic_keypad_command_action, "--", true);
|
||||
}
|
||||
publishInt(mqtt_topic_keypad_command_id, _keypadCommandId);
|
||||
publishString(mqtt_topic_keypad_command_name, _keypadCommandName);
|
||||
publishString(mqtt_topic_keypad_command_code, _keypadCommandCode);
|
||||
publishInt(mqtt_topic_keypad_command_enabled, _keypadCommandEnabled);
|
||||
publishInt(mqtt_topic_keypad_command_id, _keypadCommandId, true);
|
||||
publishString(mqtt_topic_keypad_command_name, _keypadCommandName, true);
|
||||
publishString(mqtt_topic_keypad_command_code, _keypadCommandCode, true);
|
||||
publishInt(mqtt_topic_keypad_command_enabled, _keypadCommandEnabled, true);
|
||||
}
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_id))
|
||||
@@ -221,22 +221,22 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u
|
||||
if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(value, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_CONFIG;
|
||||
publishString(mqtt_topic_query_config, "0");
|
||||
publishString(mqtt_topic_query_config, "0", true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_lockstate) && strcmp(value, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_LOCKSTATE;
|
||||
publishString(mqtt_topic_query_lockstate, "0");
|
||||
publishString(mqtt_topic_query_lockstate, "0", true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_keypad) && strcmp(value, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_KEYPAD;
|
||||
publishString(mqtt_topic_query_keypad, "0");
|
||||
publishString(mqtt_topic_query_keypad, "0", true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_battery) && strcmp(value, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_BATTERY;
|
||||
publishString(mqtt_topic_query_battery, "0");
|
||||
publishString(mqtt_topic_query_battery, "0", true);
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_config_action))
|
||||
@@ -248,7 +248,7 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u
|
||||
_configUpdateReceivedCallback(value);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_config_action, "--");
|
||||
publishString(mqtt_topic_config_action, "--", true);
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_keypad_json_action))
|
||||
@@ -260,7 +260,7 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u
|
||||
_keypadJsonCommandReceivedReceivedCallback(value);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_keypad_json_action, "--");
|
||||
publishString(mqtt_topic_keypad_json_action, "--", true);
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_timecontrol_action))
|
||||
@@ -272,11 +272,11 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u
|
||||
_timeControlCommandReceivedReceivedCallback(value);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_timecontrol_action, "--");
|
||||
publishString(mqtt_topic_timecontrol_action, "--", true);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurnerState, const NukiOpener::OpenerState& lastKeyTurnerState)
|
||||
void NukiNetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurnerState, const NukiOpener::OpenerState& lastKeyTurnerState)
|
||||
{
|
||||
_currentLockState = keyTurnerState.lockState;
|
||||
|
||||
@@ -290,7 +290,7 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
|
||||
|
||||
if((_firstTunerStatePublish || keyTurnerState.lockState != lastKeyTurnerState.lockState || keyTurnerState.nukiState != lastKeyTurnerState.nukiState) && keyTurnerState.lockState != NukiOpener::LockState::Undefined)
|
||||
{
|
||||
publishString(mqtt_topic_lock_state, str);
|
||||
publishString(mqtt_topic_lock_state, str, true);
|
||||
|
||||
if(_haEnabled)
|
||||
{
|
||||
@@ -314,7 +314,7 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
|
||||
|
||||
if(_firstTunerStatePublish || keyTurnerState.trigger != lastKeyTurnerState.trigger)
|
||||
{
|
||||
publishString(mqtt_topic_lock_trigger, str);
|
||||
publishString(mqtt_topic_lock_trigger, str, true);
|
||||
}
|
||||
|
||||
json["trigger"] = str;
|
||||
@@ -329,7 +329,7 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
|
||||
|
||||
if(_firstTunerStatePublish || keyTurnerState.lastLockAction != lastKeyTurnerState.lastLockAction)
|
||||
{
|
||||
publishString(mqtt_topic_lock_last_lock_action, str);
|
||||
publishString(mqtt_topic_lock_last_lock_action, str, true);
|
||||
}
|
||||
|
||||
json["last_lock_action"] = str;
|
||||
@@ -343,7 +343,7 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
|
||||
|
||||
if(_firstTunerStatePublish || keyTurnerState.lastLockActionCompletionStatus != lastKeyTurnerState.lastLockActionCompletionStatus)
|
||||
{
|
||||
publishString(mqtt_topic_lock_completionStatus, str);
|
||||
publishString(mqtt_topic_lock_completionStatus, str, true);
|
||||
}
|
||||
|
||||
json["lock_completion_status"] = str;
|
||||
@@ -353,7 +353,7 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
|
||||
|
||||
if(_firstTunerStatePublish || keyTurnerState.doorSensorState != lastKeyTurnerState.doorSensorState)
|
||||
{
|
||||
publishString(mqtt_topic_lock_door_sensor_state, str);
|
||||
publishString(mqtt_topic_lock_door_sensor_state, str, true);
|
||||
}
|
||||
|
||||
json["door_sensor_state"] = str;
|
||||
@@ -363,66 +363,66 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
|
||||
|
||||
if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishBool(mqtt_topic_battery_critical, critical);
|
||||
publishBool(mqtt_topic_battery_critical, critical, true);
|
||||
}
|
||||
|
||||
json["auth_id"] = _authId;
|
||||
json["auth_name"] = _authName;
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_lock_json, _buffer);
|
||||
publishString(mqtt_topic_lock_json, _buffer, true);
|
||||
|
||||
serializeJson(jsonBattery, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_battery_basic_json, _buffer);
|
||||
publishString(mqtt_topic_battery_basic_json, _buffer, true);
|
||||
|
||||
_firstTunerStatePublish = false;
|
||||
}
|
||||
|
||||
void NetworkOpener::publishRing(const bool locked)
|
||||
void NukiNetworkOpener::publishRing(const bool locked)
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
publishString(mqtt_topic_lock_ring, "ringlocked");
|
||||
publishString(mqtt_topic_lock_ring, "ringlocked", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
publishString(mqtt_topic_lock_ring, "ring");
|
||||
publishString(mqtt_topic_lock_ring, "ring", true);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_lock_binary_ring, "ring");
|
||||
publishString(mqtt_topic_lock_binary_ring, "ring", true);
|
||||
_resetRingStateTs = millis() + 2000;
|
||||
}
|
||||
|
||||
void NetworkOpener::publishState(NukiOpener::OpenerState lockState)
|
||||
void NukiNetworkOpener::publishState(NukiOpener::OpenerState lockState)
|
||||
{
|
||||
if(lockState.nukiState == NukiOpener::State::ContinuousMode)
|
||||
{
|
||||
publishString(mqtt_topic_lock_ha_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_ha_state, "unlocked", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (lockState.lockState)
|
||||
{
|
||||
case NukiOpener::LockState::Locked:
|
||||
publishString(mqtt_topic_lock_ha_state, "locked");
|
||||
publishString(mqtt_topic_lock_binary_state, "locked");
|
||||
publishString(mqtt_topic_lock_ha_state, "locked", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "locked", true);
|
||||
break;
|
||||
case NukiOpener::LockState::RTOactive:
|
||||
publishString(mqtt_topic_lock_ha_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_ha_state, "unlocked", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked", true);
|
||||
break;
|
||||
case NukiOpener::LockState::Open:
|
||||
publishString(mqtt_topic_lock_ha_state, "open");
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_ha_state, "open", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked", true);
|
||||
break;
|
||||
case NukiOpener::LockState::Opening:
|
||||
publishString(mqtt_topic_lock_ha_state, "opening");
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked");
|
||||
publishString(mqtt_topic_lock_ha_state, "opening", true);
|
||||
publishString(mqtt_topic_lock_binary_state, "unlocked", true);
|
||||
break;
|
||||
case NukiOpener::LockState::Undefined:
|
||||
case NukiOpener::LockState::Uncalibrated:
|
||||
publishString(mqtt_topic_lock_ha_state, "jammed");
|
||||
publishString(mqtt_topic_lock_ha_state, "jammed", true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -430,7 +430,7 @@ void NetworkOpener::publishState(NukiOpener::OpenerState lockState)
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntry>& logEntries, bool latest)
|
||||
void NukiNetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntry>& logEntries, bool latest)
|
||||
{
|
||||
char str[50];
|
||||
char authName[33];
|
||||
@@ -581,45 +581,45 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
|
||||
{
|
||||
_lastRollingLog = log.index;
|
||||
serializeJson(entry, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_lock_log_rolling, _buffer);
|
||||
publishInt(mqtt_topic_lock_log_rolling_last, log.index);
|
||||
publishString(mqtt_topic_lock_log_rolling, _buffer, true);
|
||||
publishInt(mqtt_topic_lock_log_rolling_last, log.index, true);
|
||||
}
|
||||
}
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
|
||||
if(latest) publishString(mqtt_topic_lock_log_latest, _buffer);
|
||||
else publishString(mqtt_topic_lock_log, _buffer);
|
||||
if(latest) publishString(mqtt_topic_lock_log_latest, _buffer, true);
|
||||
else publishString(mqtt_topic_lock_log, _buffer, true);
|
||||
|
||||
if(authIndex > 0)
|
||||
{
|
||||
publishUInt(mqtt_topic_lock_auth_id, _authId);
|
||||
publishString(mqtt_topic_lock_auth_name, _authName);
|
||||
publishUInt(mqtt_topic_lock_auth_id, _authId, true);
|
||||
publishString(mqtt_topic_lock_auth_name, _authName, true);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::clearAuthorizationInfo()
|
||||
void NukiNetworkOpener::clearAuthorizationInfo()
|
||||
{
|
||||
publishString(mqtt_topic_lock_log, "--");
|
||||
publishUInt(mqtt_topic_lock_auth_id, 0);
|
||||
publishString(mqtt_topic_lock_auth_name, "--");
|
||||
publishString(mqtt_topic_lock_log, "--", true);
|
||||
publishUInt(mqtt_topic_lock_auth_id, 0, true);
|
||||
publishString(mqtt_topic_lock_auth_name, "--", true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishCommandResult(const char *resultStr)
|
||||
void NukiNetworkOpener::publishCommandResult(const char *resultStr)
|
||||
{
|
||||
publishString(mqtt_topic_lock_action_command_result, resultStr);
|
||||
publishString(mqtt_topic_lock_action_command_result, resultStr, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishLockstateCommandResult(const char *resultStr)
|
||||
void NukiNetworkOpener::publishLockstateCommandResult(const char *resultStr)
|
||||
{
|
||||
publishString(mqtt_topic_query_lockstate_command_result, resultStr);
|
||||
publishString(mqtt_topic_query_lockstate_command_result, resultStr, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishBatteryReport(const NukiOpener::BatteryReport& batteryReport)
|
||||
void NukiNetworkOpener::publishBatteryReport(const NukiOpener::BatteryReport& batteryReport)
|
||||
{
|
||||
if(!_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0);
|
||||
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0, true);
|
||||
}
|
||||
|
||||
char str[50];
|
||||
@@ -635,10 +635,10 @@ void NetworkOpener::publishBatteryReport(const NukiOpener::BatteryReport& batter
|
||||
json["lowestVoltage"] = (float)batteryReport.lowestVoltage / 1000.0;
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_battery_advanced_json, _buffer);
|
||||
publishString(mqtt_topic_battery_advanced_json, _buffer, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishConfig(const NukiOpener::Config &config)
|
||||
void NukiNetworkOpener::publishConfig(const NukiOpener::Config &config)
|
||||
{
|
||||
char str[50];
|
||||
char curTime[20];
|
||||
@@ -689,19 +689,19 @@ void NetworkOpener::publishConfig(const NukiOpener::Config &config)
|
||||
json["timeZone"] = str;
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_config_basic_json, _buffer);
|
||||
publishString(mqtt_topic_config_basic_json, _buffer, true);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1);
|
||||
publishBool(mqtt_topic_config_led_enabled, config.ledFlashEnabled == 1);
|
||||
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1, true);
|
||||
publishBool(mqtt_topic_config_led_enabled, config.ledFlashEnabled == 1, true);
|
||||
}
|
||||
|
||||
publishString(mqtt_topic_info_firmware_version, std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]));
|
||||
publishString(mqtt_topic_info_hardware_version, std::to_string(config.hardwareRevision[0]) + "." + std::to_string(config.hardwareRevision[1]));
|
||||
publishString(mqtt_topic_info_firmware_version, std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]), true);
|
||||
publishString(mqtt_topic_info_hardware_version, std::to_string(config.hardwareRevision[0]) + "." + std::to_string(config.hardwareRevision[1]), true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &config)
|
||||
void NukiNetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &config)
|
||||
{
|
||||
char str[50];
|
||||
|
||||
@@ -745,30 +745,30 @@ void NetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &conf
|
||||
json["automaticBatteryTypeDetection"] = config.automaticBatteryTypeDetection;
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_config_advanced_json, _buffer);
|
||||
publishString(mqtt_topic_config_advanced_json, _buffer, true);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
publishUInt(mqtt_topic_config_sound_level, config.soundLevel);
|
||||
publishUInt(mqtt_topic_config_sound_level, config.soundLevel, true);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::publishRssi(const int &rssi)
|
||||
void NukiNetworkOpener::publishRssi(const int &rssi)
|
||||
{
|
||||
publishInt(mqtt_topic_lock_rssi, rssi);
|
||||
publishInt(mqtt_topic_lock_rssi, rssi, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishRetry(const std::string& message)
|
||||
void NukiNetworkOpener::publishRetry(const std::string& message)
|
||||
{
|
||||
publishString(mqtt_topic_lock_retry, message);
|
||||
publishString(mqtt_topic_lock_retry, message, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishBleAddress(const std::string &address)
|
||||
void NukiNetworkOpener::publishBleAddress(const std::string &address)
|
||||
{
|
||||
publishString(mqtt_topic_lock_address, address);
|
||||
publishString(mqtt_topic_lock_address, address, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const bool& publishAuthData, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction)
|
||||
void NukiNetworkOpener::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const bool& publishAuthData, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction)
|
||||
{
|
||||
String availabilityTopic = _preferences->getString("mqttpath");
|
||||
availabilityTopic.concat("/maintenance/mqttConnectionState");
|
||||
@@ -795,12 +795,12 @@ void NetworkOpener::publishHASSConfig(char* deviceType, const char* baseTopic, c
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::removeHASSConfig(char* uidString)
|
||||
void NukiNetworkOpener::removeHASSConfig(char* uidString)
|
||||
{
|
||||
_network->removeHASSConfig(uidString);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
|
||||
void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
|
||||
{
|
||||
uint index = 0;
|
||||
char uidString[20];
|
||||
@@ -904,7 +904,7 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
|
||||
jsonEntry["name_ha"] = entry.name;
|
||||
jsonEntry["index"] = index;
|
||||
serializeJson(jsonEntry, _buffer, _bufferSize);
|
||||
publishString(basePath.c_str(), _buffer);
|
||||
publishString(basePath.c_str(), _buffer, true);
|
||||
|
||||
String basePathPrefix = "~";
|
||||
basePathPrefix.concat(basePath);
|
||||
@@ -945,7 +945,7 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
|
||||
}
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_keypad_json, _buffer);
|
||||
publishString(mqtt_topic_keypad_json, _buffer, true);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false))
|
||||
{
|
||||
@@ -1008,7 +1008,7 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount)
|
||||
void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount)
|
||||
{
|
||||
uint index = 0;
|
||||
char str[50];
|
||||
@@ -1086,7 +1086,7 @@ void NetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeControlEn
|
||||
basePath.concat(std::to_string(index).c_str());
|
||||
jsonEntry["index"] = index;
|
||||
serializeJson(jsonEntry, _buffer, _bufferSize);
|
||||
publishString(basePath.c_str(), _buffer);
|
||||
publishString(basePath.c_str(), _buffer, true);
|
||||
|
||||
String basePathPrefix = "~";
|
||||
basePathPrefix.concat(basePath);
|
||||
@@ -1123,7 +1123,7 @@ void NetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeControlEn
|
||||
}
|
||||
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_timecontrol_json, _buffer);
|
||||
publishString(mqtt_topic_timecontrol_json, _buffer, true);
|
||||
|
||||
for(int j=timeControlEntries.size(); j<maxTimeControlEntryCount; j++)
|
||||
{
|
||||
@@ -1136,79 +1136,79 @@ void NetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeControlEn
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::publishConfigCommandResult(const char* result)
|
||||
void NukiNetworkOpener::publishConfigCommandResult(const char* result)
|
||||
{
|
||||
publishString(mqtt_topic_config_action_command_result, result);
|
||||
publishString(mqtt_topic_config_action_command_result, result, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishKeypadCommandResult(const char* result)
|
||||
void NukiNetworkOpener::publishKeypadCommandResult(const char* result)
|
||||
{
|
||||
if(_preferences->getBool(preference_disable_non_json, false)) return;
|
||||
publishString(mqtt_topic_keypad_command_result, result);
|
||||
publishString(mqtt_topic_keypad_command_result, result, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishKeypadJsonCommandResult(const char* result)
|
||||
void NukiNetworkOpener::publishKeypadJsonCommandResult(const char* result)
|
||||
{
|
||||
publishString(mqtt_topic_keypad_json_command_result, result);
|
||||
publishString(mqtt_topic_keypad_json_command_result, result, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishTimeControlCommandResult(const char* result)
|
||||
void NukiNetworkOpener::publishTimeControlCommandResult(const char* result)
|
||||
{
|
||||
publishString(mqtt_topic_timecontrol_command_result, result);
|
||||
publishString(mqtt_topic_timecontrol_command_result, result, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishStatusUpdated(const bool statusUpdated)
|
||||
void NukiNetworkOpener::publishStatusUpdated(const bool statusUpdated)
|
||||
{
|
||||
publishBool(mqtt_topic_lock_status_updated, statusUpdated);
|
||||
}
|
||||
|
||||
void NetworkOpener::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *))
|
||||
void NukiNetworkOpener::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *))
|
||||
{
|
||||
_lockActionReceivedCallback = lockActionReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkOpener::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char *))
|
||||
void NukiNetworkOpener::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char *))
|
||||
{
|
||||
_configUpdateReceivedCallback = configUpdateReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkOpener::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
|
||||
void NukiNetworkOpener::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
|
||||
{
|
||||
if(_preferences->getBool(preference_disable_non_json, false)) return;
|
||||
_keypadCommandReceivedReceivedCallback = keypadCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkOpener::setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char *))
|
||||
void NukiNetworkOpener::setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char *))
|
||||
{
|
||||
_keypadJsonCommandReceivedReceivedCallback = keypadJsonCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkOpener::setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char *))
|
||||
void NukiNetworkOpener::setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char *))
|
||||
{
|
||||
_timeControlCommandReceivedReceivedCallback = timeControlCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NetworkOpener::publishFloat(const char *topic, const float value, const uint8_t precision, bool retain)
|
||||
void NukiNetworkOpener::publishFloat(const char *topic, const float value, const uint8_t precision, bool retain)
|
||||
{
|
||||
_network->publishFloat(_mqttPath, topic, value, precision, retain);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishInt(const char *topic, const int value, bool retain)
|
||||
void NukiNetworkOpener::publishInt(const char *topic, const int value, bool retain)
|
||||
{
|
||||
_network->publishInt(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishUInt(const char *topic, const unsigned int value, bool retain)
|
||||
void NukiNetworkOpener::publishUInt(const char *topic, const unsigned int value, bool retain)
|
||||
{
|
||||
_network->publishUInt(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishBool(const char *topic, const bool value, bool retain)
|
||||
void NukiNetworkOpener::publishBool(const char *topic, const bool value, bool retain)
|
||||
{
|
||||
_network->publishBool(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishString(const char *topic, const String &value, bool retain)
|
||||
void NukiNetworkOpener::publishString(const char *topic, const String &value, bool retain)
|
||||
{
|
||||
char str[value.length() + 1];
|
||||
memset(str, 0, sizeof(str));
|
||||
@@ -1216,7 +1216,7 @@ void NetworkOpener::publishString(const char *topic, const String &value, bool r
|
||||
publishString(topic, str, retain);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishString(const char *topic, const std::string &value, bool retain)
|
||||
void NukiNetworkOpener::publishString(const char *topic, const std::string &value, bool retain)
|
||||
{
|
||||
char str[value.size() + 1];
|
||||
memset(str, 0, sizeof(str));
|
||||
@@ -1224,12 +1224,12 @@ void NetworkOpener::publishString(const char *topic, const std::string &value, b
|
||||
publishString(topic, str, retain);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishString(const char* topic, const char* value, bool retain)
|
||||
void NukiNetworkOpener::publishString(const char* topic, const char* value, bool retain)
|
||||
{
|
||||
_network->publishString(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NetworkOpener::publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry)
|
||||
void NukiNetworkOpener::publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry)
|
||||
{
|
||||
if(_preferences->getBool(preference_disable_non_json, false)) return;
|
||||
|
||||
@@ -1237,25 +1237,25 @@ void NetworkOpener::publishKeypadEntry(const String topic, NukiLock::KeypadEntry
|
||||
memset(codeName, 0, sizeof(codeName));
|
||||
memcpy(codeName, entry.name, sizeof(entry.name));
|
||||
|
||||
publishInt(concat(topic, "/id").c_str(), entry.codeId);
|
||||
publishBool(concat(topic, "/enabled").c_str(), entry.enabled);
|
||||
publishString(concat(topic, "/name").c_str(), codeName);
|
||||
publishInt(concat(topic, "/id").c_str(), entry.codeId, true);
|
||||
publishBool(concat(topic, "/enabled").c_str(), entry.enabled, true);
|
||||
publishString(concat(topic, "/name").c_str(), codeName, true);
|
||||
|
||||
if(_preferences->getBool(preference_keypad_publish_code, false))
|
||||
{
|
||||
publishInt(concat(topic, "/code").c_str(), entry.code);
|
||||
publishInt(concat(topic, "/code").c_str(), entry.code, true);
|
||||
}
|
||||
|
||||
publishInt(concat(topic, "/createdYear").c_str(), entry.dateCreatedYear);
|
||||
publishInt(concat(topic, "/createdMonth").c_str(), entry.dateCreatedMonth);
|
||||
publishInt(concat(topic, "/createdDay").c_str(), entry.dateCreatedDay);
|
||||
publishInt(concat(topic, "/createdHour").c_str(), entry.dateCreatedHour);
|
||||
publishInt(concat(topic, "/createdMin").c_str(), entry.dateCreatedMin);
|
||||
publishInt(concat(topic, "/createdSec").c_str(), entry.dateCreatedSec);
|
||||
publishInt(concat(topic, "/lockCount").c_str(), entry.lockCount);
|
||||
publishInt(concat(topic, "/createdYear").c_str(), entry.dateCreatedYear, true);
|
||||
publishInt(concat(topic, "/createdMonth").c_str(), entry.dateCreatedMonth, true);
|
||||
publishInt(concat(topic, "/createdDay").c_str(), entry.dateCreatedDay, true);
|
||||
publishInt(concat(topic, "/createdHour").c_str(), entry.dateCreatedHour, true);
|
||||
publishInt(concat(topic, "/createdMin").c_str(), entry.dateCreatedMin, true);
|
||||
publishInt(concat(topic, "/createdSec").c_str(), entry.dateCreatedSec, true);
|
||||
publishInt(concat(topic, "/lockCount").c_str(), entry.lockCount, true);
|
||||
}
|
||||
|
||||
void NetworkOpener::buildMqttPath(const char* path, char* outPath)
|
||||
void NukiNetworkOpener::buildMqttPath(const char* path, char* outPath)
|
||||
{
|
||||
int offset = 0;
|
||||
for(const char& c : _mqttPath)
|
||||
@@ -1277,14 +1277,14 @@ void NetworkOpener::buildMqttPath(const char* path, char* outPath)
|
||||
outPath[offset] = 0x00;
|
||||
}
|
||||
|
||||
void NetworkOpener::subscribe(const char *path)
|
||||
void NukiNetworkOpener::subscribe(const char *path)
|
||||
{
|
||||
char prefixedPath[500];
|
||||
buildMqttPath(path, prefixedPath);
|
||||
_network->subscribe(prefixedPath, MQTT_QOS_LEVEL);
|
||||
}
|
||||
|
||||
bool NetworkOpener::comparePrefixedPath(const char *fullPath, const char *subPath)
|
||||
bool NukiNetworkOpener::comparePrefixedPath(const char *fullPath, const char *subPath)
|
||||
{
|
||||
char prefixedPath[500];
|
||||
buildMqttPath(subPath, prefixedPath);
|
||||
@@ -1292,28 +1292,28 @@ bool NetworkOpener::comparePrefixedPath(const char *fullPath, const char *subPat
|
||||
return strcmp(fullPath, prefixedPath) == 0;
|
||||
}
|
||||
|
||||
String NetworkOpener::concat(String a, String b)
|
||||
String NukiNetworkOpener::concat(String a, String b)
|
||||
{
|
||||
String c = a;
|
||||
c.concat(b);
|
||||
return c;
|
||||
}
|
||||
|
||||
bool NetworkOpener::reconnected()
|
||||
bool NukiNetworkOpener::reconnected()
|
||||
{
|
||||
bool r = _reconnected;
|
||||
_reconnected = false;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8_t NetworkOpener::queryCommands()
|
||||
uint8_t NukiNetworkOpener::queryCommands()
|
||||
{
|
||||
uint8_t qc = _queryCommands;
|
||||
_queryCommands = 0;
|
||||
return qc;
|
||||
}
|
||||
|
||||
void NetworkOpener::buttonPressActionToString(const NukiOpener::ButtonPressAction btnPressAction, char* str) {
|
||||
void NukiNetworkOpener::buttonPressActionToString(const NukiOpener::ButtonPressAction btnPressAction, char* str) {
|
||||
switch (btnPressAction) {
|
||||
case NukiOpener::ButtonPressAction::NoAction:
|
||||
strcpy(str, "No Action");
|
||||
@@ -1345,7 +1345,7 @@ void NetworkOpener::buttonPressActionToString(const NukiOpener::ButtonPressActio
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::fobActionToString(const int fobact, char* str) {
|
||||
void NukiNetworkOpener::fobActionToString(const int fobact, char* str) {
|
||||
switch (fobact) {
|
||||
case 0:
|
||||
strcpy(str, "No Action");
|
||||
@@ -1371,7 +1371,7 @@ void NetworkOpener::fobActionToString(const int fobact, char* str) {
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::capabilitiesToString(const int capabilities, char* str) {
|
||||
void NukiNetworkOpener::capabilitiesToString(const int capabilities, char* str) {
|
||||
switch (capabilities) {
|
||||
case 0:
|
||||
strcpy(str, "Door opener");
|
||||
@@ -1388,7 +1388,7 @@ void NetworkOpener::capabilitiesToString(const int capabilities, char* str) {
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::operatingModeToString(const int opmode, char* str) {
|
||||
void NukiNetworkOpener::operatingModeToString(const int opmode, char* str) {
|
||||
switch (opmode) {
|
||||
case 0:
|
||||
strcpy(str, "Generic door opener");
|
||||
@@ -1444,7 +1444,7 @@ void NetworkOpener::operatingModeToString(const int opmode, char* str) {
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::doorbellSuppressionToString(const int dbsupr, char* str) {
|
||||
void NukiNetworkOpener::doorbellSuppressionToString(const int dbsupr, char* str) {
|
||||
switch (dbsupr) {
|
||||
case 0:
|
||||
strcpy(str, "Off");
|
||||
@@ -1476,7 +1476,7 @@ void NetworkOpener::doorbellSuppressionToString(const int dbsupr, char* str) {
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOpener::soundToString(const int sound, char* str) {
|
||||
void NukiNetworkOpener::soundToString(const int sound, char* str) {
|
||||
switch (sound) {
|
||||
case 0:
|
||||
strcpy(str, "No Sound");
|
||||
@@ -7,13 +7,13 @@
|
||||
#include <vector>
|
||||
#include "NukiConstants.h"
|
||||
#include "NukiOpenerConstants.h"
|
||||
#include "NetworkLock.h"
|
||||
#include "NukiNetworkLock.h"
|
||||
|
||||
class NetworkOpener : public MqttReceiver
|
||||
class NukiNetworkOpener : public MqttReceiver
|
||||
{
|
||||
public:
|
||||
explicit NetworkOpener(Network* network, Preferences* preferences, char* buffer, size_t bufferSize);
|
||||
virtual ~NetworkOpener() = default;
|
||||
explicit NukiNetworkOpener(NukiNetwork* network, Preferences* preferences, char* buffer, size_t bufferSize);
|
||||
virtual ~NukiNetworkOpener() = default;
|
||||
|
||||
void initialize();
|
||||
void update();
|
||||
@@ -77,7 +77,7 @@ private:
|
||||
|
||||
Preferences* _preferences;
|
||||
|
||||
Network* _network = nullptr;
|
||||
NukiNetwork* _network = nullptr;
|
||||
|
||||
char _mqttPath[181] = {0};
|
||||
bool _isConnected = false;
|
||||
@@ -10,7 +10,7 @@
|
||||
NukiOpenerWrapper* nukiOpenerInst;
|
||||
Preferences* nukiOpenerPreferences = nullptr;
|
||||
|
||||
NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NetworkOpener* network, Gpio* gpio, Preferences* preferences)
|
||||
NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkOpener* network, Gpio* gpio, Preferences* preferences)
|
||||
: _deviceName(deviceName),
|
||||
_deviceId(deviceId),
|
||||
_nukiOpener(deviceName, _deviceId->get()),
|
||||
@@ -103,6 +103,7 @@ void NukiOpenerWrapper::initialize()
|
||||
}
|
||||
|
||||
_nukiOpener.setEventHandler(this);
|
||||
_nukiOpener.setDisonnectTimeout(5000);
|
||||
|
||||
Log->print(F("Lock state interval: "));
|
||||
Log->print(_intervalLockstate);
|
||||
@@ -220,17 +221,8 @@ void NukiOpenerWrapper::update()
|
||||
|
||||
if(_nextLockAction != (NukiOpener::LockAction)0xff && ts > _nextRetryTs)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
Nuki::CmdResult cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
|
||||
char resultStr[15] = {0};
|
||||
NukiOpener::cmdResultToString(cmdResult, resultStr);
|
||||
@@ -350,28 +342,18 @@ void NukiOpenerWrapper::unpair()
|
||||
|
||||
void NukiOpenerWrapper::updateKeyTurnerState()
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Querying opener state: "));
|
||||
result =_nukiOpener.requestOpenerState(&_keyTurnerState);
|
||||
_taskRunning = false;
|
||||
if(!_nukiConfigValid) {
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
char resultStr[15];
|
||||
@@ -383,7 +365,7 @@ void NukiOpenerWrapper::updateKeyTurnerState()
|
||||
{
|
||||
_retryLockstateCount++;
|
||||
postponeBleWatchdog();
|
||||
if(_retryLockstateCount < _nrOfRetries)
|
||||
if(_retryLockstateCount < _nrOfRetries + 1)
|
||||
{
|
||||
_nextLockStateUpdateTs = millis() + _retryDelay;
|
||||
}
|
||||
@@ -435,28 +417,18 @@ void NukiOpenerWrapper::updateKeyTurnerState()
|
||||
|
||||
void NukiOpenerWrapper::updateBatteryState()
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Querying opener battery state: "));
|
||||
result = _nukiOpener.requestBatteryReport(&_batteryReport);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
printCommandResult(result);
|
||||
@@ -495,27 +467,17 @@ void NukiOpenerWrapper::updateConfig()
|
||||
const int pinStatus = _preferences->getInt(preference_opener_pin_status, 4);
|
||||
|
||||
if(isPinSet()) {
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.verifySecurityPin();
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if(result != Nuki::CmdResult::Success)
|
||||
@@ -577,28 +539,18 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved)
|
||||
if(!retrieved)
|
||||
{
|
||||
delay(250);
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Retrieve log entries: "));
|
||||
result = _nukiOpener.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
Log->println(result);
|
||||
@@ -654,28 +606,18 @@ void NukiOpenerWrapper::updateKeypad(bool retrieved)
|
||||
|
||||
if(!retrieved)
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Querying opener keypad: "));
|
||||
result = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
printCommandResult(result);
|
||||
@@ -725,28 +667,18 @@ void NukiOpenerWrapper::updateTimeControl(bool retrieved)
|
||||
|
||||
if(!retrieved)
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Querying opener time control: "));
|
||||
result = _nukiOpener.retrieveTimeControlEntries();
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
printCommandResult(result);
|
||||
@@ -1045,14 +977,6 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(basicKeys[i], "name") == 0)
|
||||
{
|
||||
if(strlen(jsonchar) <= 32)
|
||||
@@ -1210,8 +1134,6 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if(cmdResult == Nuki::CmdResult::Success) basicUpdated = true;
|
||||
@@ -1245,14 +1167,6 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(advancedKeys[j], "intercomID") == 0)
|
||||
{
|
||||
const uint16_t keyvalue = atoi(jsonchar);
|
||||
@@ -1478,8 +1392,6 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if(cmdResult == Nuki::CmdResult::Success) advancedUpdated = true;
|
||||
@@ -1573,14 +1485,6 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(command, "add") == 0)
|
||||
{
|
||||
if(name == "" || name == "--")
|
||||
@@ -1604,10 +1508,10 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
||||
size_t nameLen = name.length();
|
||||
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
||||
entry.code = codeInt;
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.addKeypadEntry(entry);
|
||||
_taskRunning = false;
|
||||
Log->print("Add keypad code: "); Log->println((int)result);
|
||||
delay(250);
|
||||
Log->print("Add keypad code: ");
|
||||
Log->println((int)result);
|
||||
updateKeypad(false);
|
||||
}
|
||||
else if(strcmp(command, "delete") == 0)
|
||||
@@ -1618,10 +1522,10 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
||||
return;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.deleteKeypadEntry(id);
|
||||
_taskRunning = false;
|
||||
Log->print("Delete keypad code: "); Log->println((int)result);
|
||||
delay(250);
|
||||
Log->print("Delete keypad code: ");
|
||||
Log->println((int)result);
|
||||
updateKeypad(false);
|
||||
}
|
||||
else if(strcmp(command, "update") == 0)
|
||||
@@ -1654,13 +1558,13 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
||||
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
||||
entry.code = codeInt;
|
||||
entry.enabled = enabled == 0 ? 0 : 1;
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.updateKeypadEntry(entry);
|
||||
_taskRunning = false;
|
||||
Log->print("Update keypad code: "); Log->println((int)result);
|
||||
delay(250);
|
||||
Log->print("Update keypad code: ");
|
||||
Log->println((int)result);
|
||||
updateKeypad(false);
|
||||
}
|
||||
else if(command == "--")
|
||||
else if(strcmp(command, "--") == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1674,8 +1578,6 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if((int)result != -1)
|
||||
@@ -1771,20 +1673,11 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(action, "delete") == 0) {
|
||||
if(idExists)
|
||||
{
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.deleteKeypadEntry(codeId);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Delete keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -1970,9 +1863,8 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.addKeypadEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Add keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -1990,17 +1882,8 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
Nuki::CmdResult resultKp = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
bool foundExisting = false;
|
||||
|
||||
if(resultKp == Nuki::CmdResult::Success)
|
||||
@@ -2075,7 +1958,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
entry.codeId = codeId;
|
||||
entry.code = code;
|
||||
|
||||
if(name.length() < 1)
|
||||
if(!name.length() > 0)
|
||||
{
|
||||
size_t nameLen = strlen(oldName);
|
||||
memcpy(&entry.name, oldName, nameLen > 20 ? 20 : nameLen);
|
||||
@@ -2128,9 +2011,8 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
}
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.updateKeypadEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Update keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2145,8 +2027,6 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
updateKeypad(false);
|
||||
@@ -2235,20 +2115,11 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(action, "delete") == 0) {
|
||||
if(idExists)
|
||||
{
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.removeTimeControlEntry(entryId);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Delete time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2306,10 +2177,8 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
}
|
||||
|
||||
entry.lockAction = timeControlLockAction;
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.addTimeControlEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Add time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2321,17 +2190,8 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
Nuki::CmdResult resultTc = _nukiOpener.retrieveTimeControlEntries();
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
bool foundExisting = false;
|
||||
|
||||
if(resultTc == Nuki::CmdResult::Success)
|
||||
@@ -2380,10 +2240,8 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
}
|
||||
|
||||
entry.lockAction = timeControlLockAction;
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.updateTimeControlEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Update time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2398,8 +2256,6 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if((int)result != -1)
|
||||
@@ -2448,6 +2304,7 @@ void NukiOpenerWrapper::notify(Nuki::EventType eventType)
|
||||
{
|
||||
if(eventType == Nuki::EventType::KeyTurnerStatusUpdated)
|
||||
{
|
||||
Log->println("KeyTurnerStatusUpdated");
|
||||
_statusUpdated = true;
|
||||
_network->publishStatusUpdated(_statusUpdated);
|
||||
}
|
||||
@@ -2455,30 +2312,19 @@ void NukiOpenerWrapper::notify(Nuki::EventType eventType)
|
||||
|
||||
void NukiOpenerWrapper::readConfig()
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Reading opener config. Result: "));
|
||||
Nuki::CmdResult result = _nukiOpener.requestConfig(&_nukiConfig);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||
|
||||
if(!_nukiConfigValid) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
char resultStr[20];
|
||||
@@ -2489,29 +2335,19 @@ void NukiOpenerWrapper::readConfig()
|
||||
|
||||
void NukiOpenerWrapper::readAdvancedConfig()
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.requestAdvancedConfig(&_nukiAdvancedConfig);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
_nukiAdvancedConfigValid = result == Nuki::CmdResult::Success;
|
||||
|
||||
if(!_nukiAdvancedConfigValid) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
char resultStr[20];
|
||||
@@ -2541,29 +2377,19 @@ void NukiOpenerWrapper::disableHASS()
|
||||
{
|
||||
if(!_nukiConfigValid) // only ask for config once to save battery life
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
result = _nukiOpener.requestConfig(&_nukiConfig);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||
|
||||
if(!_nukiConfigValid) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "NukiOpener.h"
|
||||
#include "NetworkOpener.h"
|
||||
#include "NukiNetworkOpener.h"
|
||||
#include "NukiOpenerConstants.h"
|
||||
#include "NukiDataTypes.h"
|
||||
#include "BleScanner.h"
|
||||
@@ -11,7 +11,7 @@
|
||||
class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler
|
||||
{
|
||||
public:
|
||||
NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NetworkOpener* network, Gpio* gpio, Preferences* preferences);
|
||||
NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkOpener* network, Gpio* gpio, Preferences* preferences);
|
||||
virtual ~NukiOpenerWrapper();
|
||||
|
||||
void initialize();
|
||||
@@ -90,7 +90,7 @@ private:
|
||||
NukiDeviceId* _deviceId = nullptr;
|
||||
NukiOpener::NukiOpener _nukiOpener;
|
||||
BleScanner::Scanner* _bleScanner = nullptr;
|
||||
NetworkOpener* _network = nullptr;
|
||||
NukiNetworkOpener* _network = nullptr;
|
||||
Gpio* _gpio = nullptr;
|
||||
Preferences* _preferences = nullptr;
|
||||
int _intervalLockstate = 0; // seconds
|
||||
@@ -100,7 +100,6 @@ private:
|
||||
int _restartBeaconTimeout = 0; // seconds
|
||||
bool _publishAuthData = false;
|
||||
bool _clearAuthData = false;
|
||||
bool _taskRunning = false;
|
||||
int _nrOfRetries = 0;
|
||||
int _retryDelay = 0;
|
||||
int _retryCount = 0;
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
#include "Config.h"
|
||||
|
||||
NukiWrapper* nukiInst;
|
||||
NetworkLock* networkInst;
|
||||
NukiNetworkLock* networkInst;
|
||||
Preferences* nukiLockPreferences = nullptr;
|
||||
|
||||
NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NetworkLock* network, Gpio* gpio, Preferences* preferences)
|
||||
NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, Gpio* gpio, Preferences* preferences)
|
||||
: _deviceName(deviceName),
|
||||
_deviceId(deviceId),
|
||||
_bleScanner(scanner),
|
||||
@@ -72,65 +72,106 @@ void NukiWrapper::initialize(const bool& firstStart)
|
||||
|
||||
if(firstStart)
|
||||
{
|
||||
Log->println("First start, setting preference defaults");
|
||||
_preferences->putBool(preference_network_wifi_fallback_disabled, false);
|
||||
_preferences->putBool(preference_find_best_rssi, false);
|
||||
_preferences->putBool(preference_check_updates, true);
|
||||
_preferences->putBool(preference_opener_continuous_mode, false);
|
||||
_preferences->putBool(preference_network_wifi_fallback_disabled, false);
|
||||
_preferences->putBool(preference_official_hybrid, false);
|
||||
_preferences->putBool(preference_official_hybrid_actions, false);
|
||||
_preferences->putBool(preference_official_hybrid_retry, false);
|
||||
_preferences->putBool(preference_disable_non_json, false);
|
||||
_preferences->putBool(preference_update_from_mqtt, false);
|
||||
_preferences->putBool(preference_ip_dhcp_enabled, true);
|
||||
_preferences->putBool(preference_enable_bootloop_reset, false);
|
||||
_preferences->putBool(preference_show_secrets, false);
|
||||
|
||||
_preferences->putBool(preference_conf_info_enabled, true);
|
||||
_preferences->putBool(preference_keypad_info_enabled, false);
|
||||
_preferences->putBool(preference_keypad_topic_per_entry, false);
|
||||
_preferences->putBool(preference_keypad_publish_code, false);
|
||||
_preferences->putBool(preference_keypad_control_enabled, false);
|
||||
_preferences->putBool(preference_timecontrol_info_enabled, false);
|
||||
_preferences->putBool(preference_timecontrol_topic_per_entry, false);
|
||||
_preferences->putBool(preference_timecontrol_control_enabled, false);
|
||||
_preferences->putBool(preference_publish_authdata, false);
|
||||
_preferences->putBool(preference_register_as_app, false);
|
||||
_preferences->putBool(preference_register_opener_as_app, false);
|
||||
|
||||
_preferences->putInt(preference_mqtt_broker_port, 1883);
|
||||
_preferences->putInt(preference_buffer_size, CHAR_BUFFER_SIZE);
|
||||
_preferences->putInt(preference_task_size_network, NETWORK_TASK_SIZE);
|
||||
_preferences->putInt(preference_task_size_nuki, NUKI_TASK_SIZE);
|
||||
_preferences->putInt(preference_authlog_max_entries, MAX_AUTHLOG);
|
||||
_preferences->putInt(preference_keypad_max_entries, MAX_KEYPAD);
|
||||
_preferences->putInt(preference_timecontrol_max_entries, MAX_TIMECONTROL);
|
||||
_preferences->putInt(preference_query_interval_hybrid_lockstate, 600);
|
||||
_preferences->putInt(preference_rssi_publish_interval, 60);
|
||||
_preferences->putInt(preference_network_timeout, 60);
|
||||
_preferences->putInt(preference_command_nr_of_retries, 3);
|
||||
_preferences->putInt(preference_command_retry_delay, 1000);
|
||||
_preferences->putInt(preference_restart_ble_beacon_lost, 60);
|
||||
uint32_t aclPrefs[17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
_preferences->putBytes(preference_acl, (byte*)(&aclPrefs), sizeof(aclPrefs));
|
||||
uint32_t basicLockConfigAclPrefs[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
_preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs));
|
||||
uint32_t basicOpenerConfigAclPrefs[14] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
_preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs));
|
||||
uint32_t advancedLockConfigAclPrefs[22] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
_preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs));
|
||||
uint32_t advancedOpenerConfigAclPrefs[20] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
_preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs));
|
||||
_preferences->putInt(preference_query_interval_lockstate, 1800);
|
||||
_preferences->putInt(preference_query_interval_configuration, 3600);
|
||||
_preferences->putInt(preference_query_interval_battery, 1800);
|
||||
_preferences->putInt(preference_query_interval_keypad, 1800);
|
||||
_preferences->putInt(preference_presence_detection_timeout, -1);
|
||||
}
|
||||
|
||||
if(_nrOfRetries < 0 || _nrOfRetries == 200)
|
||||
{
|
||||
Log->println("Invalid nrOfRetries, revert to default (3)");
|
||||
_nrOfRetries = 3;
|
||||
_preferences->putInt(preference_command_nr_of_retries, _nrOfRetries);
|
||||
}
|
||||
|
||||
if(_retryDelay <= 100)
|
||||
{
|
||||
Log->println("Invalid retryDelay, revert to default (100)");
|
||||
_retryDelay = 100;
|
||||
_preferences->putInt(preference_command_retry_delay, _retryDelay);
|
||||
}
|
||||
|
||||
if(_intervalLockstate == 0)
|
||||
{
|
||||
Log->println("Invalid intervalLockstate, revert to default (1800)");
|
||||
_intervalLockstate = 60 * 30;
|
||||
_preferences->putInt(preference_query_interval_lockstate, _intervalLockstate);
|
||||
}
|
||||
if(_intervalHybridLockstate == 0)
|
||||
{
|
||||
Log->println("Invalid intervalHybridLockstate, revert to default (600)");
|
||||
_intervalHybridLockstate = 60 * 10;
|
||||
_preferences->putInt(preference_query_interval_hybrid_lockstate, _intervalHybridLockstate);
|
||||
}
|
||||
if(_intervalConfig == 0)
|
||||
{
|
||||
Log->println("Invalid intervalConfig, revert to default (3600)");
|
||||
_intervalConfig = 60 * 60;
|
||||
_preferences->putInt(preference_query_interval_configuration, _intervalConfig);
|
||||
}
|
||||
if(_intervalBattery == 0)
|
||||
{
|
||||
Log->println("Invalid intervalBattery, revert to default (1800)");
|
||||
_intervalBattery = 60 * 30;
|
||||
_preferences->putInt(preference_query_interval_battery, _intervalBattery);
|
||||
}
|
||||
if(_intervalKeypad == 0)
|
||||
{
|
||||
Log->println("Invalid intervalKeypad, revert to default (1800)");
|
||||
_intervalKeypad = 60 * 30;
|
||||
_preferences->putInt(preference_query_interval_keypad, _intervalKeypad);
|
||||
}
|
||||
if(_restartBeaconTimeout < 10)
|
||||
{
|
||||
Log->println("Invalid restartBeaconTimeout, revert to default (-1)");
|
||||
_restartBeaconTimeout = -1;
|
||||
_preferences->putInt(preference_restart_ble_beacon_lost, _restartBeaconTimeout);
|
||||
}
|
||||
|
||||
|
||||
_nukiLock.setEventHandler(this);
|
||||
_nukiLock.setDisonnectTimeout(5000);
|
||||
|
||||
Log->print(F("Lock state interval: "));
|
||||
Log->print(_intervalLockstate);
|
||||
@@ -150,6 +191,7 @@ void NukiWrapper::update()
|
||||
if(!_paired)
|
||||
{
|
||||
Log->println(F("Nuki lock start pairing"));
|
||||
_preferences->getBool(preference_register_as_app) ? Log->println(F("Pairing as app")) : Log->println(F("Pairing as bridge"));
|
||||
_network->publishBleAddress("");
|
||||
|
||||
Nuki::AuthorizationIdType idType = _preferences->getBool(preference_register_as_app) ?
|
||||
@@ -190,6 +232,7 @@ void NukiWrapper::update()
|
||||
|
||||
if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
||||
{
|
||||
Log->println("Updating Lock state based on timer or query");
|
||||
_statusUpdated = false;
|
||||
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
||||
updateKeyTurnerState();
|
||||
@@ -202,11 +245,13 @@ void NukiWrapper::update()
|
||||
}
|
||||
if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs || (queryCommands & QUERY_COMMAND_BATTERY) > 0)
|
||||
{
|
||||
Log->println("Updating Lock battery state based on timer or query");
|
||||
_nextBatteryReportTs = ts + _intervalBattery * 1000;
|
||||
updateBatteryState();
|
||||
}
|
||||
if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs || (queryCommands & QUERY_COMMAND_CONFIG) > 0)
|
||||
{
|
||||
Log->println("Updating Lock config based on timer or query");
|
||||
_nextConfigUpdateTs = ts + _intervalConfig * 1000;
|
||||
updateConfig();
|
||||
if(_hassEnabled && !_hassSetupCompleted)
|
||||
@@ -247,23 +292,14 @@ void NukiWrapper::update()
|
||||
|
||||
if(_hasKeypad && _keypadEnabled && (_nextKeypadUpdateTs == 0 || ts > _nextKeypadUpdateTs || (queryCommands & QUERY_COMMAND_KEYPAD) > 0))
|
||||
{
|
||||
Log->println("Updating Lock keypad based on timer or query");
|
||||
_nextKeypadUpdateTs = ts + _intervalKeypad * 1000;
|
||||
updateKeypad(false);
|
||||
}
|
||||
|
||||
if(_nextLockAction != (NukiLock::LockAction)0xff && ts > _nextRetryTs)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
Nuki::CmdResult cmdResult = _nukiLock.lockAction(_nextLockAction, 0, 0);
|
||||
_taskRunning = false;
|
||||
|
||||
char resultStr[15] = {0};
|
||||
NukiLock::cmdResultToString(cmdResult, resultStr);
|
||||
@@ -315,6 +351,7 @@ void NukiWrapper::update()
|
||||
|
||||
if(_clearAuthData)
|
||||
{
|
||||
Log->println("Clearing Lock auth data");
|
||||
_network->clearAuthorizationInfo();
|
||||
_clearAuthData = false;
|
||||
}
|
||||
@@ -376,28 +413,23 @@ void NukiWrapper::unpair()
|
||||
|
||||
void NukiWrapper::updateKeyTurnerState()
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
Log->println("Querying lock state");
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Querying lock state: "));
|
||||
Log->print(F("Result (attempt "));
|
||||
Log->print(_retryCount + 1);
|
||||
Log->print("): ");
|
||||
result =_nukiLock.requestKeyTurnerState(&_keyTurnerState);
|
||||
_taskRunning = false;
|
||||
if(!_nukiConfigValid) {
|
||||
delay(250);
|
||||
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
char resultStr[15];
|
||||
@@ -407,10 +439,14 @@ void NukiWrapper::updateKeyTurnerState()
|
||||
|
||||
if(result != Nuki::CmdResult::Success)
|
||||
{
|
||||
Log->println("Query lock state failed");
|
||||
_retryLockstateCount++;
|
||||
postponeBleWatchdog();
|
||||
if(_retryLockstateCount < _nrOfRetries)
|
||||
if(_retryLockstateCount < _nrOfRetries + 1)
|
||||
{
|
||||
Log->print(F("Query lock state retrying in "));
|
||||
Log->print(_retryDelay);
|
||||
Log->println("ms");
|
||||
_nextLockStateUpdateTs = millis() + _retryDelay;
|
||||
}
|
||||
return;
|
||||
@@ -438,28 +474,22 @@ void NukiWrapper::updateKeyTurnerState()
|
||||
|
||||
void NukiWrapper::updateBatteryState()
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
Log->println("Querying lock battery state");
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Querying lock battery state: "));
|
||||
Log->print(F("Result (attempt "));
|
||||
Log->print(_retryCount + 1);
|
||||
Log->print("): ");
|
||||
result = _nukiLock.requestBatteryReport(&_batteryReport);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
printCommandResult(result);
|
||||
@@ -482,6 +512,13 @@ void NukiWrapper::updateConfig()
|
||||
{
|
||||
if(_preferences->getUInt(preference_nuki_id_lock, 0) == 0 || _retryConfigCount == 10)
|
||||
{
|
||||
char uidString[20];
|
||||
itoa(_nukiConfig.nukiId, uidString, 16);
|
||||
Log->print(F("Saving Nuki ID to preferences ("));
|
||||
Log->print(_nukiConfig.nukiId);
|
||||
Log->print(" / ");
|
||||
Log->print(uidString);
|
||||
Log->println(")");
|
||||
_preferences->putUInt(preference_nuki_id_lock, _nukiConfig.nukiId);
|
||||
}
|
||||
|
||||
@@ -498,37 +535,30 @@ void NukiWrapper::updateConfig()
|
||||
const int pinStatus = _preferences->getInt(preference_lock_pin_status, 4);
|
||||
|
||||
if(isPinSet()) {
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
Log->println(F("Nuki Lock PIN is set"));
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.verifySecurityPin();
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if(result != Nuki::CmdResult::Success)
|
||||
{
|
||||
if(pinStatus != 2) {
|
||||
Log->println(F("Nuki Lock PIN is invalid"));
|
||||
if(pinStatus != 2) {
|
||||
_preferences->putInt(preference_lock_pin_status, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log->println(F("Nuki Lock PIN is valid"));
|
||||
if(pinStatus != 1) {
|
||||
_preferences->putInt(preference_lock_pin_status, 1);
|
||||
}
|
||||
@@ -536,6 +566,7 @@ void NukiWrapper::updateConfig()
|
||||
}
|
||||
else
|
||||
{
|
||||
Log->println(F("Nuki Lock PIN is not set"));
|
||||
if(pinStatus != 0) {
|
||||
_preferences->putInt(preference_lock_pin_status, 0);
|
||||
}
|
||||
@@ -543,12 +574,14 @@ void NukiWrapper::updateConfig()
|
||||
}
|
||||
else
|
||||
{
|
||||
Log->println(F("Invalid/Unexpected config recieved, retrying"));
|
||||
expectedConfig = false;
|
||||
++_retryConfigCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log->println(F("Invalid/Unexpected config recieved, retrying"));
|
||||
expectedConfig = false;
|
||||
++_retryConfigCount;
|
||||
}
|
||||
@@ -559,6 +592,7 @@ void NukiWrapper::updateConfig()
|
||||
}
|
||||
else
|
||||
{
|
||||
Log->println(F("Invalid/Unexpected advanced config recieved, retrying"));
|
||||
expectedConfig = false;
|
||||
++_retryConfigCount;
|
||||
}
|
||||
@@ -573,38 +607,27 @@ void NukiWrapper::updateAuthData(bool retrieved)
|
||||
{
|
||||
if(!isPinValid())
|
||||
{
|
||||
Log->println(F("No valid PIN set"));
|
||||
Log->println(F("No valid Nuki Lock PIN set"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!retrieved)
|
||||
{
|
||||
delay(250);
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Retrieve log entries: "));
|
||||
result = _nukiLock.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
Log->println(result);
|
||||
printCommandResult(result);
|
||||
if(result == Nuki::CmdResult::Success)
|
||||
{
|
||||
@@ -657,28 +680,18 @@ void NukiWrapper::updateKeypad(bool retrieved)
|
||||
|
||||
if(!retrieved)
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Querying lock keypad: "));
|
||||
result = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
printCommandResult(result);
|
||||
@@ -728,28 +741,18 @@ void NukiWrapper::updateTimeControl(bool retrieved)
|
||||
|
||||
if(!retrieved)
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Querying lock time control: "));
|
||||
result = _nukiLock.retrieveTimeControlEntries();
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
if(result != Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
printCommandResult(result);
|
||||
@@ -977,7 +980,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
||||
_statusUpdated = true;
|
||||
_network->publishStatusUpdated(_statusUpdated);
|
||||
NukiLock::lockstateToString((NukiLock::LockState)_network->_offState, str);
|
||||
_network->publishString(mqtt_topic_lock_state, str);
|
||||
_network->publishString(mqtt_topic_lock_state, str, true);
|
||||
|
||||
Log->print(F("Lockstate: "));
|
||||
Log->println(str);
|
||||
@@ -997,7 +1000,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
||||
Log->print(F("Doorsensor state: "));
|
||||
Log->println(str);
|
||||
|
||||
_network->publishString(mqtt_topic_lock_door_sensor_state, str);
|
||||
_network->publishString(mqtt_topic_lock_door_sensor_state, str, true);
|
||||
}
|
||||
else if(strcmp(topic, mqtt_topic_official_batteryCritical) == 0)
|
||||
{
|
||||
@@ -1006,7 +1009,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
||||
Log->print(F("Battery critical: "));
|
||||
Log->println(_network->_offCritical);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_critical, _network->_offCritical);
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_critical, _network->_offCritical, true);
|
||||
publishBatteryJson = true;
|
||||
}
|
||||
else if(strcmp(topic, mqtt_topic_official_batteryCharging) == 0)
|
||||
@@ -1016,7 +1019,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
||||
Log->print(F("Battery charging: "));
|
||||
Log->println(_network->_offCharging);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_charging, _network->_offCharging);
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_charging, _network->_offCharging, true);
|
||||
publishBatteryJson = true;
|
||||
}
|
||||
else if(strcmp(topic, mqtt_topic_official_batteryChargeState) == 0)
|
||||
@@ -1026,19 +1029,19 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
||||
Log->print(F("Battery level: "));
|
||||
Log->println(_network->_offChargeState);
|
||||
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishInt(mqtt_topic_battery_level, _network->_offChargeState);
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishInt(mqtt_topic_battery_level, _network->_offChargeState, true);
|
||||
publishBatteryJson = true;
|
||||
}
|
||||
else if(strcmp(topic, mqtt_topic_official_keypadBatteryCritical) == 0)
|
||||
{
|
||||
_network->_offKeypadCritical = (strcmp(value, "true") == 0 ? 1 : 0);
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_keypad_critical, _network->_offKeypadCritical);
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_keypad_critical, _network->_offKeypadCritical, true);
|
||||
publishBatteryJson = true;
|
||||
}
|
||||
else if(strcmp(topic, mqtt_topic_official_doorsensorBatteryCritical) == 0)
|
||||
{
|
||||
_network->_offDoorsensorCritical = (strcmp(value, "true") == 0 ? 1 : 0);
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_doorsensor_critical, _network->_offDoorsensorCritical);
|
||||
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_doorsensor_critical, _network->_offDoorsensorCritical, true);
|
||||
publishBatteryJson = true;
|
||||
}
|
||||
else if(strcmp(topic, mqtt_topic_official_commandResponse) == 0)
|
||||
@@ -1068,11 +1071,11 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
||||
|
||||
memset(&str, 0, sizeof(str));
|
||||
lockactionToString((NukiLock::LockAction)_network->_offLockAction, str);
|
||||
_network->publishString(mqtt_topic_lock_last_lock_action, str);
|
||||
_network->publishString(mqtt_topic_lock_last_lock_action, str, true);
|
||||
|
||||
memset(&str, 0, sizeof(str));
|
||||
triggerToString((NukiLock::Trigger)_network->_offTrigger, str);
|
||||
_network->publishString(mqtt_topic_lock_trigger, str);
|
||||
_network->publishString(mqtt_topic_lock_trigger, str, true);
|
||||
|
||||
if(_network->_offAuthId > 0 || _network->_offCodeId > 0)
|
||||
{
|
||||
@@ -1098,7 +1101,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
||||
jsonBattery["keypadCritical"] = _network->_offKeypadCritical ? "1" : "0";
|
||||
jsonBattery["doorSensorCritical"] = _network->_offDoorsensorCritical ? "1" : "0";
|
||||
serializeJson(jsonBattery, _resbuf, sizeof(_resbuf));
|
||||
_network->publishString(mqtt_topic_battery_basic_json, _resbuf);
|
||||
_network->publishString(mqtt_topic_battery_basic_json, _resbuf, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,16 +1150,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
||||
nukiLockPreferences->getBytes(preference_conf_lock_basic_acl, &basicLockConfigAclPrefs, sizeof(basicLockConfigAclPrefs));
|
||||
nukiLockPreferences->getBytes(preference_conf_lock_advanced_acl, &advancedLockConfigAclPrefs, sizeof(advancedLockConfigAclPrefs));
|
||||
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
|
||||
for(int i=0; i < 16; i++)
|
||||
{
|
||||
if(json[basicKeys[i]])
|
||||
@@ -1176,14 +1169,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(basicKeys[i], "name") == 0)
|
||||
{
|
||||
if(strlen(jsonchar) <= 32)
|
||||
@@ -1359,12 +1344,11 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
||||
else jsonResult[basicKeys[i]] = "invalidValue";
|
||||
}
|
||||
|
||||
if(cmdResult != Nuki::CmdResult::Success) {
|
||||
delay(250);
|
||||
if(!cmdResult == Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if(cmdResult == Nuki::CmdResult::Success) basicUpdated = true;
|
||||
@@ -1398,14 +1382,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(advancedKeys[j], "unlockedPositionOffsetDegrees") == 0)
|
||||
{
|
||||
const int16_t keyvalue = atoi(jsonchar);
|
||||
@@ -1653,12 +1629,11 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
||||
else jsonResult[advancedKeys[j]] = "invalidValue";
|
||||
}
|
||||
|
||||
if(cmdResult != Nuki::CmdResult::Success) {
|
||||
delay(250);
|
||||
if(!cmdResult == Nuki::CmdResult::Success) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if(cmdResult == Nuki::CmdResult::Success) advancedUpdated = true;
|
||||
@@ -1673,8 +1648,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
||||
}
|
||||
}
|
||||
|
||||
_taskRunning = false;
|
||||
|
||||
nukiLockPreferences->end();
|
||||
|
||||
if(basicUpdated || advancedUpdated) jsonResult["general"] = "success";
|
||||
@@ -1791,14 +1764,6 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(command, "add") == 0)
|
||||
{
|
||||
if(name == "" || name == "--")
|
||||
@@ -1822,9 +1787,8 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
||||
size_t nameLen = name.length();
|
||||
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
||||
entry.code = codeInt;
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.addKeypadEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print("Add keypad code: "); Log->println((int)result);
|
||||
updateKeypad(false);
|
||||
}
|
||||
@@ -1836,9 +1800,8 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
||||
return;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.deleteKeypadEntry(id);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print("Delete keypad code: "); Log->println((int)result);
|
||||
updateKeypad(false);
|
||||
}
|
||||
@@ -1872,13 +1835,12 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
||||
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
||||
entry.code = codeInt;
|
||||
entry.enabled = enabled == 0 ? 0 : 1;
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.updateKeypadEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print("Update keypad code: "); Log->println((int)result);
|
||||
updateKeypad(false);
|
||||
}
|
||||
else if(command == "--")
|
||||
else if(strcmp(command, "--") == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1892,8 +1854,6 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if((int)result != -1)
|
||||
@@ -1989,20 +1949,11 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(action, "delete") == 0) {
|
||||
if(idExists)
|
||||
{
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.deleteKeypadEntry(codeId);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Delete keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2188,9 +2139,8 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.addKeypadEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Add keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2208,17 +2158,8 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
Nuki::CmdResult resultKp = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
bool foundExisting = false;
|
||||
|
||||
if(resultKp == Nuki::CmdResult::Success)
|
||||
@@ -2346,9 +2287,8 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
}
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.updateKeypadEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Update keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2363,8 +2303,6 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
updateKeypad(false);
|
||||
@@ -2453,20 +2391,11 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
if(strcmp(action, "delete") == 0) {
|
||||
if(idExists)
|
||||
{
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.removeTimeControlEntry(entryId);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Delete time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2525,9 +2454,8 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
|
||||
entry.lockAction = timeControlLockAction;
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.addTimeControlEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Add time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2539,17 +2467,8 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
|
||||
_taskRunning = true;
|
||||
Nuki::CmdResult resultTc = _nukiLock.retrieveTimeControlEntries();
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
bool foundExisting = false;
|
||||
|
||||
if(resultTc == Nuki::CmdResult::Success)
|
||||
@@ -2570,7 +2489,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
timeAr[0] = entry.timeHour;
|
||||
timeAr[1] = entry.timeMin;
|
||||
}
|
||||
if(lockAction.length() < 1) timeControlLockAction = entry.lockAction;
|
||||
if(lockAction.length() < 1) timeControlLockAction = entry.lockAction;
|
||||
}
|
||||
|
||||
if(!foundExisting)
|
||||
@@ -2599,9 +2518,8 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
|
||||
entry.lockAction = timeControlLockAction;
|
||||
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.updateTimeControlEntry(entry);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
Log->print(F("Update time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
@@ -2616,8 +2534,6 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if((int)result != -1)
|
||||
@@ -2658,6 +2574,7 @@ void NukiWrapper::notify(Nuki::EventType eventType)
|
||||
{
|
||||
if(_preferences->getBool(preference_official_hybrid, false) && _intervalHybridLockstate > 0 && millis() > (_intervalHybridLockstate * 1000))
|
||||
{
|
||||
Log->println("OffKeyTurnerStatusUpdated");
|
||||
_statusUpdated = true;
|
||||
_nextHybridLockStateUpdateTs = millis() + _intervalHybridLockstate * 1000;
|
||||
}
|
||||
@@ -2665,6 +2582,7 @@ void NukiWrapper::notify(Nuki::EventType eventType)
|
||||
{
|
||||
if(eventType == Nuki::EventType::KeyTurnerStatusUpdated)
|
||||
{
|
||||
Log->println("KeyTurnerStatusUpdated");
|
||||
_statusUpdated = true;
|
||||
_network->publishStatusUpdated(_statusUpdated);
|
||||
}
|
||||
@@ -2674,29 +2592,22 @@ void NukiWrapper::notify(Nuki::EventType eventType)
|
||||
|
||||
void NukiWrapper::readConfig()
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
Log->print(F("Reading config. Result: "));
|
||||
result = _nukiLock.requestConfig(&_nukiConfig);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||
|
||||
Log->print(F("Config valid: "));
|
||||
Log->println(_nukiConfigValid);
|
||||
if(!_nukiConfigValid) {
|
||||
++_retryCount;
|
||||
Log->println("Retrying in 1s");
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
char resultStr[20];
|
||||
@@ -2706,29 +2617,19 @@ void NukiWrapper::readConfig()
|
||||
|
||||
void NukiWrapper::readAdvancedConfig()
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.requestAdvancedConfig(&_nukiAdvancedConfig);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
_nukiAdvancedConfigValid = result == Nuki::CmdResult::Success;
|
||||
|
||||
if(!_nukiAdvancedConfigValid) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
char resultStr[20];
|
||||
@@ -2760,31 +2661,21 @@ bool NukiWrapper::hasDoorSensor() const
|
||||
|
||||
void NukiWrapper::disableHASS()
|
||||
{
|
||||
if(!_nukiConfigValid) // only ask for config once to save battery life
|
||||
if(!_nukiConfigValid)
|
||||
{
|
||||
Nuki::CmdResult result;
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
_retryCount = 0;
|
||||
|
||||
while(_retryCount < _nrOfRetries + 1)
|
||||
{
|
||||
int loop = 0;
|
||||
while(_taskRunning && loop < 600)
|
||||
{
|
||||
Log->println("Waiting to run Nuki BLE command");
|
||||
vTaskDelay( 50 / portTICK_PERIOD_MS);
|
||||
++loop;
|
||||
}
|
||||
_taskRunning = true;
|
||||
result = _nukiLock.requestConfig(&_nukiConfig);
|
||||
_taskRunning = false;
|
||||
delay(250);
|
||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||
|
||||
if(!_nukiConfigValid) {
|
||||
++_retryCount;
|
||||
}
|
||||
else break;
|
||||
|
||||
vTaskDelay( 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "NetworkLock.h"
|
||||
#include "NukiNetworkLock.h"
|
||||
#include "NukiConstants.h"
|
||||
#include "NukiDataTypes.h"
|
||||
#include "BleScanner.h"
|
||||
@@ -12,7 +12,7 @@
|
||||
class NukiWrapper : public Nuki::SmartlockEventHandler
|
||||
{
|
||||
public:
|
||||
NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NetworkLock* network, Gpio* gpio, Preferences* preferences);
|
||||
NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, Gpio* gpio, Preferences* preferences);
|
||||
virtual ~NukiWrapper();
|
||||
|
||||
void initialize(const bool& firstStart);
|
||||
@@ -86,7 +86,7 @@ private:
|
||||
NukiDeviceId* _deviceId = nullptr;
|
||||
NukiLock::NukiLock _nukiLock;
|
||||
BleScanner::Scanner* _bleScanner = nullptr;
|
||||
NetworkLock* _network = nullptr;
|
||||
NukiNetworkLock* _network = nullptr;
|
||||
Gpio* _gpio = nullptr;
|
||||
Preferences* _preferences;
|
||||
int _intervalLockstate = 0; // seconds
|
||||
@@ -97,7 +97,6 @@ private:
|
||||
int _restartBeaconTimeout = 0; // seconds
|
||||
bool _publishAuthData = false;
|
||||
bool _clearAuthData = false;
|
||||
bool _taskRunning = false;
|
||||
std::vector<uint16_t> _keypadCodeIds;
|
||||
std::vector<uint8_t> _timeControlIds;
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#define preference_hostname (char*)"hostname"
|
||||
#define preference_network_timeout (char*)"nettmout"
|
||||
#define preference_restart_on_disconnect (char*)"restdisc"
|
||||
#define preference_restart_timer (char*)"resttmr"
|
||||
#define preference_restart_ble_beacon_lost (char*)"rstbcn"
|
||||
#define preference_query_interval_lockstate (char*)"lockStInterval"
|
||||
#define preference_query_interval_configuration (char*)"configInterval"
|
||||
@@ -93,43 +92,66 @@
|
||||
#define preference_official_hybrid_actions (char*)"hybridAct"
|
||||
#define preference_official_hybrid_retry (char*)"hybridRtry"
|
||||
#define preference_query_interval_hybrid_lockstate (char*)"hybridTimer"
|
||||
#define preference_ota_main_url (char*)"otaMainUrl"
|
||||
#define preference_ota_updater_url (char*)"otaUpdUrl"
|
||||
#define preference_update_from_mqtt (char*)"updMqtt"
|
||||
#define preference_show_secrets (char*)"showSecr"
|
||||
|
||||
class DebugPreferences
|
||||
{
|
||||
private:
|
||||
std::vector<char*> _keys =
|
||||
{
|
||||
preference_started_before, preference_config_version, preference_device_id_lock, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_opener, preference_mqtt_broker, preference_mqtt_broker_port, preference_mqtt_user, preference_mqtt_password, preference_mqtt_log_enabled, preference_check_updates, preference_webserver_enabled,
|
||||
preference_lock_enabled, preference_lock_pin_status, preference_mqtt_lock_path, preference_opener_enabled, preference_opener_pin_status,
|
||||
preference_opener_continuous_mode, preference_mqtt_opener_path, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count, preference_lock_max_timecontrol_entry_count,
|
||||
preference_opener_max_timecontrol_entry_count, preference_enable_bootloop_reset, preference_mqtt_ca, preference_mqtt_crt, preference_mqtt_key, preference_mqtt_hass_discovery,
|
||||
preference_mqtt_hass_cu_url, preference_buffer_size, preference_ip_dhcp_enabled, preference_ip_address, preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server,
|
||||
preference_network_hardware, preference_network_wifi_fallback_disabled, preference_rssi_publish_interval, preference_hostname, preference_find_best_rssi,
|
||||
preference_network_timeout, preference_restart_on_disconnect, preference_restart_ble_beacon_lost, preference_query_interval_lockstate, preference_timecontrol_topic_per_entry,
|
||||
preference_keypad_topic_per_entry, preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_keypad_control_enabled,
|
||||
preference_started_before, preference_config_version, preference_device_id_lock, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_opener,
|
||||
preference_mqtt_broker, preference_mqtt_broker_port, preference_mqtt_user, preference_mqtt_password, preference_mqtt_log_enabled, preference_check_updates,
|
||||
preference_webserver_enabled, preference_lock_enabled, preference_lock_pin_status, preference_mqtt_lock_path, preference_opener_enabled, preference_opener_pin_status,
|
||||
preference_opener_continuous_mode, preference_mqtt_opener_path, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count,
|
||||
preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_enable_bootloop_reset, preference_mqtt_ca, preference_mqtt_crt,
|
||||
preference_mqtt_key, preference_mqtt_hass_discovery, preference_mqtt_hass_cu_url, preference_buffer_size, preference_ip_dhcp_enabled, preference_ip_address,
|
||||
preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server, preference_network_hardware, preference_network_wifi_fallback_disabled,
|
||||
preference_rssi_publish_interval, preference_hostname, preference_find_best_rssi, preference_network_timeout, preference_restart_on_disconnect,
|
||||
preference_restart_ble_beacon_lost, preference_query_interval_lockstate, preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry,
|
||||
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_keypad_control_enabled,
|
||||
preference_keypad_info_enabled, preference_keypad_publish_code, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_conf_info_enabled,
|
||||
preference_register_as_app, preference_register_opener_as_app, preference_command_nr_of_retries, preference_command_retry_delay, preference_cred_user, preference_cred_password,
|
||||
preference_disable_non_json, preference_publish_authdata, preference_publish_debug_info, preference_presence_detection_timeout, preference_official_hybrid, preference_query_interval_hybrid_lockstate,
|
||||
preference_official_hybrid_actions, preference_official_hybrid_retry, preference_has_mac_saved, preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2,
|
||||
preference_latest_version, preference_task_size_network, preference_task_size_nuki, preference_authlog_max_entries, preference_keypad_max_entries,
|
||||
preference_timecontrol_max_entries
|
||||
preference_register_as_app, preference_register_opener_as_app, preference_command_nr_of_retries, preference_command_retry_delay, preference_cred_user,
|
||||
preference_cred_password, preference_disable_non_json, preference_publish_authdata, preference_publish_debug_info, preference_presence_detection_timeout,
|
||||
preference_official_hybrid, preference_query_interval_hybrid_lockstate, preference_official_hybrid_actions, preference_official_hybrid_retry, preference_has_mac_saved,
|
||||
preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2, preference_latest_version, preference_task_size_network, preference_task_size_nuki,
|
||||
preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries, preference_update_from_mqtt, preference_show_secrets
|
||||
};
|
||||
std::vector<char*> _redact =
|
||||
{
|
||||
preference_mqtt_user, preference_mqtt_password,
|
||||
preference_mqtt_ca, preference_mqtt_crt, preference_mqtt_key,
|
||||
preference_cred_user, preference_cred_password,
|
||||
preference_mqtt_user, preference_mqtt_password, preference_mqtt_ca, preference_mqtt_crt, preference_mqtt_key, preference_cred_user, preference_cred_password,
|
||||
preference_nuki_id_lock, preference_nuki_id_opener,
|
||||
};
|
||||
std::vector<char*> _boolPrefs =
|
||||
{
|
||||
preference_started_before, preference_mqtt_log_enabled, preference_check_updates, preference_lock_enabled, preference_opener_enabled, preference_opener_continuous_mode,
|
||||
preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry, preference_enable_bootloop_reset, preference_webserver_enabled, preference_find_best_rssi, preference_restart_on_disconnect,
|
||||
preference_keypad_control_enabled, preference_keypad_info_enabled, preference_keypad_publish_code, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled,
|
||||
preference_register_as_app, preference_register_opener_as_app, preference_ip_dhcp_enabled, preference_publish_authdata, preference_has_mac_saved, preference_publish_debug_info,
|
||||
preference_network_wifi_fallback_disabled, preference_official_hybrid, preference_official_hybrid_actions, preference_official_hybrid_retry, preference_conf_info_enabled, preference_disable_non_json
|
||||
preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry, preference_enable_bootloop_reset, preference_webserver_enabled, preference_find_best_rssi,
|
||||
preference_restart_on_disconnect, preference_keypad_control_enabled, preference_keypad_info_enabled, preference_keypad_publish_code, preference_show_secrets,
|
||||
preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_register_opener_as_app, preference_ip_dhcp_enabled,
|
||||
preference_publish_authdata, preference_has_mac_saved, preference_publish_debug_info, preference_network_wifi_fallback_disabled, preference_official_hybrid,
|
||||
preference_official_hybrid_actions, preference_official_hybrid_retry, preference_conf_info_enabled, preference_disable_non_json, preference_update_from_mqtt
|
||||
};
|
||||
std::vector<char*> _bytePrefs =
|
||||
{
|
||||
preference_acl, preference_conf_info_enabled, preference_conf_lock_basic_acl, preference_conf_lock_advanced_acl, preference_conf_opener_basic_acl,
|
||||
preference_conf_opener_advanced_acl, preference_gpio_configuration
|
||||
};
|
||||
std::vector<char*> _intPrefs =
|
||||
{
|
||||
preference_config_version, preference_device_id_lock, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_opener, preference_mqtt_broker_port,
|
||||
preference_lock_pin_status, preference_opener_pin_status, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count,
|
||||
preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_buffer_size, preference_network_hardware,
|
||||
preference_rssi_publish_interval, preference_network_timeout, preference_restart_ble_beacon_lost, preference_query_interval_lockstate,
|
||||
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_command_nr_of_retries,
|
||||
preference_command_retry_delay, preference_presence_detection_timeout, preference_query_interval_hybrid_lockstate, preference_latest_version,
|
||||
preference_task_size_network, preference_task_size_nuki, preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries
|
||||
};
|
||||
std::vector<char*> _charPrefs =
|
||||
{
|
||||
preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2
|
||||
};
|
||||
|
||||
const bool isRedacted(const char* key) const
|
||||
{
|
||||
return std::find(_redact.begin(), _redact.end(), key) != _redact.end();
|
||||
@@ -270,6 +292,30 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
const std::vector<char*> getPreferencesKeys()
|
||||
{
|
||||
return _keys;
|
||||
}
|
||||
const std::vector<char*> getPreferencesRedactedKeys()
|
||||
{
|
||||
return _redact;
|
||||
}
|
||||
const std::vector<char*> getPreferencesBoolKeys()
|
||||
{
|
||||
return _boolPrefs;
|
||||
}
|
||||
const std::vector<char*> getPreferencesByteKeys()
|
||||
{
|
||||
return _bytePrefs;
|
||||
}
|
||||
const std::vector<char*> getPreferencesIntKeys()
|
||||
{
|
||||
return _intPrefs;
|
||||
}
|
||||
const std::vector<char*> getPreferencesCharKeys()
|
||||
{
|
||||
return _charPrefs;
|
||||
}
|
||||
const String preferencesToString(Preferences *preferences)
|
||||
{
|
||||
String s = "";
|
||||
|
||||
@@ -213,6 +213,24 @@ void PresenceDetection::onResult(NimBLEAdvertisedDevice *device)
|
||||
// }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string nameStr = "-";
|
||||
i=0;
|
||||
len = nameStr.length();
|
||||
while(i < len && i < sizeof(pdDevice->name)-1)
|
||||
{
|
||||
pdDevice->name[i] = nameStr.at(i);
|
||||
++i;
|
||||
}
|
||||
|
||||
pdDevice->timestamp = millis();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
_devices[addr] = pdDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if(device->haveName())
|
||||
@@ -232,4 +250,4 @@ void PresenceDetection::onResult(NimBLEAdvertisedDevice *device)
|
||||
bool PresenceDetection::enabled()
|
||||
{
|
||||
return _timeout > 0;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ enum class RestartReason
|
||||
OTATimeout,
|
||||
OTAAborted,
|
||||
OTAUnknownState,
|
||||
OTAReboot,
|
||||
ImportCompleted,
|
||||
DeviceUnpaired,
|
||||
NukiHubReset,
|
||||
NotApplicable
|
||||
@@ -99,6 +101,10 @@ inline static String getRestartReason()
|
||||
return "OTAAborted";
|
||||
case RestartReason::OTAUnknownState:
|
||||
return "OTAUnknownState";
|
||||
case RestartReason::OTAReboot:
|
||||
return "RebootToOTA";
|
||||
case RestartReason::ImportCompleted:
|
||||
return "ConfigImportCompleted";
|
||||
case RestartReason::DeviceUnpaired:
|
||||
return "DeviceUnpaired";
|
||||
case RestartReason::NukiHubReset:
|
||||
@@ -142,9 +148,11 @@ inline static String getEspRestartReason()
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
inline bool rebuildGpio()
|
||||
{
|
||||
bool rebGpio = rebuildGpioRequested;
|
||||
rebuildGpioRequested = false;
|
||||
return restartReason_isValid && rebGpio;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
1148
src/WebCfgServer.cpp
1148
src/WebCfgServer.cpp
File diff suppressed because it is too large
Load Diff
@@ -2,15 +2,15 @@
|
||||
|
||||
#include <Preferences.h>
|
||||
#include <WebServer.h>
|
||||
#include "NukiWrapper.h"
|
||||
#include "NetworkLock.h"
|
||||
#include "NukiOpenerWrapper.h"
|
||||
#include "Ota.h"
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "NukiWrapper.h"
|
||||
#include "NukiNetworkLock.h"
|
||||
#include "NukiOpenerWrapper.h"
|
||||
#include "Gpio.h"
|
||||
|
||||
extern TaskHandle_t networkTaskHandle;
|
||||
extern TaskHandle_t nukiTaskHandle;
|
||||
extern TaskHandle_t presenceDetectionTaskHandle;
|
||||
|
||||
enum class TokenType
|
||||
{
|
||||
@@ -24,36 +24,44 @@ enum class TokenType
|
||||
QueryIntervalBattery,
|
||||
};
|
||||
|
||||
#else
|
||||
#include "NukiNetwork.h"
|
||||
#endif
|
||||
|
||||
extern TaskHandle_t networkTaskHandle;
|
||||
|
||||
class WebCfgServer
|
||||
{
|
||||
public:
|
||||
WebCfgServer(NukiWrapper* nuki, NukiOpenerWrapper* nukiOpener, Network* network, Gpio* gpio, EthServer* ethServer, Preferences* preferences, bool allowRestartToPortal);
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
WebCfgServer(NukiWrapper* nuki, NukiOpenerWrapper* nukiOpener, NukiNetwork* network, Gpio* gpio, EthServer* ethServer, Preferences* preferences, bool allowRestartToPortal, uint8_t partitionType);
|
||||
#else
|
||||
WebCfgServer(NukiNetwork* network, EthServer* ethServer, Preferences* preferences, bool allowRestartToPortal, uint8_t partitionType);
|
||||
#endif
|
||||
~WebCfgServer() = default;
|
||||
|
||||
void initialize();
|
||||
void update();
|
||||
|
||||
private:
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
void sendSettings();
|
||||
bool processArgs(String& message);
|
||||
bool processImport(String& message);
|
||||
void processGpioArgs();
|
||||
void buildHtml(String& response);
|
||||
void buildAccLvlHtml(String& response);
|
||||
void buildCredHtml(String& response);
|
||||
void buildOtaHtml(String& response, bool errored);
|
||||
void buildOtaCompletedHtml(String& response);
|
||||
void buildImportExportHtml(String& response);
|
||||
void buildMqttConfigHtml(String& response);
|
||||
void buildStatusHtml(String& response);
|
||||
void buildAdvancedConfigHtml(String& response);
|
||||
void buildNukiConfigHtml(String& response);
|
||||
void buildGpioConfigHtml(String& response);
|
||||
void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5);
|
||||
void buildConfigureWifiHtml(String& response);
|
||||
void buildInfoHtml(String& response);
|
||||
void sendCss();
|
||||
void sendFavicon();
|
||||
void processUnpair(bool opener);
|
||||
void processFactoryReset();
|
||||
void buildHtmlHeader(String& response, String additionalHeader = "");
|
||||
void printInputField(String& response, const char* token, const char* description, const char* value, const size_t& maxLength, const char* id, const bool& isPassword = false, const bool& showLengthRestriction = false);
|
||||
void printInputField(String& response, const char* token, const char* description, const int value, size_t maxLength, const char* id);
|
||||
void printCheckBox(String& response, const char* token, const char* description, const bool value, const char* htmlClass);
|
||||
@@ -70,14 +78,26 @@ private:
|
||||
void printParameter(String& response, const char* description, const char* value, const char *link = "", const char *id = "");
|
||||
|
||||
String generateConfirmCode();
|
||||
|
||||
NukiWrapper* _nuki = nullptr;
|
||||
NukiOpenerWrapper* _nukiOpener = nullptr;
|
||||
Gpio* _gpio = nullptr;
|
||||
bool _pinsConfigured = false;
|
||||
bool _brokerConfigured = false;
|
||||
String _confirmCode = "----";
|
||||
#endif
|
||||
|
||||
void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5);
|
||||
void buildOtaHtml(String& response, bool errored);
|
||||
void buildOtaCompletedHtml(String& response);
|
||||
void sendCss();
|
||||
void sendFavicon();
|
||||
void buildHtmlHeader(String& response, String additionalHeader = "");
|
||||
void waitAndProcess(const bool blocking, const uint32_t duration);
|
||||
void handleOtaUpload();
|
||||
|
||||
WebServer _server;
|
||||
NukiWrapper* _nuki = nullptr;
|
||||
NukiOpenerWrapper* _nukiOpener = nullptr;
|
||||
Network* _network = nullptr;
|
||||
Gpio* _gpio = nullptr;
|
||||
NukiNetwork* _network = nullptr;
|
||||
Preferences* _preferences = nullptr;
|
||||
Ota _ota;
|
||||
|
||||
@@ -85,13 +105,9 @@ private:
|
||||
char _credUser[31] = {0};
|
||||
char _credPassword[31] = {0};
|
||||
bool _allowRestartToPortal = false;
|
||||
bool _pinsConfigured = false;
|
||||
bool _brokerConfigured = false;
|
||||
uint8_t _partitionType = 0;
|
||||
uint32_t _transferredSize = 0;
|
||||
unsigned long _otaStartTs = 0;
|
||||
String _hostname;
|
||||
|
||||
String _confirmCode = "----";
|
||||
|
||||
bool _enabled = true;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// escaped by https://www.cescaper.com/
|
||||
// source: https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css
|
||||
|
||||
const char stylecss[] = ":root{--nc-font-sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';--nc-font-mono:Consolas,monaco,'Ubuntu Mono','Liberation Mono','Courier New',Courier,monospace;--nc-tx-1:#000;--nc-tx-2:#1a1a1a;--nc-bg-1:#fff;--nc-bg-2:#f6f8fa;--nc-bg-3:#e5e7eb;--nc-lk-1:#0070f3;--nc-lk-2:#0366d6;--nc-lk-tx:#fff;--nc-ac-1:#79ffe1;--nc-ac-tx:#0c4047}@media(prefers-color-scheme:dark){:root{--nc-tx-1:#fff;--nc-tx-2:#eee;--nc-bg-1:#000;--nc-bg-2:#111;--nc-bg-3:#222;--nc-lk-1:#3291ff;--nc-lk-2:#0070f3;--nc-lk-tx:#fff;--nc-ac-1:#7928ca;--nc-ac-tx:#fff}}*{margin:0;padding:0}img,input,option,p,table,textarea,ul{margin-bottom:1rem}button,html,input,select{font-family:var(--nc-font-sans)}body{margin:0 auto;max-width:750px;padding:2rem;border-radius:6px;overflow-x:hidden;word-break:normal;overflow-wrap:anywhere;background:var(--nc-bg-1);color:var(--nc-tx-2);font-size:1.03rem;line-height:1.5}::selection{background:var(--nc-ac-1);color:var(--nc-ac-tx)}h1,h2,h3,h4,h5,h6{line-height:1;color:var(--nc-tx-1);padding-top:.875rem}h1,h2,h3{color:var(--nc-tx-1);padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid var(--nc-bg-2)}h4,h5,h6{margin-bottom:.3rem}h1{font-size:2.25rem}h2{font-size:1.85rem}h3{font-size:1.55rem}h4{font-size:1.25rem}h5{font-size:1rem}h6{font-size:.875rem}a{color:var(--nc-lk-1)}a:hover{color:var(--nc-lk-2)}abbr{cursor:help}abbr:hover{cursor:help}a button,button,input[type=button],input[type=reset],input[type=submit]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:var(--nc-lk-1);color:var(--nc-lk-tx);border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:var(--nc-lk-tx)}a button[disabled],button[disabled],input[type=button][disabled],input[type=reset][disabled],input[type=submit][disabled]{cursor:default;opacity:.5;cursor:not-allowed}.button:focus,.button:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background:var(--nc-lk-2)}table{border-collapse:collapse;width:100%}td,th{border:1px solid var(--nc-bg-3);text-align:left;padding:.5rem}th{background:var(--nc-bg-2)}tr:nth-child(even){background:var(--nc-bg-2)}textarea{max-width:100%}input,select,textarea{padding:6px 12px;margin-bottom:.5rem;background:var(--nc-bg-2);color:var(--nc-tx-2);border:1px solid var(--nc-bg-3);border-radius:4px;box-shadow:none;box-sizing:border-box}img{max-width:100%}td>input{margin-top:0;margin-bottom:0}td>textarea{margin-top:0;margin-bottom:0}td>select{margin-top:0;margin-bottom:0}.warning{color:red}@media only screen and (max-width:600px){.adapt td{display:block}.adapt input[type=text],.adapt input[type=password],.adapt input[type=submit],.adapt textarea,.adapt select{width:100%}.adapt td:has(input[type=checkbox]){text-align:center}.adapt input[type=checkbox]{width:1.5em;height:1.5em}.adapt table td:first-child{border-bottom:0}.adapt table td:last-child{border-top:0}#tblnav a li>span{max-width:140px}}#tblnav a{border:0;border-bottom:1px solid;display:block;font-size:1rem;font-weight:bold;padding:.6rem 0;line-height:1;color:var(--nc-tx-1);text-decoration:none;background:linear-gradient(to left,transparent 50%,rgba(255,255,255,0.4) 50%) right;background-size:200% 100%;transition:all .2s ease}#tblnav a:nth-child(even){background:linear-gradient(to left,var(--nc-bg-2) 50%,rgba(255,255,255,0.4) 50%) right;background-size:200% 100%}#tblnav a:hover{background-position:left;transition:all .45s ease}#tblnav a:active{background:var(--nc-lk-1);transition:all .15s ease}#tblnav a li{list-style:none;padding:.5rem;display:inline-block;width:100%}#tblnav a li>span{float:right;text-align:right;margin-right:10px;color:#f70;font-weight:100;font-style:italic;display:block}.tdbtn{text-align:center;vertical-align:middle}";
|
||||
const char stylecss[] = ":root{--nc-font-sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';--nc-font-mono:Consolas,monaco,'Ubuntu Mono','Liberation Mono','Courier New',Courier,monospace;--nc-tx-1:#000;--nc-tx-2:#1a1a1a;--nc-bg-1:#fff;--nc-bg-2:#f6f8fa;--nc-bg-3:#e5e7eb;--nc-lk-1:#0070f3;--nc-lk-2:#0366d6;--nc-lk-tx:#fff;--nc-ac-1:#79ffe1;--nc-ac-tx:#0c4047}@media(prefers-color-scheme:dark){:root{--nc-tx-1:#fff;--nc-tx-2:#eee;--nc-bg-1:#000;--nc-bg-2:#111;--nc-bg-3:#222;--nc-lk-1:#3291ff;--nc-lk-2:#0070f3;--nc-lk-tx:#fff;--nc-ac-1:#7928ca;--nc-ac-tx:#fff}}*{margin:0;padding:0}img,input,option,p,table,textarea,ul{margin-bottom:1rem}button,html,input,select{font-family:var(--nc-font-sans)}body{margin:0 auto;max-width:750px;padding:2rem;border-radius:6px;overflow-x:hidden;word-break:normal;overflow-wrap:anywhere;background:var(--nc-bg-1);color:var(--nc-tx-2);font-size:1.03rem;line-height:1.5}::selection{background:var(--nc-ac-1);color:var(--nc-ac-tx)}h1,h2,h3,h4,h5,h6{line-height:1;color:var(--nc-tx-1);padding-top:.875rem}h1,h2,h3{color:var(--nc-tx-1);padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid var(--nc-bg-2)}h4,h5,h6{margin-bottom:.3rem}h1{font-size:2.25rem}h2{font-size:1.85rem}h3{font-size:1.55rem}h4{font-size:1.25rem}h5{font-size:1rem}h6{font-size:.875rem}a{color:var(--nc-lk-1)}a:hover{color:var(--nc-lk-2) !important;}abbr{cursor:help}abbr:hover{cursor:help}a button,button,input[type=button],input[type=reset],input[type=submit]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:var(--nc-lk-1);color:var(--nc-lk-tx);border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:var(--nc-lk-tx)}a button[disabled],button[disabled],input[type=button][disabled],input[type=reset][disabled],input[type=submit][disabled]{cursor:default;opacity:.5;cursor:not-allowed}.button:focus,.button:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background:var(--nc-lk-2)}table{border-collapse:collapse;width:100%}td,th{border:1px solid var(--nc-bg-3);text-align:left;padding:.5rem}th{background:var(--nc-bg-2)}tr:nth-child(even){background:var(--nc-bg-2)}textarea{max-width:100%}input,select,textarea{padding:6px 12px;margin-bottom:.5rem;background:var(--nc-bg-2);color:var(--nc-tx-2);border:1px solid var(--nc-bg-3);border-radius:4px;box-shadow:none;box-sizing:border-box}img{max-width:100%}td>input{margin-top:0;margin-bottom:0}td>textarea{margin-top:0;margin-bottom:0}td>select{margin-top:0;margin-bottom:0}.warning{color:red}@media only screen and (max-width:600px){.adapt td{display:block}.adapt input[type=text],.adapt input[type=password],.adapt input[type=submit],.adapt textarea,.adapt select{width:100%}.adapt td:has(input[type=checkbox]){text-align:center}.adapt input[type=checkbox]{width:1.5em;height:1.5em}.adapt table td:first-child{border-bottom:0}.adapt table td:last-child{border-top:0}#tblnav a li>span{max-width:140px}}#tblnav a{border:0;border-bottom:1px solid;display:block;font-size:1rem;font-weight:bold;padding:.6rem 0;line-height:1;color:var(--nc-tx-1);text-decoration:none;background:linear-gradient(to left,transparent 50%,rgba(255,255,255,0.4) 50%) right;background-size:200% 100%;transition:all .2s ease}#tblnav a:nth-child(even){background:linear-gradient(to left,var(--nc-bg-2) 50%,rgba(255,255,255,0.4) 50%) right;background-size:200% 100%}#tblnav a:hover{background-position:left;transition:all .45s ease}#tblnav a:active{background:var(--nc-lk-1);transition:all .15s ease}#tblnav a li{list-style:none;padding:.5rem;display:inline-block;width:100%}#tblnav a li>span{float:right;text-align:right;margin-right:10px;color:#f70;font-weight:100;font-style:italic;display:block}.tdbtn{text-align:center;vertical-align:middle}";
|
||||
|
||||
// converted to char array by https://notisrac.github.io/FileToCArray/
|
||||
const unsigned char favicon_32x32[] = {
|
||||
|
||||
278
src/main.cpp
278
src/main.cpp
@@ -1,40 +1,62 @@
|
||||
#include "Arduino.h"
|
||||
#include "NukiWrapper.h"
|
||||
#include "NetworkLock.h"
|
||||
#include "WebCfgServer.h"
|
||||
#include <RTOS.h>
|
||||
#include "PreferencesKeys.h"
|
||||
#include "PresenceDetection.h"
|
||||
#include "hardware/W5500EthServer.h"
|
||||
#include "hardware/WifiEthServer.h"
|
||||
#include "NukiOpenerWrapper.h"
|
||||
#include "Gpio.h"
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include "RestartReason.h"
|
||||
#include "CharBuffer.h"
|
||||
#include "NukiDeviceId.h"
|
||||
|
||||
#define IS_VALID_DETECT 0xa00ab00bc00bd00d;
|
||||
|
||||
Network* network = nullptr;
|
||||
NetworkLock* networkLock = nullptr;
|
||||
NetworkOpener* networkOpener = nullptr;
|
||||
WebCfgServer* webCfgServer = nullptr;
|
||||
#include "Arduino.h"
|
||||
#include "hardware/W5500EthServer.h"
|
||||
#include "hardware/WifiEthServer.h"
|
||||
#include "esp_crt_bundle.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_http_client.h"
|
||||
#include "esp_https_ota.h"
|
||||
#include "Config.h"
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "NukiWrapper.h"
|
||||
#include "NukiNetworkLock.h"
|
||||
#include "PresenceDetection.h"
|
||||
#include "NukiOpenerWrapper.h"
|
||||
#include "Gpio.h"
|
||||
#include "CharBuffer.h"
|
||||
#include "NukiDeviceId.h"
|
||||
#include "WebCfgServer.h"
|
||||
#include "Logger.h"
|
||||
#include "PreferencesKeys.h"
|
||||
#include "RestartReason.h"
|
||||
|
||||
NukiNetworkLock* networkLock = nullptr;
|
||||
NukiNetworkOpener* networkOpener = nullptr;
|
||||
BleScanner::Scanner* bleScanner = nullptr;
|
||||
NukiWrapper* nuki = nullptr;
|
||||
NukiOpenerWrapper* nukiOpener = nullptr;
|
||||
PresenceDetection* presenceDetection = nullptr;
|
||||
NukiDeviceId* deviceIdLock = nullptr;
|
||||
NukiDeviceId* deviceIdOpener = nullptr;
|
||||
Preferences* preferences = nullptr;
|
||||
EthServer* ethServer = nullptr;
|
||||
Gpio* gpio = nullptr;
|
||||
|
||||
bool lockEnabled = false;
|
||||
bool openerEnabled = false;
|
||||
|
||||
TaskHandle_t nukiTaskHandle = nullptr;
|
||||
TaskHandle_t presenceDetectionTaskHandle = nullptr;
|
||||
|
||||
unsigned long restartTs = (2^32) - 5 * 60000;
|
||||
|
||||
#else
|
||||
#include "../../src/WebCfgServer.h"
|
||||
#include "../../src/Logger.h"
|
||||
#include "../../src/PreferencesKeys.h"
|
||||
#include "../../src/Config.h"
|
||||
#include "../../src/RestartReason.h"
|
||||
#include "../../src/NukiNetwork.h"
|
||||
|
||||
unsigned long restartTs = 10 * 60000;
|
||||
|
||||
#endif
|
||||
|
||||
NukiNetwork* network = nullptr;
|
||||
WebCfgServer* webCfgServer = nullptr;
|
||||
Preferences* preferences = nullptr;
|
||||
EthServer* ethServer = nullptr;
|
||||
|
||||
RTC_NOINIT_ATTR int restartReason;
|
||||
RTC_NOINIT_ATTR uint64_t restartReasonValidDetect;
|
||||
RTC_NOINIT_ATTR bool rebuildGpioRequested;
|
||||
@@ -45,9 +67,8 @@ RTC_NOINIT_ATTR int8_t bootloopCounter;
|
||||
bool restartReason_isValid;
|
||||
RestartReason currentRestartReason = RestartReason::NotApplicable;
|
||||
|
||||
TaskHandle_t otaTaskHandle = nullptr;
|
||||
TaskHandle_t networkTaskHandle = nullptr;
|
||||
TaskHandle_t nukiTaskHandle = nullptr;
|
||||
TaskHandle_t presenceDetectionTaskHandle = nullptr;
|
||||
|
||||
void networkTask(void *pvParameters)
|
||||
{
|
||||
@@ -61,6 +82,8 @@ void networkTask(void *pvParameters)
|
||||
}
|
||||
|
||||
bool connected = network->update();
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
if(connected && openerEnabled)
|
||||
{
|
||||
networkOpener->update();
|
||||
@@ -70,6 +93,9 @@ void networkTask(void *pvParameters)
|
||||
{
|
||||
webCfgServer->update();
|
||||
}
|
||||
#else
|
||||
webCfgServer->update();
|
||||
#endif
|
||||
|
||||
// millis() is about to overflow. Restart device to prevent problems with overflow
|
||||
if(millis() > restartTs)
|
||||
@@ -80,16 +106,10 @@ void networkTask(void *pvParameters)
|
||||
}
|
||||
|
||||
delay(100);
|
||||
|
||||
// if(wmts < millis())
|
||||
// {
|
||||
// Serial.print("# ");
|
||||
// Serial.println(uxTaskGetStackHighWaterMark(NULL));
|
||||
// wmts = millis() + 60000;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
void nukiTask(void *pvParameters)
|
||||
{
|
||||
while(true)
|
||||
@@ -115,13 +135,120 @@ void nukiTask(void *pvParameters)
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void setupTasks()
|
||||
uint8_t checkPartition()
|
||||
{
|
||||
const esp_partition_t* running_partition = esp_ota_get_running_partition();
|
||||
Log->print(F("Partition size: "));
|
||||
Log->println(running_partition->size);
|
||||
Log->print(F("Partition subtype: "));
|
||||
Log->println(running_partition->subtype);
|
||||
|
||||
if(running_partition->size == 1966080) return 0; //OLD PARTITION TABLE
|
||||
else if(running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0) return 1; //NEW PARTITION TABLE, RUNNING MAIN APP
|
||||
else return 2; //NEW PARTITION TABLE, RUNNING UPDATER APP
|
||||
}
|
||||
|
||||
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
||||
{
|
||||
switch (evt->event_id) {
|
||||
case HTTP_EVENT_ERROR:
|
||||
Log->println("HTTP_EVENT_ERROR");
|
||||
break;
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
Log->println("HTTP_EVENT_ON_CONNECTED");
|
||||
break;
|
||||
case HTTP_EVENT_HEADER_SENT:
|
||||
Log->println("HTTP_EVENT_HEADER_SENT");
|
||||
break;
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
Log->println("HTTP_EVENT_ON_HEADER");
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
Log->println("HTTP_EVENT_ON_DATA");
|
||||
break;
|
||||
case HTTP_EVENT_ON_FINISH:
|
||||
Log->println("HTTP_EVENT_ON_FINISH");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
Log->println("HTTP_EVENT_DISCONNECTED");
|
||||
break;
|
||||
#if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
case HTTP_EVENT_REDIRECT:
|
||||
Log->println("HTTP_EVENT_REDIRECT");
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
void otaTask(void *pvParameter)
|
||||
{
|
||||
uint8_t partitionType = checkPartition();
|
||||
String updateUrl;
|
||||
|
||||
if(partitionType==1)
|
||||
{
|
||||
updateUrl = preferences->getString(preference_ota_updater_url);
|
||||
preferences->putString(preference_ota_updater_url, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
updateUrl = preferences->getString(preference_ota_main_url);
|
||||
preferences->putString(preference_ota_main_url, "");
|
||||
}
|
||||
Log->println("Starting OTA task");
|
||||
esp_http_client_config_t config = {
|
||||
.url = updateUrl.c_str(),
|
||||
.event_handler = _http_event_handler,
|
||||
.crt_bundle_attach = esp_crt_bundle_attach,
|
||||
.keep_alive_enable = true,
|
||||
};
|
||||
|
||||
esp_https_ota_config_t ota_config = {
|
||||
.http_config = &config,
|
||||
};
|
||||
Log->print(F("Attempting to download update from "));
|
||||
Log->println(config.url);
|
||||
esp_err_t ret = esp_https_ota(&ota_config);
|
||||
if (ret == ESP_OK) {
|
||||
Log->println("OTA Succeeded, Rebooting...");
|
||||
esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL));
|
||||
restartEsp(RestartReason::OTACompleted);
|
||||
} else {
|
||||
Log->println("Firmware upgrade failed");
|
||||
restartEsp(RestartReason::OTAAborted);
|
||||
}
|
||||
while (1) {
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void setupTasks(bool ota)
|
||||
{
|
||||
// configMAX_PRIORITIES is 25
|
||||
|
||||
xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), NULL, 3, &networkTaskHandle, 1);
|
||||
xTaskCreatePinnedToCore(nukiTask, "nuki", preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), NULL, 2, &nukiTaskHandle, 1);
|
||||
if(ota)
|
||||
{
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), NULL, 3, &networkTaskHandle, 1);
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
xTaskCreatePinnedToCore(nukiTask, "nuki", preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), NULL, 2, &nukiTaskHandle, 1);
|
||||
#endif
|
||||
#else
|
||||
xTaskCreatePinnedToCore(otaTask, "ota", 8192, NULL, 2, &otaTaskHandle, 1);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), NULL, 3, &networkTaskHandle, 1);
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
xTaskCreatePinnedToCore(nukiTask, "nuki", preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), NULL, 2, &nukiTaskHandle, 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void initEthServer(const NetworkDeviceType device)
|
||||
@@ -145,24 +272,22 @@ bool initPreferences()
|
||||
preferences = new Preferences();
|
||||
preferences->begin("nukihub", false);
|
||||
|
||||
// preferences->putBool(preference_network_wifi_fallback_disabled, false);
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
bool firstStart = !preferences->getBool(preference_started_before);
|
||||
|
||||
if(firstStart)
|
||||
{
|
||||
preferences->putBool(preference_started_before, true);
|
||||
preferences->putBool(preference_lock_enabled, true);
|
||||
preferences->putBool(preference_conf_info_enabled, true);
|
||||
uint32_t aclPrefs[17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
preferences->putBytes(preference_acl, (byte*)(&aclPrefs), sizeof(aclPrefs));
|
||||
uint32_t basicLockConfigAclPrefs[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
uint32_t basicLockConfigAclPrefs[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs));
|
||||
uint32_t basicOpenerConfigAclPrefs[14] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs));
|
||||
uint32_t advancedLockConfigAclPrefs[22] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
uint32_t advancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs));
|
||||
uint32_t advancedOpenerConfigAclPrefs[20] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs));
|
||||
}
|
||||
else
|
||||
@@ -182,7 +307,7 @@ bool initPreferences()
|
||||
preferences->putBool(preference_keypad_info_enabled, false);
|
||||
}
|
||||
|
||||
switch(preferences->getInt(preference_access_level))
|
||||
switch(preferences->getInt(preference_access_level, 10))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
@@ -244,6 +369,21 @@ bool initPreferences()
|
||||
preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
preferences->putBool(preference_keypad_control_enabled, true);
|
||||
uint32_t aclPrefs[17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
preferences->putBytes(preference_acl, (byte*)(&aclPrefs), sizeof(aclPrefs));
|
||||
uint32_t basicLockConfigAclPrefs[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs));
|
||||
uint32_t basicOpenerConfigAclPrefs[14] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs));
|
||||
uint32_t advancedLockConfigAclPrefs[22] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs));
|
||||
uint32_t advancedOpenerConfigAclPrefs[20] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +392,9 @@ bool initPreferences()
|
||||
}
|
||||
|
||||
return firstStart;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bootloopDetection()
|
||||
@@ -297,19 +440,30 @@ void setup()
|
||||
Serial.begin(115200);
|
||||
Log = &Serial;
|
||||
|
||||
Log->print(F("Nuki Hub version ")); Log->println(NUKI_HUB_VERSION);
|
||||
Log->print(F("Nuki Hub build ")); Log->println(NUKI_HUB_BUILD);
|
||||
|
||||
bool firstStart = initPreferences();
|
||||
preferences->remove(preference_bootloop_counter);
|
||||
uint8_t partitionType = checkPartition();
|
||||
|
||||
initializeRestartReason();
|
||||
|
||||
|
||||
if(preferences->getBool(preference_enable_bootloop_reset, false))
|
||||
{
|
||||
bootloopDetection();
|
||||
}
|
||||
|
||||
#ifdef NUKI_HUB_UPDATER
|
||||
Log->print(F("Nuki Hub OTA version ")); Log->println(NUKI_HUB_VERSION);
|
||||
Log->print(F("Nuki Hub OTA build ")); Log->println(NUKI_HUB_BUILD);
|
||||
|
||||
network = new NukiNetwork(preferences);
|
||||
network->initialize();
|
||||
initEthServer(network->networkDeviceType());
|
||||
webCfgServer = new WebCfgServer(network, ethServer, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType);
|
||||
webCfgServer->initialize();
|
||||
#else
|
||||
Log->print(F("Nuki Hub version ")); Log->println(NUKI_HUB_VERSION);
|
||||
Log->print(F("Nuki Hub build ")); Log->println(NUKI_HUB_BUILD);
|
||||
|
||||
uint32_t devIdOpener = preferences->getUInt(preference_device_id_opener);
|
||||
|
||||
deviceIdLock = new NukiDeviceId(preferences, preference_device_id_lock);
|
||||
@@ -319,16 +473,11 @@ void setup()
|
||||
{
|
||||
deviceIdOpener->assignId(deviceIdLock->get());
|
||||
}
|
||||
|
||||
|
||||
char16_t buffer_size = preferences->getInt(preference_buffer_size, 4096);
|
||||
|
||||
CharBuffer::initialize(buffer_size);
|
||||
|
||||
if(preferences->getInt(preference_restart_timer) != 0)
|
||||
{
|
||||
preferences->remove(preference_restart_timer);
|
||||
}
|
||||
|
||||
gpio = new Gpio(preferences);
|
||||
String gpioDesc;
|
||||
gpio->getConfigurationText(gpioDesc, gpio->pinConfiguration(), "\n\r");
|
||||
@@ -340,7 +489,7 @@ void setup()
|
||||
|
||||
if(preferences->getInt(preference_presence_detection_timeout) >= 0)
|
||||
{
|
||||
presenceDetection = new PresenceDetection(preferences, bleScanner, CharBuffer::get(), CHAR_BUFFER_SIZE);
|
||||
presenceDetection = new PresenceDetection(preferences, bleScanner, CharBuffer::get(), buffer_size);
|
||||
presenceDetection->initialize();
|
||||
}
|
||||
|
||||
@@ -348,15 +497,16 @@ void setup()
|
||||
openerEnabled = preferences->getBool(preference_opener_enabled);
|
||||
|
||||
const String mqttLockPath = preferences->getString(preference_mqtt_lock_path);
|
||||
network = new Network(preferences, presenceDetection, gpio, mqttLockPath, CharBuffer::get(), buffer_size);
|
||||
|
||||
network = new NukiNetwork(preferences, presenceDetection, gpio, mqttLockPath, CharBuffer::get(), buffer_size);
|
||||
network->initialize();
|
||||
|
||||
networkLock = new NetworkLock(network, preferences, CharBuffer::get(), buffer_size);
|
||||
networkLock = new NukiNetworkLock(network, preferences, CharBuffer::get(), buffer_size);
|
||||
networkLock->initialize();
|
||||
|
||||
if(openerEnabled)
|
||||
{
|
||||
networkOpener = new NetworkOpener(network, preferences, CharBuffer::get(), buffer_size);
|
||||
networkOpener = new NukiNetworkOpener(network, preferences, CharBuffer::get(), buffer_size);
|
||||
networkOpener->initialize();
|
||||
}
|
||||
|
||||
@@ -378,14 +528,24 @@ void setup()
|
||||
|
||||
if(preferences->getBool(preference_webserver_enabled, true))
|
||||
{
|
||||
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, ethServer, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi);
|
||||
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, ethServer, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType);
|
||||
webCfgServer->initialize();
|
||||
}
|
||||
#endif
|
||||
|
||||
setupTasks();
|
||||
if((partitionType==1 && preferences->getString(preference_ota_updater_url).length() > 0) || (partitionType==2 && preferences->getString(preference_ota_main_url).length() > 0)) setupTasks(true);
|
||||
else setupTasks(false);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void printBeforeSetupInfo()
|
||||
{
|
||||
}
|
||||
|
||||
void printAfterSetupInfo()
|
||||
{
|
||||
}
|
||||
@@ -6,8 +6,10 @@
|
||||
#include "EthLan8720Device.h"
|
||||
#include "../PreferencesKeys.h"
|
||||
#include "../Logger.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "../MqttTopics.h"
|
||||
#include "espMqttClient.h"
|
||||
#endif
|
||||
#include "../RestartReason.h"
|
||||
|
||||
EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* preferences, const IPConfiguration* ipConfiguration, const std::string& deviceName, uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t ethtype, eth_clock_mode_t clock_mode, bool use_mac_from_efuse)
|
||||
@@ -23,6 +25,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* preferen
|
||||
{
|
||||
_restartOnDisconnect = preferences->getBool(preference_restart_on_disconnect);
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
size_t caLength = preferences->getString(preference_mqtt_ca, _ca, TLS_CA_MAX_SIZE);
|
||||
size_t crtLength = preferences->getString(preference_mqtt_crt, _cert, TLS_CERT_MAX_SIZE);
|
||||
size_t keyLength = preferences->getString(preference_mqtt_key, _key, TLS_KEY_MAX_SIZE);
|
||||
@@ -59,6 +62,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* preferen
|
||||
strcpy(_path, pathStr.c_str());
|
||||
Log = new MqttLogger(*getMqttClient(), _path, MqttLoggerMode::MqttAndSerial);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const String EthLan8720Device::deviceName() const
|
||||
@@ -71,23 +75,29 @@ void EthLan8720Device::initialize()
|
||||
delay(250);
|
||||
|
||||
WiFi.setHostname(_hostname.c_str());
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
_hardwareInitialized = ETH.begin(_phy_addr, _power, _mdc, _mdio, _type, _clock_mode, _use_mac_from_efuse);
|
||||
#else
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
_hardwareInitialized = ETH.begin(_type, _phy_addr, _mdc, _mdio, ETH_RESET_PIN, _clock_mode);
|
||||
#else
|
||||
_hardwareInitialized = false;
|
||||
#endif
|
||||
#endif
|
||||
ETH.setHostname(_hostname.c_str());
|
||||
if(!_ipConfiguration->dhcpEnabled())
|
||||
{
|
||||
ETH.config(_ipConfiguration->ipAddress(), _ipConfiguration->defaultGateway(), _ipConfiguration->subnet(), _ipConfiguration->dnsServer());
|
||||
}
|
||||
|
||||
if(_restartOnDisconnect)
|
||||
WiFi.onEvent([&](WiFiEvent_t event, WiFiEventInfo_t info)
|
||||
{
|
||||
WiFi.onEvent([&](WiFiEvent_t event, WiFiEventInfo_t info)
|
||||
if(event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED)
|
||||
{
|
||||
if(event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED)
|
||||
{
|
||||
onDisconnected();
|
||||
}
|
||||
});
|
||||
}
|
||||
onDisconnected();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EthLan8720Device::reconfigure()
|
||||
@@ -128,10 +138,8 @@ ReconnectStatus EthLan8720Device::reconnect()
|
||||
|
||||
void EthLan8720Device::onDisconnected()
|
||||
{
|
||||
if(millis() > 60000)
|
||||
{
|
||||
restartEsp(RestartReason::RestartOnDisconnectWatchdog);
|
||||
}
|
||||
if(_restartOnDisconnect && (millis() > 60000)) restartEsp(RestartReason::RestartOnDisconnectWatchdog);
|
||||
reconnect();
|
||||
}
|
||||
|
||||
int8_t EthLan8720Device::signalStrength()
|
||||
|
||||
@@ -1,10 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||
typedef enum {
|
||||
ETH_CLOCK_GPIO0_IN = 0,
|
||||
ETH_CLOCK_GPIO16_OUT = 2,
|
||||
ETH_CLOCK_GPIO17_OUT = 3
|
||||
} eth_clock_mode_t;
|
||||
|
||||
#define ETH_PHY_TYPE ETH_PHY_MAX
|
||||
#else
|
||||
#define ETH_PHY_TYPE ETH_PHY_LAN8720
|
||||
#endif
|
||||
|
||||
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN
|
||||
|
||||
#define ETH_PHY_ADDR 0
|
||||
#define ETH_PHY_MDC 23
|
||||
#define ETH_PHY_MDIO 18
|
||||
#define ETH_PHY_POWER -1
|
||||
#define ETH_RESET_PIN 1
|
||||
#endif
|
||||
|
||||
#include <WiFiClient.h>
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
#include <WiFiClientSecure.h>
|
||||
#else
|
||||
#include <NetworkClientSecure.h>
|
||||
#endif
|
||||
#include <Preferences.h>
|
||||
#include "NetworkDevice.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "espMqttClient.h"
|
||||
#endif
|
||||
#include <ETH.h>
|
||||
|
||||
class EthLan8720Device : public NetworkDevice
|
||||
@@ -54,8 +82,9 @@ private:
|
||||
eth_phy_type_t _type;
|
||||
eth_clock_mode_t _clock_mode;
|
||||
bool _use_mac_from_efuse;
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
char _ca[TLS_CA_MAX_SIZE] = {0};
|
||||
char _cert[TLS_CERT_MAX_SIZE] = {0};
|
||||
char _key[TLS_KEY_MAX_SIZE] = {0};
|
||||
};
|
||||
#endif
|
||||
};
|
||||
@@ -8,6 +8,7 @@ void NetworkDevice::printError()
|
||||
Log->println(ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
void NetworkDevice::update()
|
||||
{
|
||||
if (_mqttEnabled)
|
||||
@@ -40,6 +41,18 @@ void NetworkDevice::mqttSetCleanSession(bool cleanSession)
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevice::mqttSetKeepAlive(uint16_t keepAlive)
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->setKeepAlive(keepAlive);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->setKeepAlive(keepAlive);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t NetworkDevice::mqttPublish(const char *topic, uint8_t qos, bool retain, const char *payload)
|
||||
{
|
||||
return getMqttClient()->publish(topic, qos, retain, payload);
|
||||
@@ -158,4 +171,9 @@ MqttClient *NetworkDevice::getMqttClient() const
|
||||
{
|
||||
return _mqttClient;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void NetworkDevice::update()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "espMqttClient.h"
|
||||
#include "MqttClientSetup.h"
|
||||
#endif
|
||||
#include "IPConfiguration.h"
|
||||
|
||||
enum class ReconnectStatus
|
||||
@@ -35,8 +37,10 @@ public:
|
||||
virtual String localIP() = 0;
|
||||
virtual String BSSIDstr() = 0;
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
virtual void mqttSetClientId(const char* clientId);
|
||||
virtual void mqttSetCleanSession(bool cleanSession);
|
||||
virtual void mqttSetKeepAlive(uint16_t keepAlive);
|
||||
virtual uint16_t mqttPublish(const char* topic, uint8_t qos, bool retain, const char* payload);
|
||||
virtual uint16_t mqttPublish(const char* topic, uint8_t qos, bool retain, const uint8_t* payload, size_t length);
|
||||
virtual bool mqttConnected() const;
|
||||
@@ -51,16 +55,19 @@ public:
|
||||
virtual void disableMqtt();
|
||||
|
||||
virtual uint16_t mqttSubscribe(const char* topic, uint8_t qos);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
espMqttClient *_mqttClient = nullptr;
|
||||
espMqttClientSecure *_mqttClientSecure = nullptr;
|
||||
|
||||
bool _useEncryption = false;
|
||||
bool _mqttEnabled = true;
|
||||
|
||||
|
||||
MqttClient *getMqttClient() const;
|
||||
#endif
|
||||
|
||||
const String _hostname;
|
||||
const IPConfiguration* _ipConfiguration = nullptr;
|
||||
|
||||
MqttClient *getMqttClient() const;
|
||||
};
|
||||
@@ -3,7 +3,9 @@
|
||||
#include "W5500Device.h"
|
||||
#include "../PreferencesKeys.h"
|
||||
#include "../Logger.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "../MqttTopics.h"
|
||||
#endif
|
||||
#include "sdkconfig.h"
|
||||
|
||||
W5500Device::W5500Device(const String &hostname, Preferences* preferences, const IPConfiguration* ipConfiguration, int variant)
|
||||
@@ -27,8 +29,9 @@ W5500Device::W5500Device(const String &hostname, Preferences* preferences, const
|
||||
}
|
||||
}
|
||||
Log->println();
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
_mqttClient = new espMqttClientW5500();
|
||||
#endif
|
||||
}
|
||||
|
||||
W5500Device::~W5500Device()
|
||||
@@ -61,6 +64,7 @@ void W5500Device::initialize()
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
if(_preferences->getBool(preference_mqtt_log_enabled))
|
||||
{
|
||||
String pathStr = _preferences->getString(preference_mqtt_lock_path);
|
||||
@@ -70,6 +74,7 @@ void W5500Device::initialize()
|
||||
strcpy(_path, pathStr.c_str());
|
||||
Log = new MqttLogger(*getMqttClient(), _path, MqttLoggerMode::MqttAndSerial);
|
||||
}
|
||||
#endif
|
||||
|
||||
reconnect();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "NetworkDevice.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "espMqttClient.h"
|
||||
#include "espMqttClientW5500.h"
|
||||
#endif
|
||||
#include <Ethernet.h>
|
||||
#include <Preferences.h>
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#include "WifiDevice.h"
|
||||
#include "../PreferencesKeys.h"
|
||||
#include "../Logger.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "../MqttTopics.h"
|
||||
#include "espMqttClient.h"
|
||||
#endif
|
||||
#include "../RestartReason.h"
|
||||
|
||||
RTC_NOINIT_ATTR char WiFiDevice_reconfdetect[17];
|
||||
@@ -15,6 +17,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* preferences, const I
|
||||
{
|
||||
_startAp = strcmp(WiFiDevice_reconfdetect, "reconfigure_wifi") == 0;
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
_restartOnDisconnect = preferences->getBool(preference_restart_on_disconnect);
|
||||
|
||||
size_t caLength = preferences->getString(preference_mqtt_ca, _ca, TLS_CA_MAX_SIZE);
|
||||
@@ -53,6 +56,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* preferences, const I
|
||||
strcpy(_path, pathStr.c_str());
|
||||
Log = new MqttLogger(*getMqttClient(), _path, MqttLoggerMode::MqttAndSerial);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const String WifiDevice::deviceName() const
|
||||
@@ -94,9 +98,9 @@ void WifiDevice::initialize()
|
||||
|
||||
if(!res)
|
||||
{
|
||||
esp_wifi_disconnect ();
|
||||
esp_wifi_stop ();
|
||||
esp_wifi_deinit ();
|
||||
esp_wifi_disconnect();
|
||||
esp_wifi_stop();
|
||||
esp_wifi_deinit();
|
||||
|
||||
Log->println(F("Failed to connect. Wait for ESP restart."));
|
||||
delay(1000);
|
||||
@@ -107,16 +111,17 @@ void WifiDevice::initialize()
|
||||
Log->println(WiFi.localIP().toString());
|
||||
}
|
||||
|
||||
if(_restartOnDisconnect)
|
||||
WiFi.onEvent([&](WiFiEvent_t event, WiFiEventInfo_t info)
|
||||
{
|
||||
WiFi.onEvent([&](WiFiEvent_t event, WiFiEventInfo_t info)
|
||||
if(event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED)
|
||||
{
|
||||
if(event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED)
|
||||
{
|
||||
onDisconnected();
|
||||
}
|
||||
});
|
||||
}
|
||||
onDisconnected();
|
||||
}
|
||||
else if(event == ARDUINO_EVENT_WIFI_STA_GOT_IP)
|
||||
{
|
||||
onConnected();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void WifiDevice::reconfigure()
|
||||
@@ -138,16 +143,30 @@ bool WifiDevice::isConnected()
|
||||
|
||||
ReconnectStatus WifiDevice::reconnect()
|
||||
{
|
||||
delay(3000);
|
||||
if(!isConnected() && !_isReconnecting)
|
||||
{
|
||||
_isReconnecting = true;
|
||||
_wm.autoConnect();
|
||||
delay(10000);
|
||||
_isReconnecting = false;
|
||||
}
|
||||
|
||||
if(!isConnected() && _disconnectTs > millis() - 120000) _wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled));
|
||||
return isConnected() ? ReconnectStatus::Success : ReconnectStatus::Failure;
|
||||
}
|
||||
|
||||
void WifiDevice::onConnected()
|
||||
{
|
||||
_isReconnecting = false;
|
||||
_wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled));
|
||||
}
|
||||
|
||||
void WifiDevice::onDisconnected()
|
||||
{
|
||||
if(millis() > 60000)
|
||||
{
|
||||
restartEsp(RestartReason::RestartOnDisconnectWatchdog);
|
||||
}
|
||||
_disconnectTs = millis();
|
||||
if(_restartOnDisconnect && (millis() > 60000)) restartEsp(RestartReason::RestartOnDisconnectWatchdog);
|
||||
_wm.setEnableConfigPortal(false);
|
||||
reconnect();
|
||||
}
|
||||
|
||||
int8_t WifiDevice::signalStrength()
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <WiFiClient.h>
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||
#include <WiFiClientSecure.h>
|
||||
#else
|
||||
#include <NetworkClientSecure.h>
|
||||
#endif
|
||||
#include <Preferences.h>
|
||||
#include "NetworkDevice.h"
|
||||
#include "WiFiManager.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "espMqttClient.h"
|
||||
#endif
|
||||
#include "IPConfiguration.h"
|
||||
|
||||
class WifiDevice : public NetworkDevice
|
||||
@@ -31,15 +37,20 @@ private:
|
||||
static void clearRtcInitVar(WiFiManager*);
|
||||
|
||||
void onDisconnected();
|
||||
void onConnected();
|
||||
|
||||
WiFiManager _wm;
|
||||
Preferences* _preferences = nullptr;
|
||||
|
||||
bool _restartOnDisconnect = false;
|
||||
bool _startAp = false;
|
||||
bool _isReconnecting = false;
|
||||
char* _path;
|
||||
unsigned long _disconnectTs = 0;
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
char _ca[TLS_CA_MAX_SIZE] = {0};
|
||||
char _cert[TLS_CERT_MAX_SIZE] = {0};
|
||||
char _key[TLS_KEY_MAX_SIZE] = {0};
|
||||
#endif
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user