Merge branch 'master' into check-keypad-codes
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
#define NUKI_HUB_VERSION "9.02"
|
||||
#define NUKI_HUB_BUILD "unknownbuildnr"
|
||||
#define NUKI_HUB_DATE "2024-10-28"
|
||||
#define NUKI_HUB_DATE "2024-11-01"
|
||||
|
||||
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
|
||||
#define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json"
|
||||
@@ -110,11 +110,9 @@
|
||||
#define MQTT_QOS_LEVEL 1
|
||||
#define MQTT_CLEAN_SESSIONS false
|
||||
#define MQTT_KEEP_ALIVE 60
|
||||
#define MQTT_STACK_SIZE 12288
|
||||
#define GPIO_DEBOUNCE_TIME 200
|
||||
#define CHAR_BUFFER_SIZE 4096
|
||||
#define NUKI_TASK_SIZE 8192
|
||||
#define PD_TASK_SIZE 1024
|
||||
#define MAX_AUTHLOG 5
|
||||
#define MAX_KEYPAD 10
|
||||
#define MAX_TIMECONTROL 10
|
||||
@@ -122,3 +120,4 @@
|
||||
#endif
|
||||
|
||||
#define NETWORK_TASK_SIZE 12288
|
||||
#define HTTPD_TASK_SIZE 8192
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
class MqttReceiver
|
||||
{
|
||||
public:
|
||||
virtual void onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) = 0;
|
||||
virtual void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) = 0;
|
||||
};
|
||||
@@ -1,28 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#define mqtt_topic_lock_action "/lock/action"
|
||||
#define mqtt_topic_lock_status_updated "/lock/statusUpdated"
|
||||
#define mqtt_topic_lock_state "/lock/state"
|
||||
#define mqtt_topic_lock_ha_state "/lock/hastate"
|
||||
#define mqtt_topic_lock_json "/lock/json"
|
||||
#define mqtt_topic_lock_binary_state "/lock/binaryState"
|
||||
#define mqtt_topic_lock_continuous_mode "/lock/continuousMode"
|
||||
#define mqtt_topic_lock_ring "/lock/ring"
|
||||
#define mqtt_topic_lock_binary_ring "/lock/binaryRing"
|
||||
#define mqtt_topic_lock_trigger "/lock/trigger"
|
||||
#define mqtt_topic_lock_last_lock_action "/lock/lastLockAction"
|
||||
#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_auth_id "/lock/authorizationId"
|
||||
#define mqtt_topic_lock_auth_name "/lock/authorizationName"
|
||||
#define mqtt_topic_lock_completionStatus "/lock/completionStatus"
|
||||
#define mqtt_topic_lock_action_command_result "/lock/commandResult"
|
||||
#define mqtt_topic_lock_door_sensor_state "/lock/doorSensorState"
|
||||
#define mqtt_topic_lock_rssi "/lock/rssi"
|
||||
#define mqtt_topic_lock_address "/lock/address"
|
||||
#define mqtt_topic_lock_retry "/lock/retry"
|
||||
#define mqtt_topic_lock_action "/action"
|
||||
#define mqtt_topic_lock_status_updated "/statusUpdated"
|
||||
#define mqtt_topic_lock_state "/state"
|
||||
#define mqtt_topic_lock_ha_state "/hastate"
|
||||
#define mqtt_topic_lock_json "/json"
|
||||
#define mqtt_topic_lock_binary_state "/binaryState"
|
||||
#define mqtt_topic_lock_continuous_mode "/continuousMode"
|
||||
#define mqtt_topic_lock_ring "/ring"
|
||||
#define mqtt_topic_lock_binary_ring "/binaryRing"
|
||||
#define mqtt_topic_lock_trigger "/trigger"
|
||||
#define mqtt_topic_lock_last_lock_action "/lastLockAction"
|
||||
#define mqtt_topic_lock_log "/log"
|
||||
#define mqtt_topic_lock_log_latest "/shortLog"
|
||||
#define mqtt_topic_lock_log_rolling "/rollingLog"
|
||||
#define mqtt_topic_lock_log_rolling_last "/lastRollingLog"
|
||||
#define mqtt_topic_lock_auth_id "/authorizationId"
|
||||
#define mqtt_topic_lock_auth_name "/authorizationName"
|
||||
#define mqtt_topic_lock_completionStatus "/completionStatus"
|
||||
#define mqtt_topic_lock_action_command_result "/commandResult"
|
||||
#define mqtt_topic_lock_door_sensor_state "/doorSensorState"
|
||||
#define mqtt_topic_lock_rssi "/rssi"
|
||||
#define mqtt_topic_lock_address "/address"
|
||||
#define mqtt_topic_lock_retry "/retry"
|
||||
|
||||
#define mqtt_topic_official_lock_action "/lockAction"
|
||||
//#define mqtt_topic_official_mode "/mode"
|
||||
@@ -49,11 +49,11 @@
|
||||
#define mqtt_topic_config_single_lock "/configuration/singleLock"
|
||||
#define mqtt_topic_config_sound_level "/configuration/soundLevel"
|
||||
|
||||
#define mqtt_topic_query_config "/lock/query/config"
|
||||
#define mqtt_topic_query_lockstate "/lock/query/lockstate"
|
||||
#define mqtt_topic_query_keypad "/lock/query/keypad"
|
||||
#define mqtt_topic_query_battery "/lock/query/battery"
|
||||
#define mqtt_topic_query_lockstate_command_result "/lock/query/lockstateCommandResult"
|
||||
#define mqtt_topic_query_config "/query/config"
|
||||
#define mqtt_topic_query_lockstate "/query/lockstate"
|
||||
#define mqtt_topic_query_keypad "/query/keypad"
|
||||
#define mqtt_topic_query_battery "/query/battery"
|
||||
#define mqtt_topic_query_lockstate_command_result "/query/lockstateCommandResult"
|
||||
|
||||
#define mqtt_topic_battery_level "/battery/level"
|
||||
#define mqtt_topic_battery_critical "/battery/critical"
|
||||
@@ -110,9 +110,7 @@
|
||||
#define mqtt_topic_restart_reason_esp "/maintenance/restartReasonNukiEsp"
|
||||
#define mqtt_topic_mqtt_connection_state "/maintenance/mqttConnectionState"
|
||||
#define mqtt_topic_network_device "/maintenance/networkDevice"
|
||||
#define mqtt_hybrid_state "/maintenance/hybridConnected"
|
||||
|
||||
#define mqtt_topic_presence "/presence/devices"
|
||||
#define mqtt_hybrid_state "/hybridConnected"
|
||||
|
||||
#define mqtt_topic_gpio_prefix "/gpio"
|
||||
#define mqtt_topic_gpio_pin "/pin_"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,6 @@
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "MqttReceiver.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "MqttTopics.h"
|
||||
#include "Gpio.h"
|
||||
#include <ArduinoJson.h>
|
||||
@@ -28,6 +27,7 @@ public:
|
||||
void scan(bool passive = false, bool async = true);
|
||||
bool isApOpen();
|
||||
bool isConnected();
|
||||
bool wifiConnected();
|
||||
void clearWifiFallback();
|
||||
|
||||
const String networkDeviceName() const;
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
void publishULong(const char* prefix, const char* topic, const unsigned long value, bool retain);
|
||||
void publishLongLong(const char* prefix, const char* topic, int64_t value, bool retain);
|
||||
void publishBool(const char* prefix, const char* topic, const bool value, bool retain);
|
||||
bool publishString(const char* prefix, const char* topic, const char* value, bool retain);
|
||||
void publishString(const char* prefix, const char* topic, const char* value, bool retain);
|
||||
|
||||
void 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 publishHASSConfigAdditionalLockEntities(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
||||
@@ -91,7 +91,6 @@ public:
|
||||
bool mqttRecentlyConnected();
|
||||
bool pathEquals(const char* prefix, const char* path, const char* referencePath);
|
||||
uint16_t subscribe(const char* topic, uint8_t qos);
|
||||
|
||||
void addReconnectedCallback(std::function<void()> reconnectedCallback);
|
||||
#endif
|
||||
private:
|
||||
@@ -106,8 +105,8 @@ private:
|
||||
IPConfiguration* _ipConfiguration = nullptr;
|
||||
String _hostname;
|
||||
char _hostnameArr[101] = {0};
|
||||
char _nukiHubPath[181] = {0};
|
||||
NetworkDevice* _device = nullptr;
|
||||
|
||||
std::function<void()> _keepAliveCallback = nullptr;
|
||||
std::vector<std::function<void()>> _reconnectedCallbacks;
|
||||
|
||||
@@ -118,10 +117,11 @@ private:
|
||||
bool _offEnabled = false;
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
static void mqtt_event_handler_cb(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
||||
void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
||||
void onMqttDataReceived(char* topic, int topic_len, char* data, int data_len);
|
||||
void parseGpioTopics(char* topic, int topic_len, char* data, int data_len);
|
||||
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 onMqttConnect(const bool& sessionPresent);
|
||||
void onMqttDisconnect(const espMqttClientTypes::DisconnectReason& reason);
|
||||
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);
|
||||
|
||||
String createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
|
||||
@@ -144,23 +144,17 @@ private:
|
||||
char _mqttConnectionStateTopic[211] = {0};
|
||||
String _lockPath;
|
||||
String _discoveryTopic;
|
||||
String _brokerAddr;
|
||||
|
||||
Gpio* _gpio;
|
||||
|
||||
esp_mqtt_client_config_t _mqtt_cfg = { 0 };
|
||||
bool _mqttClientInitiated = false;
|
||||
|
||||
int _mqttConnectionState = 0;
|
||||
bool _mqttConnected = false;
|
||||
int _mqttConnectCounter = 0;
|
||||
int _mqttPort = 1883;
|
||||
long _mqttConnectedTs = -1;
|
||||
bool _connectReplyReceived = false;
|
||||
bool _firstDisconnected = true;
|
||||
|
||||
esp_mqtt_client_handle_t _mqttClient;
|
||||
char _ca[TLS_CA_MAX_SIZE] = {0};
|
||||
char _cert[TLS_CERT_MAX_SIZE] = {0};
|
||||
char _key[TLS_KEY_MAX_SIZE] = {0};
|
||||
|
||||
int64_t _nextReconnect = 0;
|
||||
char _mqttBrokerAddr[101] = {0};
|
||||
char _mqttUser[31] = {0};
|
||||
@@ -170,6 +164,7 @@ private:
|
||||
int _networkTimeout = 0;
|
||||
std::vector<MqttReceiver*> _mqttReceivers;
|
||||
bool _restartOnDisconnect = false;
|
||||
bool _disableNetworkIfNotConnected = false;
|
||||
bool _checkUpdates = false;
|
||||
bool _firstConnect = true;
|
||||
bool _publishDebugInfo = false;
|
||||
@@ -177,6 +172,7 @@ private:
|
||||
std::vector<String> _subscribedTopics;
|
||||
std::map<String, String> _initTopics;
|
||||
int64_t _lastConnectedTs = 0;
|
||||
int64_t _lastMQTTConnectionAttemptTs = 0;
|
||||
int64_t _lastMaintenanceTs = 0;
|
||||
int64_t _lastUpdateCheckTs = 0;
|
||||
int64_t _lastRssiTs = 0;
|
||||
|
||||
@@ -37,18 +37,12 @@ NukiNetworkLock::~NukiNetworkLock()
|
||||
void NukiNetworkLock::initialize()
|
||||
{
|
||||
String mqttPath = _preferences->getString(preference_mqtt_lock_path, "");
|
||||
if(mqttPath.length() > 0)
|
||||
mqttPath.concat("/lock");
|
||||
|
||||
size_t len = mqttPath.length();
|
||||
for(int i=0; i < len; i++)
|
||||
{
|
||||
size_t len = mqttPath.length();
|
||||
for(int i=0; i < len; i++)
|
||||
{
|
||||
_mqttPath[i] = mqttPath.charAt(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(_mqttPath, "nuki");
|
||||
_preferences->putString(preference_mqtt_lock_path, _mqttPath);
|
||||
_mqttPath[i] = mqttPath.charAt(i);
|
||||
}
|
||||
|
||||
_haEnabled = _preferences->getString(preference_mqtt_hass_discovery, "") != "";
|
||||
@@ -58,18 +52,6 @@ void NukiNetworkLock::initialize()
|
||||
_network->subscribe(_mqttPath, mqtt_topic_lock_action);
|
||||
_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_update);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_update, "0");
|
||||
}
|
||||
|
||||
_network->subscribe(_mqttPath, mqtt_topic_webserver_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_webserver_action, "--");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_webserver_state, (_preferences->getBool(preference_webserver_enabled, true) || forceEnableWebServer ? "1" : "0"));
|
||||
|
||||
_network->initTopic(_mqttPath, mqtt_topic_query_config, "0");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_query_lockstate, "0");
|
||||
@@ -100,7 +82,6 @@ void NukiNetworkLock::initialize()
|
||||
_network->removeTopic(_mqttPath, mqtt_topic_battery_max_turn_current);
|
||||
_network->removeTopic(_mqttPath, mqtt_topic_battery_lock_distance);
|
||||
_network->removeTopic(_mqttPath, mqtt_topic_battery_keypad_critical);
|
||||
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
|
||||
}
|
||||
|
||||
if(!_preferences->getBool(preference_conf_info_enabled, true))
|
||||
@@ -119,34 +100,34 @@ void NukiNetworkLock::initialize()
|
||||
{
|
||||
if(!_disableNonJSON)
|
||||
{
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_name);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_code);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_enabled);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_action, "--");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_id, "0");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_name, "--");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_code, "000000");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_enabled, "1");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_name);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_code);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_enabled);
|
||||
}
|
||||
|
||||
_network->subscribe(_mqttPath, mqtt_topic_query_keypad);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_json_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_query_keypad, "0");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_json_action, "--");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_query_keypad);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_json_action);
|
||||
}
|
||||
|
||||
if(_preferences->getBool(preference_timecontrol_control_enabled))
|
||||
{
|
||||
_network->subscribe(_mqttPath, mqtt_topic_timecontrol_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_timecontrol_action);
|
||||
}
|
||||
|
||||
if(_preferences->getBool(preference_auth_control_enabled))
|
||||
{
|
||||
_network->subscribe(_mqttPath, mqtt_topic_auth_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_auth_action, "--");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_auth_action);
|
||||
}
|
||||
|
||||
if(_nukiOfficial->getOffEnabled())
|
||||
@@ -163,7 +144,7 @@ void NukiNetworkLock::initialize()
|
||||
{
|
||||
_network->subscribe(_mqttPath, mqtt_topic_lock_log_rolling_last);
|
||||
}
|
||||
|
||||
|
||||
_network->addReconnectedCallback([&]()
|
||||
{
|
||||
_reconnected = true;
|
||||
@@ -178,8 +159,10 @@ void NukiNetworkLock::update()
|
||||
}
|
||||
}
|
||||
|
||||
void NukiNetworkLock::onMqttDataReceived(char* topic, int topic_len, char* data, int data_len)
|
||||
void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const unsigned int length)
|
||||
{
|
||||
char* data = (char*)payload;
|
||||
|
||||
if(_network->mqttRecentlyConnected() && _network->pathEquals(_mqttPath, mqtt_topic_lock_action, topic))
|
||||
{
|
||||
Log->println("MQTT recently connected, ignoring lock action.");
|
||||
@@ -445,22 +428,22 @@ void NukiNetworkLock::onMqttDataReceived(char* topic, int topic_len, char* data,
|
||||
if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(data, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_CONFIG;
|
||||
publishString(mqtt_topic_query_config, "0", true);
|
||||
publishInt(mqtt_topic_query_config, 0, true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_lockstate) && strcmp(data, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_LOCKSTATE;
|
||||
publishString(mqtt_topic_query_lockstate, "0", true);
|
||||
publishInt(mqtt_topic_query_lockstate, 0, true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_keypad) && strcmp(data, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_KEYPAD;
|
||||
publishString(mqtt_topic_query_keypad, "0", true);
|
||||
publishInt(mqtt_topic_query_keypad, 0, true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_battery) && strcmp(data, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_BATTERY;
|
||||
publishString(mqtt_topic_query_battery, "0", true);
|
||||
publishInt(mqtt_topic_query_battery, 0, true);
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_config_action))
|
||||
@@ -1053,6 +1036,7 @@ void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entr
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/lock");
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : entries)
|
||||
@@ -1296,6 +1280,7 @@ void NukiNetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEn
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/lock");
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : timeControlEntries)
|
||||
@@ -1428,6 +1413,7 @@ void NukiNetworkLock::publishAuth(const std::list<NukiLock::AuthorizationEntry>&
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/lock");
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : authEntries)
|
||||
@@ -1680,7 +1666,9 @@ bool NukiNetworkLock::comparePrefixedPath(const char *fullPath, const char *subP
|
||||
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);
|
||||
String availabilityTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
availabilityTopic.concat("/maintenance/mqttConnectionState");
|
||||
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, softwareVersion, hardwareVersion, availabilityTopic.c_str(), hasKeypad, lockAction, unlockAction, openAction);
|
||||
_network->publishHASSConfigAdditionalLockEntities(deviceType, baseTopic, name, uidString);
|
||||
|
||||
if(hasDoorSensor)
|
||||
@@ -1719,57 +1707,63 @@ void NukiNetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic,
|
||||
|
||||
void NukiNetworkLock::removeHASSConfig(char *uidString)
|
||||
{
|
||||
return _network->removeHASSConfig(uidString);
|
||||
_network->removeHASSConfig(uidString);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::publishOffAction(const int value)
|
||||
{
|
||||
return _network->publishInt(_nukiOfficial->getMqttPath(), mqtt_topic_official_lock_action, value, false);
|
||||
_network->publishInt(_nukiOfficial->getMqttPath(), mqtt_topic_official_lock_action, value, false);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::publishFloat(const char *topic, const float value, bool retain, const uint8_t precision)
|
||||
{
|
||||
return _nukiPublisher->publishFloat(topic, value, retain, precision);
|
||||
_nukiPublisher->publishFloat(topic, value, retain, precision);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::publishInt(const char *topic, const int value, bool retain)
|
||||
{
|
||||
return _nukiPublisher->publishInt(topic, value, retain);
|
||||
_nukiPublisher->publishInt(topic, value, retain);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::publishUInt(const char *topic, const unsigned int value, bool retain)
|
||||
{
|
||||
return _nukiPublisher->publishUInt(topic, value, retain);
|
||||
_nukiPublisher->publishUInt(topic, value, retain);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::publishBool(const char *topic, const bool value, bool retain)
|
||||
{
|
||||
return _nukiPublisher->publishBool(topic, value, retain);
|
||||
_nukiPublisher->publishBool(topic, value, retain);
|
||||
}
|
||||
|
||||
bool NukiNetworkLock::publishString(const char *topic, const String &value, bool retain)
|
||||
void NukiNetworkLock::publishString(const char *topic, const String &value, bool retain)
|
||||
{
|
||||
return _nukiPublisher->publishString(topic, value, retain);
|
||||
char str[value.length() + 1];
|
||||
memset(str, 0, sizeof(str));
|
||||
memcpy(str, value.begin(), value.length());
|
||||
publishString(topic, str, retain);
|
||||
}
|
||||
|
||||
bool NukiNetworkLock::publishString(const char *topic, const std::string &value, bool retain)
|
||||
void NukiNetworkLock::publishString(const char *topic, const std::string &value, bool retain)
|
||||
{
|
||||
return _nukiPublisher->publishString(topic, value, retain);
|
||||
char str[value.size() + 1];
|
||||
memset(str, 0, sizeof(str));
|
||||
memcpy(str, value.data(), value.length());
|
||||
publishString(topic, str, retain);
|
||||
}
|
||||
|
||||
bool NukiNetworkLock::publishString(const char *topic, const char *value, bool retain)
|
||||
void NukiNetworkLock::publishString(const char *topic, const char *value, bool retain)
|
||||
{
|
||||
return _nukiPublisher->publishString(topic, value, retain);
|
||||
_nukiPublisher->publishString(topic, value, retain);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::publishULong(const char *topic, const unsigned long value, bool retain)
|
||||
{
|
||||
return _nukiPublisher->publishULong(topic, value, retain);
|
||||
_nukiPublisher->publishULong(topic, value, retain);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::publishLongLong(const char *topic, int64_t value, bool retain)
|
||||
{
|
||||
return _nukiPublisher->publishLongLong(topic, value, retain);
|
||||
_nukiPublisher->publishLongLong(topic, value, retain);
|
||||
}
|
||||
|
||||
String NukiNetworkLock::concat(String a, String b)
|
||||
@@ -1786,6 +1780,11 @@ bool NukiNetworkLock::reconnected()
|
||||
return r;
|
||||
}
|
||||
|
||||
int NukiNetworkLock::mqttConnectionState()
|
||||
{
|
||||
return _network->mqttConnectionState();
|
||||
}
|
||||
|
||||
uint8_t NukiNetworkLock::queryCommands()
|
||||
{
|
||||
uint8_t qc = _queryCommands;
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
void setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char* value));
|
||||
void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value));
|
||||
void setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char* value));
|
||||
void onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) override;
|
||||
void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override;
|
||||
|
||||
void publishFloat(const char* topic, const float value, bool retain, const uint8_t precision = 2);
|
||||
void publishInt(const char* topic, const int value, bool retain);
|
||||
@@ -65,12 +65,12 @@ public:
|
||||
void publishULong(const char* topic, const unsigned long value, bool retain);
|
||||
void publishLongLong(const char* topic, int64_t value, bool retain);
|
||||
void publishBool(const char* topic, const bool value, bool retain);
|
||||
bool publishString(const char* topic, const String& value, bool retain);
|
||||
bool publishString(const char* topic, const std::string& value, bool retain);
|
||||
bool publishString(const char* topic, const char* value, bool retain);
|
||||
void publishString(const char* topic, const String& value, bool retain);
|
||||
void publishString(const char* topic, const std::string& value, bool retain);
|
||||
void publishString(const char* topic, const char* value, bool retain);
|
||||
|
||||
const uint32_t getAuthId() const;
|
||||
|
||||
int mqttConnectionState();
|
||||
bool reconnected();
|
||||
uint8_t queryCommands();
|
||||
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
bool _firstTunerStatePublish = true;
|
||||
int64_t _lastMaintenanceTs = 0;
|
||||
bool _haEnabled = false;
|
||||
bool _reconnected = false;
|
||||
bool _reconnected = false; //SETBACK
|
||||
bool _disableNonJSON = false;
|
||||
|
||||
String _keypadCommandName = "";
|
||||
|
||||
@@ -22,24 +22,18 @@ NukiNetworkOpener::NukiNetworkOpener(NukiNetwork* network, Preferences* preferen
|
||||
|
||||
void NukiNetworkOpener::initialize()
|
||||
{
|
||||
String mqttPath = _preferences->getString(preference_mqtt_opener_path);
|
||||
if(mqttPath.length() > 0)
|
||||
String mqttPath = _preferences->getString(preference_mqtt_lock_path, "");
|
||||
mqttPath.concat("/opener");
|
||||
|
||||
size_t len = mqttPath.length();
|
||||
for(int i=0; i < len; i++)
|
||||
{
|
||||
size_t len = mqttPath.length();
|
||||
for(int i=0; i < len; i++)
|
||||
{
|
||||
_mqttPath[i] = mqttPath.charAt(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(_mqttPath, "nukiopener");
|
||||
_preferences->putString(preference_mqtt_opener_path, _mqttPath);
|
||||
_mqttPath[i] = mqttPath.charAt(i);
|
||||
}
|
||||
|
||||
_haEnabled = _preferences->getString(preference_mqtt_hass_discovery, "") != "";
|
||||
_disableNonJSON = _preferences->getBool(preference_disable_non_json, false);
|
||||
|
||||
|
||||
_network->initTopic(_mqttPath, mqtt_topic_lock_action, "--");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_lock_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_config_action, "--");
|
||||
@@ -52,7 +46,7 @@ void NukiNetworkOpener::initialize()
|
||||
_network->subscribe(_mqttPath, mqtt_topic_query_config);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_query_lockstate);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_query_battery);
|
||||
|
||||
|
||||
if(_disableNonJSON)
|
||||
{
|
||||
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_action);
|
||||
@@ -69,7 +63,6 @@ void NukiNetworkOpener::initialize()
|
||||
_network->removeTopic(_mqttPath, mqtt_topic_battery_charging);
|
||||
_network->removeTopic(_mqttPath, mqtt_topic_battery_voltage);
|
||||
_network->removeTopic(_mqttPath, mqtt_topic_battery_keypad_critical);
|
||||
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
|
||||
}
|
||||
|
||||
if(!_preferences->getBool(preference_conf_info_enabled, true))
|
||||
@@ -88,34 +81,34 @@ void NukiNetworkOpener::initialize()
|
||||
{
|
||||
if(!_disableNonJSON)
|
||||
{
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_action, "--");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_id, "0");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_name, "--");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_code, "000000");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_enabled, "1");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_name);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_code);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_enabled);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_action, "--");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_id, "0");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_name, "--");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_code, "000000");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_command_enabled, "1");
|
||||
}
|
||||
|
||||
_network->subscribe(_mqttPath, mqtt_topic_query_keypad);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_json_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_query_keypad, "0");
|
||||
_network->initTopic(_mqttPath, mqtt_topic_keypad_json_action, "--");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_query_keypad);
|
||||
_network->subscribe(_mqttPath, mqtt_topic_keypad_json_action);
|
||||
}
|
||||
|
||||
if(_preferences->getBool(preference_timecontrol_control_enabled, false))
|
||||
{
|
||||
_network->subscribe(_mqttPath, mqtt_topic_timecontrol_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_timecontrol_action);
|
||||
}
|
||||
|
||||
if(_preferences->getBool(preference_auth_control_enabled))
|
||||
{
|
||||
_network->subscribe(_mqttPath, mqtt_topic_auth_action);
|
||||
_network->initTopic(_mqttPath, mqtt_topic_auth_action, "--");
|
||||
_network->subscribe(_mqttPath, mqtt_topic_auth_action);
|
||||
}
|
||||
|
||||
if(_preferences->getBool(preference_publish_authdata, false))
|
||||
@@ -124,9 +117,9 @@ void NukiNetworkOpener::initialize()
|
||||
}
|
||||
|
||||
_network->addReconnectedCallback([&]()
|
||||
{
|
||||
_reconnected = true;
|
||||
});
|
||||
{
|
||||
_reconnected = true;
|
||||
});
|
||||
}
|
||||
|
||||
void NukiNetworkOpener::update()
|
||||
@@ -138,8 +131,10 @@ void NukiNetworkOpener::update()
|
||||
}
|
||||
}
|
||||
|
||||
void NukiNetworkOpener::onMqttDataReceived(char* topic, int topic_len, char* data, int data_len)
|
||||
void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const unsigned int length)
|
||||
{
|
||||
char* data = (char*)payload;
|
||||
|
||||
if(_network->mqttRecentlyConnected() && _network->pathEquals(_mqttPath, mqtt_topic_lock_action, topic))
|
||||
{
|
||||
Log->println("MQTT recently connected, ignoring opener action.");
|
||||
@@ -246,22 +241,22 @@ void NukiNetworkOpener::onMqttDataReceived(char* topic, int topic_len, char* dat
|
||||
if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(data, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_CONFIG;
|
||||
publishString(mqtt_topic_query_config, "0", true);
|
||||
publishInt(mqtt_topic_query_config, 0, true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_lockstate) && strcmp(data, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_LOCKSTATE;
|
||||
publishString(mqtt_topic_query_lockstate, "0", true);
|
||||
publishInt(mqtt_topic_query_lockstate, 0, true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_keypad) && strcmp(data, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_KEYPAD;
|
||||
publishString(mqtt_topic_query_keypad, "0", true);
|
||||
publishInt(mqtt_topic_query_keypad, 0, true);
|
||||
}
|
||||
else if(comparePrefixedPath(topic, mqtt_topic_query_battery) && strcmp(data, "1") == 0)
|
||||
{
|
||||
_queryCommands = _queryCommands | QUERY_COMMAND_BATTERY;
|
||||
publishString(mqtt_topic_query_battery, "0", true);
|
||||
publishInt(mqtt_topic_query_battery, 0, true);
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_config_action))
|
||||
@@ -849,7 +844,7 @@ void NukiNetworkOpener::publishBleAddress(const std::string &address)
|
||||
|
||||
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");
|
||||
String availabilityTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
availabilityTopic.concat("/maintenance/mqttConnectionState");
|
||||
|
||||
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, softwareVersion, hardwareVersion, availabilityTopic.c_str(), hasKeypad, lockAction, unlockAction, openAction);
|
||||
@@ -886,7 +881,8 @@ void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& en
|
||||
uint index = 0;
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_opener, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_opener_path);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/opener");
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : entries)
|
||||
@@ -1098,7 +1094,8 @@ void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeContr
|
||||
char str[50];
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_opener, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_opener_path);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/opener");
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : timeControlEntries)
|
||||
@@ -1228,7 +1225,8 @@ void NukiNetworkOpener::publishAuth(const std::list<NukiOpener::AuthorizationEnt
|
||||
char str[50];
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_opener, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_opener_path);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/opener");
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : authEntries)
|
||||
@@ -1561,6 +1559,11 @@ bool NukiNetworkOpener::reconnected()
|
||||
return r;
|
||||
}
|
||||
|
||||
int NukiNetworkOpener::mqttConnectionState()
|
||||
{
|
||||
return _network->mqttConnectionState();
|
||||
}
|
||||
|
||||
uint8_t NukiNetworkOpener::queryCommands()
|
||||
{
|
||||
uint8_t qc = _queryCommands;
|
||||
|
||||
@@ -48,9 +48,10 @@ public:
|
||||
void setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char* value));
|
||||
void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value));
|
||||
void setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char* value));
|
||||
void onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) override;
|
||||
void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override;
|
||||
|
||||
bool reconnected();
|
||||
int mqttConnectionState();
|
||||
bool reconnected(); //SETBACK
|
||||
uint8_t queryCommands();
|
||||
char _nukiName[33];
|
||||
|
||||
@@ -87,7 +88,7 @@ private:
|
||||
bool _isConnected = false;
|
||||
bool _firstTunerStatePublish = true;
|
||||
bool _haEnabled = false;
|
||||
bool _reconnected = false;
|
||||
bool _reconnected = false; //SETBACK
|
||||
bool _disableNonJSON = false;
|
||||
|
||||
String _keypadCommandName = "";
|
||||
|
||||
@@ -69,7 +69,7 @@ private:
|
||||
uint8_t offTrigger = 0;
|
||||
uint32_t offAuthId = 0;
|
||||
uint32_t offCodeId = 0;
|
||||
// uint8_t offContext = 0;
|
||||
//uint8_t offContext = 0;
|
||||
bool offEnabled = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -114,6 +114,8 @@ void NukiOpenerWrapper::readSettings()
|
||||
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
|
||||
_disableNonJSON = _preferences->getBool(preference_disable_non_json, false);
|
||||
_checkKeypadCodes = _preferences->getBool(preference_keypad_check_code_enabled, false);
|
||||
_pairedAsApp = _preferences->getBool(preference_register_opener_as_app, false);
|
||||
|
||||
_preferences->getBytes(preference_conf_opener_basic_acl, &_basicOpenerConfigAclPrefs, sizeof(_basicOpenerConfigAclPrefs));
|
||||
_preferences->getBytes(preference_conf_opener_advanced_acl, &_advancedOpenerConfigAclPrefs, sizeof(_advancedOpenerConfigAclPrefs));
|
||||
|
||||
@@ -216,67 +218,65 @@ void NukiOpenerWrapper::update()
|
||||
|
||||
_nukiOpener.updateConnectionState();
|
||||
|
||||
if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
||||
if(_network->mqttConnectionState() == 2)
|
||||
{
|
||||
_statusUpdated = false;
|
||||
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
||||
updateKeyTurnerState();
|
||||
_network->publishStatusUpdated(_statusUpdated);
|
||||
}
|
||||
if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs || (queryCommands & QUERY_COMMAND_BATTERY) > 0)
|
||||
{
|
||||
_nextBatteryReportTs = ts + _intervalBattery * 1000;
|
||||
updateBatteryState();
|
||||
}
|
||||
if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs || (queryCommands & QUERY_COMMAND_CONFIG) > 0)
|
||||
{
|
||||
_nextConfigUpdateTs = ts + _intervalConfig * 1000;
|
||||
updateConfig();
|
||||
if(_hassEnabled && !_hassSetupCompleted)
|
||||
if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
||||
{
|
||||
_statusUpdated = false;
|
||||
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
||||
updateKeyTurnerState();
|
||||
_network->publishStatusUpdated(_statusUpdated);
|
||||
}
|
||||
if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs || (queryCommands & QUERY_COMMAND_BATTERY) > 0)
|
||||
{
|
||||
_nextBatteryReportTs = ts + _intervalBattery * 1000;
|
||||
updateBatteryState();
|
||||
}
|
||||
if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs || (queryCommands & QUERY_COMMAND_CONFIG) > 0)
|
||||
{
|
||||
_nextConfigUpdateTs = ts + _intervalConfig * 1000;
|
||||
updateConfig();
|
||||
}
|
||||
if(_waitAuthLogUpdateTs != 0 && ts > _waitAuthLogUpdateTs)
|
||||
{
|
||||
_waitAuthLogUpdateTs = 0;
|
||||
updateAuthData(true);
|
||||
}
|
||||
if(_waitKeypadUpdateTs != 0 && ts > _waitKeypadUpdateTs)
|
||||
{
|
||||
_waitKeypadUpdateTs = 0;
|
||||
updateKeypad(true);
|
||||
}
|
||||
if(_waitTimeControlUpdateTs != 0 && ts > _waitTimeControlUpdateTs)
|
||||
{
|
||||
_waitTimeControlUpdateTs = 0;
|
||||
updateTimeControl(true);
|
||||
}
|
||||
if(_waitAuthUpdateTs != 0 && ts > _waitAuthUpdateTs)
|
||||
{
|
||||
_waitAuthUpdateTs = 0;
|
||||
updateAuth(true);
|
||||
}
|
||||
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && !_hassSetupCompleted)
|
||||
{
|
||||
setupHASS();
|
||||
}
|
||||
}
|
||||
if(_waitAuthLogUpdateTs != 0 && ts > _waitAuthLogUpdateTs)
|
||||
{
|
||||
_waitAuthLogUpdateTs = 0;
|
||||
updateAuthData(true);
|
||||
}
|
||||
if(_waitKeypadUpdateTs != 0 && ts > _waitKeypadUpdateTs)
|
||||
{
|
||||
_waitKeypadUpdateTs = 0;
|
||||
updateKeypad(true);
|
||||
}
|
||||
if(_waitTimeControlUpdateTs != 0 && ts > _waitTimeControlUpdateTs)
|
||||
{
|
||||
_waitTimeControlUpdateTs = 0;
|
||||
updateTimeControl(true);
|
||||
}
|
||||
if(_waitAuthUpdateTs != 0 && ts > _waitAuthUpdateTs)
|
||||
{
|
||||
_waitAuthUpdateTs = 0;
|
||||
updateAuth(true);
|
||||
}
|
||||
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && _network->reconnected())
|
||||
{
|
||||
setupHASS();
|
||||
}
|
||||
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
|
||||
{
|
||||
_nextRssiTs = ts + _rssiPublishInterval;
|
||||
|
||||
int rssi = _nukiOpener.getRssi();
|
||||
if(rssi != _lastRssi)
|
||||
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
|
||||
{
|
||||
_network->publishRssi(rssi);
|
||||
_lastRssi = rssi;
|
||||
}
|
||||
}
|
||||
_nextRssiTs = ts + _rssiPublishInterval;
|
||||
|
||||
if(_hasKeypad && _keypadEnabled && (_nextKeypadUpdateTs == 0 || ts > _nextKeypadUpdateTs || (queryCommands & QUERY_COMMAND_KEYPAD) > 0))
|
||||
{
|
||||
_nextKeypadUpdateTs = ts + _intervalKeypad * 1000;
|
||||
updateKeypad(false);
|
||||
int rssi = _nukiOpener.getRssi();
|
||||
if(rssi != _lastRssi)
|
||||
{
|
||||
_network->publishRssi(rssi);
|
||||
_lastRssi = rssi;
|
||||
}
|
||||
}
|
||||
if(_hasKeypad && _keypadEnabled && (_nextKeypadUpdateTs == 0 || ts > _nextKeypadUpdateTs || (queryCommands & QUERY_COMMAND_KEYPAD) > 0))
|
||||
{
|
||||
_nextKeypadUpdateTs = ts + _intervalKeypad * 1000;
|
||||
updateKeypad(false);
|
||||
}
|
||||
}
|
||||
|
||||
if(_checkKeypadCodes && _invalidCount > 0 && ts - 120000 < _lastCodeCheck)
|
||||
@@ -540,7 +540,7 @@ void NukiOpenerWrapper::updateConfig()
|
||||
|
||||
if(_preferences->getUInt(preference_nuki_id_opener, 0) == _nukiConfig.nukiId)
|
||||
{
|
||||
_hasKeypad = _nukiConfig.hasKeypad > 0 || _nukiConfig.hasKeypadV2 > 0;
|
||||
_hasKeypad = _nukiConfig.hasKeypad == 1 || _nukiConfig.hasKeypadV2 == 1;
|
||||
_firmwareVersion = std::to_string(_nukiConfig.firmwareVersion[0]) + "." + std::to_string(_nukiConfig.firmwareVersion[1]) + "." + std::to_string(_nukiConfig.firmwareVersion[2]);
|
||||
_hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]);
|
||||
if(_preferences->getBool(preference_conf_info_enabled, true))
|
||||
@@ -889,6 +889,12 @@ void NukiOpenerWrapper::updateTimeControl(bool retrieved)
|
||||
|
||||
void NukiOpenerWrapper::updateAuth(bool retrieved)
|
||||
{
|
||||
if(!isPinValid())
|
||||
{
|
||||
Log->println(F("No valid Nuki Lock PIN set"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!_preferences->getBool(preference_auth_info_enabled))
|
||||
{
|
||||
return;
|
||||
@@ -3870,7 +3876,7 @@ BleScanner::Scanner *NukiOpenerWrapper::bleScanner()
|
||||
|
||||
void NukiOpenerWrapper::notify(Nuki::EventType eventType)
|
||||
{
|
||||
if(eventType == Nuki::EventType::KeyTurnerStatusUpdated)
|
||||
if(!_pairedAsApp && eventType == Nuki::EventType::KeyTurnerStatusUpdated && !_statusUpdated)
|
||||
{
|
||||
Log->println("KeyTurnerStatusUpdated");
|
||||
_statusUpdated = true;
|
||||
@@ -3946,7 +3952,8 @@ void NukiOpenerWrapper::setupHASS()
|
||||
return;
|
||||
}
|
||||
|
||||
String baseTopic = _preferences->getString(preference_mqtt_opener_path);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/opener");
|
||||
char uidString[20];
|
||||
itoa(_nukiConfig.nukiId, uidString, 16);
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ private:
|
||||
bool _clearAuthData = false;
|
||||
bool _disableNonJSON = false;
|
||||
bool _checkKeypadCodes = false;
|
||||
bool _pairedAsApp = false;
|
||||
int _nrOfRetries = 0;
|
||||
int _retryDelay = 0;
|
||||
int _retryConfigCount = 0;
|
||||
|
||||
@@ -27,33 +27,27 @@ void NukiPublisher::publishBool(const char *topic, const bool value, bool retain
|
||||
_network->publishBool(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
bool NukiPublisher::publishString(const char *topic, const String &value, bool retain)
|
||||
void NukiPublisher::publishString(const char *topic, const String &value, bool retain)
|
||||
{
|
||||
char str[value.length() + 1];
|
||||
memset(str, 0, sizeof(str));
|
||||
memcpy(str, value.begin(), value.length());
|
||||
return publishString(topic, str, retain);
|
||||
publishString(topic, value.c_str(), retain);
|
||||
}
|
||||
|
||||
bool NukiPublisher::publishString(const char *topic, const std::string &value, bool retain)
|
||||
void NukiPublisher::publishString(const char *topic, const std::string &value, bool retain)
|
||||
{
|
||||
char str[value.size() + 1];
|
||||
memset(str, 0, sizeof(str));
|
||||
memcpy(str, value.data(), value.length());
|
||||
return publishString(topic, str, retain);
|
||||
publishString(topic, value.c_str(), retain);
|
||||
}
|
||||
|
||||
bool NukiPublisher::publishString(const char *topic, const char *value, bool retain)
|
||||
void NukiPublisher::publishString(const char *topic, const char *value, bool retain)
|
||||
{
|
||||
return _network->publishString(_mqttPath, topic, value, retain);
|
||||
_network->publishString(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NukiPublisher::publishULong(const char *topic, const unsigned long value, bool retain)
|
||||
{
|
||||
return _network->publishULong(_mqttPath, topic, value, retain);
|
||||
_network->publishULong(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
void NukiPublisher::publishLongLong(const char *topic, int64_t value, bool retain)
|
||||
{
|
||||
return _network->publishLongLong(_mqttPath, topic, value, retain);
|
||||
_network->publishLongLong(_mqttPath, topic, value, retain);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ public:
|
||||
void publishULong(const char* topic, const unsigned long value, bool retain);
|
||||
void publishLongLong(const char* topic, int64_t value, bool retain);
|
||||
void publishBool(const char* topic, const bool value, bool retain);
|
||||
bool publishString(const char* topic, const String& value, bool retain);
|
||||
bool publishString(const char* topic, const std::string& value, bool retain);
|
||||
bool publishString(const char* topic, const char* value, bool retain);
|
||||
void publishString(const char* topic, const String& value, bool retain);
|
||||
void publishString(const char* topic, const std::string& value, bool retain);
|
||||
void publishString(const char* topic, const char* value, bool retain);
|
||||
|
||||
private:
|
||||
NukiNetwork* _network;
|
||||
|
||||
@@ -82,6 +82,8 @@ void NukiWrapper::initialize(const bool& firstStart)
|
||||
Log->println("Failed to clear NVS Wi-Fi configuration");
|
||||
}
|
||||
#endif
|
||||
_preferences->putString(preference_mqtt_lock_path, "nukihub");
|
||||
|
||||
_preferences->putBool(preference_check_updates, true);
|
||||
_preferences->putBool(preference_opener_continuous_mode, false);
|
||||
_preferences->putBool(preference_official_hybrid_enabled, false);
|
||||
@@ -184,6 +186,8 @@ void NukiWrapper::readSettings()
|
||||
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
|
||||
_disableNonJSON = _preferences->getBool(preference_disable_non_json, false);
|
||||
_checkKeypadCodes = _preferences->getBool(preference_keypad_check_code_enabled, false);
|
||||
_pairedAsApp = _preferences->getBool(preference_register_as_app, false);
|
||||
|
||||
_preferences->getBytes(preference_conf_lock_basic_acl, &_basicLockConfigaclPrefs, sizeof(_basicLockConfigaclPrefs));
|
||||
_preferences->getBytes(preference_conf_lock_advanced_acl, &_advancedLockConfigaclPrefs, sizeof(_advancedLockConfigaclPrefs));
|
||||
|
||||
@@ -355,84 +359,83 @@ void NukiWrapper::update()
|
||||
_nextLockAction = (NukiLock::LockAction) 0xff;
|
||||
}
|
||||
}
|
||||
if(_nukiOfficial->getStatusUpdated() || _statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
||||
if(_network->mqttConnectionState() == 2)
|
||||
{
|
||||
Log->println("Updating Lock state based on status, timer or query");
|
||||
_statusUpdated = false;
|
||||
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
||||
updateKeyTurnerState();
|
||||
_network->publishStatusUpdated(_statusUpdated);
|
||||
}
|
||||
if(!_statusUpdated)
|
||||
{
|
||||
if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs || (queryCommands & QUERY_COMMAND_BATTERY) > 0)
|
||||
if(_nukiOfficial->getStatusUpdated() || _statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
||||
{
|
||||
Log->println("Updating Lock battery state based on timer or query");
|
||||
_nextBatteryReportTs = ts + _intervalBattery * 1000;
|
||||
updateBatteryState();
|
||||
Log->println("Updating Lock state based on status, timer or query");
|
||||
_statusUpdated = false;
|
||||
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
||||
updateKeyTurnerState();
|
||||
_network->publishStatusUpdated(_statusUpdated);
|
||||
}
|
||||
if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs || (queryCommands & QUERY_COMMAND_CONFIG) > 0)
|
||||
if(!_statusUpdated)
|
||||
{
|
||||
Log->println("Updating Lock config based on timer or query");
|
||||
_nextConfigUpdateTs = ts + _intervalConfig * 1000;
|
||||
updateConfig();
|
||||
if(_hassEnabled && !_hassSetupCompleted)
|
||||
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(_waitAuthLogUpdateTs != 0 && ts > _waitAuthLogUpdateTs)
|
||||
{
|
||||
_waitAuthLogUpdateTs = 0;
|
||||
updateAuthData(true);
|
||||
}
|
||||
if(_waitKeypadUpdateTs != 0 && ts > _waitKeypadUpdateTs)
|
||||
{
|
||||
_waitKeypadUpdateTs = 0;
|
||||
updateKeypad(true);
|
||||
}
|
||||
if(_waitTimeControlUpdateTs != 0 && ts > _waitTimeControlUpdateTs)
|
||||
{
|
||||
_waitTimeControlUpdateTs = 0;
|
||||
updateTimeControl(true);
|
||||
}
|
||||
if(_waitAuthUpdateTs != 0 && ts > _waitAuthUpdateTs)
|
||||
{
|
||||
_waitAuthUpdateTs = 0;
|
||||
updateAuth(true);
|
||||
}
|
||||
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && !_hassSetupCompleted)
|
||||
{
|
||||
setupHASS();
|
||||
}
|
||||
}
|
||||
if(_waitAuthLogUpdateTs != 0 && ts > _waitAuthLogUpdateTs)
|
||||
{
|
||||
_waitAuthLogUpdateTs = 0;
|
||||
updateAuthData(true);
|
||||
}
|
||||
if(_waitKeypadUpdateTs != 0 && ts > _waitKeypadUpdateTs)
|
||||
{
|
||||
_waitKeypadUpdateTs = 0;
|
||||
updateKeypad(true);
|
||||
}
|
||||
if(_waitTimeControlUpdateTs != 0 && ts > _waitTimeControlUpdateTs)
|
||||
{
|
||||
_waitTimeControlUpdateTs = 0;
|
||||
updateTimeControl(true);
|
||||
}
|
||||
if(_waitAuthUpdateTs != 0 && ts > _waitAuthUpdateTs)
|
||||
{
|
||||
_waitAuthUpdateTs = 0;
|
||||
updateAuth(true);
|
||||
}
|
||||
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && _network->reconnected())
|
||||
{
|
||||
setupHASS();
|
||||
}
|
||||
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
|
||||
{
|
||||
_nextRssiTs = ts + _rssiPublishInterval;
|
||||
|
||||
int rssi = _nukiLock.getRssi();
|
||||
if(rssi != _lastRssi)
|
||||
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
|
||||
{
|
||||
_network->publishRssi(rssi);
|
||||
_lastRssi = rssi;
|
||||
_nextRssiTs = ts + _rssiPublishInterval;
|
||||
|
||||
int rssi = _nukiLock.getRssi();
|
||||
if(rssi != _lastRssi)
|
||||
{
|
||||
_network->publishRssi(rssi);
|
||||
_lastRssi = rssi;
|
||||
}
|
||||
}
|
||||
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(_hasKeypad && _keypadEnabled && (_nextKeypadUpdateTs == 0 || ts > _nextKeypadUpdateTs || (queryCommands & QUERY_COMMAND_KEYPAD) > 0))
|
||||
if(_clearAuthData)
|
||||
{
|
||||
Log->println("Updating Lock keypad based on timer or query");
|
||||
_nextKeypadUpdateTs = ts + _intervalKeypad * 1000;
|
||||
updateKeypad(false);
|
||||
Log->println("Clearing Lock auth data");
|
||||
_network->clearAuthorizationInfo();
|
||||
_clearAuthData = false;
|
||||
}
|
||||
if(_checkKeypadCodes && _invalidCount > 0 && ts - 120000 < _lastCodeCheck)
|
||||
{
|
||||
_invalidCount--;
|
||||
}
|
||||
}
|
||||
if(_clearAuthData)
|
||||
{
|
||||
Log->println("Clearing Lock auth data");
|
||||
_network->clearAuthorizationInfo();
|
||||
_clearAuthData = false;
|
||||
}
|
||||
|
||||
memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiLock::KeyTurnerState));
|
||||
}
|
||||
@@ -625,7 +628,7 @@ void NukiWrapper::updateConfig()
|
||||
|
||||
if(_preferences->getUInt(preference_nuki_id_lock, 0) == _nukiConfig.nukiId)
|
||||
{
|
||||
_hasKeypad = _nukiConfig.hasKeypad > 0 || _nukiConfig.hasKeypadV2 > 0;
|
||||
_hasKeypad = _nukiConfig.hasKeypad == 1 || _nukiConfig.hasKeypadV2 == 1;
|
||||
_firmwareVersion = std::to_string(_nukiConfig.firmwareVersion[0]) + "." + std::to_string(_nukiConfig.firmwareVersion[1]) + "." + std::to_string(_nukiConfig.firmwareVersion[2]);
|
||||
_hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]);
|
||||
if(_preferences->getBool(preference_conf_info_enabled, true))
|
||||
@@ -968,6 +971,12 @@ void NukiWrapper::updateTimeControl(bool retrieved)
|
||||
|
||||
void NukiWrapper::updateAuth(bool retrieved)
|
||||
{
|
||||
if(!isPinValid())
|
||||
{
|
||||
Log->println(F("No valid Nuki Lock PIN set"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!_preferences->getBool(preference_auth_info_enabled))
|
||||
{
|
||||
return;
|
||||
@@ -3985,7 +3994,7 @@ void NukiWrapper::notify(Nuki::EventType eventType)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(eventType == Nuki::EventType::KeyTurnerStatusUpdated)
|
||||
if(!_pairedAsApp && eventType == Nuki::EventType::KeyTurnerStatusUpdated && !_statusUpdated)
|
||||
{
|
||||
Log->println("KeyTurnerStatusUpdated");
|
||||
_statusUpdated = true;
|
||||
@@ -4064,6 +4073,7 @@ void NukiWrapper::setupHASS()
|
||||
}
|
||||
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/lock");
|
||||
char uidString[20];
|
||||
itoa(_nukiConfig.nukiId, uidString, 16);
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ private:
|
||||
bool _hassEnabled = false;
|
||||
bool _hassSetupCompleted = false;
|
||||
bool _disableNonJSON = false;
|
||||
bool _pairedAsApp = false;
|
||||
bool _paired = false;
|
||||
bool _statusUpdated = false;
|
||||
bool _hasKeypad = false;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define preference_lock_enabled (char*)"lockena"
|
||||
#define preference_mqtt_lock_path (char*)"mqttpath"
|
||||
#define preference_opener_enabled (char*)"openerena"
|
||||
#define preference_mqtt_opener_path (char*)"mqttoppath"
|
||||
#define preference_mqtt_ca (char*)"mqttca"
|
||||
#define preference_mqtt_crt (char*)"mqttcrt"
|
||||
#define preference_mqtt_key (char*)"mqttkey"
|
||||
@@ -54,6 +53,7 @@
|
||||
#define preference_official_hybrid_enabled (char*)"offHybrid"
|
||||
#define preference_wifi_ssid (char*)"wifiSSID"
|
||||
#define preference_wifi_pass (char*)"wifiPass"
|
||||
#define preference_disable_network_not_connected (char*)"disNtwNoCon"
|
||||
|
||||
// CHANGE DOES NOT REQUIRE REBOOT TO TAKE EFFECT
|
||||
#define preference_ntw_reconfigure (char*)"ntwRECONF"
|
||||
@@ -276,7 +276,7 @@ private:
|
||||
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_opener_continuous_mode, 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,
|
||||
@@ -292,7 +292,8 @@ private:
|
||||
preference_network_custom_mdc, preference_network_custom_clk, preference_network_custom_phy, preference_network_custom_addr, preference_network_custom_irq,
|
||||
preference_network_custom_rst, preference_network_custom_cs, preference_network_custom_sck, preference_network_custom_miso, preference_network_custom_mosi,
|
||||
preference_network_custom_pwr, preference_network_custom_mdio, preference_ntw_reconfigure, preference_lock_max_auth_entry_count, preference_opener_max_auth_entry_count,
|
||||
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_auth_max_entries, preference_keypad_check_code_enabled, preference_wifi_ssid, preference_wifi_pass
|
||||
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_auth_max_entries, preference_wifi_ssid, preference_wifi_pass,
|
||||
preference_keypad_check_code_enabled, preference_disable_network_not_connected
|
||||
};
|
||||
std::vector<char*> _redact =
|
||||
{
|
||||
@@ -308,7 +309,7 @@ private:
|
||||
preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled,
|
||||
preference_official_hybrid_actions, preference_official_hybrid_retry, preference_conf_info_enabled, preference_disable_non_json, preference_update_from_mqtt,
|
||||
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_webserial_enabled,
|
||||
preference_ntw_reconfigure, preference_keypad_check_code_enabled
|
||||
preference_ntw_reconfigure, preference_keypad_check_code_enabled, preference_disable_network_not_connected
|
||||
};
|
||||
std::vector<char*> _bytePrefs =
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ enum class RestartReason
|
||||
DeviceUnpaired,
|
||||
NukiHubReset,
|
||||
ReconfigureWebServer,
|
||||
DisableNetworkIfNotConnected,
|
||||
NotApplicable
|
||||
};
|
||||
|
||||
@@ -112,6 +113,8 @@ inline static String getRestartReason()
|
||||
return "DeviceUnpaired";
|
||||
case RestartReason::NukiHubReset:
|
||||
return "NukiHubFactoryReset";
|
||||
case RestartReason::DisableNetworkIfNotConnected:
|
||||
return "NetworkDisabledOnNotConnected";
|
||||
case RestartReason::NotApplicable:
|
||||
return "NotApplicable";
|
||||
default:
|
||||
|
||||
@@ -245,6 +245,14 @@ void WebCfgServer::initialize()
|
||||
}
|
||||
return buildCredHtml(request);
|
||||
});
|
||||
_psychicServer->on("/ntwconfig", HTTP_GET, [&](PsychicRequest *request)
|
||||
{
|
||||
if(strlen(_credUser) > 0 && strlen(_credPassword) > 0) if(!request->authenticate(_credUser, _credPassword))
|
||||
{
|
||||
return request->requestAuthentication(BASIC_AUTH, "Nuki Hub", "You must log in.");
|
||||
}
|
||||
return buildNetworkConfigHtml(request);
|
||||
});
|
||||
_psychicServer->on("/mqttconfig", HTTP_GET, [&](PsychicRequest *request)
|
||||
{
|
||||
if(strlen(_credUser) > 0 && strlen(_credPassword) > 0) if(!request->authenticate(_credUser, _credPassword))
|
||||
@@ -1518,16 +1526,6 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message)
|
||||
configChanged = true;
|
||||
}
|
||||
}
|
||||
else if(key == "MQTTOPPATH")
|
||||
{
|
||||
if(_preferences->getString(preference_mqtt_opener_path, "") != value)
|
||||
{
|
||||
_preferences->putString(preference_mqtt_opener_path, value);
|
||||
Log->print(F("Setting changed: "));
|
||||
Log->println(key);
|
||||
configChanged = true;
|
||||
}
|
||||
}
|
||||
else if(key == "MQTTCA")
|
||||
{
|
||||
if(_preferences->getString(preference_mqtt_ca, "") != value)
|
||||
@@ -2128,6 +2126,16 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message)
|
||||
//configChanged = true;
|
||||
}
|
||||
}
|
||||
else if(key == "DISNTWNOCON")
|
||||
{
|
||||
if(_preferences->getBool(preference_disable_network_not_connected, false) != (value == "1"))
|
||||
{
|
||||
_preferences->putBool(preference_disable_network_not_connected, (value == "1"));
|
||||
Log->print(F("Setting changed: "));
|
||||
Log->println(key);
|
||||
configChanged = true;
|
||||
}
|
||||
}
|
||||
else if(key == "OTAUPD")
|
||||
{
|
||||
if(_preferences->getString(preference_ota_updater_url, "") != value)
|
||||
@@ -3344,7 +3352,8 @@ esp_err_t WebCfgServer::buildHtml(PsychicRequest *request)
|
||||
}
|
||||
response.print("</table><br>");
|
||||
response.print("<ul id=\"tblnav\">");
|
||||
buildNavigationMenuEntry(&response, "MQTT and Network Configuration", "/mqttconfig", _brokerConfigured ? "" : "Please configure MQTT broker");
|
||||
buildNavigationMenuEntry(&response, "Network Configuration", "/ntwconfig");
|
||||
buildNavigationMenuEntry(&response, "MQTT Configuration", "/mqttconfig", _brokerConfigured ? "" : "Please configure MQTT broker");
|
||||
buildNavigationMenuEntry(&response, "Nuki Configuration", "/nukicfg");
|
||||
buildNavigationMenuEntry(&response, "Access Level Configuration", "/acclvl");
|
||||
buildNavigationMenuEntry(&response, "Credentials", "/cred", _pinsConfigured ? "" : "Please configure PIN");
|
||||
@@ -3454,48 +3463,23 @@ esp_err_t WebCfgServer::buildCredHtml(PsychicRequest *request)
|
||||
return response.endSend();
|
||||
}
|
||||
|
||||
esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request)
|
||||
esp_err_t WebCfgServer::buildNetworkConfigHtml(PsychicRequest *request)
|
||||
{
|
||||
PsychicStreamResponse response(request, "text/plain");
|
||||
response.beginSend();
|
||||
buildHtmlHeader(&response);
|
||||
response.print("<form class=\"adapt\" method=\"post\" action=\"savecfg\">");
|
||||
response.print("<h3>Basic MQTT and Network Configuration</h3>");
|
||||
response.print("<h3>Network Configuration</h3>");
|
||||
response.print("<table>");
|
||||
printInputField(&response, "HOSTNAME", "Host name", _preferences->getString(preference_hostname).c_str(), 100, "");
|
||||
printInputField(&response, "MQTTSERVER", "MQTT Broker", _preferences->getString(preference_mqtt_broker).c_str(), 100, "");
|
||||
printInputField(&response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5, "");
|
||||
printInputField(&response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30, "", false, true);
|
||||
printInputField(&response, "MQTTPASS", "MQTT Password", "*", 30, "", true, true);
|
||||
response.print("</table><br>");
|
||||
|
||||
response.print("<h3>Advanced MQTT and Network Configuration</h3>");
|
||||
response.print("<table>");
|
||||
printInputField(&response, "HASSDISCOVERY", "Home Assistant discovery topic (empty to disable; usually homeassistant)", _preferences->getString(preference_mqtt_hass_discovery).c_str(), 30, "");
|
||||
printInputField(&response, "HASSCUURL", "Home Assistant device configuration URL (empty to use http://LOCALIP; fill when using a reverse proxy for example)", _preferences->getString(preference_mqtt_hass_cu_url).c_str(), 261, "");
|
||||
if(_preferences->getBool(preference_opener_enabled, false))
|
||||
{
|
||||
printCheckBox(&response, "OPENERCONT", "Set Nuki Opener Lock/Unlock action in Home Assistant to Continuous mode", _preferences->getBool(preference_opener_continuous_mode), "");
|
||||
}
|
||||
printTextarea(&response, "MQTTCA", "MQTT SSL CA Certificate (*, optional)", _preferences->getString(preference_mqtt_ca).c_str(), TLS_CA_MAX_SIZE, true, true);
|
||||
printTextarea(&response, "MQTTCRT", "MQTT SSL Client Certificate (*, optional)", _preferences->getString(preference_mqtt_crt).c_str(), TLS_CERT_MAX_SIZE, true, true);
|
||||
printTextarea(&response, "MQTTKEY", "MQTT SSL Client Key (*, optional)", _preferences->getString(preference_mqtt_key).c_str(), TLS_KEY_MAX_SIZE, true, true);
|
||||
printDropDown(&response, "NWHW", "Network hardware", String(_preferences->getInt(preference_network_hardware)), getNetworkDetectionOptions(), "");
|
||||
printInputField(&response, "HASSCUURL", "Home Assistant device configuration URL (empty to use http://LOCALIP; fill when using a reverse proxy for example)", _preferences->getString(preference_mqtt_hass_cu_url).c_str(), 261, "");
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||
printInputField(&response, "RSSI", "RSSI Publish interval (seconds; -1 to disable)", _preferences->getInt(preference_rssi_publish_interval), 6, "");
|
||||
#endif
|
||||
printInputField(&response, "NETTIMEOUT", "MQTT Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5, "");
|
||||
printCheckBox(&response, "RSTDISC", "Restart on disconnect", _preferences->getBool(preference_restart_on_disconnect), "");
|
||||
printCheckBox(&response, "MQTTLOG", "Enable MQTT logging", _preferences->getBool(preference_mqtt_log_enabled), "");
|
||||
printCheckBox(&response, "CHECKUPDATE", "Check for Firmware Updates every 24h", _preferences->getBool(preference_check_updates), "");
|
||||
printCheckBox(&response, "UPDATEMQTT", "Allow updating using MQTT", _preferences->getBool(preference_update_from_mqtt), "");
|
||||
printCheckBox(&response, "DISNONJSON", "Disable some extraneous non-JSON topics", _preferences->getBool(preference_disable_non_json), "");
|
||||
printCheckBox(&response, "OFFHYBRID", "Enable hybrid official MQTT and Nuki Hub setup", _preferences->getBool(preference_official_hybrid_enabled), "");
|
||||
printCheckBox(&response, "HYBRIDACT", "Enable sending actions through official MQTT", _preferences->getBool(preference_official_hybrid_actions), "");
|
||||
printInputField(&response, "HYBRIDTIMER", "Time between status updates when official MQTT is offline (seconds)", _preferences->getInt(preference_query_interval_hybrid_lockstate), 5, "");
|
||||
// printCheckBox(&response, "HYBRIDRETRY", "Retry command sent using official MQTT over BLE if failed", _preferences->getBool(preference_official_hybrid_retry), ""); // NOT IMPLEMENTED (YET?)
|
||||
response.print("</table>");
|
||||
response.print("* If no encryption is configured for the MQTT broker, leave empty.<br><br>");
|
||||
response.print("<h3>IP Address assignment</h3>");
|
||||
response.print("<table>");
|
||||
printCheckBox(&response, "DHCPENA", "Enable DHCP", _preferences->getBool(preference_ip_dhcp_enabled), "");
|
||||
@@ -3510,6 +3494,47 @@ esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request)
|
||||
return response.endSend();
|
||||
}
|
||||
|
||||
esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request)
|
||||
{
|
||||
PsychicStreamResponse response(request, "text/plain");
|
||||
response.beginSend();
|
||||
buildHtmlHeader(&response);
|
||||
response.print("<form class=\"adapt\" method=\"post\" action=\"savecfg\">");
|
||||
response.print("<h3>Basic MQTT Configuration</h3>");
|
||||
response.print("<table>");
|
||||
printInputField(&response, "MQTTSERVER", "MQTT Broker", _preferences->getString(preference_mqtt_broker).c_str(), 100, "");
|
||||
printInputField(&response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5, "");
|
||||
printInputField(&response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30, "", false, true);
|
||||
printInputField(&response, "MQTTPASS", "MQTT Password", "*", 30, "", true, true);
|
||||
printInputField(&response, "MQTTPATH", "MQTT NukiHub Path", _preferences->getString(preference_mqtt_lock_path).c_str(), 180, "");
|
||||
response.print("</table><br>");
|
||||
|
||||
response.print("<h3>Advanced MQTT Configuration</h3>");
|
||||
response.print("<table>");
|
||||
printInputField(&response, "HASSDISCOVERY", "Home Assistant discovery topic (empty to disable; usually homeassistant)", _preferences->getString(preference_mqtt_hass_discovery).c_str(), 30, "");
|
||||
if(_preferences->getBool(preference_opener_enabled, false))
|
||||
{
|
||||
printCheckBox(&response, "OPENERCONT", "Set Nuki Opener Lock/Unlock action in Home Assistant to Continuous mode", _preferences->getBool(preference_opener_continuous_mode), "");
|
||||
}
|
||||
printTextarea(&response, "MQTTCA", "MQTT SSL CA Certificate (*, optional)", _preferences->getString(preference_mqtt_ca).c_str(), TLS_CA_MAX_SIZE, true, true);
|
||||
printTextarea(&response, "MQTTCRT", "MQTT SSL Client Certificate (*, optional)", _preferences->getString(preference_mqtt_crt).c_str(), TLS_CERT_MAX_SIZE, true, true);
|
||||
printTextarea(&response, "MQTTKEY", "MQTT SSL Client Key (*, optional)", _preferences->getString(preference_mqtt_key).c_str(), TLS_KEY_MAX_SIZE, true, true);
|
||||
printInputField(&response, "NETTIMEOUT", "MQTT Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5, "");
|
||||
printCheckBox(&response, "MQTTLOG", "Enable MQTT logging", _preferences->getBool(preference_mqtt_log_enabled), "");
|
||||
printCheckBox(&response, "UPDATEMQTT", "Allow updating using MQTT", _preferences->getBool(preference_update_from_mqtt), "");
|
||||
printCheckBox(&response, "DISNONJSON", "Disable some extraneous non-JSON topics", _preferences->getBool(preference_disable_non_json), "");
|
||||
printCheckBox(&response, "OFFHYBRID", "Enable hybrid official MQTT and Nuki Hub setup", _preferences->getBool(preference_official_hybrid_enabled), "");
|
||||
printCheckBox(&response, "HYBRIDACT", "Enable sending actions through official MQTT", _preferences->getBool(preference_official_hybrid_actions), "");
|
||||
printInputField(&response, "HYBRIDTIMER", "Time between status updates when official MQTT is offline (seconds)", _preferences->getInt(preference_query_interval_hybrid_lockstate), 5, "");
|
||||
// printCheckBox(&response, "HYBRIDRETRY", "Retry command sent using official MQTT over BLE if failed", _preferences->getBool(preference_official_hybrid_retry), ""); // NOT IMPLEMENTED (YET?)
|
||||
response.print("</table>");
|
||||
response.print("* If no encryption is configured for the MQTT broker, leave empty.<br><br>");
|
||||
response.print("<br><input type=\"submit\" name=\"submit\" value=\"Save\">");
|
||||
response.print("</form>");
|
||||
response.print("</body></html>");
|
||||
return response.endSend();
|
||||
}
|
||||
|
||||
esp_err_t WebCfgServer::buildAdvancedConfigHtml(PsychicRequest *request)
|
||||
{
|
||||
PsychicStreamResponse response(request, "text/plain");
|
||||
@@ -3522,6 +3547,7 @@ esp_err_t WebCfgServer::buildAdvancedConfigHtml(PsychicRequest *request)
|
||||
response.print("<tr><td>Current bootloop prevention state</td><td>");
|
||||
response.print(_preferences->getBool(preference_enable_bootloop_reset, false) ? "Enabled" : "Disabled");
|
||||
response.print("</td></tr>");
|
||||
printCheckBox(&response, "DISNTWNOCON", "Disable Network if not connected within 60s", _preferences->getBool(preference_disable_network_not_connected, false), "");
|
||||
printCheckBox(&response, "WEBLOG", "Enable WebSerial logging", _preferences->getBool(preference_webserial_enabled), "");
|
||||
printCheckBox(&response, "BTLPRST", "Enable Bootloop prevention (Try to reset these settings to default on bootloop)", true, "");
|
||||
printInputField(&response, "BUFFSIZE", "Char buffer size (min 4096, max 32768)", _preferences->getInt(preference_buffer_size, CHAR_BUFFER_SIZE), 6, "");
|
||||
@@ -3864,15 +3890,7 @@ esp_err_t WebCfgServer::buildNukiConfigHtml(PsychicRequest *request)
|
||||
response.print("<h3>Basic Nuki Configuration</h3>");
|
||||
response.print("<table>");
|
||||
printCheckBox(&response, "LOCKENA", "Nuki Lock enabled", _preferences->getBool(preference_lock_enabled), "");
|
||||
if(_preferences->getBool(preference_lock_enabled))
|
||||
{
|
||||
printInputField(&response, "MQTTPATH", "MQTT Nuki Lock Path", _preferences->getString(preference_mqtt_lock_path).c_str(), 180, "");
|
||||
}
|
||||
printCheckBox(&response, "OPENA", "Nuki Opener enabled", _preferences->getBool(preference_opener_enabled), "");
|
||||
if(_preferences->getBool(preference_opener_enabled))
|
||||
{
|
||||
printInputField(&response, "MQTTOPPATH", "MQTT Nuki Opener Path", _preferences->getString(preference_mqtt_opener_path).c_str(), 180, "");
|
||||
}
|
||||
response.print("</table><br>");
|
||||
response.print("<h3>Advanced Nuki Configuration</h3>");
|
||||
response.print("<table>");
|
||||
@@ -4137,16 +4155,8 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request)
|
||||
response.print(_preferences->getString(preference_mqtt_user, "").length() > 0 ? "***" : "Not set");
|
||||
response.print("\nMQTT password: ");
|
||||
response.print(_preferences->getString(preference_mqtt_password, "").length() > 0 ? "***" : "Not set");
|
||||
if(_preferences->getBool(preference_lock_enabled, true))
|
||||
{
|
||||
response.print("\nMQTT lock base topic: ");
|
||||
response.print(_preferences->getString(preference_mqtt_lock_path, ""));
|
||||
}
|
||||
if(_preferences->getBool(preference_opener_enabled, false))
|
||||
{
|
||||
response.print("\nMQTT opener base topic: ");
|
||||
response.print(_preferences->getString(preference_mqtt_lock_path, ""));
|
||||
}
|
||||
response.print("\nMQTT base topic: ");
|
||||
response.print(_preferences->getString(preference_mqtt_lock_path, ""));
|
||||
response.print("\nMQTT SSL CA: ");
|
||||
response.print(_preferences->getString(preference_mqtt_ca, "").length() > 0 ? "***" : "Not set");
|
||||
response.print("\nMQTT SSL CRT: ");
|
||||
@@ -4430,7 +4440,7 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request)
|
||||
response.print(_nukiOpener->isPaired() ? _nukiOpener->isPinValid() ? "Yes" : "No" : "-");
|
||||
response.print("\nOpener has keypad: ");
|
||||
response.print(_nukiOpener->hasKeypad() ? "Yes" : "No");
|
||||
if(_nuki->hasKeypad())
|
||||
if(_nukiOpener->hasKeypad())
|
||||
{
|
||||
response.print("\nKeypad highest entries count: ");
|
||||
response.print(_preferences->getInt(preference_opener_max_keypad_code_count, 0));
|
||||
|
||||
@@ -54,6 +54,7 @@ private:
|
||||
esp_err_t buildAccLvlHtml(PsychicRequest *request);
|
||||
esp_err_t buildCredHtml(PsychicRequest *request);
|
||||
esp_err_t buildImportExportHtml(PsychicRequest *request);
|
||||
esp_err_t buildNetworkConfigHtml(PsychicRequest *request);
|
||||
esp_err_t buildMqttConfigHtml(PsychicRequest *request);
|
||||
esp_err_t buildStatusHtml(PsychicRequest *request);
|
||||
esp_err_t buildAdvancedConfigHtml(PsychicRequest *request);
|
||||
|
||||
188
src/main.cpp
188
src/main.cpp
@@ -42,6 +42,7 @@ Gpio* gpio = nullptr;
|
||||
|
||||
bool lockEnabled = false;
|
||||
bool openerEnabled = false;
|
||||
bool wifiConnected = false;
|
||||
|
||||
TaskHandle_t nukiTaskHandle = nullptr;
|
||||
|
||||
@@ -64,12 +65,16 @@ NukiNetwork* network = nullptr;
|
||||
WebCfgServer* webCfgServer = nullptr;
|
||||
Preferences* preferences = nullptr;
|
||||
|
||||
RTC_NOINIT_ATTR int espRunning;
|
||||
RTC_NOINIT_ATTR int restartReason;
|
||||
RTC_NOINIT_ATTR uint64_t restartReasonValidDetect;
|
||||
RTC_NOINIT_ATTR bool rebuildGpioRequested;
|
||||
RTC_NOINIT_ATTR uint64_t bootloopValidDetect;
|
||||
RTC_NOINIT_ATTR int8_t bootloopCounter;
|
||||
RTC_NOINIT_ATTR bool forceEnableWebServer;
|
||||
RTC_NOINIT_ATTR bool disableNetwork;
|
||||
RTC_NOINIT_ATTR bool wifiFallback;
|
||||
RTC_NOINIT_ATTR bool ethCriticalFailure;
|
||||
|
||||
bool restartReason_isValid;
|
||||
RestartReason currentRestartReason = RestartReason::NotApplicable;
|
||||
@@ -144,14 +149,9 @@ void networkTask(void *pvParameters)
|
||||
}
|
||||
}
|
||||
|
||||
bool connected = network->update();
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
if(connected && networkLock != nullptr)
|
||||
{
|
||||
networkLock->update();
|
||||
}
|
||||
|
||||
network->update();
|
||||
bool connected = network->isConnected();
|
||||
|
||||
#ifdef DEBUG_NUKIHUB
|
||||
if(connected && reroute)
|
||||
{
|
||||
@@ -159,6 +159,15 @@ void networkTask(void *pvParameters)
|
||||
setReroute();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
wifiConnected = network->wifiConnected();
|
||||
|
||||
if(connected && lockEnabled)
|
||||
{
|
||||
networkLock->update();
|
||||
}
|
||||
|
||||
if(connected && openerEnabled)
|
||||
{
|
||||
networkOpener->update();
|
||||
@@ -172,7 +181,6 @@ void networkTask(void *pvParameters)
|
||||
}
|
||||
|
||||
esp_task_wdt_reset();
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,37 +192,40 @@ void nukiTask(void *pvParameters)
|
||||
|
||||
while(true)
|
||||
{
|
||||
bleScanner->update();
|
||||
delay(20);
|
||||
|
||||
bool needsPairing = (lockEnabled && !nuki->isPaired()) || (openerEnabled && !nukiOpener->isPaired());
|
||||
|
||||
if (needsPairing)
|
||||
if(disableNetwork || wifiConnected)
|
||||
{
|
||||
delay(5000);
|
||||
}
|
||||
else if (!whiteListed)
|
||||
{
|
||||
whiteListed = true;
|
||||
bleScanner->update();
|
||||
delay(20);
|
||||
|
||||
bool needsPairing = (lockEnabled && !nuki->isPaired()) || (openerEnabled && !nukiOpener->isPaired());
|
||||
|
||||
if (needsPairing)
|
||||
{
|
||||
delay(5000);
|
||||
}
|
||||
else if (!whiteListed)
|
||||
{
|
||||
whiteListed = true;
|
||||
if(lockEnabled)
|
||||
{
|
||||
bleScanner->whitelist(nuki->getBleAddress());
|
||||
}
|
||||
if(openerEnabled)
|
||||
{
|
||||
bleScanner->whitelist(nukiOpener->getBleAddress());
|
||||
}
|
||||
}
|
||||
|
||||
if(lockEnabled)
|
||||
{
|
||||
bleScanner->whitelist(nuki->getBleAddress());
|
||||
nuki->update();
|
||||
}
|
||||
if(openerEnabled)
|
||||
{
|
||||
bleScanner->whitelist(nukiOpener->getBleAddress());
|
||||
nukiOpener->update();
|
||||
}
|
||||
}
|
||||
|
||||
if(lockEnabled)
|
||||
{
|
||||
nuki->update();
|
||||
}
|
||||
if(openerEnabled)
|
||||
{
|
||||
nukiOpener->update();
|
||||
}
|
||||
|
||||
if(espMillis() - nukiLoopTs > 120000)
|
||||
{
|
||||
Log->println("nukiTask is running");
|
||||
@@ -241,7 +252,6 @@ void bootloopDetection()
|
||||
if(esp_reset_reason() == esp_reset_reason_t::ESP_RST_PANIC ||
|
||||
esp_reset_reason() == esp_reset_reason_t::ESP_RST_INT_WDT ||
|
||||
esp_reset_reason() == esp_reset_reason_t::ESP_RST_TASK_WDT ||
|
||||
true ||
|
||||
esp_reset_reason() == esp_reset_reason_t::ESP_RST_WDT)
|
||||
{
|
||||
bootloopCounter++;
|
||||
@@ -400,10 +410,13 @@ void setupTasks(bool ota)
|
||||
}
|
||||
else
|
||||
{
|
||||
xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), NULL, 3, &networkTaskHandle, 1);
|
||||
esp_task_wdt_add(networkTaskHandle);
|
||||
if(!disableNetwork)
|
||||
{
|
||||
xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), NULL, 3, &networkTaskHandle, 1);
|
||||
esp_task_wdt_add(networkTaskHandle);
|
||||
}
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
if(!network->isApOpen())
|
||||
if(!network->isApOpen() && (lockEnabled || openerEnabled))
|
||||
{
|
||||
xTaskCreatePinnedToCore(nukiTask, "nuki", preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), NULL, 2, &nukiTaskHandle, 0);
|
||||
esp_task_wdt_add(nukiTaskHandle);
|
||||
@@ -414,12 +427,16 @@ void setupTasks(bool ota)
|
||||
|
||||
void setup()
|
||||
{
|
||||
//Set Log level to error for all TAGS
|
||||
esp_log_level_set("*", ESP_LOG_ERROR);
|
||||
//Set Log level to none for mqtt TAG
|
||||
esp_log_level_set("mqtt", ESP_LOG_NONE);
|
||||
//Start Serial and setup Log class
|
||||
Serial.begin(115200);
|
||||
Log = &Serial;
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
//
|
||||
stdout = funopen(NULL, NULL, &write_fn, NULL, NULL);
|
||||
static char linebuf[1024];
|
||||
setvbuf(stdout, linebuf, _IOLBF, sizeof(linebuf));
|
||||
@@ -435,6 +452,17 @@ void setup()
|
||||
|
||||
initializeRestartReason();
|
||||
|
||||
//default disableNetwork RTC_ATTR to false on power-on
|
||||
if(espRunning != 1)
|
||||
{
|
||||
espRunning = 1;
|
||||
forceEnableWebServer = false;
|
||||
disableNetwork = false;
|
||||
wifiFallback = false;
|
||||
ethCriticalFailure = false;
|
||||
}
|
||||
|
||||
//determine if an OTA update was requested
|
||||
if((partitionType==1 && preferences->getString(preference_ota_updater_url, "").length() > 0) || (partitionType==2 && preferences->getString(preference_ota_main_url, "").length() > 0))
|
||||
{
|
||||
doOta = true;
|
||||
@@ -496,7 +524,7 @@ void setup()
|
||||
deviceIdOpener->assignId(deviceIdLock->get());
|
||||
}
|
||||
|
||||
char16_t buffer_size = preferences->getInt(preference_buffer_size, 4096);
|
||||
char16_t buffer_size = preferences->getInt(preference_buffer_size, CHAR_BUFFER_SIZE);
|
||||
CharBuffer::initialize(buffer_size);
|
||||
|
||||
gpio = new Gpio(preferences);
|
||||
@@ -520,26 +548,26 @@ void setup()
|
||||
openerEnabled = false;
|
||||
}
|
||||
|
||||
bleScanner = new BleScanner::Scanner();
|
||||
// Scan interval and window according to Nuki recommendations:
|
||||
// https://developer.nuki.io/t/bluetooth-specification-questions/1109/27
|
||||
bleScanner->initialize("NukiHub", true, 40, 40);
|
||||
bleScanner->setScanDuration(0);
|
||||
|
||||
nukiOfficial = new NukiOfficial(preferences);
|
||||
|
||||
networkLock = new NukiNetworkLock(network, nukiOfficial, preferences, CharBuffer::get(), buffer_size);
|
||||
networkLock->initialize();
|
||||
|
||||
if(openerEnabled)
|
||||
if(lockEnabled || openerEnabled)
|
||||
{
|
||||
networkOpener = new NukiNetworkOpener(network, preferences, CharBuffer::get(), buffer_size);
|
||||
networkOpener->initialize();
|
||||
bleScanner = new BleScanner::Scanner();
|
||||
// Scan interval and window according to Nuki recommendations:
|
||||
// https://developer.nuki.io/t/bluetooth-specification-questions/1109/27
|
||||
bleScanner->initialize("NukiHub", true, 40, 40);
|
||||
bleScanner->setScanDuration(0);
|
||||
}
|
||||
|
||||
Log->println(lockEnabled ? F("Nuki Lock enabled") : F("Nuki Lock disabled"));
|
||||
if(lockEnabled)
|
||||
{
|
||||
nukiOfficial = new NukiOfficial(preferences);
|
||||
networkLock = new NukiNetworkLock(network, nukiOfficial, preferences, CharBuffer::get(), buffer_size);
|
||||
|
||||
if(!disableNetwork)
|
||||
{
|
||||
networkLock->initialize();
|
||||
}
|
||||
|
||||
nuki = new NukiWrapper("NukiHub", deviceIdLock, bleScanner, networkLock, nukiOfficial, gpio, preferences);
|
||||
nuki->initialize(firstStart);
|
||||
}
|
||||
@@ -547,41 +575,47 @@ void setup()
|
||||
Log->println(openerEnabled ? F("Nuki Opener enabled") : F("Nuki Opener disabled"));
|
||||
if(openerEnabled)
|
||||
{
|
||||
networkOpener = new NukiNetworkOpener(network, preferences, CharBuffer::get(), buffer_size);
|
||||
|
||||
if(!disableNetwork)
|
||||
{
|
||||
networkOpener->initialize();
|
||||
}
|
||||
|
||||
nukiOpener = new NukiOpenerWrapper("NukiHub", deviceIdOpener, bleScanner, networkOpener, gpio, preferences);
|
||||
nukiOpener->initialize();
|
||||
}
|
||||
|
||||
if(forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true) || preferences->getBool(preference_webserial_enabled, false))
|
||||
if(!doOta && !disableNetwork && (forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true) || preferences->getBool(preference_webserial_enabled, false)))
|
||||
{
|
||||
if(!doOta)
|
||||
psychicServer = new PsychicHttpServer;
|
||||
psychicServer->config.max_uri_handlers = 40;
|
||||
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
|
||||
psychicServer->maxUploadSize = 8192;
|
||||
psychicServer->maxRequestBodySize = 8192;
|
||||
psychicServer->listen(80);
|
||||
|
||||
if(forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true))
|
||||
{
|
||||
psychicServer = new PsychicHttpServer;
|
||||
psychicServer->config.max_uri_handlers = 40;
|
||||
psychicServer->config.stack_size = 8192;
|
||||
psychicServer->listen(80);
|
||||
|
||||
if(forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true))
|
||||
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
|
||||
webCfgServer->initialize();
|
||||
psychicServer->onNotFound([](PsychicRequest* request)
|
||||
{
|
||||
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
|
||||
webCfgServer->initialize();
|
||||
psychicServer->onNotFound([](PsychicRequest* request)
|
||||
{
|
||||
return request->redirect("/");
|
||||
});
|
||||
}
|
||||
/*
|
||||
#ifdef DEBUG_NUKIHUB
|
||||
else psychicServer->onNotFound([](PsychicRequest* request) { return request->redirect("/webserial"); });
|
||||
|
||||
if(preferences->getBool(preference_webserial_enabled, false))
|
||||
{
|
||||
WebSerial.setAuthentication(preferences->getString(preference_cred_user), preferences->getString(preference_cred_password));
|
||||
WebSerial.begin(asyncServer);
|
||||
WebSerial.setBuffer(1024);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
return request->redirect("/");
|
||||
});
|
||||
}
|
||||
/*
|
||||
#ifdef DEBUG_NUKIHUB
|
||||
else psychicServer->onNotFound([](PsychicRequest* request) { return request->redirect("/webserial"); });
|
||||
|
||||
if(preferences->getBool(preference_webserial_enabled, false))
|
||||
{
|
||||
WebSerial.setAuthentication(preferences->getString(preference_cred_user), preferences->getString(preference_cred_password));
|
||||
WebSerial.begin(asyncServer);
|
||||
WebSerial.setBuffer(1024);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#include "EthernetDevice.h"
|
||||
#include "../PreferencesKeys.h"
|
||||
#include "../Logger.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "../MqttTopics.h"
|
||||
#include "espMqttClient.h"
|
||||
#endif
|
||||
#include "../RestartReason.h"
|
||||
|
||||
RTC_NOINIT_ATTR bool criticalEthFailure;
|
||||
extern char WiFi_fallbackDetect[14];
|
||||
extern bool ethCriticalFailure;
|
||||
extern bool wifiFallback;
|
||||
|
||||
EthernetDevice::EthernetDevice(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)
|
||||
: NetworkDevice(hostname, ipConfiguration),
|
||||
@@ -49,6 +53,51 @@ EthernetDevice::EthernetDevice(const String &hostname,
|
||||
init();
|
||||
}
|
||||
|
||||
void EthernetDevice::init()
|
||||
{
|
||||
#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);
|
||||
|
||||
_useEncryption = caLength > 1; // length is 1 when empty
|
||||
|
||||
if(_useEncryption)
|
||||
{
|
||||
Log->println(F("MQTT over TLS."));
|
||||
_mqttClientSecure = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO);
|
||||
_mqttClientSecure->setCACert(_ca);
|
||||
if(crtLength > 1 && keyLength > 1) // length is 1 when empty
|
||||
{
|
||||
Log->println(F("MQTT with client certificate."));
|
||||
_mqttClientSecure->setCertificate(_cert);
|
||||
_mqttClientSecure->setPrivateKey(_key);
|
||||
}
|
||||
} else
|
||||
{
|
||||
Log->println(F("MQTT without TLS."));
|
||||
_mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::NO);
|
||||
}
|
||||
|
||||
if(_preferences->getBool(preference_mqtt_log_enabled, false) || _preferences->getBool(preference_webserial_enabled, false))
|
||||
{
|
||||
MqttLoggerMode mode;
|
||||
|
||||
if(_preferences->getBool(preference_mqtt_log_enabled, false) && _preferences->getBool(preference_webserial_enabled, false)) mode = MqttLoggerMode::MqttAndSerialAndWeb;
|
||||
else if (_preferences->getBool(preference_webserial_enabled, false)) mode = MqttLoggerMode::SerialAndWeb;
|
||||
else mode = MqttLoggerMode::MqttAndSerial;
|
||||
|
||||
_path = new char[200];
|
||||
memset(_path, 0, sizeof(_path));
|
||||
|
||||
String pathStr = _preferences->getString(preference_mqtt_lock_path);
|
||||
pathStr.concat(mqtt_topic_log);
|
||||
strcpy(_path, pathStr.c_str());
|
||||
Log = new MqttLogger(*getMqttClient(), _path, mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const String EthernetDevice::deviceName() const
|
||||
{
|
||||
return _deviceName.c_str();
|
||||
@@ -57,12 +106,12 @@ const String EthernetDevice::deviceName() const
|
||||
void EthernetDevice::initialize()
|
||||
{
|
||||
delay(250);
|
||||
if(criticalEthFailure)
|
||||
if(ethCriticalFailure)
|
||||
{
|
||||
criticalEthFailure = false;
|
||||
ethCriticalFailure = false;
|
||||
Log->println(F("Failed to initialize ethernet hardware"));
|
||||
Log->println("Network device has a critical failure, enable fallback to Wi-Fi and reboot.");
|
||||
strcpy(WiFi_fallbackDetect, "wifi_fallback");
|
||||
wifiFallback = true;
|
||||
delay(200);
|
||||
restartEsp(RestartReason::NetworkDeviceCriticalFailure);
|
||||
return;
|
||||
@@ -73,18 +122,18 @@ void EthernetDevice::initialize()
|
||||
if(_useSpi)
|
||||
{
|
||||
Log->println(F("Use SPI"));
|
||||
criticalEthFailure = true;
|
||||
ethCriticalFailure = true;
|
||||
SPI.begin(_spi_sck, _spi_miso, _spi_mosi);
|
||||
_hardwareInitialized = ETH.begin(_type, _phy_addr, _cs, _irq, _rst, SPI);
|
||||
criticalEthFailure = false;
|
||||
ethCriticalFailure = false;
|
||||
}
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
else
|
||||
{
|
||||
Log->println(F("Use RMII"));
|
||||
criticalEthFailure = true;
|
||||
ethCriticalFailure = true;
|
||||
_hardwareInitialized = ETH.begin(_type, _phy_addr, _mdc, _mdio, _power, _clock_mode);
|
||||
criticalEthFailure = false;
|
||||
ethCriticalFailure = false;
|
||||
if(!_ipConfiguration->dhcpEnabled())
|
||||
{
|
||||
_checkIpTs = espMillis() + 2000;
|
||||
@@ -95,7 +144,7 @@ void EthernetDevice::initialize()
|
||||
if(_hardwareInitialized)
|
||||
{
|
||||
Log->println(F("Ethernet hardware Initialized"));
|
||||
memset(WiFi_fallbackDetect, 0, sizeof(WiFi_fallbackDetect));
|
||||
wifiFallback = false;
|
||||
|
||||
if(_useSpi && !_ipConfiguration->dhcpEnabled())
|
||||
{
|
||||
@@ -111,7 +160,7 @@ void EthernetDevice::initialize()
|
||||
{
|
||||
Log->println(F("Failed to initialize ethernet hardware"));
|
||||
Log->println("Network device has a critical failure, enable fallback to Wi-Fi and reboot.");
|
||||
strcpy(WiFi_fallbackDetect, "wifi_fallback");
|
||||
wifiFallback = true;
|
||||
delay(200);
|
||||
restartEsp(RestartReason::NetworkDeviceCriticalFailure);
|
||||
return;
|
||||
@@ -120,18 +169,19 @@ void EthernetDevice::initialize()
|
||||
|
||||
void EthernetDevice::update()
|
||||
{
|
||||
if(_checkIpTs != -1)
|
||||
NetworkDevice::update();
|
||||
|
||||
if(_checkIpTs != -1 && _checkIpTs < espMillis())
|
||||
{
|
||||
if(_ipConfiguration->ipAddress() != ETH.localIP())
|
||||
{
|
||||
Log->println(F("ETH Set static IP"));
|
||||
ETH.config(_ipConfiguration->ipAddress(), _ipConfiguration->defaultGateway(), _ipConfiguration->subnet(), _ipConfiguration->dnsServer());
|
||||
_checkIpTs = espMillis() + 2000;
|
||||
}
|
||||
else
|
||||
{
|
||||
_checkIpTs = -1;
|
||||
_checkIpTs = espMillis() + 5000;
|
||||
return;
|
||||
}
|
||||
|
||||
_checkIpTs = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <NetworkClientSecure.h>
|
||||
#include <Preferences.h>
|
||||
#include "NetworkDevice.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "espMqttClient.h"
|
||||
#endif
|
||||
|
||||
class EthernetDevice : public NetworkDevice
|
||||
{
|
||||
@@ -45,8 +48,8 @@ public:
|
||||
virtual void initialize();
|
||||
virtual void reconfigure();
|
||||
virtual void update();
|
||||
virtual void scan(bool passive = false, bool async = true);
|
||||
|
||||
virtual void scan(bool passive = false, bool async = true);
|
||||
virtual bool isConnected();
|
||||
virtual bool isApOpen();
|
||||
|
||||
@@ -58,10 +61,12 @@ public:
|
||||
private:
|
||||
Preferences* _preferences;
|
||||
|
||||
void init();
|
||||
void onDisconnected();
|
||||
void onNetworkEvent(arduino_event_id_t event, arduino_event_info_t info);
|
||||
|
||||
bool _connected = false;
|
||||
char* _path;
|
||||
bool _hardwareInitialized = false;
|
||||
|
||||
const std::string _deviceName;
|
||||
@@ -85,4 +90,10 @@ private:
|
||||
eth_phy_type_t _type;
|
||||
eth_clock_mode_t _clock_mode;
|
||||
bool _useSpi = false;
|
||||
|
||||
#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
|
||||
};
|
||||
@@ -1,6 +1,179 @@
|
||||
#include <Arduino.h>
|
||||
#include "NetworkDevice.h"
|
||||
#include "../Logger.h"
|
||||
|
||||
void NetworkDevice::printError()
|
||||
{
|
||||
Log->print(F("Free Heap: "));
|
||||
Log->println(ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
void NetworkDevice::update()
|
||||
{
|
||||
}
|
||||
if (_mqttEnabled)
|
||||
{
|
||||
getMqttClient()->loop();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevice::mqttSetClientId(const char *clientId)
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->setClientId(clientId);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->setClientId(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevice::mqttSetCleanSession(bool cleanSession)
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->setCleanSession(cleanSession);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->setCleanSession(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);
|
||||
}
|
||||
|
||||
uint16_t NetworkDevice::mqttPublish(const char *topic, uint8_t qos, bool retain, const uint8_t *payload, size_t length)
|
||||
{
|
||||
return getMqttClient()->publish(topic, qos, retain, payload, length);
|
||||
}
|
||||
|
||||
bool NetworkDevice::mqttConnected() const
|
||||
{
|
||||
return getMqttClient()->connected();
|
||||
}
|
||||
|
||||
void NetworkDevice::mqttSetServer(const char *host, uint16_t port)
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->setServer(host, port);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->setServer(host, port);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkDevice::mqttConnect()
|
||||
{
|
||||
return getMqttClient()->connect();
|
||||
}
|
||||
|
||||
bool NetworkDevice::mqttDisconnect(bool force)
|
||||
{
|
||||
return getMqttClient()->disconnect(force);
|
||||
}
|
||||
|
||||
void NetworkDevice::setWill(const char *topic, uint8_t qos, bool retain, const char *payload)
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->setWill(topic, qos, retain, payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->setWill(topic, qos, retain, payload);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevice::mqttSetCredentials(const char *username, const char *password)
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->setCredentials(username, password);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->setCredentials(username, password);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevice::mqttOnMessage(espMqttClientTypes::OnMessageCallback callback)
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->onMessage(callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->onMessage(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevice::mqttOnConnect(espMqttClientTypes::OnConnectCallback callback)
|
||||
{
|
||||
if(_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->onConnect(callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->onConnect(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevice::mqttOnDisconnect(espMqttClientTypes::OnDisconnectCallback callback)
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
_mqttClientSecure->onDisconnect(callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mqttClient->onDisconnect(callback);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t NetworkDevice::mqttSubscribe(const char *topic, uint8_t qos)
|
||||
{
|
||||
return getMqttClient()->subscribe(topic, qos);
|
||||
}
|
||||
|
||||
void NetworkDevice::disableMqtt()
|
||||
{
|
||||
getMqttClient()->disconnect();
|
||||
_mqttEnabled = false;
|
||||
}
|
||||
|
||||
MqttClient *NetworkDevice::getMqttClient() const
|
||||
{
|
||||
if (_useEncryption)
|
||||
{
|
||||
return _mqttClientSecure;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _mqttClient;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void NetworkDevice::update()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -1,4 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "espMqttClient.h"
|
||||
#include "MqttClientSetup.h"
|
||||
#endif
|
||||
#include "IPConfiguration.h"
|
||||
#include "../EspMillis.h"
|
||||
|
||||
@@ -14,16 +19,48 @@ public:
|
||||
|
||||
virtual void initialize() = 0;
|
||||
virtual void reconfigure() = 0;
|
||||
virtual void printError();
|
||||
|
||||
virtual void update();
|
||||
virtual void scan(bool passive = false, bool async = true) = 0;
|
||||
|
||||
virtual bool isConnected() = 0;
|
||||
virtual bool isApOpen() = 0;
|
||||
virtual int8_t signalStrength() = 0;
|
||||
|
||||
virtual String localIP() = 0;
|
||||
virtual String BSSIDstr() = 0;
|
||||
protected:
|
||||
|
||||
#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;
|
||||
virtual void mqttSetServer(const char* host, uint16_t port);
|
||||
virtual bool mqttConnect();
|
||||
virtual bool mqttDisconnect(bool force);
|
||||
virtual void setWill(const char* topic, uint8_t qos, bool retain, const char* payload);
|
||||
virtual void mqttSetCredentials(const char* username, const char* password);
|
||||
virtual void mqttOnMessage(espMqttClientTypes::OnMessageCallback callback);
|
||||
virtual void mqttOnConnect(espMqttClientTypes::OnConnectCallback callback);
|
||||
virtual void mqttOnDisconnect(espMqttClientTypes::OnDisconnectCallback callback);
|
||||
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;
|
||||
};
|
||||
@@ -3,14 +3,59 @@
|
||||
#include "WifiDevice.h"
|
||||
#include "../PreferencesKeys.h"
|
||||
#include "../Logger.h"
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "../MqttTopics.h"
|
||||
#include "espMqttClient.h"
|
||||
#endif
|
||||
#include "../RestartReason.h"
|
||||
|
||||
WifiDevice::WifiDevice(const String& hostname, Preferences* preferences, const IPConfiguration* ipConfiguration)
|
||||
: NetworkDevice(hostname, ipConfiguration),
|
||||
_preferences(preferences)
|
||||
{
|
||||
#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);
|
||||
|
||||
_useEncryption = caLength > 1; // length is 1 when empty
|
||||
|
||||
if(_useEncryption)
|
||||
{
|
||||
Log->println(F("MQTT over TLS."));
|
||||
_mqttClientSecure = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO);
|
||||
_mqttClientSecure->setCACert(_ca);
|
||||
if(crtLength > 1 && keyLength > 1) // length is 1 when empty
|
||||
{
|
||||
Log->println(F("MQTT with client certificate."));
|
||||
_mqttClientSecure->setCertificate(_cert);
|
||||
_mqttClientSecure->setPrivateKey(_key);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log->println(F("MQTT without TLS."));
|
||||
_mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::NO);
|
||||
}
|
||||
|
||||
if(preferences->getBool(preference_mqtt_log_enabled, false) || preferences->getBool(preference_webserial_enabled, false))
|
||||
{
|
||||
MqttLoggerMode mode;
|
||||
|
||||
if(preferences->getBool(preference_mqtt_log_enabled, false) && preferences->getBool(preference_webserial_enabled, false)) mode = MqttLoggerMode::MqttAndSerialAndWeb;
|
||||
else if (preferences->getBool(preference_webserial_enabled, false)) mode = MqttLoggerMode::SerialAndWeb;
|
||||
else mode = MqttLoggerMode::MqttAndSerial;
|
||||
_path = new char[200];
|
||||
memset(_path, 0, sizeof(_path));
|
||||
String pathStr = preferences->getString(preference_mqtt_lock_path);
|
||||
pathStr.concat(mqtt_topic_log);
|
||||
strcpy(_path, pathStr.c_str());
|
||||
Log = new MqttLogger(*getMqttClient(), _path, mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
const String WifiDevice::deviceName() const
|
||||
{
|
||||
return "Built-in Wi-Fi";
|
||||
@@ -373,7 +418,7 @@ void WifiDevice::onDisconnected()
|
||||
}
|
||||
|
||||
_connecting = false;
|
||||
//END QUICK RECONECT
|
||||
//END QUICK RECONNECT
|
||||
|
||||
if(!isConnected())
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ private:
|
||||
void onDisconnected();
|
||||
void onConnected();
|
||||
bool connect();
|
||||
char* _path;
|
||||
|
||||
Preferences* _preferences = nullptr;
|
||||
|
||||
@@ -44,4 +45,10 @@ private:
|
||||
uint8_t _connectedChannel = 0;
|
||||
uint8_t* _connectedBSSID;
|
||||
int64_t _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