add access level feature
This commit is contained in:
8
AccessLevel.h
Normal file
8
AccessLevel.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
enum class AccessLevel
|
||||
{
|
||||
Full = 0,
|
||||
LockOnly = 1,
|
||||
ReadOnly = 2
|
||||
};
|
||||
@@ -53,6 +53,8 @@ set(SRCFILES
|
||||
networkDevices/ClientSyncW5500.cpp
|
||||
networkDevices/espMqttClientW5500.cpp
|
||||
networkDevices/IPConfiguration.cpp
|
||||
AccessLevel.h
|
||||
LockActionResult.h
|
||||
QueryCommand.h
|
||||
NukiWrapper.cpp
|
||||
NukiOpenerWrapper.cpp
|
||||
|
||||
9
LockActionResult.h
Normal file
9
LockActionResult.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
enum class LockActionResult
|
||||
{
|
||||
Success,
|
||||
UnknownAction,
|
||||
AccessDenied,
|
||||
Failed
|
||||
};
|
||||
@@ -102,16 +102,36 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_lock_action))
|
||||
{
|
||||
if(strcmp(value, "") == 0 || strcmp(value, "--") == 0 || strcmp(value, "ack") == 0 || strcmp(value, "unknown_action") == 0) return;
|
||||
if(strcmp(value, "") == 0 ||
|
||||
strcmp(value, "--") == 0 ||
|
||||
strcmp(value, "ack") == 0 ||
|
||||
strcmp(value, "unknown_action") == 0 ||
|
||||
strcmp(value, "denied") == 0 ||
|
||||
strcmp(value, "error") == 0) return;
|
||||
|
||||
Log->print(F("Lock action received: "));
|
||||
Log->println(value);
|
||||
bool success = false;
|
||||
LockActionResult lockActionResult = LockActionResult::Failed;
|
||||
if(_lockActionReceivedCallback != NULL)
|
||||
{
|
||||
success = _lockActionReceivedCallback(value);
|
||||
lockActionResult = _lockActionReceivedCallback(value);
|
||||
}
|
||||
|
||||
switch(lockActionResult)
|
||||
{
|
||||
case LockActionResult::Success:
|
||||
publishString(mqtt_topic_lock_action, "ack");
|
||||
break;
|
||||
case LockActionResult::UnknownAction:
|
||||
publishString(mqtt_topic_lock_action, "unknown_action");
|
||||
break;
|
||||
case LockActionResult::AccessDenied:
|
||||
publishString(mqtt_topic_lock_action, "denied");
|
||||
break;
|
||||
case LockActionResult::Failed:
|
||||
publishString(mqtt_topic_lock_action, "error");
|
||||
break;
|
||||
}
|
||||
publishString(mqtt_topic_lock_action, success ? "ack" : "unknown_action");
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_keypad_command_action))
|
||||
@@ -458,7 +478,7 @@ void NetworkLock::publishKeypadCommandResult(const char* result)
|
||||
publishString(mqtt_topic_keypad_command_result, result);
|
||||
}
|
||||
|
||||
void NetworkLock::setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char *))
|
||||
void NetworkLock::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *))
|
||||
{
|
||||
_lockActionReceivedCallback = lockActionReceivedCallback;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "NukiLockConstants.h"
|
||||
#include "Network.h"
|
||||
#include "QueryCommand.h"
|
||||
#include "LockActionResult.h"
|
||||
|
||||
#define LOCK_LOG_JSON_BUFFER_SIZE 2048
|
||||
|
||||
@@ -38,7 +39,7 @@ public:
|
||||
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
||||
void publishKeypadCommandResult(const char* result);
|
||||
|
||||
void setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char* value));
|
||||
void setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char* value));
|
||||
void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* path, const char* value));
|
||||
void setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled));
|
||||
|
||||
@@ -84,7 +85,7 @@ private:
|
||||
char* _buffer;
|
||||
size_t _bufferSize;
|
||||
|
||||
bool (*_lockActionReceivedCallback)(const char* value) = nullptr;
|
||||
LockActionResult (*_lockActionReceivedCallback)(const char* value) = nullptr;
|
||||
void (*_configUpdateReceivedCallback)(const char* path, const char* value) = nullptr;
|
||||
void (*_keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled) = nullptr;
|
||||
};
|
||||
|
||||
@@ -93,16 +93,36 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_lock_action))
|
||||
{
|
||||
if(strcmp((char*)payload, "") == 0 || strcmp(value, "--") == 0 || strcmp(value, "ack") == 0 || strcmp(value, "unknown_action") == 0) return;
|
||||
if(strcmp(value, "") == 0 ||
|
||||
strcmp(value, "--") == 0 ||
|
||||
strcmp(value, "ack") == 0 ||
|
||||
strcmp(value, "unknown_action") == 0 ||
|
||||
strcmp(value, "denied") == 0 ||
|
||||
strcmp(value, "error") == 0) return;
|
||||
|
||||
Log->print(F("Opener lock action received: "));
|
||||
Log->print(F("Lock action received: "));
|
||||
Log->println(value);
|
||||
bool success = false;
|
||||
LockActionResult lockActionResult = LockActionResult::Failed;
|
||||
if(_lockActionReceivedCallback != NULL)
|
||||
{
|
||||
success = _lockActionReceivedCallback(value);
|
||||
lockActionResult = _lockActionReceivedCallback(value);
|
||||
}
|
||||
|
||||
switch(lockActionResult)
|
||||
{
|
||||
case LockActionResult::Success:
|
||||
publishString(mqtt_topic_lock_action, "ack");
|
||||
break;
|
||||
case LockActionResult::UnknownAction:
|
||||
publishString(mqtt_topic_lock_action, "unknown_action");
|
||||
break;
|
||||
case LockActionResult::AccessDenied:
|
||||
publishString(mqtt_topic_lock_action, "denied");
|
||||
break;
|
||||
case LockActionResult::Failed:
|
||||
publishString(mqtt_topic_lock_action, "error");
|
||||
break;
|
||||
}
|
||||
publishString(mqtt_topic_lock_action, success ? "ack" : "unknown_action");
|
||||
}
|
||||
|
||||
if(comparePrefixedPath(topic, mqtt_topic_keypad_command_action))
|
||||
@@ -508,7 +528,7 @@ void NetworkOpener::publishKeypadCommandResult(const char* result)
|
||||
publishString(mqtt_topic_keypad_command_result, result);
|
||||
}
|
||||
|
||||
void NetworkOpener::setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char *))
|
||||
void NetworkOpener::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *))
|
||||
{
|
||||
_lockActionReceivedCallback = lockActionReceivedCallback;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
||||
void publishKeypadCommandResult(const char* result);
|
||||
|
||||
void setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char* value));
|
||||
void setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char* value));
|
||||
void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* path, const char* value));
|
||||
void setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled));
|
||||
|
||||
@@ -86,7 +86,7 @@ private:
|
||||
char* _buffer;
|
||||
const size_t _bufferSize;
|
||||
|
||||
bool (*_lockActionReceivedCallback)(const char* value) = nullptr;
|
||||
LockActionResult (*_lockActionReceivedCallback)(const char* value) = nullptr;
|
||||
void (*_configUpdateReceivedCallback)(const char* path, const char* value) = nullptr;
|
||||
void (*_keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled) = nullptr;
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <NukiOpenerUtils.h>
|
||||
|
||||
NukiOpenerWrapper* nukiOpenerInst;
|
||||
AccessLevel NukiOpenerWrapper::_accessLevel = AccessLevel::ReadOnly;
|
||||
|
||||
NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Gpio* gpio, Preferences* preferences)
|
||||
: _deviceName(deviceName),
|
||||
@@ -55,6 +56,7 @@ void NukiOpenerWrapper::initialize()
|
||||
_nrOfRetries = _preferences->getInt(preference_command_nr_of_retries);
|
||||
_retryDelay = _preferences->getInt(preference_command_retry_delay);
|
||||
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
|
||||
_accessLevel = (AccessLevel)_preferences->getInt(preference_access_level);
|
||||
|
||||
if(_retryDelay <= 100)
|
||||
{
|
||||
@@ -465,11 +467,33 @@ NukiOpener::LockAction NukiOpenerWrapper::lockActionToEnum(const char *str)
|
||||
return (NukiOpener::LockAction)0xff;
|
||||
}
|
||||
|
||||
bool NukiOpenerWrapper::onLockActionReceivedCallback(const char *value)
|
||||
LockActionResult NukiOpenerWrapper::onLockActionReceivedCallback(const char *value)
|
||||
{
|
||||
NukiOpener::LockAction action = nukiOpenerInst->lockActionToEnum(value);
|
||||
nukiOpenerInst->_nextLockAction = action;
|
||||
return (int)action != 0xff;
|
||||
if((int)action == 0xff)
|
||||
{
|
||||
return LockActionResult::UnknownAction;
|
||||
}
|
||||
|
||||
switch(_accessLevel)
|
||||
{
|
||||
case AccessLevel::Full:
|
||||
nukiOpenerInst->_nextLockAction = action;
|
||||
return LockActionResult::Success;
|
||||
break;
|
||||
case AccessLevel::LockOnly:
|
||||
if(action == NukiOpener::LockAction::DeactivateRTO || action == NukiOpener::LockAction::DeactivateCM)
|
||||
{
|
||||
nukiOpenerInst->_nextLockAction = action;
|
||||
return LockActionResult::Success;
|
||||
}
|
||||
return LockActionResult::AccessDenied;
|
||||
break;
|
||||
case AccessLevel::ReadOnly:
|
||||
default:
|
||||
return LockActionResult::AccessDenied;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NukiOpenerWrapper::onConfigUpdateReceivedCallback(const char *topic, const char *value)
|
||||
@@ -503,6 +527,8 @@ void NukiOpenerWrapper::gpioActionCallback(const GpioAction &action)
|
||||
|
||||
void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *value)
|
||||
{
|
||||
if(_accessLevel != AccessLevel::Full) return;
|
||||
|
||||
if(strcmp(topic, mqtt_topic_config_button_enabled) == 0)
|
||||
{
|
||||
bool newValue = atoi(value) > 0;
|
||||
@@ -528,6 +554,8 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *va
|
||||
|
||||
void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint &id, const String &name, const String &code, const int& enabled)
|
||||
{
|
||||
if(_accessLevel != AccessLevel::Full) return;
|
||||
|
||||
if(!_hasKeypad)
|
||||
{
|
||||
if(_configRead)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "NukiDataTypes.h"
|
||||
#include "BleScanner.h"
|
||||
#include "Gpio.h"
|
||||
#include "AccessLevel.h"
|
||||
|
||||
class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler
|
||||
{
|
||||
@@ -43,7 +44,7 @@ public:
|
||||
void notify(NukiOpener::EventType eventType) override;
|
||||
|
||||
private:
|
||||
static bool onLockActionReceivedCallback(const char* value);
|
||||
static LockActionResult onLockActionReceivedCallback(const char* value);
|
||||
static void onConfigUpdateReceivedCallback(const char* topic, const char* value);
|
||||
static void onKeypadCommandReceivedCallback(const char* command, const uint& id, const String& name, const String& code, const int& enabled);
|
||||
static void gpioActionCallback(const GpioAction& action);
|
||||
@@ -85,6 +86,7 @@ private:
|
||||
int _retryDelay = 0;
|
||||
int _retryCount = 0;
|
||||
int _retryLockstateCount = 0;
|
||||
static AccessLevel _accessLevel;
|
||||
unsigned long _nextRetryTs = 0;
|
||||
std::vector<uint16_t> _keypadCodeIds;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <NukiLockUtils.h>
|
||||
|
||||
NukiWrapper* nukiInst;
|
||||
AccessLevel NukiWrapper::_accessLevel = AccessLevel::ReadOnly;
|
||||
|
||||
NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkLock* network, Gpio* gpio, Preferences* preferences)
|
||||
: _deviceName(deviceName),
|
||||
@@ -56,6 +57,7 @@ void NukiWrapper::initialize(const bool& firstStart)
|
||||
_nrOfRetries = _preferences->getInt(preference_command_nr_of_retries);
|
||||
_retryDelay = _preferences->getInt(preference_command_retry_delay);
|
||||
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
|
||||
_accessLevel = (AccessLevel)_preferences->getInt(preference_access_level);
|
||||
|
||||
if(firstStart)
|
||||
{
|
||||
@@ -433,11 +435,34 @@ NukiLock::LockAction NukiWrapper::lockActionToEnum(const char *str)
|
||||
return (NukiLock::LockAction)0xff;
|
||||
}
|
||||
|
||||
bool NukiWrapper::onLockActionReceivedCallback(const char *value)
|
||||
LockActionResult NukiWrapper::onLockActionReceivedCallback(const char *value)
|
||||
{
|
||||
NukiLock::LockAction action = nukiInst->lockActionToEnum(value);
|
||||
nukiInst->_nextLockAction = action;
|
||||
return (int)action != 0xff;
|
||||
|
||||
if((int)action == 0xff)
|
||||
{
|
||||
return LockActionResult::UnknownAction;
|
||||
}
|
||||
|
||||
switch(_accessLevel)
|
||||
{
|
||||
case AccessLevel::Full:
|
||||
nukiInst->_nextLockAction = action;
|
||||
return LockActionResult::Success;
|
||||
break;
|
||||
case AccessLevel::LockOnly:
|
||||
if(action == NukiLock::LockAction::Lock)
|
||||
{
|
||||
nukiInst->_nextLockAction = action;
|
||||
return LockActionResult::Success;
|
||||
}
|
||||
return LockActionResult::AccessDenied;
|
||||
break;
|
||||
case AccessLevel::ReadOnly:
|
||||
default:
|
||||
return LockActionResult::AccessDenied;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NukiWrapper::onConfigUpdateReceivedCallback(const char *topic, const char *value)
|
||||
@@ -468,6 +493,8 @@ void NukiWrapper::gpioActionCallback(const GpioAction &action)
|
||||
|
||||
void NukiWrapper::onConfigUpdateReceived(const char *topic, const char *value)
|
||||
{
|
||||
if(_accessLevel != AccessLevel::Full) return;
|
||||
|
||||
if(strcmp(topic, mqtt_topic_config_button_enabled) == 0)
|
||||
{
|
||||
bool newValue = atoi(value) > 0;
|
||||
@@ -521,6 +548,8 @@ void NukiWrapper::onConfigUpdateReceived(const char *topic, const char *value)
|
||||
|
||||
void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, const String &name, const String &code, const int& enabled)
|
||||
{
|
||||
if(_accessLevel != AccessLevel::Full) return;
|
||||
|
||||
if(!_hasKeypad)
|
||||
{
|
||||
if(_configRead)
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "BleScanner.h"
|
||||
#include "NukiLock.h"
|
||||
#include "Gpio.h"
|
||||
#include "AccessLevel.h"
|
||||
#include "LockActionResult.h"
|
||||
|
||||
class NukiWrapper : public Nuki::SmartlockEventHandler
|
||||
{
|
||||
@@ -40,7 +42,7 @@ public:
|
||||
void notify(Nuki::EventType eventType) override;
|
||||
|
||||
private:
|
||||
static bool onLockActionReceivedCallback(const char* value);
|
||||
static LockActionResult onLockActionReceivedCallback(const char* value);
|
||||
static void onConfigUpdateReceivedCallback(const char* topic, const char* value);
|
||||
static void onKeypadCommandReceivedCallback(const char* command, const uint& id, const String& name, const String& code, const int& enabled);
|
||||
static void gpioActionCallback(const GpioAction& action);
|
||||
@@ -105,6 +107,7 @@ private:
|
||||
int _retryCount = 0;
|
||||
int _retryLockstateCount = 0;
|
||||
long _rssiPublishInterval = 0;
|
||||
static AccessLevel _accessLevel;
|
||||
unsigned long _nextRetryTs = 0;
|
||||
unsigned long _nextLockStateUpdateTs = 0;
|
||||
unsigned long _nextBatteryReportTs = 0;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#define preference_query_interval_battery "batInterval"
|
||||
#define preference_query_interval_keypad "kpInterval"
|
||||
#define preference_keypad_control_enabled "kpEnabled"
|
||||
#define preference_access_level "accLvl"
|
||||
#define preference_register_as_app "regAsApp" // true = register as hub; false = register as app
|
||||
#define preference_command_nr_of_retries "nrRetry"
|
||||
#define preference_command_retry_delay "rtryDelay"
|
||||
@@ -67,7 +68,8 @@ private:
|
||||
preference_hostname, preference_network_timeout, preference_restart_on_disconnect,
|
||||
preference_restart_ble_beacon_lost, preference_query_interval_lockstate,
|
||||
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad,
|
||||
preference_keypad_control_enabled, preference_register_as_app, preference_command_nr_of_retries,
|
||||
preference_keypad_control_enabled, preference_access_level,
|
||||
preference_register_as_app, preference_command_nr_of_retries,
|
||||
preference_command_retry_delay, preference_cred_user, preference_cred_password, preference_publish_authdata,
|
||||
preference_publish_debug_info, preference_presence_detection_timeout,
|
||||
preference_has_mac_saved, preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Logger.h"
|
||||
#include "Config.h"
|
||||
#include "RestartReason.h"
|
||||
#include "AccessLevel.h"
|
||||
#include <esp_task_wdt.h>
|
||||
|
||||
WebCfgServer::WebCfgServer(NukiWrapper* nuki, NukiOpenerWrapper* nukiOpener, Network* network, Gpio* gpio, EthServer* ethServer, Preferences* preferences, bool allowRestartToPortal)
|
||||
@@ -406,6 +407,11 @@ bool WebCfgServer::processArgs(String& message)
|
||||
_preferences->putInt(preference_query_interval_battery, value.toInt());
|
||||
configChanged = true;
|
||||
}
|
||||
else if(key == "ACCLVL")
|
||||
{
|
||||
_preferences->putInt(preference_access_level, value.toInt());
|
||||
configChanged = true;
|
||||
}
|
||||
else if(key == "KPINT")
|
||||
{
|
||||
_preferences->putInt(preference_query_interval_keypad, value.toInt());
|
||||
@@ -801,6 +807,8 @@ void WebCfgServer::buildNukiConfigHtml(String &response)
|
||||
printInputField(response, "LSTINT", "Query interval lock state (seconds)", _preferences->getInt(preference_query_interval_lockstate), 10);
|
||||
printInputField(response, "CFGINT", "Query interval configuration (seconds)", _preferences->getInt(preference_query_interval_configuration), 10);
|
||||
printInputField(response, "BATINT", "Query interval battery (seconds)", _preferences->getInt(preference_query_interval_battery), 10);
|
||||
printDropDown(response, "ACCLVL", "Access level", String(_preferences->getInt(preference_access_level)), getAccessLevelOptions());
|
||||
|
||||
if((_nuki != nullptr && _nuki->hasKeypad()) || (_nukiOpener != nullptr && _nukiOpener->hasKeypad()))
|
||||
{
|
||||
printInputField(response, "KPINT", "Query interval keypad (seconds)", _preferences->getInt(preference_query_interval_keypad), 10);
|
||||
@@ -1289,6 +1297,17 @@ const std::vector<std::pair<String, String>> WebCfgServer::getGpioOptions() cons
|
||||
return options;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<String, String>> WebCfgServer::getAccessLevelOptions() const
|
||||
{
|
||||
std::vector<std::pair<String, String>> options;
|
||||
|
||||
options.push_back(std::make_pair(std::to_string((int)AccessLevel::Full).c_str(), "Full"));
|
||||
options.push_back(std::make_pair(std::to_string((int)AccessLevel::LockOnly).c_str(), "Lock operation only"));
|
||||
options.push_back(std::make_pair(std::to_string((int)AccessLevel::ReadOnly).c_str(), "Read only"));
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
String WebCfgServer::getPreselectionForGpio(const uint8_t &pin)
|
||||
{
|
||||
const std::vector<PinEntry>& pinConfiguration = _gpio->pinConfiguration();
|
||||
|
||||
@@ -60,6 +60,7 @@ private:
|
||||
|
||||
const std::vector<std::pair<String, String>> getNetworkDetectionOptions() const;
|
||||
const std::vector<std::pair<String, String>> getGpioOptions() const;
|
||||
const std::vector<std::pair<String, String>> getAccessLevelOptions() const;
|
||||
String getPreselectionForGpio(const uint8_t& pin);
|
||||
|
||||
void printParameter(String& response, const char* description, const char* value, const char *link = "");
|
||||
|
||||
Reference in New Issue
Block a user