diff --git a/CMakeLists.txt b/CMakeLists.txt index 61f98e4..51c7871 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ include_directories(${PROJECT_NAME} set(SRCFILES Pins.h Config.h + CharBuffer.cpp Network.cpp MqttReceiver.h NetworkLock.cpp diff --git a/CharBuffer.cpp b/CharBuffer.cpp new file mode 100644 index 0000000..62b47b7 --- /dev/null +++ b/CharBuffer.cpp @@ -0,0 +1,13 @@ +#include "CharBuffer.h" + +void CharBuffer::initialize() +{ + _buffer = new char[CHAR_BUFFER_SIZE]; +} + +char *CharBuffer::get() +{ + return _buffer; +} + +char* CharBuffer::_buffer; diff --git a/CharBuffer.h b/CharBuffer.h new file mode 100644 index 0000000..4abaf87 --- /dev/null +++ b/CharBuffer.h @@ -0,0 +1,13 @@ +#pragma once + +#define CHAR_BUFFER_SIZE 4096 + +class CharBuffer +{ +public: + static void initialize(); + static char* get(); + +private: + static char* _buffer; +}; \ No newline at end of file diff --git a/Config.h b/Config.h index faf5950..e50050b 100644 --- a/Config.h +++ b/Config.h @@ -1,6 +1,6 @@ #pragma once -#define NUKI_HUB_VERSION "8.18-lilygo-1" +#define NUKI_HUB_VERSION "8.19-pre-3" #define MQTT_QOS_LEVEL 1 #define MQTT_CLEAN_SESSIONS false diff --git a/Config.h.save b/Config.h.save deleted file mode 100644 index aad4e52..0000000 --- a/Config.h.save +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#define NUKI_HUB_VERSION "8.13" - -#define MQTT_QOS_LEVEL 1 -#define MQTT_CLEAN_SESSIONS false diff --git a/MqttTopics.h b/MqttTopics.h index f96b612..dce7bf2 100644 --- a/MqttTopics.h +++ b/MqttTopics.h @@ -36,10 +36,11 @@ #define mqtt_topic_config_auto_lock "/configuration/autoLock" #define mqtt_topic_config_single_lock "/configuration/singleLock" #define mqtt_topic_config_sound_level "/configuration/soundLevel" +#define mqtt_topic_config_last_action_authorization "/configuration/lastActionAuthorizaton" #define mqtt_topic_info_hardware_version "/info/hardwareVersion" #define mqtt_topic_info_firmware_version "/info/firmwareVersion" - +#define mqtt_topic_info_nuki_hub_version "/info/nukiHubVersion" #define mqtt_topic_keypad "/keypad" #define mqtt_topic_keypad_command_action "/keypad/command/action" @@ -57,4 +58,5 @@ #define mqtt_topic_log "/maintenance/log" #define mqtt_topic_freeheap "/maintenance/freeHeap" #define mqtt_topic_restart_reason_fw "/maintenance/restartReasonNukiHub" -#define mqtt_topic_restart_reason_esp "/maintenance/restartReasonNukiEsp" \ No newline at end of file +#define mqtt_topic_restart_reason_esp "/maintenance/restartReasonNukiEsp" +#define mqtt_topic_network_device "/maintenance/networkDevice" \ No newline at end of file diff --git a/Network.cpp b/Network.cpp index 9a76860..8ab8cdc 100644 --- a/Network.cpp +++ b/Network.cpp @@ -11,11 +11,14 @@ Network* Network::_inst = nullptr; unsigned long Network::_ignoreSubscriptionsTs = 0; +bool _versionPublished = false; RTC_NOINIT_ATTR char WiFi_fallbackDetect[14]; -Network::Network(Preferences *preferences, const String& maintenancePathPrefix) -: _preferences(preferences) +Network::Network(Preferences *preferences, const String& maintenancePathPrefix, char* buffer, size_t bufferSize) +: _preferences(preferences), + _buffer(buffer), + _bufferSize(bufferSize) { _inst = this; _hostname = _preferences->getString(preference_hostname); @@ -296,6 +299,10 @@ bool Network::update() publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_fw, getRestartReason().c_str()); publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_esp, getEspRestartReason().c_str()); } + if (!_versionPublished) { + publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_version, NUKI_HUB_VERSION); + _versionPublished = true; + } _lastMaintenanceTs = ts; } @@ -403,6 +410,7 @@ bool Network::reconnect() if(_firstConnect) { _firstConnect = false; + publishString(_maintenancePathPrefix, mqtt_topic_network_device, _device->deviceName().c_str()); for(const auto& it : _initTopics) { _device->mqttPublish(it.first.c_str(), MQTT_QOS_LEVEL, true, it.second.c_str()); @@ -585,7 +593,6 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n if (discoveryTopic != "") { - char* jsonOut = new char[JSON_BUFFER_SIZE]; DynamicJsonDocument json(JSON_BUFFER_SIZE); auto dev = json.createNestedObject("dev"); @@ -606,16 +613,14 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n json["stat_unlocked"] = unlockedState; json["opt"] = "false"; - serializeJson(json, reinterpret_cast(*jsonOut)); + serializeJson(json, _buffer, _bufferSize); String path = discoveryTopic; path.concat("/lock/"); path.concat(uidString); path.concat("/smartlock/config"); - _device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, jsonOut); - - delete jsonOut; + _device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer); // Battery critical publishHassTopic("binary_sensor", @@ -724,6 +729,23 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n { { "enabled_by_default", "true" }, {"ic", "mdi:counter"}}); + // NUKI Hub version + publishHassTopic("sensor", + "nuki_hub_version", + uidString, + "_nuki_hub__version", + "NUKI Hub version", + name, + baseTopic, + mqtt_topic_info_nuki_hub_version, + deviceType, + "", + "", + "diagnostic", + "", + { { "enabled_by_default", "true" }, + {"ic", "mdi:counter"}}); + // LED enabled publishHassTopic("switch", "led_enabled", @@ -863,7 +885,7 @@ void Network::publishHASSConfigLedBrightness(char *deviceType, const char *baseT void Network::publishHASSConfigSoundLevel(char *deviceType, const char *baseTopic, char *name, char *uidString) { - publishHassTopic("number", + publishHassTopic("sensor", "sound_level", uidString, "_sound_level", @@ -881,6 +903,45 @@ void Network::publishHASSConfigSoundLevel(char *deviceType, const char *baseTopi { "max", "255" }}); } + +void Network::publishHASSConfigAccessLog(char *deviceType, const char *baseTopic, char *name, char *uidString) +{ + publishHassTopic("sensor", + "last_action_authorization", + uidString, + "_last_action_authorization", + "Last action authorization", + name, + baseTopic, + mqtt_topic_lock_log, + deviceType, + "", + "", + "diagnostic", + "", + { { "ic", "mdi:format-list-bulleted" }, + { "value_template", "{{ (value_json|selectattr('type', 'eq', 'LockAction')|selectattr('action', 'in', ['Lock', 'Unlock', 'Unlatch'])|first).authorizationName }}" }}); +} + +void Network::publishHASSConfigKeypadAttemptInfo(char *deviceType, const char *baseTopic, char *name, char *uidString) +{ + publishHassTopic("sensor", + "keypad_status", + uidString, + "_keypad_stats", + "Keypad status", + name, + baseTopic, + mqtt_topic_lock_log, + deviceType, + "", + "", + "diagnostic", + "", + { { "ic", "mdi:drag-vertical" }, + { "value_template", "{{ (value_json|selectattr('type', 'eq', 'KeypadAction')|first).completionStatus }}" }}); +} + void Network::publishHASSWifiRssiConfig(char *deviceType, const char *baseTopic, char *name, char *uidString) { if(_device->signalStrength() == 127) @@ -952,8 +1013,7 @@ void Network::publishHassTopic(const String& mqttDeviceType, if (discoveryTopic != "") { - char *jsonOut = new char[JSON_BUFFER_SIZE]; - DynamicJsonDocument json(JSON_BUFFER_SIZE); + DynamicJsonDocument json(_bufferSize); // Battery level json.clear(); @@ -990,7 +1050,7 @@ void Network::publishHassTopic(const String& mqttDeviceType, json[entry.first] = entry.second; } - serializeJson(json, reinterpret_cast(*jsonOut)); + serializeJson(json, _buffer, _bufferSize); String path = discoveryTopic; path.concat("/"); @@ -1001,9 +1061,7 @@ void Network::publishHassTopic(const String& mqttDeviceType, path.concat(mattDeviceName); path.concat("/config"); - _device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, jsonOut); - - delete jsonOut; + _device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer); } } @@ -1090,9 +1148,9 @@ void Network::removeHASSConfig(char* uidString) } } -void Network::removeHASSConfigDoorSensor(char *deviceType, const char *baseTopic, char *name, char *uidString) +void Network::removeHASSConfigTopic(char *deviceType, char *name, char *uidString) { - removeHassTopic("binary_sensor", "door_sensor", uidString); + removeHassTopic(deviceType, name, uidString); } void Network::publishPresenceDetection(char *csv) diff --git a/Network.h b/Network.h index 9cd3085..e14f553 100644 --- a/Network.h +++ b/Network.h @@ -22,7 +22,7 @@ enum class NetworkDeviceType class Network { public: - explicit Network(Preferences* preferences, const String& maintenancePathPrefix); + explicit Network(Preferences* preferences, const String& maintenancePathPrefix, char* buffer, size_t bufferSize); void initialize(); bool update(); @@ -47,10 +47,12 @@ public: void publishHASSConfigRingDetect(char* deviceType, const char* baseTopic, char* name, char* uidString); void publishHASSConfigLedBrightness(char* deviceType, const char* baseTopic, char* name, char* uidString); void publishHASSConfigSoundLevel(char* deviceType, const char* baseTopic, char* name, char* uidString); + void publishHASSConfigAccessLog(char* deviceType, const char* baseTopic, char* name, char* uidString); + void publishHASSConfigKeypadAttemptInfo(char* deviceType, const char* baseTopic, char* name, char* uidString); void publishHASSWifiRssiConfig(char* deviceType, const char* baseTopic, char* name, char* uidString); void publishHASSBleRssiConfig(char* deviceType, const char* baseTopic, char* name, char* uidString); void removeHASSConfig(char* uidString); - void removeHASSConfigDoorSensor(char* deviceType, const char* baseTopic, char* name, char* uidString); + void removeHASSConfigTopic(char* deviceType, char* name, char* uidString); void clearWifiFallback(); @@ -126,6 +128,10 @@ private: bool _mqttEnabled = true; static unsigned long _ignoreSubscriptionsTs; long _rssiPublishInterval = 0; + + char* _buffer; + const size_t _bufferSize; + std::function _keepAliveCallback = nullptr; std::vector> _reconnectedCallbacks; diff --git a/NetworkLock.cpp b/NetworkLock.cpp index 34845a1..6e332a7 100644 --- a/NetworkLock.cpp +++ b/NetworkLock.cpp @@ -5,10 +5,13 @@ #include "PreferencesKeys.h" #include "Logger.h" #include "RestartReason.h" +#include -NetworkLock::NetworkLock(Network* network, Preferences* preferences) +NetworkLock::NetworkLock(Network* network, Preferences* preferences, char* buffer, size_t bufferSize) : _network(network), - _preferences(preferences) + _preferences(preferences), + _buffer(buffer), + _bufferSize(bufferSize) { _configTopics.reserve(5); _configTopics.push_back(mqtt_topic_config_button_enabled); @@ -273,7 +276,6 @@ void NetworkLock::publishBinaryState(NukiLock::LockState lockState) } } - void NetworkLock::publishAuthorizationInfo(const std::list& logEntries) { char str[50]; @@ -283,7 +285,7 @@ void NetworkLock::publishAuthorizationInfo(const std::list& char authName[33]; memset(authName, 0, sizeof(authName)); - String json = "[\n"; + DynamicJsonDocument json(_bufferSize); for(const auto& log : logEntries) { @@ -294,90 +296,75 @@ void NetworkLock::publishAuthorizationInfo(const std::list& memcpy(authName, log.name, sizeof(log.name)); } - json.concat("{\n"); + auto entry = json.add(); - json.concat("\"index\": "); json.concat(log.index); json.concat(",\n"); - json.concat("\"authorizationId\": "); json.concat(log.authId); json.concat(",\n"); - - memset(str, 0, sizeof(str)); - memcpy(str, log.name, sizeof(log.name)); - json.concat("\"authorizationName\": \""); json.concat(str); json.concat("\",\n"); - - json.concat("\"timeYear\": "); json.concat(log.timeStampYear); json.concat(",\n"); - json.concat("\"timeMonth\": "); json.concat(log.timeStampMonth); json.concat(",\n"); - json.concat("\"timeDay\": "); json.concat(log.timeStampDay); json.concat(",\n"); - json.concat("\"timeHour\": "); json.concat(log.timeStampHour); json.concat(",\n"); - json.concat("\"timeMinute\": "); json.concat(log.timeStampMinute); json.concat(",\n"); - json.concat("\"timeSecond\": "); json.concat(log.timeStampSecond); json.concat(",\n"); + entry["index"] = log.index; + entry["authorizationId"] = log.authId; + entry["authorizationName"] = log.name; + entry["timeYear"] = log.timeStampYear; + entry["timeMonth"] = log.timeStampMonth; + entry["timeDay"] = log.timeStampDay; + entry["timeHour"] = log.timeStampHour; + entry["timeMinute"] = log.timeStampMinute; + entry["timeSecond"] = log.timeStampSecond; memset(str, 0, sizeof(str)); loggingTypeToString(log.loggingType, str); - json.concat("\"type\": \""); json.concat(str); json.concat("\",\n"); + entry["type"] = str; switch(log.loggingType) { case NukiLock::LoggingType::LockAction: memset(str, 0, sizeof(str)); NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str); - json.concat("\"action\": \""); json.concat(str); json.concat("\",\n"); + entry["action"] = str; memset(str, 0, sizeof(str)); NukiLock::triggerToString((NukiLock::Trigger)log.data[1], str); - json.concat("\"trigger\": \""); json.concat(str); json.concat("\",\n"); + entry["trigger"] = str; memset(str, 0, sizeof(str)); NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[3], str); - json.concat("\"completionStatus\": \""); json.concat(str); json.concat("\"\n"); + entry["completionStatus"] = str; break; case NukiLock::LoggingType::KeypadAction: memset(str, 0, sizeof(str)); NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str); - json.concat("\"action\": \""); json.concat(str); json.concat("\",\n"); + entry["action"] = str; memset(str, 0, sizeof(str)); NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[2], str); - json.concat("\"completionStatus\": \""); json.concat(str); json.concat("\"\n"); + entry["completionStatus"] = str; break; case NukiLock::LoggingType::DoorSensor: memset(str, 0, sizeof(str)); NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str); - json.concat("\"action\": \""); + switch(log.data[0]) { case 0: - json.concat("DoorOpened"); + entry["action"] = "DoorOpened"; break; case 1: - json.concat("DoorClosed"); + entry["action"] = "DoorClosed"; break; case 2: - json.concat("SensorJammed"); + entry["action"] = "SensorJammed"; break; default: - json.concat("Unknown"); + entry["action"] = "Unknown"; break; } - json.concat("\",\n"); memset(str, 0, sizeof(str)); NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[2], str); - json.concat("\"completionStatus\": \""); json.concat(str); json.concat("\"\n"); + entry["completionStatus"] = str; break; } - - json.concat("}"); - if(&log == &logEntries.back()) - { - json.concat("\n"); - } - else - { - json.concat(",\n"); - } } - json.concat("]"); - publishString(mqtt_topic_lock_log, json); + serializeJson(json, _buffer, _bufferSize); + publishString(mqtt_topic_lock_log, _buffer); if(authFound) { @@ -515,7 +502,7 @@ bool NetworkLock::comparePrefixedPath(const char *fullPath, const char *subPath) return strcmp(fullPath, prefixedPath) == 0; } -void NetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, char *name, char *uidString, const bool& hasDoorSensor, const bool& hasKeypad, char *lockAction, +void NetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, char *name, char *uidString, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char *lockAction, char *unlockAction, char *openAction, char *lockedState, char *unlockedState) { _network->publishHASSConfig(deviceType, baseTopic, name, uidString, hasKeypad, lockAction, unlockAction, openAction, lockedState, unlockedState); @@ -527,10 +514,28 @@ void NetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, cha } else { - _network->removeHASSConfigDoorSensor(deviceType, baseTopic, name, uidString); + _network->removeHASSConfigTopic("binary_sensor", "door_sensor", uidString); } _network->publishHASSWifiRssiConfig(deviceType, baseTopic, name, uidString); _network->publishHASSBleRssiConfig(deviceType, baseTopic, name, uidString); + + if(publishAuthData) + { + _network->publishHASSConfigAccessLog(deviceType, baseTopic, name, uidString); + } + else + { + _network->removeHASSConfigTopic("sensor", "last_action_authorization", uidString); + } + + if(hasKeypad) + { + _network->publishHASSConfigKeypadAttemptInfo(deviceType, baseTopic, name, uidString); + } + else + { + _network->removeHASSConfigTopic("sensor", "keypad_status", uidString); + } } void NetworkLock::removeHASSConfig(char *uidString) diff --git a/NetworkLock.h b/NetworkLock.h index d722d3d..47fb12f 100644 --- a/NetworkLock.h +++ b/NetworkLock.h @@ -11,10 +11,12 @@ #include "Network.h" #include "QueryCommand.h" +#define LOCK_LOG_JSON_BUFFER_SIZE 2048 + class NetworkLock : public MqttReceiver { public: - explicit NetworkLock(Network* network, Preferences* preferences); + explicit NetworkLock(Network* network, Preferences* preferences, char* buffer, size_t bufferSize); virtual ~NetworkLock(); void initialize(); @@ -31,7 +33,7 @@ public: void publishRssi(const int& rssi); void publishRetry(const std::string& message); void publishBleAddress(const std::string& address); - void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& hasDoorSensor, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState); + void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState); void removeHASSConfig(char* uidString); void publishKeypad(const std::list& entries, uint maxKeypadCodeCount); void publishKeypadCommandResult(const char* result); @@ -79,6 +81,9 @@ private: int _keypadCommandEnabled = 1; uint8_t _queryCommands = 0; + char* _buffer; + size_t _bufferSize; + bool (*_lockActionReceivedCallback)(const char* value) = nullptr; void (*_configUpdateReceivedCallback)(const char* path, const char* value) = nullptr; void (*_keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled) = nullptr; diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index 0650a5d..ab2fabe 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -4,10 +4,13 @@ #include "PreferencesKeys.h" #include "Logger.h" #include "Config.h" +#include -NetworkOpener::NetworkOpener(Network* network, Preferences* preferences) +NetworkOpener::NetworkOpener(Network* network, Preferences* preferences, char* buffer, size_t bufferSize) : _preferences(preferences), - _network(network) + _network(network), + _buffer(buffer), + _bufferSize(bufferSize) { _configTopics.reserve(5); _configTopics.push_back(mqtt_topic_config_button_enabled); @@ -268,130 +271,111 @@ void NetworkOpener::publishAuthorizationInfo(const std::listgetString(preference_mqtt_opener_path); char uidString[20]; itoa(_nukiConfig.nukiId, uidString, 16); - _network->publishHASSConfig("Opener",baseTopic.c_str(),(char*)_nukiConfig.name,uidString,"deactivateRTO","activateRTO","electricStrikeActuation","locked","unlocked"); + _network->publishHASSConfig("Opener",baseTopic.c_str(),(char*)_nukiConfig.name,uidString, "deactivateRTO","activateRTO","electricStrikeActuation","locked","unlocked"); _hassSetupCompleted = true; Log->println("HASS setup for opener completed."); diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 35d828a..24ac52a 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -661,7 +661,7 @@ void NukiWrapper::setupHASS() char uidString[20]; itoa(_nukiConfig.nukiId, uidString, 16); - _network->publishHASSConfig("SmartLock", baseTopic.c_str(),(char*)_nukiConfig.name, uidString, hasDoorSensor(), _hasKeypad, "lock", "unlock", "unlatch", "locked", "unlocked"); + _network->publishHASSConfig("SmartLock", baseTopic.c_str(),(char*)_nukiConfig.name, uidString, hasDoorSensor(), _hasKeypad, _publishAuthData,"lock", "unlock", "unlatch", "locked", "unlocked"); _hassSetupCompleted = true; Log->println("HASS setup for lock completed."); diff --git a/PresenceDetection.cpp b/PresenceDetection.cpp index 786f4cb..45a8702 100644 --- a/PresenceDetection.cpp +++ b/PresenceDetection.cpp @@ -1,14 +1,15 @@ #include "PresenceDetection.h" #include "PreferencesKeys.h" #include "Logger.h" +#include "CharBuffer.h" -PresenceDetection::PresenceDetection(Preferences* preferences, BleScanner::Scanner *bleScanner, Network* network) +PresenceDetection::PresenceDetection(Preferences* preferences, BleScanner::Scanner *bleScanner, Network* network, char* buffer, size_t bufferSize) : _preferences(preferences), _bleScanner(bleScanner), - _network(network) + _network(network), + _csv(buffer), + _bufferSize(bufferSize) { - _csv = new char[presence_detection_buffer_size]; - _timeout = _preferences->getInt(preference_presence_detection_timeout) * 1000; if(_timeout == 0) { @@ -41,7 +42,7 @@ void PresenceDetection::update() delay(3000); if(_timeout < 0) return; - memset(_csv, 0, presence_detection_buffer_size); + memset(_csv, 0, _bufferSize); if(_devices.size() == 0) { @@ -60,7 +61,7 @@ void PresenceDetection::update() } // Prevent csv buffer overflow - if(_csvIndex > presence_detection_buffer_size - (sizeof(it.second.name) + sizeof(it.second.address) + 10)) + if(_csvIndex > _bufferSize - (sizeof(it.second.name) + sizeof(it.second.address) + 10)) { break; } diff --git a/PresenceDetection.h b/PresenceDetection.h index 6cc210c..049af9f 100644 --- a/PresenceDetection.h +++ b/PresenceDetection.h @@ -13,12 +13,10 @@ struct PdDevice bool hasRssi = false; }; -#define presence_detection_buffer_size 4096 - class PresenceDetection : public BleScanner::Subscriber { public: - PresenceDetection(Preferences* preferences, BleScanner::Scanner* bleScanner, Network* network); + PresenceDetection(Preferences* preferences, BleScanner::Scanner* bleScanner, Network* network, char* buffer, size_t bufferSize); virtual ~PresenceDetection(); void initialize(); @@ -33,6 +31,7 @@ private: BleScanner::Scanner* _bleScanner; Network* _network; char* _csv = {0}; + size_t _bufferSize = 0; std::map _devices; int _timeout = 20000; int _csvIndex = 0; diff --git a/README.md b/README.md index 26e4d3e..5a78170 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Note: It is possible to run NUKI Hub alongside a NUKI Bridge. This is not recomm ## Support If you haven't ordered your NUKI product yet, you can support me by using my referrer code when placing your order:
-REFPGVT4XJ5JW
+REFXQ847A4ZDG
This will also give you a 30€ discount for your order. This project is free to use for everyone. However if you feel like donating, you can buy me a coffee at ko-fi.com: @@ -187,8 +187,11 @@ The Pin configuration is:
## Connecting via LAN (Optional) -If you prefer to connect to the MQTT Broker via LAN instead of WiFi, you can use a Wiznet W5x00 Module (W5100, W5200, W5500 are supported). -To connect, just wire the module and connect the LAN cable: +If you prefer to connect to the MQTT Broker via LAN instead of WiFi, you either use one of the supported ESP32 modules (see about section above), +or wire a seperate Wiznet W5x00 Module (W5100, W5200, W5500 are supported). To use a supported module, flash the firmware, connect via Wifi and +select the correct network hardware in the MQTT and network settings section.
+ +To wire an external W5x00 module to the ESP, use this wiring scheme:
- Connect W5x00 to ESP32 SPI0:
W5x00 SCK to GPIO18
@@ -199,10 +202,10 @@ W5x00 CS/SS to GPIO5 W5x00 reset to GPIO33 - Last but not least, on the ESP32 bridge GPIO26 and GND. This let's the firmware know that a LAN Module is connected -Wifi is now disabled, and the module doesn't boot into WifiManager anymore. - -As an alternative to do the wiring yourself, you can use an [M5Stack Atom POE](https://docs.m5stack.com/en/atom/atom_poe). -After flashing, go to MQTT and network settings and select the module under "Network hardware". +Wifi is now disabled, and the module doesn't boot into WifiManager anymore.
+Note: Encrypted MQTT is only available for Wifi and LAN8720 modules, W5x00 modules don't support encryption +(that leaves Olimex, WT32-ETH01 and M5Stack PoESP32 Unit if encryption is desired). If encryption is needed, Olimex +is the easiest option, since it has USB for flashing onboard. ## Troubleshooting diff --git a/main.cpp b/main.cpp index b6ffd5b..7fe8644 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,7 @@ #include "Logger.h" #include "Config.h" #include "RestartReason.h" +#include "CharBuffer.h" Network* network = nullptr; NetworkLock* networkLock = nullptr; @@ -170,6 +171,8 @@ void setup() bool firstStart = initPreferences(); initializeRestartReason(); + CharBuffer::initialize(); + if(preferences->getInt(preference_restart_timer) > 0) { restartTs = preferences->getInt(preference_restart_timer) * 60 * 1000; @@ -179,15 +182,15 @@ void setup() openerEnabled = preferences->getBool(preference_opener_enabled); const String mqttLockPath = preferences->getString(preference_mqtt_lock_path); - network = new Network(preferences, mqttLockPath); + network = new Network(preferences, mqttLockPath, CharBuffer::get(), CHAR_BUFFER_SIZE); network->initialize(); - networkLock = new NetworkLock(network, preferences); + networkLock = new NetworkLock(network, preferences, CharBuffer::get(), CHAR_BUFFER_SIZE); networkLock->initialize(); if(openerEnabled) { - networkOpener = new NetworkOpener(network, preferences); + networkOpener = new NetworkOpener(network, preferences, CharBuffer::get(), CHAR_BUFFER_SIZE); networkOpener->initialize(); } @@ -226,7 +229,7 @@ void setup() webCfgServer = new WebCfgServer(nuki, nukiOpener, network, ethServer, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi); webCfgServer->initialize(); - presenceDetection = new PresenceDetection(preferences, bleScanner, network); + presenceDetection = new PresenceDetection(preferences, bleScanner, network, CharBuffer::get(), CHAR_BUFFER_SIZE); presenceDetection->initialize(); setupTasks(); diff --git a/networkDevices/W5500Device.cpp b/networkDevices/W5500Device.cpp index 6d4e517..a6d5801 100644 --- a/networkDevices/W5500Device.cpp +++ b/networkDevices/W5500Device.cpp @@ -115,6 +115,7 @@ ReconnectStatus W5500Device::reconnect() } else { + hardwareFound = true; _hasDHCPAddress = true; dhcpRetryCnt = 1000; if(_ipConfiguration->dhcpEnabled())