add opener gpio control

This commit is contained in:
technyon
2023-04-07 16:23:51 +02:00
parent a783750741
commit 0ae0fb6265
6 changed files with 139 additions and 25 deletions

View File

@@ -43,6 +43,22 @@ void Gpio::init()
pinMode(entry.pin, INPUT_PULLUP);
attachInterrupt(entry.pin, isrUnlatch, FALLING);
break;
case PinRole::InputElectricStrikeActuation:
pinMode(entry.pin, INPUT_PULLUP);
attachInterrupt(entry.pin, isrElectricStrikeActuation, FALLING);
break;
case PinRole::InputActivateRTO:
pinMode(entry.pin, INPUT_PULLUP);
attachInterrupt(entry.pin, isrActivateRTO, FALLING);
break;
case PinRole::InputActivateCM:
pinMode(entry.pin, INPUT_PULLUP);
attachInterrupt(entry.pin, isrActivateCM, FALLING);
break;
case PinRole::InputDeactivateRtoCm:
pinMode(entry.pin, INPUT_PULLUP);
attachInterrupt(entry.pin, isrDeactivateRtoCm, FALLING);
break;
default:
pinMode(entry.pin, OUTPUT);
break;
@@ -115,19 +131,6 @@ const std::vector<PinEntry> &Gpio::pinConfiguration() const
return _pinConfiguration;
}
PinRole Gpio::getPinRole(uint8_t pin)
{
for(const auto& entry : _pinConfiguration)
{
if(entry.pin == pin)
{
return entry.role;
}
}
return PinRole::Disabled;
}
String Gpio::getRoleDescription(PinRole role) const
{
switch(role)
@@ -140,6 +143,14 @@ String Gpio::getRoleDescription(PinRole role) const
return "Input: Unlock";
case PinRole::InputUnlatch:
return "Input: Unlatch";
case PinRole::InputElectricStrikeActuation:
return "Input: Electric strike actuation";
case PinRole::InputActivateRTO:
return "Input: Activate RTO";
case PinRole::InputActivateCM:
return "Input: Activate CM";
case PinRole::InputDeactivateRtoCm:
return "Input: Deactivate RTO/CM";
case PinRole::OutputHighLocked:
return "Output: High when locked";
case PinRole::OutputHighUnlocked:
@@ -211,6 +222,34 @@ void Gpio::isrUnlatch()
_debounceTs = millis() + _debounceTime;
}
void Gpio::isrElectricStrikeActuation()
{
if(millis() < _debounceTs) return;
_inst->notify(GpioAction::ElectricStrikeActuation);
_debounceTs = millis() + _debounceTime;
}
void Gpio::isrActivateRTO()
{
if(millis() < _debounceTs) return;
_inst->notify(GpioAction::ActivateRTO);
_debounceTs = millis() + _debounceTime;
}
void Gpio::isrActivateCM()
{
if(millis() < _debounceTs) return;
_inst->notify(GpioAction::ActivateCM);
_debounceTs = millis() + _debounceTime;
}
void Gpio::isrDeactivateRtoCm()
{
if(millis() < _debounceTs) return;
_inst->notify(GpioAction::DeactivateRtoCm);
_debounceTs = millis() + _debounceTime;
}
void Gpio::setPinOutput(const uint8_t& pin, const uint8_t& state)
{
digitalWrite(pin, state);

19
Gpio.h
View File

@@ -10,6 +10,10 @@ enum class PinRole
InputLock,
InputUnlock,
InputUnlatch,
InputElectricStrikeActuation,
InputActivateRTO,
InputActivateCM,
InputDeactivateRtoCm,
OutputHighLocked,
OutputHighUnlocked,
OutputHighMotorBlocked,
@@ -19,7 +23,11 @@ enum class GpioAction
{
Lock,
Unlock,
Unlatch
Unlatch,
ElectricStrikeActuation,
ActivateRTO,
ActivateCM,
DeactivateRtoCm
};
struct PinEntry
@@ -42,7 +50,6 @@ public:
const std::vector<uint8_t>& availablePins() const;
const std::vector<PinEntry>& pinConfiguration() const;
PinRole getPinRole(uint8_t pin);
String getRoleDescription(PinRole role) const;
void getConfigurationText(String& text, const std::vector<PinEntry>& pinConfiguration) const;
@@ -60,6 +67,10 @@ private:
PinRole::InputLock,
PinRole::InputUnlock,
PinRole::InputUnlatch,
PinRole::InputElectricStrikeActuation,
PinRole::InputActivateRTO,
PinRole::InputActivateCM,
PinRole::InputDeactivateRtoCm,
PinRole::OutputHighLocked,
PinRole::OutputHighUnlocked
};
@@ -70,6 +81,10 @@ private:
static void IRAM_ATTR isrLock();
static void IRAM_ATTR isrUnlock();
static void IRAM_ATTR isrUnlatch();
static void IRAM_ATTR isrElectricStrikeActuation();
static void IRAM_ATTR isrActivateRTO();
static void IRAM_ATTR isrActivateCM();
static void IRAM_ATTR isrDeactivateRtoCm();
std::vector<std::function<void(const GpioAction&)>> _callbacks;

View File

@@ -8,11 +8,12 @@
NukiOpenerWrapper* nukiOpenerInst;
NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences)
NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Gpio* gpio, Preferences* preferences)
: _deviceName(deviceName),
_nukiOpener(deviceName, id),
_bleScanner(scanner),
_network(network),
_gpio(gpio),
_preferences(preferences)
{
nukiOpenerInst = this;
@@ -26,6 +27,8 @@ NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id,
network->setLockActionReceivedCallback(nukiOpenerInst->onLockActionReceivedCallback);
network->setConfigUpdateReceivedCallback(nukiOpenerInst->onConfigUpdateReceivedCallback);
network->setKeypadCommandReceivedCallback(nukiOpenerInst->onKeypadCommandReceivedCallback);
_gpio->addCallback(NukiOpenerWrapper::gpioActionCallback);
}
@@ -252,6 +255,36 @@ void NukiOpenerWrapper::update()
memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiOpener::OpenerState));
}
void NukiOpenerWrapper::electricStrikeActuation()
{
_nextLockAction = NukiOpener::LockAction::ElectricStrikeActuation;
}
void NukiOpenerWrapper::activateRTO()
{
_nextLockAction = NukiOpener::LockAction::ActivateRTO;
}
void NukiOpenerWrapper::activateCM()
{
_nextLockAction = NukiOpener::LockAction::ActivateCM;
}
void NukiOpenerWrapper::deactivateRtoCm()
{
if(_keyTurnerState.nukiState == NukiOpener::State::ContinuousMode)
{
_nextLockAction = NukiOpener::LockAction::DeactivateCM;
return;
}
if(_keyTurnerState.lockState == NukiOpener::LockState::RTOactive)
{
_nextLockAction = NukiOpener::LockAction::DeactivateRTO;
}
}
bool NukiOpenerWrapper::isPinSet()
{
return _nukiOpener.getSecurityPincode() != 0;
@@ -448,6 +481,25 @@ void NukiOpenerWrapper::onKeypadCommandReceivedCallback(const char *command, con
nukiOpenerInst->onKeypadCommandReceived(command, id, name, code, enabled);
}
void NukiOpenerWrapper::gpioActionCallback(const GpioAction &action)
{
switch(action)
{
case GpioAction::ElectricStrikeActuation:
nukiOpenerInst->electricStrikeActuation();
break;
case GpioAction::ActivateRTO:
nukiOpenerInst->activateRTO();
break;
case GpioAction::ActivateCM:
nukiOpenerInst->activateCM();
break;
case GpioAction::DeactivateRtoCm:
nukiOpenerInst->deactivateRtoCm();
break;
}
}
void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *value)
{
if(strcmp(topic, mqtt_topic_config_button_enabled) == 0)

View File

@@ -5,16 +5,22 @@
#include "NukiOpenerConstants.h"
#include "NukiDataTypes.h"
#include "BleScanner.h"
#include "Gpio.h"
class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler
{
public:
NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences);
NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Gpio* gpio, Preferences* preferences);
virtual ~NukiOpenerWrapper();
void initialize();
void update();
void electricStrikeActuation();
void activateRTO();
void activateCM();
void deactivateRtoCm();
bool isPinSet();
void setPin(const uint16_t pin);
@@ -40,6 +46,7 @@ private:
static bool 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);
void onConfigUpdateReceived(const char* topic, const char* value);
void onKeypadCommandReceived(const char* command, const uint& id, const String& name, const String& code, const int& enabled);
@@ -61,9 +68,10 @@ private:
std::string _deviceName;
NukiOpener::NukiOpener _nukiOpener;
BleScanner::Scanner* _bleScanner;
NetworkOpener* _network;
Preferences* _preferences;
BleScanner::Scanner* _bleScanner = nullptr;
NetworkOpener* _network = nullptr;
Gpio* _gpio = nullptr;
Preferences* _preferences = nullptr;
int _intervalLockstate = 0; // seconds
int _intervalBattery = 0; // seconds
int _intervalConfig = 60 * 60; // seconds

View File

@@ -36,13 +36,13 @@ WebCfgServer::WebCfgServer(NukiWrapper* nuki, NukiOpenerWrapper* nukiOpener, Net
_pinsConfigured = true;
if(_nuki != nullptr)
if(_nuki != nullptr && !_nuki->isPinSet())
{
_pinsConfigured = _pinsConfigured && _nuki->isPinSet();
_pinsConfigured = false;
}
if(_nukiOpener != nullptr)
if(_nukiOpener != nullptr && !_nukiOpener->isPinSet())
{
_pinsConfigured = _pinsConfigured && _nukiOpener->isPinSet();
_pinsConfigured = false;
}
_brokerConfigured = _preferences->getString(preference_mqtt_broker).length() > 0 && _preferences->getInt(preference_mqtt_broker_port) > 0;

View File

@@ -230,7 +230,7 @@ void setup()
Log->println(openerEnabled ? F("NUKI Opener enabled") : F("NUKI Opener disabled"));
if(openerEnabled)
{
nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, bleScanner, networkOpener, preferences);
nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, bleScanner, networkOpener, gpio, preferences);
nukiOpener->initialize();
}