Fixes/Enhancements for pio/preferences, new info page, add reboot button, remove old files (#451)

* Preferences

* Info page

* Info page

* Remove old files + Info page
This commit is contained in:
iranl
2024-08-12 17:53:00 +02:00
committed by GitHub
parent 21adca01e7
commit 346c5c65d1
59 changed files with 1459 additions and 1403 deletions

View File

@@ -1 +0,0 @@
// #include <FreeRTOS.h>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,22 +0,0 @@
{
"release": {
"time": "2024-07-18 00:00:00",
"version": "8.35",
"fullversion": "8.35",
"build": ""
},
"beta": {
"time": "2024-08-01 14:05:28",
"version": "9.00",
"fullversion": "9.00-beta4",
"build": "10199751147.8.1",
"number": 4
},
"master": {
"time": "2024-08-01 14:21:27",
"version": "9.00",
"fullversion": "9.00-master4",
"build": "10199923947.18.1",
"number": 4
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,8 +1,7 @@
""" PlatformIO POST script execution to copy artifacts """
Import("env")
import os
import shutil
import re, shutil, os
from pathlib import Path
def get_board_name(env):
@@ -77,4 +76,14 @@ env.AddPostAction("$BUILD_DIR/bootloader.bin", copy_files)
if env.GetProjectOption("custom_build") == 'debug':
env.AddPostAction("$BUILD_DIR/firmware.elf", copy_files)
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", merge_bin)
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", merge_bin)
regex = r"\#define NUKI_HUB_DATE \"(.*)\""
content_new = ""
with open ('src/Config.h', 'r' ) as readfile:
file_content = readfile.read()
content_new = re.sub(regex, "#define NUKI_HUB_DATE \"unknownbuilddate\"", file_content, flags = re.M)
with open('src/Config.h', 'w') as writefile:
writefile.write(content_new)

View File

@@ -1,6 +1,15 @@
Import("env")
import re, shutil, os
from datetime import datetime, timezone
def recursive_purge(dir, pattern):
if os.path.isdir(dir):
for f in os.listdir(dir):
if os.path.isdir(os.path.join(dir, f)):
recursive_purge(os.path.join(dir, f), pattern)
elif re.search(pattern, os.path.join(dir, f)):
os.remove(os.path.join(dir, f))
regex = r"\#define NUKI_HUB_DATE \"(.*)\""
content_new = ""
@@ -10,3 +19,16 @@ with open ('src/Config.h', 'r' ) as readfile:
with open('src/Config.h', 'w') as writefile:
writefile.write(content_new)
recursive_purge("managed_components", ".component_hash")
if env.get('BOARD_MCU') == "esp32":
board = "esp32dev"
else:
board = env.get('BOARD_MCU')
if os.path.exists("sdkconfig." + board):
os.remove("sdkconfig." + board)
if os.path.exists("sdkconfig." + board + "_dbg"):
os.remove("sdkconfig." + board + "_dbg")

View File

@@ -1,3 +1,5 @@
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
CONFIG_LOG_DEFAULT_LEVEL=4
CONFIG_ESP_IPC_TASK_STACK_SIZE=8192
CONFIG_ESP_IPC_TASK_STACK_SIZE=8192
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
CONFIG_BOOTLOADER_LOG_LEVEL=1

View File

@@ -75,6 +75,4 @@ CONFIG_ARDUINO_SELECTIVE_SimpleBLE=n
CONFIG_HEAP_TASK_TRACKING=n
CONFIG_LOG_COLORS=n
CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=n
CONFIG_LOG_MAXIMUM_LEVEL=4
CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y
CONFIG_LOG_BOOTLOADER_LEVEL=2
CONFIG_LOG_MAXIMUM_LEVEL=4

View File

@@ -1,3 +1,5 @@
CONFIG_LOG_DEFAULT_LEVEL_NONE=y
CONFIG_LOG_DEFAULT_LEVEL=0
CONFIG_ESP_IPC_TASK_STACK_SIZE=1024
CONFIG_ESP_IPC_TASK_STACK_SIZE=1024
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
CONFIG_BOOTLOADER_LOG_LEVEL=1

View File

@@ -17,7 +17,7 @@ Gpio::Gpio(Preferences* preferences)
_inst = this;
loadPinConfiguration();
if(_preferences->getBool(preference_gpio_locking_enabled))
if(_preferences->getBool(preference_gpio_locking_enabled, false))
{
migrateObsoleteSetting();
}

View File

@@ -8,7 +8,7 @@ NukiDeviceId::NukiDeviceId(Preferences* preferences, const std::string& preferen
: _preferences(preferences),
_preferencesId(preferencesId)
{
_deviceId = _preferences->getUInt(_preferencesId.c_str());
_deviceId = _preferences->getUInt(_preferencesId.c_str(), 0);
if(_deviceId == 0)
{

View File

@@ -215,7 +215,7 @@ NetworkDevice *NukiNetwork::device()
#ifdef NUKI_HUB_UPDATER
void NukiNetwork::initialize()
{
_hostname = _preferences->getString(preference_hostname);
_hostname = _preferences->getString(preference_hostname, "");
if(_hostname == "")
{
@@ -240,9 +240,9 @@ void NukiNetwork::initialize()
_restartOnDisconnect = _preferences->getBool(preference_restart_on_disconnect, false);
_checkUpdates = _preferences->getBool(preference_check_updates, false);
_reconnectNetworkOnMqttDisconnect = _preferences->getBool(preference_recon_netw_on_mqtt_discon, false);
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
_hostname = _preferences->getString(preference_hostname);
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval, 0) * 1000;
_hostname = _preferences->getString(preference_hostname, "");
_discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery, "");
if(_hostname == "")
{
@@ -251,8 +251,8 @@ void NukiNetwork::initialize()
}
if(_rssiPublishInterval == 0)
{
_rssiPublishInterval = 60;
_preferences->putInt(preference_rssi_publish_interval, _rssiPublishInterval);
_rssiPublishInterval = 60000;
_preferences->putInt(preference_rssi_publish_interval, 60);
}
strcpy(_hostnameArr, _hostname.c_str());
_device->initialize();
@@ -263,7 +263,7 @@ void NukiNetwork::initialize()
String brokerAddr = _preferences->getString(preference_mqtt_broker);
strcpy(_mqttBrokerAddr, brokerAddr.c_str());
int port = _preferences->getInt(preference_mqtt_broker_port);
int port = _preferences->getInt(preference_mqtt_broker_port, 0);
if(port == 0)
{
port = 1883;
@@ -299,14 +299,14 @@ void NukiNetwork::initialize()
_device->mqttSetCleanSession(MQTT_CLEAN_SESSIONS);
_device->mqttSetKeepAlive(MQTT_KEEP_ALIVE);
_networkTimeout = _preferences->getInt(preference_network_timeout);
_networkTimeout = _preferences->getInt(preference_network_timeout, 0);
if(_networkTimeout == 0)
{
_networkTimeout = -1;
_preferences->putInt(preference_network_timeout, _networkTimeout);
}
_publishDebugInfo = _preferences->getBool(preference_publish_debug_info);
_publishDebugInfo = _preferences->getBool(preference_publish_debug_info, false);
char gpioPath[250];
bool rebGpio = rebuildGpio();
@@ -433,7 +433,7 @@ bool NukiNetwork::update()
_lastConnectedTs = ts;
#if PRESENCE_DETECTION_ENABLED
#if PRESENCE_DETECTION_ENABLED
if(_presenceDetection != nullptr && (_lastPresenceTs == 0 || (ts - _lastPresenceTs) > 3000))
{
char* presenceCsv = _presenceDetection->generateCsv();
@@ -446,7 +446,7 @@ bool NukiNetwork::update()
_lastPresenceTs = ts;
}
#endif
#endif
if(_device->signalStrength() != 127 && _rssiPublishInterval > 0 && ts - _lastRssiTs > _rssiPublishInterval)
{
@@ -515,7 +515,7 @@ bool NukiNetwork::update()
if(strcmp(_latestVersion, _preferences->getString(preference_latest_version).c_str()) != 0) _preferences->putString(preference_latest_version, _latestVersion);
}
}
}
}
https.end();
}
delete client;
@@ -592,7 +592,7 @@ void NukiNetwork::onMqttDisconnect(const espMqttClientTypes::DisconnectReason &r
bool NukiNetwork::reconnect()
{
_mqttConnectionState = 0;
int port = _preferences->getInt(preference_mqtt_broker_port);
int port = _preferences->getInt(preference_mqtt_broker_port, 1883);
while (!_device->mqttConnected() && (esp_timer_get_time() / 1000) > _nextReconnect)
{
@@ -907,7 +907,7 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha
json["dev"]["sw"] = softwareVersion;
json["dev"]["hw"] = hardwareVersion;
String cuUrl = _preferences->getString(preference_mqtt_hass_cu_url);
String cuUrl = _preferences->getString(preference_mqtt_hass_cu_url, "");
if (cuUrl != "")
{
@@ -942,7 +942,7 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha
serializeJson(json, _buffer, _bufferSize);
String path = _preferences->getString(preference_mqtt_hass_discovery);
String path = _preferences->getString(preference_mqtt_hass_discovery, "homeassistant");
path.concat("/lock/");
path.concat(uidString);
path.concat("/smartlock/config");
@@ -3453,9 +3453,7 @@ void NukiNetwork::publishHassTopic(const String& mqttDeviceType,
std::vector<std::pair<char*, char*>> additionalEntries
)
{
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);
if (discoveryTopic != "")
if (_discoveryTopic != "")
{
JsonDocument json;
json = createHassJson(uidString, uidStringPostfix, displayName, name, baseTopic, stateTopic, deviceType, deviceClass, stateClass, entityCat, commandTopic, additionalEntries);
@@ -3467,8 +3465,7 @@ void NukiNetwork::publishHassTopic(const String& mqttDeviceType,
String NukiNetwork::createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString)
{
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);
String path = discoveryTopic;
String path = _discoveryTopic;
path.concat("/");
path.concat(mqttDeviceType);
path.concat("/");
@@ -3482,9 +3479,7 @@ String NukiNetwork::createHassTopicPath(const String& mqttDeviceType, const Stri
void NukiNetwork::removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString)
{
String discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery);
if (discoveryTopic != "")
if (_discoveryTopic != "")
{
String path = createHassTopicPath(mqttDeviceType, mqttDeviceName, uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, "");
@@ -3883,4 +3878,9 @@ String NukiNetwork::localIP()
{
return _device->localIP();
}
bool NukiNetwork::isConnected()
{
return _device->isConnected();
}
#endif

View File

@@ -55,6 +55,7 @@ public:
void disableAutoRestarts(); // disable on OTA start
void disableMqtt();
String localIP();
bool isConnected();
void subscribe(const char* prefix, const char* path);
void initTopic(const char* prefix, const char* path, const char* value);
@@ -153,6 +154,7 @@ private:
const char* _lastWillPayload = "offline";
char _mqttConnectionStateTopic[211] = {0};
String _lockPath;
String _discoveryTopic;
PresenceDetection* _presenceDetection;
Gpio* _gpio;

View File

@@ -40,7 +40,7 @@ NukiNetworkLock::~NukiNetworkLock()
void NukiNetworkLock::initialize()
{
String mqttPath = _preferences->getString(preference_mqtt_lock_path);
String mqttPath = _preferences->getString(preference_mqtt_lock_path, "");
if(mqttPath.length() > 0)
{
size_t len = mqttPath.length();
@@ -55,11 +55,13 @@ void NukiNetworkLock::initialize()
_preferences->putString(preference_mqtt_lock_path, _mqttPath);
}
#if PRESENCE_DETECTION_ENABLED
#if PRESENCE_DETECTION_ENABLED
_network->setMqttPresencePath(_mqttPath);
#endif
#endif
_haEnabled = _preferences->getString(preference_mqtt_hass_discovery) != "";
_haEnabled = _preferences->getString(preference_mqtt_hass_discovery, "") != "";
_disableNonJSON = _preferences->getBool(preference_disable_non_json, false);
_offEnabled = _preferences->getBool(preference_official_hybrid, false);
_network->initTopic(_mqttPath, mqtt_topic_lock_action, "--");
_network->subscribe(_mqttPath, mqtt_topic_lock_action);
@@ -86,7 +88,7 @@ void NukiNetworkLock::initialize()
_network->subscribe(_mqttPath, mqtt_topic_query_lockstate);
_network->subscribe(_mqttPath, mqtt_topic_query_battery);
if(_preferences->getBool(preference_disable_non_json, false))
if(_disableNonJSON)
{
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_action);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_id);
@@ -125,7 +127,7 @@ void NukiNetworkLock::initialize()
if(_preferences->getBool(preference_keypad_control_enabled))
{
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
@@ -151,7 +153,7 @@ void NukiNetworkLock::initialize()
_network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--");
}
if(_preferences->getBool(preference_official_hybrid, false))
if(_offEnabled)
{
char uidString[20];
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
@@ -253,7 +255,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
if(atoi(value) > 0 && atoi(value) > _lastRollingLog) _lastRollingLog = atoi(value);
}
if(_preferences->getBool(preference_official_hybrid, false))
if(_offEnabled)
{
for(auto offTopic : _offTopics)
{
@@ -301,7 +303,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
}
}
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
if(comparePrefixedPath(topic, mqtt_topic_keypad_command_action))
{
@@ -515,14 +517,14 @@ void NukiNetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyT
jsonBattery["level"] = level;
jsonBattery["keypadCritical"] = keypadCritical ? "1" : "0";
if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_disableNonJSON)
{
publishBool(mqtt_topic_battery_critical, critical, true);
publishBool(mqtt_topic_battery_charging, charging, true);
publishInt(mqtt_topic_battery_level, level, true);
}
if((_firstTunerStatePublish || keyTurnerState.accessoryBatteryState != lastKeyTurnerState.accessoryBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
if((_firstTunerStatePublish || keyTurnerState.accessoryBatteryState != lastKeyTurnerState.accessoryBatteryState) && !_disableNonJSON)
{
publishBool(mqtt_topic_battery_keypad_critical, keypadCritical, true);
}
@@ -736,7 +738,7 @@ void NukiNetworkLock::publishLockstateCommandResult(const char *resultStr)
void NukiNetworkLock::publishBatteryReport(const NukiLock::BatteryReport& batteryReport)
{
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0, true);
publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain, true); // milliwatt seconds
@@ -818,7 +820,7 @@ void NukiNetworkLock::publishConfig(const NukiLock::Config &config)
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_basic_json, _buffer, true);
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1, true);
publishBool(mqtt_topic_config_led_enabled, config.ledEnabled == 1, true);
@@ -873,7 +875,7 @@ void NukiNetworkLock::publishAdvancedConfig(const NukiLock::AdvancedConfig &conf
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_advanced_json, _buffer, true);
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0, true);
publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1, true);
@@ -897,6 +899,8 @@ void NukiNetworkLock::publishBleAddress(const std::string &address)
void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
{
bool publishCode = _preferences->getBool(preference_keypad_publish_code, false);
bool topicPerEntry = _preferences->getBool(preference_keypad_topic_per_entry, false);
uint index = 0;
char uidString[20];
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
@@ -914,11 +918,7 @@ void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entr
jsonEntry["codeId"] = entry.codeId;
if(_preferences->getBool(preference_keypad_publish_code, false))
{
jsonEntry["code"] = entry.code;
}
if(publishCode) jsonEntry["code"] = entry.code;
jsonEntry["enabled"] = entry.enabled;
jsonEntry["name"] = entry.name;
char createdDT[20];
@@ -991,7 +991,7 @@ void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entr
sprintf(allowedUntilTimeT, "%02d:%02d", entry.allowedUntilTimeHour, entry.allowedUntilTimeMin);
jsonEntry["allowedUntilTime"] = allowedUntilTimeT;
if(_preferences->getBool(preference_keypad_topic_per_entry, false))
if(topicPerEntry)
{
basePath = mqtt_topic_keypad;
basePath.concat("/codes/");
@@ -1042,7 +1042,7 @@ void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entr
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_keypad_json, _buffer, true);
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
while(index < maxKeypadCodeCount)
{
@@ -1056,7 +1056,7 @@ void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entr
++index;
}
if(!_preferences->getBool(preference_keypad_publish_code, false))
if(!publishCode)
{
for(int i=0; i<maxKeypadCodeCount; i++)
{
@@ -1107,7 +1107,7 @@ void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entr
void NukiNetworkLock::publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(_disableNonJSON) return;
char codeName[sizeof(entry.name) + 1];
memset(codeName, 0, sizeof(codeName));
@@ -1133,6 +1133,7 @@ void NukiNetworkLock::publishKeypadEntry(const String topic, NukiLock::KeypadEnt
void NukiNetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount)
{
bool topicPerEntry = _preferences->getBool(preference_timecontrol_topic_per_entry, false);
uint index = 0;
char str[50];
char uidString[20];
@@ -1202,7 +1203,7 @@ void NukiNetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEn
NukiLock::lockactionToString(entry.lockAction, str);
jsonEntry["lockAction"] = str;
if(_preferences->getBool(preference_timecontrol_topic_per_entry, false))
if(topicPerEntry)
{
String basePath = mqtt_topic_timecontrol;
basePath.concat("/entries/");
@@ -1267,7 +1268,7 @@ void NukiNetworkLock::publishConfigCommandResult(const char* result)
void NukiNetworkLock::publishKeypadCommandResult(const char* result)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(_disableNonJSON) return;
publishString(mqtt_topic_keypad_command_result, result, true);
}
@@ -1303,7 +1304,7 @@ void NukiNetworkLock::setConfigUpdateReceivedCallback(void (*configUpdateReceive
void NukiNetworkLock::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(_disableNonJSON) return;
_keypadCommandReceivedReceivedCallback = keypadCommandReceivedReceivedCallback;
}

View File

@@ -109,6 +109,8 @@ private:
int64_t _lastMaintenanceTs = 0;
bool _haEnabled = false;
bool _reconnected = false;
bool _disableNonJSON = false;
bool _offEnabled = false;
String _keypadCommandName = "";
String _keypadCommandCode = "";

View File

@@ -35,7 +35,8 @@ void NukiNetworkOpener::initialize()
_preferences->putString(preference_mqtt_opener_path, _mqttPath);
}
_haEnabled = _preferences->getString(preference_mqtt_hass_discovery) != "";
_haEnabled = _preferences->getString(preference_mqtt_hass_discovery, "") != "";
_disableNonJSON = _preferences->getBool(preference_disable_non_json, false);
_network->initTopic(_mqttPath, mqtt_topic_lock_action, "--");
_network->subscribe(_mqttPath, mqtt_topic_lock_action);
@@ -50,7 +51,7 @@ void NukiNetworkOpener::initialize()
_network->subscribe(_mqttPath, mqtt_topic_query_lockstate);
_network->subscribe(_mqttPath, mqtt_topic_query_battery);
if(_preferences->getBool(preference_disable_non_json, false))
if(_disableNonJSON)
{
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_action);
_network->removeTopic(_mqttPath, mqtt_topic_keypad_command_id);
@@ -81,9 +82,9 @@ void NukiNetworkOpener::initialize()
_network->removeTopic(_mqttPath, mqtt_topic_config_single_lock);
}
if(_preferences->getBool(preference_keypad_control_enabled))
if(_preferences->getBool(preference_keypad_control_enabled, false))
{
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_action);
_network->subscribe(_mqttPath, mqtt_topic_keypad_command_id);
@@ -103,7 +104,7 @@ void NukiNetworkOpener::initialize()
_network->initTopic(_mqttPath, mqtt_topic_keypad_json_action, "--");
}
if(_preferences->getBool(preference_timecontrol_control_enabled))
if(_preferences->getBool(preference_timecontrol_control_enabled, false))
{
_network->subscribe(_mqttPath, mqtt_topic_timecontrol_action);
_network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--");
@@ -181,7 +182,7 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con
}
}
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
if(comparePrefixedPath(topic, mqtt_topic_keypad_command_action))
{
@@ -367,7 +368,7 @@ void NukiNetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& key
bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0;
jsonBattery["critical"] = critical ? "1" : "0";
if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_preferences->getBool(preference_disable_non_json, false))
if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_disableNonJSON)
{
publishBool(mqtt_topic_battery_critical, critical, true);
}
@@ -623,7 +624,7 @@ void NukiNetworkOpener::publishLockstateCommandResult(const char *resultStr)
void NukiNetworkOpener::publishBatteryReport(const NukiOpener::BatteryReport& batteryReport)
{
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0, true);
}
@@ -697,7 +698,7 @@ void NukiNetworkOpener::publishConfig(const NukiOpener::Config &config)
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_basic_json, _buffer, true);
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1, true);
publishBool(mqtt_topic_config_led_enabled, config.ledFlashEnabled == 1, true);
@@ -753,7 +754,7 @@ void NukiNetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_advanced_json, _buffer, true);
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
publishUInt(mqtt_topic_config_sound_level, config.soundLevel, true);
}
@@ -808,6 +809,8 @@ void NukiNetworkOpener::removeHASSConfig(char* uidString)
void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
{
bool publishCode = _preferences->getBool(preference_keypad_publish_code, false);
bool topicPerEntry = _preferences->getBool(preference_keypad_topic_per_entry, false);
uint index = 0;
char uidString[20];
itoa(_preferences->getUInt(preference_nuki_id_opener, 0), uidString, 16);
@@ -825,11 +828,7 @@ void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& en
jsonEntry["codeId"] = entry.codeId;
if(_preferences->getBool(preference_keypad_publish_code, false))
{
jsonEntry["code"] = entry.code;
}
if(publishCode) jsonEntry["code"] = entry.code;
jsonEntry["enabled"] = entry.enabled;
jsonEntry["name"] = entry.name;
char createdDT[20];
@@ -902,7 +901,7 @@ void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& en
sprintf(allowedUntilTimeT, "%02d:%02d", entry.allowedUntilTimeHour, entry.allowedUntilTimeMin);
jsonEntry["allowedUntilTime"] = allowedUntilTimeT;
if(_preferences->getBool(preference_keypad_topic_per_entry, false))
if(topicPerEntry)
{
basePath = mqtt_topic_keypad;
basePath.concat("/codes/");
@@ -953,7 +952,7 @@ void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& en
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_keypad_json, _buffer, true);
if(!_preferences->getBool(preference_disable_non_json, false))
if(!_disableNonJSON)
{
while(index < maxKeypadCodeCount)
{
@@ -967,7 +966,7 @@ void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& en
++index;
}
if(!_preferences->getBool(preference_keypad_publish_code, false))
if(!publishCode)
{
for(int i=0; i<maxKeypadCodeCount; i++)
{
@@ -1016,6 +1015,7 @@ void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& en
void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount)
{
bool topicPerEntry = _preferences->getBool(preference_timecontrol_topic_per_entry, false);
uint index = 0;
char str[50];
char uidString[20];
@@ -1085,7 +1085,7 @@ void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeContr
NukiOpener::lockactionToString(entry.lockAction, str);
jsonEntry["lockAction"] = str;
if(_preferences->getBool(preference_timecontrol_topic_per_entry, false))
if(topicPerEntry)
{
String basePath = mqtt_topic_timecontrol;
basePath.concat("/entries/");
@@ -1149,7 +1149,7 @@ void NukiNetworkOpener::publishConfigCommandResult(const char* result)
void NukiNetworkOpener::publishKeypadCommandResult(const char* result)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(_disableNonJSON) return;
publishString(mqtt_topic_keypad_command_result, result, true);
}
@@ -1180,7 +1180,7 @@ void NukiNetworkOpener::setConfigUpdateReceivedCallback(void (*configUpdateRecei
void NukiNetworkOpener::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(_disableNonJSON) return;
_keypadCommandReceivedReceivedCallback = keypadCommandReceivedReceivedCallback;
}
@@ -1237,7 +1237,7 @@ void NukiNetworkOpener::publishString(const char* topic, const char* value, bool
void NukiNetworkOpener::publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(_disableNonJSON) return;
char codeName[sizeof(entry.name) + 1];
memset(codeName, 0, sizeof(codeName));

View File

@@ -82,8 +82,9 @@ private:
char _mqttPath[181] = {0};
bool _isConnected = false;
bool _firstTunerStatePublish = true;
bool _haEnabled= false;
bool _haEnabled = false;
bool _reconnected = false;
bool _disableNonJSON = false;
String _keypadCommandName = "";
String _keypadCommandCode = "";

View File

@@ -1,5 +1,4 @@
#include "NukiOpenerWrapper.h"
#include <RTOS.h>
#include "PreferencesKeys.h"
#include "MqttTopics.h"
#include "Logger.h"
@@ -51,14 +50,16 @@ void NukiOpenerWrapper::initialize()
esp_power_level_t powerLevel;
if(_preferences->getInt(preference_ble_tx_power, 9) >= 9) powerLevel = ESP_PWR_LVL_P9;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 6) powerLevel = ESP_PWR_LVL_P6;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 3) powerLevel = ESP_PWR_LVL_P6;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 0) powerLevel = ESP_PWR_LVL_P3;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -3) powerLevel = ESP_PWR_LVL_N3;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -6) powerLevel = ESP_PWR_LVL_N6;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -9) powerLevel = ESP_PWR_LVL_N9;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -12) powerLevel = ESP_PWR_LVL_N12;
int pwrLvl = _preferences->getInt(preference_ble_tx_power, 9);
if(pwrLvl >= 9) powerLevel = ESP_PWR_LVL_P9;
else if(pwrLvl >= 6) powerLevel = ESP_PWR_LVL_P6;
else if(pwrLvl >= 3) powerLevel = ESP_PWR_LVL_P6;
else if(pwrLvl >= 0) powerLevel = ESP_PWR_LVL_P3;
else if(pwrLvl >= -3) powerLevel = ESP_PWR_LVL_N3;
else if(pwrLvl >= -6) powerLevel = ESP_PWR_LVL_N6;
else if(pwrLvl >= -9) powerLevel = ESP_PWR_LVL_N9;
else if(pwrLvl >= -12) powerLevel = ESP_PWR_LVL_N12;
_nukiOpener.setPower(powerLevel);
_nukiOpener.registerBleScanner(_bleScanner);
@@ -76,6 +77,8 @@ void NukiOpenerWrapper::initialize()
_nrOfRetries = _preferences->getInt(preference_command_nr_of_retries, 200);
_retryDelay = _preferences->getInt(preference_command_retry_delay);
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
_preferences->getBytes(preference_conf_opener_basic_acl, &_basicOpenerConfigAclPrefs, sizeof(_basicOpenerConfigAclPrefs));
_preferences->getBytes(preference_conf_opener_advanced_acl, &_advancedOpenerConfigAclPrefs, sizeof(_advancedOpenerConfigAclPrefs));
if(_nrOfRetries < 0 || _nrOfRetries == 200)
{
@@ -477,7 +480,8 @@ void NukiOpenerWrapper::updateConfig()
_firmwareVersion = std::to_string(_nukiConfig.firmwareVersion[0]) + "." + std::to_string(_nukiConfig.firmwareVersion[1]) + "." + std::to_string(_nukiConfig.firmwareVersion[2]);
_hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]);
if(_preferences->getBool(preference_conf_info_enabled, true)) _network->publishConfig(_nukiConfig);
if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl(false);
_retryConfigCount = 0;
if(_preferences->getBool(preference_timecontrol_info_enabled, false)) updateTimeControl(false);
const int pinStatus = _preferences->getInt(preference_opener_pin_status, 4);
@@ -993,13 +997,6 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
const char *advancedKeys[20] = {"intercomID", "busModeSwitch", "shortCircuitDuration", "electricStrikeDelay", "randomElectricStrikeDelay", "electricStrikeDuration", "disableRtoAfterRing", "rtoTimeout", "doorbellSuppression", "doorbellSuppressionDuration", "soundRing", "soundOpen", "soundRto", "soundCm", "soundConfirmation", "soundLevel", "singleButtonPressAction", "doubleButtonPressAction", "batteryType", "automaticBatteryTypeDetection"};
bool basicUpdated = false;
bool advancedUpdated = false;
uint32_t basicOpenerConfigAclPrefs[16];
uint32_t advancedOpenerConfigAclPrefs[20];
nukiOpenerPreferences = new Preferences();
nukiOpenerPreferences->begin("nukihub", true);
nukiOpenerPreferences->getBytes(preference_conf_opener_basic_acl, &basicOpenerConfigAclPrefs, sizeof(basicOpenerConfigAclPrefs));
nukiOpenerPreferences->getBytes(preference_conf_opener_advanced_acl, &advancedOpenerConfigAclPrefs, sizeof(advancedOpenerConfigAclPrefs));
for(int i=0; i < 14; i++)
{
@@ -1013,7 +1010,7 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
continue;
}
if((int)basicOpenerConfigAclPrefs[i] == 1)
if((int)_basicOpenerConfigAclPrefs[i] == 1)
{
cmdResult = Nuki::CmdResult::Error;
_retryCount = 0;
@@ -1203,7 +1200,7 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
continue;
}
if((int)advancedOpenerConfigAclPrefs[j] == 1)
if((int)_advancedOpenerConfigAclPrefs[j] == 1)
{
cmdResult = Nuki::CmdResult::Error;
_retryCount = 0;
@@ -1449,8 +1446,6 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
}
}
nukiOpenerPreferences->end();
if(basicUpdated || advancedUpdated) jsonResult["general"] = "success";
else jsonResult["general"] = "noChange";
@@ -1501,7 +1496,7 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(!_preferences->getBool(preference_keypad_control_enabled))
if(!_preferences->getBool(preference_keypad_control_enabled, false))
{
_network->publishKeypadCommandResult("KeypadControlDisabled");
return;
@@ -1637,7 +1632,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
return;
}
if(!_preferences->getBool(preference_keypad_control_enabled))
if(!_preferences->getBool(preference_keypad_control_enabled, false))
{
_network->publishKeypadJsonCommandResult("keypadControlDisabled");
return;
@@ -2097,7 +2092,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
return;
}
if(!_preferences->getBool(preference_timecontrol_control_enabled))
if(!_preferences->getBool(preference_timecontrol_control_enabled, false))
{
_network->publishTimeControlCommandResult("timeControlControlDisabled");
return;
@@ -2399,7 +2394,7 @@ void NukiOpenerWrapper::setupHASS()
char uidString[20];
itoa(_nukiConfig.nukiId, uidString, 16);
if(_preferences->getBool(preference_opener_continuous_mode)) _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");
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;

View File

@@ -140,6 +140,8 @@ private:
int64_t _nextRssiTs = 0;
int64_t _lastRssi = 0;
int64_t _disableBleWatchdogTs = 0;
uint32_t _basicOpenerConfigAclPrefs[16];
uint32_t _advancedOpenerConfigAclPrefs[20];
std::string _firmwareVersion = "";
std::string _hardwareVersion = "";
NukiOpener::LockAction _nextLockAction = (NukiOpener::LockAction)0xff;

View File

@@ -1,5 +1,4 @@
#include "NukiWrapper.h"
#include <RTOS.h>
#include "PreferencesKeys.h"
#include "MqttTopics.h"
#include "Logger.h"
@@ -35,7 +34,7 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId,
network->setLockActionReceivedCallback(nukiInst->onLockActionReceivedCallback);
network->setOfficialUpdateReceivedCallback(nukiInst->onOfficialUpdateReceivedCallback);
network->setConfigUpdateReceivedCallback(nukiInst->onConfigUpdateReceivedCallback);
if(_preferences->getBool(preference_disable_non_json, false)) network->setKeypadCommandReceivedCallback(nukiInst->onKeypadCommandReceivedCallback);
if(_disableNonJSON) network->setKeypadCommandReceivedCallback(nukiInst->onKeypadCommandReceivedCallback);
network->setKeypadJsonCommandReceivedCallback(nukiInst->onKeypadJsonCommandReceivedCallback);
network->setTimeControlCommandReceivedCallback(nukiInst->onTimeControlCommandReceivedCallback);
@@ -54,15 +53,16 @@ void NukiWrapper::initialize(const bool& firstStart)
_nukiLock.initialize();
esp_power_level_t powerLevel;
int pwrLvl = _preferences->getInt(preference_ble_tx_power, 9);
if(_preferences->getInt(preference_ble_tx_power, 9) >= 9) powerLevel = ESP_PWR_LVL_P9;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 6) powerLevel = ESP_PWR_LVL_P6;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 3) powerLevel = ESP_PWR_LVL_P6;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 0) powerLevel = ESP_PWR_LVL_P3;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -3) powerLevel = ESP_PWR_LVL_N3;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -6) powerLevel = ESP_PWR_LVL_N6;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -9) powerLevel = ESP_PWR_LVL_N9;
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -12) powerLevel = ESP_PWR_LVL_N12;
if(pwrLvl >= 9) powerLevel = ESP_PWR_LVL_P9;
else if(pwrLvl >= 6) powerLevel = ESP_PWR_LVL_P6;
else if(pwrLvl >= 3) powerLevel = ESP_PWR_LVL_P6;
else if(pwrLvl >= 0) powerLevel = ESP_PWR_LVL_P3;
else if(pwrLvl >= -3) powerLevel = ESP_PWR_LVL_N3;
else if(pwrLvl >= -6) powerLevel = ESP_PWR_LVL_N6;
else if(pwrLvl >= -9) powerLevel = ESP_PWR_LVL_N9;
else if(pwrLvl >= -12) powerLevel = ESP_PWR_LVL_N12;
_nukiLock.setPower(powerLevel);
_nukiLock.registerBleScanner(_bleScanner);
@@ -81,6 +81,11 @@ void NukiWrapper::initialize(const bool& firstStart)
_nrOfRetries = _preferences->getInt(preference_command_nr_of_retries, 200);
_retryDelay = _preferences->getInt(preference_command_retry_delay);
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
_offEnabled = _preferences->getBool(preference_official_hybrid, false);
_disableNonJSON = _preferences->getBool(preference_disable_non_json, false);
_preferences->getBytes(preference_conf_lock_basic_acl, &_basicLockConfigaclPrefs, sizeof(_basicLockConfigaclPrefs));
_preferences->getBytes(preference_conf_lock_advanced_acl, &_advancedLockConfigaclPrefs, sizeof(_advancedLockConfigaclPrefs));
if(firstStart)
{
@@ -128,9 +133,9 @@ void NukiWrapper::initialize(const bool& firstStart)
_preferences->putInt(preference_query_interval_configuration, 3600);
_preferences->putInt(preference_query_interval_battery, 1800);
_preferences->putInt(preference_query_interval_keypad, 1800);
#if PRESENCE_DETECTION_ENABLED
#if PRESENCE_DETECTION_ENABLED
_preferences->putInt(preference_presence_detection_timeout, -1);
#endif
#endif
}
if(_nrOfRetries < 0 || _nrOfRetries == 200)
@@ -898,6 +903,7 @@ LockActionResult NukiWrapper::onLockActionReceivedCallback(const char *value)
}
nukiLockPreferences->end();
return LockActionResult::AccessDenied;
}
@@ -1041,10 +1047,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
Log->print(F("Lockstate: "));
Log->println(str);
if(_preferences->getString(preference_mqtt_hass_discovery) != "")
{
_network->publishState((NukiLock::LockState)_network->_offState);
}
_network->publishState((NukiLock::LockState)_network->_offState);
}
else if(strcmp(topic, mqtt_topic_official_doorsensorState) == 0)
{
@@ -1066,7 +1069,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
Log->print(F("Battery critical: "));
Log->println(_network->_offCritical);
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_critical, _network->_offCritical, true);
if(!_disableNonJSON) _network->publishBool(mqtt_topic_battery_critical, _network->_offCritical, true);
publishBatteryJson = true;
}
else if(strcmp(topic, mqtt_topic_official_batteryCharging) == 0)
@@ -1076,7 +1079,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
Log->print(F("Battery charging: "));
Log->println(_network->_offCharging);
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_charging, _network->_offCharging, true);
if(!_disableNonJSON) _network->publishBool(mqtt_topic_battery_charging, _network->_offCharging, true);
publishBatteryJson = true;
}
else if(strcmp(topic, mqtt_topic_official_batteryChargeState) == 0)
@@ -1086,19 +1089,19 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
Log->print(F("Battery level: "));
Log->println(_network->_offChargeState);
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishInt(mqtt_topic_battery_level, _network->_offChargeState, true);
if(!_disableNonJSON) _network->publishInt(mqtt_topic_battery_level, _network->_offChargeState, true);
publishBatteryJson = true;
}
else if(strcmp(topic, mqtt_topic_official_keypadBatteryCritical) == 0)
{
_network->_offKeypadCritical = (strcmp(value, "true") == 0 ? 1 : 0);
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_keypad_critical, _network->_offKeypadCritical, true);
if(!_disableNonJSON) _network->publishBool(mqtt_topic_battery_keypad_critical, _network->_offKeypadCritical, true);
publishBatteryJson = true;
}
else if(strcmp(topic, mqtt_topic_official_doorsensorBatteryCritical) == 0)
{
_network->_offDoorsensorCritical = (strcmp(value, "true") == 0 ? 1 : 0);
if(!_preferences->getBool(preference_disable_non_json, false)) _network->publishBool(mqtt_topic_battery_doorsensor_critical, _network->_offDoorsensorCritical, true);
if(!_disableNonJSON) _network->publishBool(mqtt_topic_battery_doorsensor_critical, _network->_offDoorsensorCritical, true);
publishBatteryJson = true;
}
else if(strcmp(topic, mqtt_topic_official_commandResponse) == 0)
@@ -1197,13 +1200,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
const char *advancedKeys[22] = {"unlockedPositionOffsetDegrees", "lockedPositionOffsetDegrees", "singleLockedPositionOffsetDegrees", "unlockedToLockedTransitionOffsetDegrees", "lockNgoTimeout", "singleButtonPressAction", "doubleButtonPressAction", "detachedCylinder", "batteryType", "automaticBatteryTypeDetection", "unlatchDuration", "autoLockTimeOut", "autoUnLockDisabled", "nightModeEnabled", "nightModeStartTime", "nightModeEndTime", "nightModeAutoLockEnabled", "nightModeAutoUnlockDisabled", "nightModeImmediateLockOnStart", "autoLockEnabled", "immediateAutoLockEnabled", "autoUpdateEnabled"};
bool basicUpdated = false;
bool advancedUpdated = false;
uint32_t basicLockConfigAclPrefs[16];
uint32_t advancedLockConfigAclPrefs[22];
nukiLockPreferences = new Preferences();
nukiLockPreferences->begin("nukihub", true);
nukiLockPreferences->getBytes(preference_conf_lock_basic_acl, &basicLockConfigAclPrefs, sizeof(basicLockConfigAclPrefs));
nukiLockPreferences->getBytes(preference_conf_lock_advanced_acl, &advancedLockConfigAclPrefs, sizeof(advancedLockConfigAclPrefs));
for(int i=0; i < 16; i++)
{
@@ -1217,7 +1213,7 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
continue;
}
if((int)basicLockConfigAclPrefs[i] == 1)
if((int)_basicLockConfigaclPrefs[i] == 1)
{
cmdResult = Nuki::CmdResult::Error;
_retryCount = 0;
@@ -1429,7 +1425,7 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
continue;
}
if((int)advancedLockConfigAclPrefs[j] == 1)
if((int)_advancedLockConfigaclPrefs[j] == 1)
{
cmdResult = Nuki::CmdResult::Error;
_retryCount = 0;
@@ -1701,8 +1697,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
}
}
nukiLockPreferences->end();
if(basicUpdated || advancedUpdated) jsonResult["general"] = "success";
else jsonResult["general"] = "noChange";
@@ -1731,9 +1725,6 @@ void NukiWrapper::onTimeControlCommandReceivedCallback(const char *value)
void NukiWrapper::gpioActionCallback(const GpioAction &action, const int& pin)
{
nukiLockPreferences = new Preferences();
nukiLockPreferences->begin("nukihub", true);
switch(action)
{
case GpioAction::Lock:
@@ -1782,13 +1773,11 @@ void NukiWrapper::gpioActionCallback(const GpioAction &action, const int& pin)
}
break;
}
nukiLockPreferences->end();
}
void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, const String &name, const String &code, const int& enabled)
{
if(_preferences->getBool(preference_disable_non_json, false)) return;
if(_disableNonJSON) return;
if(!_preferences->getBool(preference_keypad_control_enabled))
{
@@ -2619,7 +2608,7 @@ void NukiWrapper::notify(Nuki::EventType eventType)
{
if(!_network->_offConnected)
{
if(_preferences->getBool(preference_official_hybrid, false) && _intervalHybridLockstate > 0 && (esp_timer_get_time() / 1000) > (_intervalHybridLockstate * 1000))
if(_offEnabled && _intervalHybridLockstate > 0 && (esp_timer_get_time() / 1000) > (_intervalHybridLockstate * 1000))
{
Log->println("OffKeyTurnerStatusUpdated");
_statusUpdated = true;

View File

@@ -113,7 +113,8 @@ private:
bool _nukiAdvancedConfigValid = false;
bool _hassEnabled = false;
bool _hassSetupCompleted = false;
bool _offEnabled = false;
bool _disableNonJSON = false;
bool _paired = false;
bool _statusUpdated = false;
bool _hasKeypad = false;
@@ -139,6 +140,8 @@ private:
int64_t _nextRssiTs = 0;
int64_t _lastRssi = 0;
int64_t _disableBleWatchdogTs = 0;
uint32_t _basicLockConfigaclPrefs[16];
uint32_t _advancedLockConfigaclPrefs[22];
std::string _firmwareVersion = "";
std::string _hardwareVersion = "";
volatile NukiLock::LockAction _nextLockAction = (NukiLock::LockAction)0xff;

View File

@@ -103,12 +103,12 @@
inline bool initPreferences(Preferences* preferences)
{
#ifdef NUKI_HUB_UPDATER
#ifdef NUKI_HUB_UPDATER
bool firstStart = false;
return firstStart;
#else
#else
bool firstStart = !preferences->getBool(preference_started_before);
#endif
#endif
preferences->remove(preference_bootloop_counter);
@@ -289,145 +289,6 @@ private:
{
preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2
};
const bool isRedacted(const char* key) const
{
return std::find(_redact.begin(), _redact.end(), key) != _redact.end();
}
const String redact(const String s) const
{
return s == "" ? "" : "***";
}
const String redact(const int32_t i) const
{
return i == 0 ? "" : "***";
}
const String redact(const uint32_t i) const
{
return i == 0 ? "" : "***";
}
const String redact(const int64_t i) const
{
return i == 0 ? "" : "***";
}
const String redact(const uint64_t i) const
{
return i == 0 ? "" : "***";
}
const void appendPreferenceInt8(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const int32_t)preferences->getChar(key)) : String(preferences->getChar(key)));
s.concat("\n");
}
const void appendPreferenceUInt8(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const uint32_t)preferences->getUChar(key)) : String(preferences->getUChar(key)));
s.concat("\n");
}
const void appendPreferenceInt16(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const int32_t)preferences->getShort(key)) : String(preferences->getShort(key)));
s.concat("\n");
}
const void appendPreferenceUInt16(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const uint32_t)preferences->getUShort(key)) : String(preferences->getUShort(key)));
s.concat("\n");
}
const void appendPreferenceInt32(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const int32_t)preferences->getInt(key)) : String(preferences->getInt(key)));
s.concat("\n");
}
const void appendPreferenceUInt32(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const uint32_t)preferences->getUInt(key)) : String(preferences->getUInt(key)));
s.concat("\n");
}
const void appendPreferenceInt64(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const int64_t)preferences->getLong64(key)) : String(preferences->getLong64(key)));
s.concat("\n");
}
const void appendPreferenceUInt64(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const uint64_t)preferences->getULong64(key)) : String(preferences->getULong64(key)));
s.concat("\n");
}
const void appendPreferenceBool(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(preferences->getBool(key) ? "true" : "false");
s.concat("\n");
}
const void appendPreferenceString(Preferences *preferences, String& s, const char* description, const char* key)
{
s.concat(description);
s.concat(": ");
s.concat(isRedacted(key) ? redact((const String)preferences->getString(key)) : preferences->getString(key));
s.concat("\n");
}
const void appendPreference(Preferences *preferences, String& s, const char* key)
{
if(std::find(_boolPrefs.begin(), _boolPrefs.end(), key) != _boolPrefs.end())
{
appendPreferenceBool(preferences, s, key, key);
return;
}
switch(preferences->getType(key))
{
case PT_I8:
appendPreferenceInt8(preferences, s, key, key);
break;
case PT_I16:
appendPreferenceInt16(preferences, s, key, key);
break;
case PT_I32:
appendPreferenceInt32(preferences, s, key, key);
break;
case PT_I64:
appendPreferenceInt64(preferences, s, key, key);
break;
case PT_U8:
appendPreferenceUInt8(preferences, s, key, key);
break;
case PT_U16:
appendPreferenceUInt16(preferences, s, key, key);
break;
case PT_U32:
appendPreferenceUInt32(preferences, s, key, key);
break;
case PT_U64:
appendPreferenceUInt64(preferences, s, key, key);
break;
case PT_STR:
appendPreferenceString(preferences, s, key, key);
break;
default:
appendPreferenceString(preferences, s, key, key);
break;
}
}
public:
const std::vector<char*> getPreferencesKeys()
{
@@ -453,16 +314,4 @@ public:
{
return _charPrefs;
}
const String preferencesToString(Preferences *preferences)
{
String s = "";
for(const auto& key : _keys)
{
appendPreference(preferences, s, key);
}
return s;
}
};

View File

@@ -13,7 +13,7 @@ PresenceDetection::PresenceDetection(Preferences* preferences, BleScanner::Scann
_csv(buffer),
_bufferSize(bufferSize)
{
_timeout = _preferences->getInt(preference_presence_detection_timeout) * 1000;
_timeout = _preferences->getInt(preference_presence_detection_timeout, 0) * 1000;
if(_timeout == 0)
{
_timeout = 60000;

View File

@@ -3,6 +3,7 @@
enum class RestartReason
{
RequestedViaMqtt,
RequestedViaWebServer,
BLEBeaconWatchdog,
RestartOnDisconnectWatchdog,
RestartIntervalWatchdog,
@@ -69,6 +70,8 @@ inline static String getRestartReason()
{
case RestartReason::RequestedViaMqtt:
return "RequestedViaMqtt";
case RestartReason::RequestedViaWebServer:
return "RequestedViaWebServer";
case RestartReason::BLEBeaconWatchdog:
return "BLEBeaconWatchdog";
case RestartReason::RestartOnDisconnectWatchdog:

File diff suppressed because it is too large Load Diff

View File

@@ -49,34 +49,34 @@ private:
bool processArgs(String& message);
bool processImport(String& message);
void processGpioArgs();
void buildHtml(String& response);
void buildAccLvlHtml(String& response);
void buildCredHtml(String& response);
void buildImportExportHtml(String& response);
void buildMqttConfigHtml(String& response);
void buildStatusHtml(String& response);
void buildAdvancedConfigHtml(String& response);
void buildNukiConfigHtml(String& response);
void buildGpioConfigHtml(String& response);
void buildConfigureWifiHtml(String& response);
void buildInfoHtml(String& response);
void buildHtml();
void buildAccLvlHtml();
void buildCredHtml();
void buildImportExportHtml();
void buildMqttConfigHtml();
void buildStatusHtml();
void buildAdvancedConfigHtml();
void buildNukiConfigHtml();
void buildGpioConfigHtml();
void buildConfigureWifiHtml();
void buildInfoHtml();
void processUnpair(bool opener);
void processUpdate();
void processFactoryReset();
void printInputField(String& response, const char* token, const char* description, const char* value, const size_t& maxLength, const char* id, const bool& isPassword = false, const bool& showLengthRestriction = false);
void printInputField(String& response, const char* token, const char* description, const int value, size_t maxLength, const char* id);
void printCheckBox(String& response, const char* token, const char* description, const bool value, const char* htmlClass);
void printTextarea(String& response, const char *token, const char *description, const char *value, const size_t& maxLength, const bool& enabled = true, const bool& showLengthRestriction = false);
void printDropDown(String &response, const char *token, const char *description, const String preselectedValue, std::vector<std::pair<String, String>> options);
void buildNavigationButton(String& response, const char* caption, const char* targetPath, const char* labelText = "");
void buildNavigationMenuEntry(String &response, const char *title, const char *targetPath, const char* warningMessage = "");
void printInputField(const char* token, const char* description, const char* value, const size_t& maxLength, const char* id, const bool& isPassword = false, const bool& showLengthRestriction = false);
void printInputField(const char* token, const char* description, const int value, size_t maxLength, const char* id);
void printCheckBox(const char* token, const char* description, const bool value, const char* htmlClass);
void printTextarea(const char *token, const char *description, const char *value, const size_t& maxLength, const bool& enabled = true, const bool& showLengthRestriction = false);
void printDropDown(const char *token, const char *description, const String preselectedValue, std::vector<std::pair<String, String>> options);
void buildNavigationButton(const char* caption, const char* targetPath, const char* labelText = "");
void buildNavigationMenuEntry(const char *title, const char *targetPath, const char* warningMessage = "");
const std::vector<std::pair<String, String>> getNetworkDetectionOptions() const;
const std::vector<std::pair<String, String>> getGpioOptions() const;
String getPreselectionForGpio(const uint8_t& pin);
String pinStateToString(uint8_t value);
void printParameter(String& response, const char* description, const char* value, const char *link = "", const char *id = "");
void printParameter(const char* description, const char* value, const char *link = "", const char *id = "");
NukiWrapper* _nuki = nullptr;
NukiOpenerWrapper* _nukiOpener = nullptr;
@@ -87,12 +87,12 @@ private:
String generateConfirmCode();
String _confirmCode = "----";
void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5, bool redirect = false);
void buildOtaHtml(String& response, bool errored, bool debug = false);
void buildOtaCompletedHtml(String& response);
void buildConfirmHtml(const String &message, uint32_t redirectDelay = 5, bool redirect = false);
void buildOtaHtml(bool errored, bool debug = false);
void buildOtaCompletedHtml();
void sendCss();
void sendFavicon();
void buildHtmlHeader(String& response, String additionalHeader = "");
void buildHtmlHeader(String additionalHeader = "");
void waitAndProcess(const bool blocking, const uint32_t duration);
void handleOtaUpload();
@@ -109,5 +109,6 @@ private:
uint32_t _transferredSize = 0;
int64_t _otaStartTs = 0;
String _hostname;
String _response;
bool _enabled = true;
};

View File

@@ -121,7 +121,8 @@ void setReroute(){
void networkTask(void *pvParameters)
{
int64_t networkLoopTs = 0;
bool secrets = preferences->getBool(preference_show_secrets);
bool secrets = preferences->getBool(preference_show_secrets, false);
bool webEnabled = preferences->getBool(preference_webserver_enabled, true);
bool reroute = true;
while(true)
@@ -436,7 +437,7 @@ void setup()
gpio = new Gpio(preferences);
String gpioDesc;
gpio->getConfigurationText(gpioDesc, gpio->pinConfiguration(), "\n\r");
Serial.print(gpioDesc.c_str());
Log->print(gpioDesc.c_str());
bleScanner = new BleScanner::Scanner();
// Scan interval and window according to Nuki recommendations:
@@ -498,7 +499,7 @@ void setup()
webserialserver.begin();
#endif
if((partitionType==1 && preferences->getString(preference_ota_updater_url).length() > 0) || (partitionType==2 && preferences->getString(preference_ota_main_url).length() > 0)) setupTasks(true);
if((partitionType==1 && preferences->getString(preference_ota_updater_url, "").length() > 0) || (partitionType==2 && preferences->getString(preference_ota_main_url, "").length() > 0)) setupTasks(true);
else setupTasks(false);
}

View File

@@ -5,16 +5,16 @@
IPConfiguration::IPConfiguration(Preferences *preferences)
: _preferences(preferences)
{
if(_preferences->getString(preference_ip_address).length() <= 0)
if(_preferences->getString(preference_ip_address, "").length() <= 0)
{
Log->println("IP address empty, falling back to DHCP.");
_preferences->putBool(preference_ip_dhcp_enabled, true);
}
_ipAddress.fromString(_preferences->getString(preference_ip_address));
_subnet.fromString(_preferences->getString(preference_ip_subnet));
_gateway.fromString(_preferences->getString(preference_ip_gateway));
_dnsServer.fromString(_preferences->getString(preference_ip_dns_server));
_ipAddress.fromString(_preferences->getString(preference_ip_address, ""));
_subnet.fromString(_preferences->getString(preference_ip_subnet, ""));
_gateway.fromString(_preferences->getString(preference_ip_gateway, ""));
_dnsServer.fromString(_preferences->getString(preference_ip_dns_server, ""));
Log->print(F("IP configuration: "));
if(dhcpEnabled())
@@ -32,7 +32,7 @@ IPConfiguration::IPConfiguration(Preferences *preferences)
bool IPConfiguration::dhcpEnabled() const
{
return _preferences->getBool(preference_ip_dhcp_enabled);
return _preferences->getBool(preference_ip_dhcp_enabled, true);
}
const IPAddress IPConfiguration::ipAddress() const

View File

@@ -197,7 +197,7 @@ void W5500Device::initializeMacAddress(byte *mac)
mac[1] = 0x08; // wiznet prefix
mac[2] = 0xDC; // wiznet prefix
if(_preferences->getBool(preference_has_mac_saved))
if(_preferences->getBool(preference_has_mac_saved, false))
{
mac[3] = _preferences->getChar(preference_has_mac_byte_0);
mac[4] = _preferences->getChar(preference_has_mac_byte_1);

View File

@@ -13,12 +13,12 @@ RTC_NOINIT_ATTR char WiFiDevice_reconfdetect[17];
WifiDevice::WifiDevice(const String& hostname, Preferences* preferences, const IPConfiguration* ipConfiguration)
: NetworkDevice(hostname, ipConfiguration),
_preferences(preferences),
_wm(preferences->getString(preference_cred_user).c_str(), preferences->getString(preference_cred_password).c_str())
_wm(preferences->getString(preference_cred_user, "").c_str(), preferences->getString(preference_cred_password, "").c_str())
{
_startAp = strcmp(WiFiDevice_reconfdetect, "reconfigure_wifi") == 0;
#ifndef NUKI_HUB_UPDATER
_restartOnDisconnect = preferences->getBool(preference_restart_on_disconnect);
_restartOnDisconnect = preferences->getBool(preference_restart_on_disconnect, false);
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);
@@ -75,7 +75,7 @@ void WifiDevice::initialize()
std::vector<const char *> wm_menu;
wm_menu.push_back("wifi");
wm_menu.push_back("exit");
_wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled));
_wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled, false));
// reduced timeout if ESP is set to restart on disconnect
_wm.setFindBestRSSI(_preferences->getBool(preference_find_best_rssi));
_wm.setConnectTimeout(20);
@@ -167,14 +167,14 @@ ReconnectStatus WifiDevice::reconnect(bool force)
_isReconnecting = false;
}
if(!isConnected() && _disconnectTs > (esp_timer_get_time() / 1000) - 120000) _wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled));
if(!isConnected() && _disconnectTs > (esp_timer_get_time() / 1000) - 120000) _wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled, false));
return isConnected() ? ReconnectStatus::Success : ReconnectStatus::Failure;
}
void WifiDevice::onConnected()
{
_isReconnecting = false;
_wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled));
_wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled, false));
}
void WifiDevice::onDisconnected()

View File

@@ -1,9 +1,7 @@
""" PlatformIO POST script execution to copy updater """
Import("env")
import glob
import os
import shutil
import glob, re, shutil, os
from pathlib import Path
def get_board_name(env):
@@ -42,3 +40,13 @@ def remove_files(source, target, env):
env.AddPostAction("$BUILD_DIR/firmware.bin", copy_files)
env.AddPostAction("$BUILD_DIR/firmware.bin", remove_files)
regex = r"\#define NUKI_HUB_DATE \"(.*)\""
content_new = ""
with open ('../src/Config.h', 'r' ) as readfile:
file_content = readfile.read()
content_new = re.sub(regex, "#define NUKI_HUB_DATE \"unknownbuilddate\"", file_content, flags = re.M)
with open('../src/Config.h', 'w') as writefile:
writefile.write(content_new)

View File

@@ -1,6 +1,15 @@
Import("env")
import re, shutil, os
from datetime import datetime, timezone
def recursive_purge(dir, pattern):
if os.path.isdir(dir):
for f in os.listdir(dir):
if os.path.isdir(os.path.join(dir, f)):
recursive_purge(os.path.join(dir, f), pattern)
elif re.search(pattern, os.path.join(dir, f)):
os.remove(os.path.join(dir, f))
regex = r"\#define NUKI_HUB_DATE \"(.*)\""
content_new = ""
@@ -12,3 +21,12 @@ with open('../src/Config.h', 'w') as writefile:
writefile.write(content_new)
shutil.copy("../src/main.cpp", "src/main.cpp")
recursive_purge("managed_components", ".component_hash")
if env.get('BOARD_MCU') == "esp32":
board = "esp32dev"
else:
board = env.get('BOARD_MCU')
if os.path.exists("sdkconfig.updater_" + board):
os.remove("sdkconfig." + board)

View File

@@ -12,4 +12,11 @@ CONFIG_ARDUINO_SELECTIVE_COMPILATION=y
CONFIG_ARDUINO_SELECTIVE_HTTPClient=n
CONFIG_ARDUINO_SELECTIVE_WebServer=n
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
CONFIG_LOG_COLORS=n
CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=n
CONFIG_LOG_MAXIMUM_LEVEL=4
CONFIG_LOG_DEFAULT_LEVEL_NONE=y
CONFIG_LOG_DEFAULT_LEVEL=0
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
CONFIG_BOOTLOADER_LOG_LEVEL=1

View File

@@ -1,30 +0,0 @@
{
"name": "nukihub",
"new_install_prompt_erase": true,
"builds": [
{
"chipFamily": "ESP32",
"parts": [
{ "path": "webflash_nuki_hub_esp32.bin", "offset": 0 }
]
},
{
"chipFamily": "ESP32-S3",
"parts": [
{ "path": "webflash_nuki_hub_esp32s3.bin", "offset": 0 }
]
},
{
"chipFamily": "ESP32-C3",
"parts": [
{ "path": "webflash_nuki_hub_esp32c3.bin", "offset": 0 }
]
},
{
"chipFamily": "ESP32-C6",
"parts": [
{ "path": "webflash_nuki_hub_esp32c6.bin", "offset": 0 }
]
}
]
}

Binary file not shown.