Merge remote-tracking branch 'upstream/master' into esp-nimble-nuki-ble-update

This commit is contained in:
iranl
2024-11-11 19:24:34 +01:00
30 changed files with 3497 additions and 3475 deletions

View File

@@ -49,7 +49,7 @@ See the "[Connecting via Ethernet](#connecting-via-ethernet-optional)" section f
## Recommended ESP32 devices
- If WIFI6 is required: ESP32-C6
- If WIFI6 is absolutely required: ESP32-C6
- If PoE is required: Any of the above mentioned devices with PoE or any other ESP device in combination with a SPI Ethernet module ([W5500](https://www.aliexpress.com/w/wholesale-w5500.html)) and [PoE to Ethernet and USB type B/C splitter](https://aliexpress.com/w/wholesale-poe-splitter-usb-c.html)
- If you want maximum performance and intend to run any or multiple of the following:
- a Nuki Lock and Nuki Opener and/or
@@ -69,17 +69,17 @@ The ESP32-S3 is a dual-core CPU with many GPIO's, ability to enlarge RAM using P
| Feature | Nuki Hub | Nuki Bridge |
|---|---|---|
| Bridge API | | x |
| Smart Lock remote control | (optional via smarthome solution) | x |
| Smart Lock remote control | x | x |
| Smart Home integration via Matter | | x |
| Apple HomeKit integration via Matter | | x |
| MQTT API | x | x (only for SL > 3, Pro models) |
| MQTT API | x | x (only for SL 3, 4 and 4 Pro models) |
| Wired LAN support | x | |
| Power over Ethernet (PoE) | x (if supported by LAN/ESP module) | |
| WLAN support | x | x (only for SL > 3, Pro Models) || Home Assistant integration | x (full integration of most Nuki features) | x |
| WLAN support | x | x (only for SL 3 and 4 Pro Models) || Home Assistant integration | x (full integration of most Nuki features) | x |
| Home Automation platform integration | x | x |
| Cloud support | (optional via smarthome solution) | x |
| Cloud-less operation | x | x (since fw 3.8.2, to be tested) |
| Smarthome app integration | | x |
| Cloud support | x (optional via smarthome solution) | x |
| Cloud-less operation | x | x (since fw 3.8.2) |
| Official Nuki app integration | | x |
| Nuki Smartlocks all models | x | x |
| Nuki opener | x | x |
| Nuki Keypad (1.0 and 2.0) | x | x |
@@ -87,14 +87,12 @@ The ESP32-S3 is a dual-core CPU with many GPIO's, ability to enlarge RAM using P
| Fine-grained access control of MQTT API | x | |
| Export of lock actions via MQTT API | x | |
| Control via GPIO | x | |
| Hybrid mode for Pro locks | x | |
| Hybrid mode for WiFI and Thread connected locks | x | |
## Support Nuki Hub development
If you haven't ordered your Nuki product yet, you can support me by using my referrer code when placing your order:<br>
REF443RM5HR5X<br>
REF2BJHFVHZKK<br>
This will also give you a 10% discount on your order.<br>
<br>
This project is free to use for everyone. However if you feel like donating, you can buy me a coffee at ko-fi.com:<br>
@@ -345,39 +343,39 @@ After importing the device will reboot.
- opener/retry: Reports the current number of retries for the current command. 0 when command is successful, "failed" if the number of retries is greater than the maximum configured number of retries.
### Configuration
- [lock/opener]/configuration/buttonEnabled: 1 if the Nuki Lock/Opener button is enabled, otherwise 0.
- [lock/opener]/configuration/ledEnabled: 1 if the Nuki Lock/Opener LED is enabled, otherwise 0.
- [lock/opener]/configuration/ledBrightness: Set to the brightness of the LED on the Nuki Lock (0=min; 5=max) (Lock only).
- [lock/opener]/configuration/singleLock: 0 if the Nuki Lock is set to double-lock the door, otherwise 1 (= single-lock) (Lock only).
- [lock/opener]/configuration/autoLock: 1 if the Nuki Lock is set to Auto Lock, otherwise 0 (Lock only).
- [lock/opener]/configuration/autoUnlock: 1 if the Nuki Lock is set to Auto Unlock, otherwise 0 (Lock only).
- [lock/opener]/configuration/soundLevel: Set to the volume for sounds the Nuki Opener plays (0 = min; 255 = max) (Opener only).
- [lock/opener]/configuration/action: Allows changing configuration settings of the Nuki Lock/Opener using a JSON formatted value. After receiving the action, the value is set to "--". See the "[Changing Nuki Lock/Opener Configuration](#changing-nuki-lockopener-configuration)" section of this README for possible actions/values
- [lock/opener]/configuration/commandResult: Result of the last configuration change action as JSON data. See the "[Changing Nuki Lock/Opener Configuration](#changing-nuki-lockopener-configuration)" section of this README for possible values
- [lock/opener]/configuration/basicJson: The current basic configuration of the Nuki Lock/Opener as JSON data. See [Nuki Smart Lock API](https://developer.nuki.io/page/nuki-smart-lock-api-2/2/#heading--set-config) and [Nuki Opener API](https://developer.nuki.io/page/nuki-opener-api-1/7/#heading--set-config) for available settings. Please note: Longitude and Latitude of the Lock/Opener are not published to MQTT by design. These values can still be changed though.
- [lock/opener]/configuration/advancedJson: The current advanced configuration of the Nuki Lock/Opener as JSON data. See [Nuki Smart Lock API](https://developer.nuki.io/page/nuki-smart-lock-api-2/2/#heading--advanced-config) and [Nuki Opener API](https://developer.nuki.io/page/nuki-opener-api-1/7/#heading--advanced-config) for available settings.
- [lock/opener/]configuration/buttonEnabled: 1 if the Nuki Lock/Opener button is enabled, otherwise 0.
- [lock/opener/]configuration/ledEnabled: 1 if the Nuki Lock/Opener LED is enabled, otherwise 0.
- [lock/opener/]configuration/ledBrightness: Set to the brightness of the LED on the Nuki Lock (0=min; 5=max) (Lock only).
- [lock/opener/]configuration/singleLock: 0 if the Nuki Lock is set to double-lock the door, otherwise 1 (= single-lock) (Lock only).
- [lock/opener/]configuration/autoLock: 1 if the Nuki Lock is set to Auto Lock, otherwise 0 (Lock only).
- [lock/opener/]configuration/autoUnlock: 1 if the Nuki Lock is set to Auto Unlock, otherwise 0 (Lock only).
- [lock/opener/]configuration/soundLevel: Set to the volume for sounds the Nuki Opener plays (0 = min; 255 = max) (Opener only).
- [lock/opener/]configuration/action: Allows changing configuration settings of the Nuki Lock/Opener using a JSON formatted value. After receiving the action, the value is set to "--". See the "[Changing Nuki Lock/Opener Configuration](#changing-nuki-lockopener-configuration)" section of this README for possible actions/values
- [lock/opener/]configuration/commandResult: Result of the last configuration change action as JSON data. See the "[Changing Nuki Lock/Opener Configuration](#changing-nuki-lockopener-configuration)" section of this README for possible values
- [lock/opener/]configuration/basicJson: The current basic configuration of the Nuki Lock/Opener as JSON data. See [Nuki Smart Lock API](https://developer.nuki.io/page/nuki-smart-lock-api-2/2/#heading--set-config) and [Nuki Opener API](https://developer.nuki.io/page/nuki-opener-api-1/7/#heading--set-config) for available settings. Please note: Longitude and Latitude of the Lock/Opener are not published to MQTT by design. These values can still be changed though.
- [lock/opener/]configuration/advancedJson: The current advanced configuration of the Nuki Lock/Opener as JSON data. See [Nuki Smart Lock API](https://developer.nuki.io/page/nuki-smart-lock-api-2/2/#heading--advanced-config) and [Nuki Opener API](https://developer.nuki.io/page/nuki-opener-api-1/7/#heading--advanced-config) for available settings.
### Query
- [lock/opener]/query/lockstate: Set to 1 to trigger query lockstate. Auto-resets to 0.
- [lock/opener]/query/config: Set to 1 to trigger query config. Auto-resets to 0.
- [lock/opener]/query/keypad: Set to 1 to trigger query keypad. Auto-resets to 0.
- [lock/opener]/query/battery: Set to 1 to trigger query battery. Auto-resets to 0.
- [lock/opener]/query/lockstateCommandResult: Set to 1 to trigger query lockstate command result. Auto-resets to 0.
- [lock/opener/]query/lockstate: Set to 1 to trigger query lockstate. Auto-resets to 0.
- [lock/opener/]query/config: Set to 1 to trigger query config. Auto-resets to 0.
- [lock/opener/]query/keypad: Set to 1 to trigger query keypad. Auto-resets to 0.
- [lock/opener/]query/battery: Set to 1 to trigger query battery. Auto-resets to 0.
- [lock/opener/]query/lockstateCommandResult: Set to 1 to trigger query lockstate command result. Auto-resets to 0.
### Battery
- [lock/opener]/battery/level: Battery level in percent (Lock only).
- [lock/opener]/battery/critical: 1 if battery level is critical, otherwise 0.
- [lock/opener]/battery/charging: 1 if charging, otherwise 0 (Lock only).
- [lock/opener]/battery/voltage: Current Battery voltage (V).
- [lock/opener]/battery/drain: The drain of the last lock action in Milliwattseconds (mWs) (Lock only).
- [lock/opener]/battery/maxTurnCurrent: The highest current of the turn motor during the last lock action (A) (Lock only).
- [lock/opener]/battery/lockDistance: The total distance during the last lock action in centidegrees (Lock only).
- [lock/opener]/battery/keypadCritical: 1 if the battery level of a connected keypad is critical, otherwise 0.
- [lock/opener]/battery/doorSensorCritical (only available in hybdrid mode): 1 if the battery level of a connected doorsensor is critical, otherwise 0.
- [lock/opener]/battery/basicJson: The current battery state (critical, charging, level and keypad critical) of the Nuki Lock/Opener as JSON data.
- [lock/opener]/battery/advancedJson: : The current battery state (critical, batteryDrain, batteryVoltage, lockAction, startVoltage, lowestVoltage, lockDistance, startTemperature, maxTurnCurrent and batteryResistance) of the Nuki Lock/Opener as JSON data.
- [lock/opener/]battery/level: Battery level in percent (Lock only).
- [lock/opener/]battery/critical: 1 if battery level is critical, otherwise 0.
- [lock/opener/]battery/charging: 1 if charging, otherwise 0 (Lock only).
- [lock/opener/]battery/voltage: Current Battery voltage (V).
- [lock/opener/]battery/drain: The drain of the last lock action in Milliwattseconds (mWs) (Lock only).
- [lock/opener/]battery/maxTurnCurrent: The highest current of the turn motor during the last lock action (A) (Lock only).
- [lock/opener/]battery/lockDistance: The total distance during the last lock action in centidegrees (Lock only).
- [lock/opener/]battery/keypadCritical: 1 if the battery level of a connected keypad is critical, otherwise 0.
- [lock/opener/]battery/doorSensorCritical (only available in hybrid mode): 1 if the battery level of a connected doorsensor is critical, otherwise 0.
- [lock/opener/]battery/basicJson: The current battery state (critical, charging, level and keypad critical) of the Nuki Lock/Opener as JSON data.
- [lock/opener/]battery/advancedJson: : The current battery state (critical, batteryDrain, batteryVoltage, lockAction, startVoltage, lowestVoltage, lockDistance, startTemperature, maxTurnCurrent and batteryResistance) of the Nuki Lock/Opener as JSON data.
### Keypad
@@ -390,8 +388,8 @@ After importing the device will reboot.
### Info
- info/nukiHubVersion: Set to the current version number of the Nuki Hub firmware.
- info/firmwareVersion: Set to the current version number of the Nuki Lock/Opener firmware.
- info/hardwareVersion: Set to the hardware version number of the Nuki Lock/Opener.
- [lock/opener/]info/firmwareVersion: Set to the current version number of the Nuki Lock/Opener firmware.
- [lock/opener/]info/hardwareVersion: Set to the hardware version number of the Nuki Lock/Opener.
- info/nukiHubIp: Set to the IP of the Nuki Hub.
- info/nukiHubLatest: Set to the latest available Nuki Hub firmware version number (if update checking is enabled in the settings).
@@ -519,10 +517,10 @@ If Home Assistant discovery is enabled (see the [Home Assistant Discovery](#hom
After the initial installation of the Nuki Hub firmware via serial connection, further updates can be deployed via OTA update from a browser.<br>
In the configuration portal, select "Firmware update" from the main page.<br>
<br>
The easiest way to upgrade Nuki Hub, if Nuki Hub is connected to the internet, is to select "Auto Update".<br>
The easiest way to upgrade Nuki Hub, if Nuki Hub is connected to the internet, is to select "Update to latest version".<br>
This will download the latest Nuki Hub and Nuki Hub updater and automatically upgrade both applications.<br>
Nuki Hub will reboot 3 times during this process, which will take about 5 minutes.<br>
If you have enabled "Allow updating using MQTT" you can also use the Home Assistant updater or write "1" to the `nukihub/maintanance/reset` topic to start the update process.<br>
If you have enabled "Allow updating using MQTT" you can also use the Home Assistant updater or write "1" to the `nukihub/maintanance/update` topic to start the update process.<br>
<br>
Alternatively you can select a binary file from your file system to update Nuki Hub or the Nuki Hub updator manually<br>
You can only update Nuki Hub from the Nuki Hub updater and update the updater only from Nuki Hub<br>
@@ -566,7 +564,7 @@ openssl req -new -key server.key -out server.csr -subj "/C=US/ST=YourState/L=You
## Home Assistant Discovery (optional)
This software supports [MQTT Discovery](https://www.home-assistant.io/docs/mqtt/discovery/) for integrating Nuki Hub with Home Assistant.<br>
To enable autodiscovery, supply the discovery topic that is configured in your Home Assistant instance (If you have not changed this setting in Home Assistant the default is "homeassistant") in the MQTT Configuration page.<br>
To enable autodiscovery, enable the checkbox on the "MQTT Configuration" page.<br>
Once enabled, the Nuki Lock and/or Opener and related entities should automatically appear in your Home Assistant MQTT devices.
The following mapping between Home Assistant services and Nuki commands is setup when enabling autodiscovery:
@@ -734,7 +732,7 @@ To enable GPIO control, go the the "GPIO Configuration" page where each GPIO can
If you prefer to connect to via Ethernet instead of Wi-Fi, you either use one of the supported ESP32 modules with built-in ethernet (see "[Supported devices](#supported-devices)" section)
or wire a seperate SPI Ethernet module.<Br>
Currently the Wiznet W5x00 Module (W5100, W5200, W5500), DN9051 and KSZ8851SNL chips are supported.<br>
To use a supported module, flash the firmware, connect via Wi-Fi and select the correct network hardware in the "MQTT and Network Configuration" section.
To use a supported module, flash the firmware, connect via Wi-Fi and select the correct network hardware in the "Network Configuration" section.
To wire an external W5x00 module to the ESP, use this wiring scheme:
@@ -749,7 +747,7 @@ To wire an external W5x00 module to the ESP, use this wiring scheme:
Now connect via Wi-Fi and change the network hardware to "Generic W5500".<br>
If Ethernet hwardware isn't detected, Wi-Fi is used as a fallback, unless this is disabled in the settings.<br>
If Ethernet hardware isn't detected or initialised properly after changing the network device, Wi-Fi will be used as a fallback.<br>
<br>
Note: LAN8720 modules are only supported on the ESP32 and ESP32-Solo1, not on the ESP32-S3, ESP32-C3 or ESP-C6<br>
@@ -758,7 +756,7 @@ Note: LAN8720 modules are only supported on the ESP32 and ESP32-Solo1, not on th
### Random Wi-Fi disconnects
Unfortunately the ESP32 has problems with some access points and reconnecting fails.<br>
As a workaround you can navigate to "MQTT and Network Configuration" and enable "Restart on disconnect".<br>
As a workaround you can navigate to "Network Configuration" and enable "Restart on disconnect".<br>
This will reboot the ESP as soon as it gets disconnected from Wi-Fi.<br>
Also, this reduces the config portal timeout to three minutes to prevent the ESP being stuck in config mode in case an access point is offline temporarily.<br>
If this still doesn't fix the disconnects and the ESP becomes unreachable, the "Restart timer" option can be used as a last resort.<br>
@@ -781,7 +779,7 @@ A note about the [M5Stack PoESP32 Unit](https://docs.m5stack.com/en/unit/poesp32
Make sure you are using at least version 2023.8.0 of Home Assistant.<br>
The Home Assistant developers have made changes to MQTT auto discovery which break support for older version and Nuki Hub has adopted these changes.<br>
This unfortunately means that older versions of Home Assistant are not supported by the Nuki Hub discovery implemenation anymore.
This unfortunately means that older versions of Home Assistant are not supported by the Nuki Hub discovery implementation anymore.
## FAQ
@@ -815,7 +813,7 @@ This button is disabled by default, but can be enabled in the Home Assistant UI.
### When controlling two locks (or openers) connected to two ESPs, both devices react to the same command. When using Home Asistant, the same status is display for both locks.
When using multiple Nuki devices, different paths for each device have to be configured.<br>
Navigate to "Nuki Configuration" and change the "MQTT Nuki Smartlock Path" or "MQTT Nuki Opener Path" under "Basic Nuki Configuration" for at least one of the devices.<br>
Navigate to "MQTT Configuration" and change the "MQTT NukiHub Path" under "Basic MQTT Configuration" for at least one of the devices.<br>
### The Nuki battery is draining quickly.

View File

@@ -49,6 +49,7 @@ set(SRCFILES
../src/util/NetworkUtil.cpp
../src/enums/NetworkDeviceType.h
../src/util/NetworkDeviceInstantiator.cpp
../src/HomeAssistantDiscovery.cpp
../src/NukiOfficial.cpp
../src/NukiPublisher.cpp
../src/EspMillis.h

View File

@@ -4,7 +4,7 @@
#define NUKI_HUB_VERSION "9.02"
#define NUKI_HUB_BUILD "unknownbuildnr"
#define NUKI_HUB_DATE "2024-11-06"
#define NUKI_HUB_DATE "2024-11-08"
#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"
@@ -22,6 +22,7 @@
#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32c3.bin"
#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32c3.bin"
#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32c3.bin"
#define NUKI_HUB_HW (char*)"ESP32-C3"
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
#if defined(CONFIG_SPIRAM_MODE_OCT)
#define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32s3oct.bin"
@@ -36,6 +37,7 @@
#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32s3oct.bin"
#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32s3oct.bin"
#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32s3oct.bin"
#define NUKI_HUB_HW (char*)"ESP32-S3 (Octal PSRAM)"
#else
#define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32s3.bin"
#define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_updater_esp32s3.bin"
@@ -49,6 +51,7 @@
#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32s3.bin"
#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32s3.bin"
#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32s3.bin"
#define NUKI_HUB_HW (char*)"ESP32-S3"
#endif
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
#define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32c6.bin"
@@ -63,6 +66,7 @@
#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32c6.bin"
#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32c6.bin"
#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32c6.bin"
#define NUKI_HUB_HW (char*)"ESP32-C6"
#elif defined(CONFIG_IDF_TARGET_ESP32H2)
#define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32h2.bin"
#define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_updater_esp32h2.bin"
@@ -76,6 +80,7 @@
#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32h2.bin"
#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32h2.bin"
#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32h2.bin"
#define NUKI_HUB_HW (char*)"ESP32-H2"
#else
#if defined(CONFIG_FREERTOS_UNICORE)
#define GITHUB_LATEST_RELEASE_BINARY_URL "https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32-solo1.bin"
@@ -90,6 +95,7 @@
#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32-solo1.bin"
#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32-solo1.bin"
#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32-solo1.bin"
#define NUKI_HUB_HW (char*)"ESP32-SOLO1"
#else
#define GITHUB_LATEST_RELEASE_BINARY_URL "https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32.bin"
#define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_updater_esp32.bin"
@@ -103,6 +109,7 @@
#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32.bin"
#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32.bin"
#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32.bin"
#define NUKI_HUB_HW (char*)"ESP32"
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
#pragma once
#include <Preferences.h>
#include <ArduinoJson.h>
#include "networkDevices/NetworkDevice.h"
class HomeAssistantDiscovery
{
public:
explicit HomeAssistantDiscovery(NetworkDevice* device, Preferences* preferences, char* buffer, size_t bufferSize);
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad);
void disableHASS();
void removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
void publishHassTopic(const String& mqttDeviceType,
const String& mqttDeviceName,
const String& uidString,
const String& uidStringPostfix,
const String& displayName,
const String& name,
const String& baseTopic,
const String& stateTopic,
const String& deviceType,
const String& deviceClass,
const String& stateClass = "",
const String& entityCat = "",
const String& commandTopic = "",
std::vector<std::pair<char*, char*>> additionalEntries = {}
);
private:
void 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);
void publishHASSDeviceConfig(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 publishHASSNukiHubConfig();
void publishHASSConfigAdditionalLockEntities(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigDoorSensor(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigAdditionalOpenerEntities(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigAccessLog(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigKeypad(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigWifiRssi(char* deviceType, const char* baseTopic, char* name, char* uidString);
void removeHASSConfig(char* uidString);
void removeHASSConfigTopic(char* deviceType, char* name, char* uidString);
String createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
JsonDocument createHassJson(const String& uidString,
const String& uidStringPostfix,
const String& displayName,
const String& name,
const String& baseTopic,
const String& stateTopic,
const String& deviceType,
const String& deviceClass,
const String& stateClass = "",
const String& entityCat = "",
const String& commandTopic = "",
std::vector<std::pair<char*, char*>> additionalEntries = {}
);
NetworkDevice* _device = nullptr;
Preferences* _preferences = nullptr;
String _discoveryTopic;
String _baseTopic;
String _hostname;
char _nukiHubUidString[20];
bool _offEnabled = false;
bool _checkUpdates = false;
bool _updateFromMQTT = false;
char* _buffer;
const size_t _bufferSize;
};

View File

@@ -1,7 +1,5 @@
#pragma once
#include <Arduino.h>
class MqttReceiver
{
public:

View File

@@ -110,7 +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 "/hybridConnected"
#define mqtt_topic_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

View File

@@ -15,6 +15,7 @@
#include "Gpio.h"
#include <ArduinoJson.h>
#include "NukiConstants.h"
#include "HomeAssistantDiscovery.h"
#endif
class NukiNetwork
@@ -56,37 +57,31 @@ public:
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);
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);
void publishHASSConfigDoorSensor(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigAdditionalOpenerEntities(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigAccessLog(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSConfigKeypad(char* deviceType, const char* baseTopic, char* name, char* uidString);
void publishHASSWifiRssiConfig(char* deviceType, const char* baseTopic, char* name, char* uidString);
void removeHASSConfig(char* uidString);
void removeHASSConfigTopic(char* deviceType, char* name, char* uidString);
void publishHassTopic(const String& mqttDeviceType,
const String& mqttDeviceName,
const String& uidString,
const String& uidStringPostfix,
const String& displayName,
const String& name,
const String& baseTopic,
const String& stateTopic,
const String& deviceType,
const String& deviceClass,
const String& stateClass = "",
const String& entityCat = "",
const String& commandTopic = "",
std::vector<std::pair<char*, char*>> additionalEntries = {}
);
void removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
void publish(const char *topic, const char *value, bool retain);
void removeTopic(const String& mqttPath, const String& mqttTopic);
void batteryTypeToString(const Nuki::BatteryType battype, char* str);
void advertisingModeToString(const Nuki::AdvertisingMode advmode, char* str);
void timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* str);
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad);
void disableHASS();
void publishHassTopic(const String& mqttDeviceType,
const String& mqttDeviceName,
const String& uidString,
const String& uidStringPostfix,
const String& displayName,
const String& name,
const String& baseTopic,
const String& stateTopic,
const String& deviceType,
const String& deviceClass,
const String& stateClass,
const String& entityCat,
const String& commandTopic,
std::vector<std::pair<char*, char*>> additionalEntries
);
void removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
int mqttConnectionState(); // 0 = not connected; 1 = connected; 2 = connected and mqtt processed
bool mqttRecentlyConnected();
bool pathEquals(const char* prefix, const char* path, const char* referencePath);
@@ -113,8 +108,6 @@ private:
NetworkDeviceType _networkDeviceType = (NetworkDeviceType)-1;
bool _firstBootAfterDeviceChange = false;
bool _webEnabled = true;
bool _updateFromMQTT = false;
bool _offEnabled = false;
#ifndef NUKI_HUB_UPDATER
static void onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
@@ -125,30 +118,16 @@ private:
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);
bool comparePrefixedPath(const char* fullPath, const char* subPath);
String createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
JsonDocument createHassJson(const String& uidString,
const String& uidStringPostfix,
const String& displayName,
const String& name,
const String& baseTopic,
const String& stateTopic,
const String& deviceType,
const String& deviceClass,
const String& stateClass = "",
const String& entityCat = "",
const String& commandTopic = "",
std::vector<std::pair<char*, char*>> additionalEntries = {}
);
void buildMqttPath(char* outPath, std::initializer_list<const char*> paths);
void buildMqttPath(const char *path, char *outPath);
void buildMqttPath(char* outPath, std::initializer_list<const char*> paths);
const char* _lastWillPayload = "offline";
char _mqttConnectionStateTopic[211] = {0};
String _lockPath;
String _discoveryTopic;
String _brokerAddr;
HomeAssistantDiscovery* _hadiscovery = nullptr;
Gpio* _gpio;
int _mqttConnectionState = 0;

View File

@@ -1516,53 +1516,6 @@ bool NukiNetworkLock::comparePrefixedPath(const char *fullPath, const char *subP
return strcmp(fullPath, prefixedPath) == 0;
}
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)
{
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)
{
_network->publishHASSConfigDoorSensor(deviceType, baseTopic, name, uidString);
}
else
{
_network->removeHASSConfigTopic((char*)"binary_sensor", (char*)"door_sensor", uidString);
}
#ifndef CONFIG_IDF_TARGET_ESP32H2
_network->publishHASSWifiRssiConfig(deviceType, baseTopic, name, uidString);
#endif
if(publishAuthData)
{
_network->publishHASSConfigAccessLog(deviceType, baseTopic, name, uidString);
}
else
{
_network->removeHASSConfigTopic((char*)"sensor", (char*)"last_action_authorization", uidString);
_network->removeHASSConfigTopic((char*)"sensor", (char*)"rolling_log", uidString);
}
if(hasKeypad)
{
_network->publishHASSConfigKeypad(deviceType, baseTopic, name, uidString);
}
else
{
_network->removeHASSConfigTopic((char*)"sensor", (char*)"keypad_status", uidString);
_network->removeHASSConfigTopic((char*)"binary_sensor", (char*)"keypad_battery_low", uidString);
}
}
void NukiNetworkLock::removeHASSConfig(char *uidString)
{
_network->removeHASSConfig(uidString);
}
void NukiNetworkLock::publishOffAction(const int value)
{
_network->publishInt(_nukiOfficial->getMqttPath(), mqtt_topic_official_lock_action, value, false);
@@ -1645,6 +1598,11 @@ uint8_t NukiNetworkLock::queryCommands()
return qc;
}
void NukiNetworkLock::setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad)
{
_network->setupHASS(type, nukiId, nukiName, firmwareVersion, hardwareVersion, hasDoorSensor, hasKeypad);
}
void NukiNetworkLock::buttonPressActionToString(const NukiLock::ButtonPressAction btnPressAction, char* str)
{
switch (btnPressAction)

View File

@@ -37,8 +37,6 @@ 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 char *softwareVersion, const char *hardwareVersion, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction);
void removeHASSConfig(char* uidString);
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
void publishTimeControl(const std::list<NukiLock::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount);
void publishAuth(const std::list<NukiLock::AuthorizationEntry>& authEntries, uint maxAuthEntryCount);
@@ -58,6 +56,7 @@ public:
void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value));
void setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char* value));
void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override;
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad);
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);

View File

@@ -859,38 +859,6 @@ void NukiNetworkOpener::publishBleAddress(const std::string &address)
publishString(mqtt_topic_lock_address, address, true);
}
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(preference_mqtt_lock_path);
availabilityTopic.concat("/maintenance/mqttConnectionState");
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, softwareVersion, hardwareVersion, availabilityTopic.c_str(), hasKeypad, lockAction, unlockAction, openAction);
_network->publishHASSConfigAdditionalOpenerEntities(deviceType, baseTopic, name, uidString);
if(publishAuthData)
{
_network->publishHASSConfigAccessLog(deviceType, baseTopic, name, uidString);
}
else
{
_network->removeHASSConfigTopic((char*)"sensor", (char*)"last_action_authorization", uidString);
_network->removeHASSConfigTopic((char*)"sensor", (char*)"rolling_log", uidString);
}
if(hasKeypad)
{
_network->publishHASSConfigKeypad(deviceType, baseTopic, name, uidString);
}
else
{
_network->removeHASSConfigTopic((char*)"sensor", (char*)"keypad_status", uidString);
_network->removeHASSConfigTopic((char*)"binary_sensor", (char*)"keypad_battery_low", uidString);
}
}
void NukiNetworkOpener::removeHASSConfig(char* uidString)
{
_network->removeHASSConfig(uidString);
}
void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
{
bool publishCode = _preferences->getBool(preference_keypad_publish_code, false);
@@ -1588,6 +1556,11 @@ uint8_t NukiNetworkOpener::queryCommands()
return qc;
}
void NukiNetworkOpener::setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad)
{
_network->setupHASS(type, nukiId, nukiName, firmwareVersion, hardwareVersion, hasDoorSensor, hasKeypad);
}
void NukiNetworkOpener::buttonPressActionToString(const NukiOpener::ButtonPressAction btnPressAction, char* str)
{
switch (btnPressAction)

View File

@@ -30,8 +30,6 @@ 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 char *softwareVersion, const char *hardwareVersion, const bool& publishAuthData, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction);
void removeHASSConfig(char* uidString);
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
void publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount);
void publishAuth(const std::list<NukiLock::AuthorizationEntry>& authEntries, uint maxAuthEntryCount);
@@ -49,6 +47,7 @@ public:
void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value));
void setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char* value));
void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override;
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad);
int mqttConnectionState();
bool reconnected(); //SETBACK

View File

@@ -13,7 +13,6 @@ NukiOfficial::NukiOfficial(Preferences *preferences)
_disableNonJSON = preferences->getBool(preference_disable_non_json, false);
}
void NukiOfficial::setUid(const uint32_t& uid)
{
char uidString[20];
@@ -43,7 +42,6 @@ void NukiOfficial::setPublisher(NukiPublisher *publisher)
_publisher = publisher;
}
const char *NukiOfficial::getMqttPath() const
{
return mqttPath;
@@ -88,7 +86,7 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
bool publishBatteryJson = false;
memset(&str, 0, sizeof(str));
Log->println("Official Nuki change recieved");
Log->println("Official Nuki change received");
Log->print(F("Topic: "));
Log->println(topic);
Log->print(F("Value: "));
@@ -99,14 +97,14 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
Log->print(F("Connected: "));
Log->println((strcmp(value, "true") == 0 ? 1 : 0));
offConnected = (strcmp(value, "true") == 0 ? 1 : 0);
_publisher->publishBool(mqtt_hybrid_state, offConnected, true);
_publisher->publishBool(mqtt_topic_hybrid_state, offConnected, true);
}
else if(strcmp(topic, mqtt_topic_official_state) == 0)
{
offState = atoi(value);
_statusUpdated = true;
Log->println(F("Lock: Updating status on Hybrid state change"));
_publisher->publishBool(mqtt_hybrid_state, offConnected, true);
_publisher->publishBool(mqtt_topic_hybrid_state, offConnected, true);
NukiLock::lockstateToString((NukiLock::LockState)offState, str);
_publisher->publishString(mqtt_topic_lock_state, str, true);

View File

@@ -54,7 +54,7 @@ void NukiOpenerWrapper::initialize()
_nukiOpener.setConnectTimeout(3);
_nukiOpener.setDisconnectTimeout(5000);
_hassEnabled = _preferences->getString(preference_mqtt_hass_discovery) != "";
_hassEnabled = _preferences->getBool(preference_mqtt_hass_enabled, false);
readSettings();
}
@@ -313,7 +313,8 @@ void NukiOpenerWrapper::update()
}
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && !_hassSetupCompleted)
{
setupHASS();
_network->setupHASS(2, _nukiConfig.nukiId, (char*)_nukiConfig.name, _firmwareVersion.c_str(), _hardwareVersion.c_str(), false, _hasKeypad);
_hassSetupCompleted = true;
}
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
{
@@ -610,13 +611,13 @@ void NukiOpenerWrapper::updateConfig()
}
else
{
Log->println(F("Invalid/Unexpected opener config recieved, ID does not matched saved ID"));
Log->println(F("Invalid/Unexpected opener config received, ID does not matched saved ID"));
expectedConfig = false;
}
}
else
{
Log->println(F("Invalid/Unexpected opener config recieved, Config is not valid"));
Log->println(F("Invalid/Unexpected opener config received, Config is not valid"));
expectedConfig = false;
}
@@ -633,7 +634,7 @@ void NukiOpenerWrapper::updateConfig()
}
else
{
Log->println(F("Invalid/Unexpected opener advanced config recieved, Advanced config is not valid"));
Log->println(F("Invalid/Unexpected opener advanced config received, Advanced config is not valid"));
expectedConfig = false;
}
}
@@ -646,7 +647,7 @@ void NukiOpenerWrapper::updateConfig()
else
{
++_retryConfigCount;
Log->println(F("Invalid/Unexpected opener config and/or advanced config recieved, retrying in 10 seconds"));
Log->println(F("Invalid/Unexpected opener config and/or advanced config received, retrying in 10 seconds"));
int64_t ts = espMillis();
_nextConfigUpdateTs = ts + 10000;
}
@@ -3957,43 +3958,6 @@ void NukiOpenerWrapper::readAdvancedConfig()
postponeBleWatchdog();
}
void NukiOpenerWrapper::setupHASS()
{
if(!_nukiConfigValid)
{
return;
}
if(_preferences->getUInt(preference_nuki_id_opener, 0) != _nukiConfig.nukiId)
{
return;
}
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
baseTopic.concat("/opener");
char uidString[20];
itoa(_nukiConfig.nukiId, uidString, 16);
if(_preferences->getBool(preference_opener_continuous_mode, false))
{
_network->publishHASSConfig((char*)"Opener", baseTopic.c_str(), (char*)_nukiConfig.name, uidString, _firmwareVersion.c_str(), _hardwareVersion.c_str(), _publishAuthData, _hasKeypad, (char*)"deactivateCM", (char*)"activateCM", (char*)"electricStrikeActuation");
}
else
{
_network->publishHASSConfig((char*)"Opener", baseTopic.c_str(), (char*)_nukiConfig.name, uidString, _firmwareVersion.c_str(), _hardwareVersion.c_str(), _publishAuthData, _hasKeypad, (char*)"deactivateRTO", (char*)"activateRTO", (char*)"electricStrikeActuation");
}
_hassSetupCompleted = true;
Log->println("HASS setup for opener completed.");
}
void NukiOpenerWrapper::disableHASS()
{
char uidString[20];
itoa(_preferences->getUInt(preference_nuki_id_opener, 0), uidString, 16);
_network->removeHASSConfig(uidString);
}
void NukiOpenerWrapper::printCommandResult(Nuki::CmdResult result)
{
char resultStr[15];

View File

@@ -31,9 +31,6 @@ public:
uint16_t getPin();
void unpair();
void disableHASS();
void disableWatchdog();
const NukiOpener::OpenerState& keyTurnerState();
@@ -77,8 +74,6 @@ private:
void readConfig();
void readAdvancedConfig();
void setupHASS();
void printCommandResult(Nuki::CmdResult result);
NukiOpener::LockAction lockActionToEnum(const char* str); // char array at least 14 characters

View File

@@ -1,6 +1,3 @@
#ifndef CONFIG_IDF_TARGET_ESP32H2
#include "esp_wifi.h"
#endif
#include "NukiWrapper.h"
#include "PreferencesKeys.h"
#include "MqttTopics.h"
@@ -50,7 +47,7 @@ NukiWrapper::~NukiWrapper()
}
void NukiWrapper::initialize(const bool& firstStart)
void NukiWrapper::initialize()
{
_nukiLock.initialize();
_nukiLock.registerBleScanner(_bleScanner);
@@ -58,75 +55,7 @@ void NukiWrapper::initialize(const bool& firstStart)
_nukiLock.setConnectTimeout(3);
_nukiLock.setDisconnectTimeout(5000);
if(firstStart)
{
Log->println("First start, setting preference defaults");
#ifndef CONFIG_IDF_TARGET_ESP32H2
wifi_config_t wifi_cfg;
if(esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg) != ESP_OK)
{
Log->println("Failed to get Wi-Fi configuration in RAM");
}
if (esp_wifi_set_storage(WIFI_STORAGE_FLASH) != ESP_OK)
{
Log->println("Failed to set storage Wi-Fi");
}
memset(wifi_cfg.sta.ssid, 0, sizeof(wifi_cfg.sta.ssid));
memset(wifi_cfg.sta.password, 0, sizeof(wifi_cfg.sta.password));
if (esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg) != ESP_OK)
{
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);
_preferences->putBool(preference_official_hybrid_actions, false);
_preferences->putBool(preference_official_hybrid_retry, false);
_preferences->putBool(preference_disable_non_json, false);
_preferences->putBool(preference_update_from_mqtt, false);
_preferences->putBool(preference_ip_dhcp_enabled, true);
_preferences->putBool(preference_enable_bootloop_reset, false);
_preferences->putBool(preference_show_secrets, false);
_preferences->putBool(preference_conf_info_enabled, true);
_preferences->putBool(preference_keypad_info_enabled, false);
_preferences->putBool(preference_keypad_topic_per_entry, false);
_preferences->putBool(preference_keypad_publish_code, false);
_preferences->putBool(preference_keypad_control_enabled, false);
_preferences->putBool(preference_timecontrol_info_enabled, false);
_preferences->putBool(preference_timecontrol_topic_per_entry, false);
_preferences->putBool(preference_timecontrol_control_enabled, false);
_preferences->putBool(preference_publish_authdata, false);
_preferences->putBool(preference_register_as_app, false);
_preferences->putBool(preference_register_opener_as_app, false);
_preferences->putInt(preference_mqtt_broker_port, 1883);
_preferences->putInt(preference_buffer_size, CHAR_BUFFER_SIZE);
_preferences->putInt(preference_task_size_network, NETWORK_TASK_SIZE);
_preferences->putInt(preference_task_size_nuki, NUKI_TASK_SIZE);
_preferences->putInt(preference_authlog_max_entries, MAX_AUTHLOG);
_preferences->putInt(preference_keypad_max_entries, MAX_KEYPAD);
_preferences->putInt(preference_timecontrol_max_entries, MAX_TIMECONTROL);
_preferences->putInt(preference_query_interval_hybrid_lockstate, 600);
_preferences->putInt(preference_rssi_publish_interval, 60);
_preferences->putInt(preference_network_timeout, 60);
_preferences->putInt(preference_command_nr_of_retries, 3);
_preferences->putInt(preference_command_retry_delay, 100);
_preferences->putInt(preference_restart_ble_beacon_lost, 60);
_preferences->putInt(preference_query_interval_lockstate, 1800);
_preferences->putInt(preference_query_interval_configuration, 3600);
_preferences->putInt(preference_query_interval_battery, 1800);
_preferences->putInt(preference_query_interval_keypad, 1800);
}
_hassEnabled = _preferences->getString(preference_mqtt_hass_discovery) != "";
_hassEnabled = _preferences->getBool(preference_mqtt_hass_enabled, false);
readSettings();
}
@@ -405,7 +334,8 @@ void NukiWrapper::update()
}
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && !_hassSetupCompleted)
{
setupHASS();
_network->setupHASS(1, _nukiConfig.nukiId, (char*)_nukiConfig.name, _firmwareVersion.c_str(), _hardwareVersion.c_str(), hasDoorSensor(), _hasKeypad);
_hassSetupCompleted = true;
}
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
{
@@ -693,13 +623,13 @@ void NukiWrapper::updateConfig()
}
else
{
Log->println(F("Invalid/Unexpected lock config recieved, ID does not matched saved ID"));
Log->println(F("Invalid/Unexpected lock config received, ID does not matched saved ID"));
expectedConfig = false;
}
}
else
{
Log->println(F("Invalid/Unexpected lock config recieved, Config is not valid"));
Log->println(F("Invalid/Unexpected lock config received, Config is not valid"));
expectedConfig = false;
}
@@ -716,7 +646,7 @@ void NukiWrapper::updateConfig()
}
else
{
Log->println(F("Invalid/Unexpected lock advanced config recieved, Advanced config is not valid"));
Log->println(F("Invalid/Unexpected lock advanced config received, Advanced config is not valid"));
expectedConfig = false;
}
}
@@ -729,7 +659,7 @@ void NukiWrapper::updateConfig()
else
{
++_retryConfigCount;
Log->println(F("Invalid/Unexpected lock config and/or advanced config recieved, retrying in 10 seconds"));
Log->println(F("Invalid/Unexpected lock config and/or advanced config received, retrying in 10 seconds"));
int64_t ts = espMillis();
_nextConfigUpdateTs = ts + 10000;
}
@@ -4074,28 +4004,6 @@ void NukiWrapper::readAdvancedConfig()
}
}
void NukiWrapper::setupHASS()
{
if(!_nukiConfigValid)
{
return;
}
if(_preferences->getUInt(preference_nuki_id_lock, 0) != _nukiConfig.nukiId)
{
return;
}
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
baseTopic.concat("/lock");
char uidString[20];
itoa(_nukiConfig.nukiId, uidString, 16);
_network->publishHASSConfig((char*)"SmartLock", baseTopic.c_str(),(char*)_nukiConfig.name, uidString, _firmwareVersion.c_str(), _hardwareVersion.c_str(), hasDoorSensor(), _hasKeypad, _publishAuthData, (char*)"lock", (char*)"unlock", (char*)"unlatch");
_hassSetupCompleted = true;
Log->println("HASS setup for lock completed.");
}
bool NukiWrapper::hasDoorSensor() const
{
return _keyTurnerState.doorSensorState == Nuki::DoorSensorState::DoorClosed ||
@@ -4103,13 +4011,6 @@ bool NukiWrapper::hasDoorSensor() const
_keyTurnerState.doorSensorState == Nuki::DoorSensorState::Calibrating;
}
void NukiWrapper::disableHASS()
{
char uidString[20];
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
_network->removeHASSConfig(uidString);
}
const BLEAddress NukiWrapper::getBleAddress() const
{
return _nukiLock.getBleAddress();

View File

@@ -17,7 +17,7 @@ public:
NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences);
virtual ~NukiWrapper();
void initialize(const bool& firstStart);
void initialize();
void readSettings();
void update();
@@ -33,8 +33,6 @@ public:
uint16_t getPin();
void unpair();
void disableHASS();
void disableWatchdog();
const NukiLock::KeyTurnerState& keyTurnerState();
@@ -81,8 +79,6 @@ private:
void readConfig();
void readAdvancedConfig();
void setupHASS();
void printCommandResult(Nuki::CmdResult result);
NukiLock::LockAction lockActionToEnum(const char* str); // char array at least 14 characters

View File

@@ -2,6 +2,9 @@
#include <vector>
#include "Config.h"
#ifndef CONFIG_IDF_TARGET_ESP32H2
#include "esp_wifi.h"
#endif
//CHANGE REQUIRES REBOOT TO TAKE EFFECT
#define preference_ip_dhcp_enabled (char*)"dhcpena"
@@ -48,6 +51,7 @@
#define preference_gpio_configuration (char*)"gpiocfg"
#define preference_mqtt_hass_enabled (char*)"hassena"
#define preference_mqtt_hass_discovery (char*)"hassdiscovery"
#define preference_hass_device_discovery (char*)"hassdevdisc"
#define preference_webserver_enabled (char*)"websrvena"
#define preference_update_from_mqtt (char*)"updMqtt"
#define preference_disable_non_json (char*)"disnonjson"
@@ -128,17 +132,17 @@
#define preference_presence_detection_timeout (char*)"prdtimeout"
#define preference_network_wifi_fallback_disabled (char*)"nwwififb"
inline bool initPreferences(Preferences* preferences)
inline void initPreferences(Preferences* preferences)
{
#ifdef NUKI_HUB_UPDATER
bool firstStart = false;
return firstStart;
return;
#else
bool firstStart = !preferences->getBool(preference_started_before);
#endif
if(firstStart)
{
Serial.println("First start, setting preference defaults");
preferences->putBool(preference_started_before, true);
preferences->putBool(preference_lock_enabled, true);
uint32_t aclPrefs[17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
@@ -151,6 +155,69 @@ inline bool initPreferences(Preferences* preferences)
preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs));
uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs));
#ifndef CONFIG_IDF_TARGET_ESP32H2
wifi_config_t wifi_cfg;
if(esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg) != ESP_OK)
{
Serial.println("Failed to get Wi-Fi configuration in RAM");
}
if (esp_wifi_set_storage(WIFI_STORAGE_FLASH) != ESP_OK)
{
Serial.println("Failed to set storage Wi-Fi");
}
memset(wifi_cfg.sta.ssid, 0, sizeof(wifi_cfg.sta.ssid));
memset(wifi_cfg.sta.password, 0, sizeof(wifi_cfg.sta.password));
if (esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg) != ESP_OK)
{
Serial.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);
preferences->putBool(preference_official_hybrid_actions, false);
preferences->putBool(preference_official_hybrid_retry, false);
preferences->putBool(preference_disable_non_json, false);
preferences->putBool(preference_update_from_mqtt, false);
preferences->putBool(preference_ip_dhcp_enabled, true);
preferences->putBool(preference_enable_bootloop_reset, false);
preferences->putBool(preference_show_secrets, false);
preferences->putBool(preference_conf_info_enabled, true);
preferences->putBool(preference_keypad_info_enabled, false);
preferences->putBool(preference_keypad_topic_per_entry, false);
preferences->putBool(preference_keypad_publish_code, false);
preferences->putBool(preference_keypad_control_enabled, false);
preferences->putBool(preference_timecontrol_info_enabled, false);
preferences->putBool(preference_timecontrol_topic_per_entry, false);
preferences->putBool(preference_timecontrol_control_enabled, false);
preferences->putBool(preference_publish_authdata, false);
preferences->putBool(preference_register_as_app, false);
preferences->putBool(preference_register_opener_as_app, false);
preferences->putInt(preference_mqtt_broker_port, 1883);
preferences->putInt(preference_buffer_size, CHAR_BUFFER_SIZE);
preferences->putInt(preference_task_size_network, NETWORK_TASK_SIZE);
preferences->putInt(preference_task_size_nuki, NUKI_TASK_SIZE);
preferences->putInt(preference_authlog_max_entries, MAX_AUTHLOG);
preferences->putInt(preference_keypad_max_entries, MAX_KEYPAD);
preferences->putInt(preference_timecontrol_max_entries, MAX_TIMECONTROL);
preferences->putInt(preference_query_interval_hybrid_lockstate, 600);
preferences->putInt(preference_rssi_publish_interval, 60);
preferences->putInt(preference_network_timeout, 60);
preferences->putInt(preference_command_nr_of_retries, 3);
preferences->putInt(preference_command_retry_delay, 100);
preferences->putInt(preference_restart_ble_beacon_lost, 60);
preferences->putInt(preference_query_interval_lockstate, 1800);
preferences->putInt(preference_query_interval_configuration, 3600);
preferences->putInt(preference_query_interval_battery, 1800);
preferences->putInt(preference_query_interval_keypad, 1800);
}
else
{
@@ -265,8 +332,7 @@ inline bool initPreferences(Preferences* preferences)
preferences->putInt(preference_config_version, atof(NUKI_HUB_VERSION) * 100);
}
}
return firstStart;
#endif
}
class DebugPreferences
@@ -294,7 +360,7 @@ private:
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_wifi_ssid, preference_wifi_pass,
preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_mqtt_hass_enabled
preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_mqtt_hass_enabled, preference_hass_device_discovery
};
std::vector<char*> _redact =
{
@@ -309,7 +375,7 @@ private:
preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_register_opener_as_app, preference_ip_dhcp_enabled,
preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled, preference_mqtt_hass_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_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_webserial_enabled, preference_hass_device_discovery,
preference_ntw_reconfigure, preference_keypad_check_code_enabled, preference_disable_network_not_connected
};
std::vector<char*> _bytePrefs =

View File

@@ -1740,21 +1740,22 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message)
//configChanged = true;
}
}
else if(key == "HADEVDISC")
{
if(_preferences->getBool(preference_hass_device_discovery, false) != (value == "1"))
{
_network->disableHASS();
_preferences->putBool(preference_hass_device_discovery, (value == "1"));
Log->print(F("Setting changed: "));
Log->println(key);
configChanged = true;
}
}
else if(key == "ENHADISC")
{
if(_preferences->getBool(preference_mqtt_hass_enabled, false) != (value == "1"))
{
if(!_preferences->getBool(preference_mqtt_hass_enabled, false))
{
if (_nuki != nullptr)
{
_nuki->disableHASS();
}
if (_nukiOpener != nullptr)
{
_nukiOpener->disableHASS();
}
}
_network->disableHASS();
_preferences->putBool(preference_mqtt_hass_enabled, (value == "1"));
Log->print(F("Setting changed: "));
Log->println(key);
@@ -1765,14 +1766,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message)
{
if(_preferences->getString(preference_mqtt_hass_discovery, "") != value)
{
if (_nuki != nullptr)
{
_nuki->disableHASS();
}
if (_nukiOpener != nullptr)
{
_nukiOpener->disableHASS();
}
_network->disableHASS();
_preferences->putString(preference_mqtt_hass_discovery, value);
Log->print(F("Setting changed: "));
Log->println(key);
@@ -3548,6 +3542,7 @@ esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request)
response.print("<h3>Advanced MQTT Configuration</h3>");
response.print("<table>");
printInputField(&response, "HASSDISCOVERY", "Home Assistant discovery topic (usually \"homeassistant\")", _preferences->getString(preference_mqtt_hass_discovery).c_str(), 30, "class=\"chkHass\"");
//printCheckBox(&response, "HADEVDISC", "Use Home Assistant device based discovery (2024.11+)", _preferences->getBool(preference_hass_device_discovery), "");
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), "");
@@ -4209,7 +4204,7 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request)
response.print(_preferences->getInt(preference_command_nr_of_retries, 3));
response.print("\nBluetooth command retry delay (ms): ");
response.print(_preferences->getInt(preference_command_retry_delay, 100));
response.print("\nSeconds until reboot when no BLE beacons recieved: ");
response.print("\nSeconds until reboot when no BLE beacons received: ");
response.print(_preferences->getInt(preference_restart_ble_beacon_lost, 60));
response.print("\n\n------------ QUERY / PUBLISH SETTINGS ------------");
response.print("\nLock/Opener state query interval (s): ");
@@ -4643,14 +4638,14 @@ esp_err_t WebCfgServer::processUnpair(PsychicRequest *request, bool opener)
if(!opener && _nuki != nullptr)
{
_nuki->disableHASS();
_nuki->unpair();
}
if(opener && _nukiOpener != nullptr)
{
_nukiOpener->disableHASS();
_nukiOpener->unpair();
}
_network->disableHASS();
waitAndProcess(false, 1000);
restartEsp(RestartReason::DeviceUnpaired);
return res;
@@ -4769,15 +4764,14 @@ esp_err_t WebCfgServer::processFactoryReset(PsychicRequest *request)
if(_nuki != nullptr)
{
_nuki->disableHASS();
_nuki->unpair();
}
if(_nukiOpener != nullptr)
{
_nukiOpener->disableHASS();
_nukiOpener->unpair();
}
_network->disableHASS();
_preferences->clear();
#ifndef CONFIG_IDF_TARGET_ESP32H2

View File

@@ -2,7 +2,9 @@
#include <Preferences.h>
#include <PsychicHttp.h>
#ifdef CONFIG_ESP_HTTPS_SERVER_ENABLE
#include <PsychicHttpsServer.h>
#endif
#include "esp_ota_ops.h"
#include "Config.h"

View File

@@ -446,7 +446,7 @@ void setup()
preferences = new Preferences();
preferences->begin("nukihub", false);
bool firstStart = initPreferences(preferences);
initPreferences(preferences);
bool doOta = false;
uint8_t partitionType = checkPartition();
@@ -468,13 +468,6 @@ void setup()
doOta = true;
}
#ifndef NUKI_HUB_UPDATER
if(preferences->getBool(preference_enable_bootloop_reset, false))
{
bootloopDetection();
}
#endif
#ifdef NUKI_HUB_UPDATER
Log->print(F("Nuki Hub OTA version "));
Log->println(NUKI_HUB_VERSION);
@@ -511,6 +504,11 @@ void setup()
});
}
#else
if(preferences->getBool(preference_enable_bootloop_reset, false))
{
bootloopDetection();
}
Log->print(F("Nuki Hub version "));
Log->println(NUKI_HUB_VERSION);
Log->print(F("Nuki Hub build "));
@@ -571,7 +569,7 @@ void setup()
}
nuki = new NukiWrapper("NukiHub", deviceIdLock, bleScanner, networkLock, nukiOfficial, gpio, preferences);
nuki->initialize(firstStart);
nuki->initialize();
}
Log->println(openerEnabled ? F("Nuki Opener enabled") : F("Nuki Opener disabled"));

View File

@@ -1,17 +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"
#include "../EspMillis.h"
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),
: NetworkDevice(hostname, preferences, ipConfiguration),
_deviceName(deviceName),
_phy_addr(phy_addr),
_power(power),
@@ -22,7 +19,9 @@ EthernetDevice::EthernetDevice(const String& hostname, Preferences* preferences,
_useSpi(false),
_preferences(preferences)
{
init();
#ifndef NUKI_HUB_UPDATER
NetworkDevice::init();
#endif
}
EthernetDevice::EthernetDevice(const String &hostname,
@@ -37,7 +36,7 @@ EthernetDevice::EthernetDevice(const String &hostname,
int spi_miso,
int spi_mosi,
eth_phy_type_t ethtype)
: NetworkDevice(hostname, ipConfiguration),
: NetworkDevice(hostname, preferences, ipConfiguration),
_deviceName(deviceName),
_phy_addr(phy_addr),
_cs(cs),
@@ -49,52 +48,9 @@ EthernetDevice::EthernetDevice(const String &hostname,
_type(ethtype),
_useSpi(true),
_preferences(preferences)
{
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);
}
NetworkDevice::init();
#endif
}

View File

@@ -11,9 +11,6 @@
#include <NetworkClientSecure.h>
#include <Preferences.h>
#include "NetworkDevice.h"
#ifndef NUKI_HUB_UPDATER
#include "espMqttClient.h"
#endif
class EthernetDevice : public NetworkDevice
{
@@ -61,21 +58,24 @@ 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;
bool _useSpi = false;
int64_t _checkIpTs = -1;
const std::string _deviceName;
uint8_t _phy_addr;
eth_phy_type_t _type;
// LAN8720
int _power;
int _mdc;
int _mdio;
eth_clock_mode_t _clock_mode;
// W55000 and DM9051
int _cs;
@@ -84,16 +84,4 @@ private:
int _spi_sck;
int _spi_miso;
int _spi_mosi;
int64_t _checkIpTs = -1;
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
};

View File

@@ -2,19 +2,19 @@
#ifndef CONFIG_IDF_TARGET_ESP32
typedef enum {
ETH_CLOCK_GPIO0_IN = 0,
ETH_CLOCK_GPIO16_OUT = 2,
ETH_CLOCK_GPIO17_OUT = 3
} eth_clock_mode_t;
ETH_CLOCK_GPIO0_IN = 0,
ETH_CLOCK_GPIO16_OUT = 2,
ETH_CLOCK_GPIO17_OUT = 3
} eth_clock_mode_t;
#define ETH_PHY_TYPE_LAN8720 ETH_PHY_MAX
#define ETH_PHY_TYPE_LAN8720 ETH_PHY_MAX
#else
#define ETH_PHY_TYPE_LAN8720 ETH_PHY_LAN8720
#endif
#define ETH_CLK_MODE_LAN8720 ETH_CLOCK_GPIO0_IN
#define ETH_PHY_ADDR_LAN8720 0
#define ETH_PHY_MDC_LAN8720 23
#define ETH_PHY_MDIO_LAN8720 18
#define ETH_PHY_POWER_LAN8720 -1
#define ETH_RESET_PIN_LAN8720 1
#define ETH_CLK_MODE_LAN8720 ETH_CLOCK_GPIO0_IN
#define ETH_PHY_ADDR_LAN8720 0
#define ETH_PHY_MDC_LAN8720 23
#define ETH_PHY_MDIO_LAN8720 18
#define ETH_PHY_POWER_LAN8720 -1
#define ETH_RESET_PIN_LAN8720 1

View File

@@ -2,13 +2,52 @@
#include "NetworkDevice.h"
#include "../Logger.h"
void NetworkDevice::printError()
{
Log->print(F("Free Heap: "));
Log->println(ESP.getFreeHeap());
}
#ifndef NUKI_HUB_UPDATER
#include "../MqttTopics.h"
#include "PreferencesKeys.h"
void NetworkDevice::init()
{
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);
}
}
void NetworkDevice::update()
{
if (_mqttEnabled)
@@ -90,7 +129,7 @@ bool NetworkDevice::mqttDisconnect(bool force)
return getMqttClient()->disconnect(force);
}
void NetworkDevice::setWill(const char *topic, uint8_t qos, bool retain, const char *payload)
void NetworkDevice::mqttSetWill(const char *topic, uint8_t qos, bool retain, const char *payload)
{
if (_useEncryption)
{
@@ -155,7 +194,7 @@ uint16_t NetworkDevice::mqttSubscribe(const char *topic, uint8_t qos)
return getMqttClient()->subscribe(topic, qos);
}
void NetworkDevice::disableMqtt()
void NetworkDevice::mqttDisable()
{
getMqttClient()->disconnect();
_mqttEnabled = false;

View File

@@ -2,16 +2,15 @@
#ifndef NUKI_HUB_UPDATER
#include "espMqttClient.h"
#include "MqttClientSetup.h"
#endif
#include "IPConfiguration.h"
#include "../EspMillis.h"
class NetworkDevice
{
public:
explicit NetworkDevice(const String& hostname, const IPConfiguration* ipConfiguration)
explicit NetworkDevice(const String& hostname, Preferences* preferences, const IPConfiguration* ipConfiguration)
: _hostname(hostname),
_preferences(preferences),
_ipConfiguration(ipConfiguration)
{}
@@ -19,7 +18,6 @@ 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;
@@ -31,36 +29,45 @@ public:
virtual String BSSIDstr() = 0;
#ifndef NUKI_HUB_UPDATER
virtual bool mqttConnect();
virtual bool mqttDisconnect(bool force);
virtual void mqttDisable();
virtual bool mqttConnected() const;
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 uint16_t mqttSubscribe(const char* topic, uint8_t qos);
virtual void mqttSetServer(const char* host, uint16_t port);
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 mqttSetWill(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:
const IPConfiguration* _ipConfiguration = nullptr;
Preferences* _preferences = nullptr;
#ifndef NUKI_HUB_UPDATER
espMqttClient *_mqttClient = nullptr;
espMqttClientSecure *_mqttClientSecure = nullptr;
bool _useEncryption = false;
bool _mqttEnabled = true;
void init();
MqttClient *getMqttClient() const;
bool _useEncryption = false;
bool _mqttEnabled = true;
char* _path;
char _ca[TLS_CA_MAX_SIZE] = {0};
char _cert[TLS_CERT_MAX_SIZE] = {0};
char _key[TLS_KEY_MAX_SIZE] = {0};
#endif
const String _hostname;
const IPConfiguration* _ipConfiguration = nullptr;
};

View File

@@ -1,61 +1,20 @@
#include "WifiDevice.h"
#include "esp_wifi.h"
#include <WiFi.h>
#include "WifiDevice.h"
#include "../PreferencesKeys.h"
#include "../Logger.h"
#ifndef NUKI_HUB_UPDATER
#include "../MqttTopics.h"
#include "espMqttClient.h"
#endif
#include "../RestartReason.h"
#include "../EspMillis.h"
WifiDevice::WifiDevice(const String& hostname, Preferences* preferences, const IPConfiguration* ipConfiguration)
: NetworkDevice(hostname, ipConfiguration),
: NetworkDevice(hostname, preferences, 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
#ifndef NUKI_HUB_UPDATER
NetworkDevice::init();
#endif
}
const String WifiDevice::deviceName() const
{
return "Built-in Wi-Fi";

View File

@@ -1,7 +1,5 @@
#pragma once
#include <WiFiClient.h>
#include <NetworkClientSecure.h>
#include <Preferences.h>
#include "NetworkDevice.h"
#include "IPConfiguration.h"
@@ -29,10 +27,10 @@ private:
void onDisconnected();
void onConnected();
bool connect();
char* _path;
Preferences* _preferences = nullptr;
char* _path;
int _foundNetworks = 0;
int _disconnectCount = 0;
bool _connectOnScanDone = false;
@@ -45,10 +43,4 @@ 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
};
};