set gpio output depending on lock state
This commit is contained in:
63
Gpio.cpp
63
Gpio.cpp
@@ -6,23 +6,20 @@
|
||||
#include "PreferencesKeys.h"
|
||||
|
||||
Gpio* Gpio::_inst = nullptr;
|
||||
NukiWrapper* Gpio::_nuki = nullptr;
|
||||
unsigned long Gpio::_lockedTs = 0;
|
||||
unsigned long Gpio::_debounceTs = 0;
|
||||
const uint Gpio::_debounceTime = 1000;
|
||||
|
||||
Gpio::Gpio(Preferences* preferences, NukiWrapper* nuki)
|
||||
Gpio::Gpio(Preferences* preferences)
|
||||
: _preferences(preferences)
|
||||
{
|
||||
_inst = this;
|
||||
loadPinConfiguration();
|
||||
|
||||
_inst->init(nuki);
|
||||
_inst->init();
|
||||
}
|
||||
|
||||
void Gpio::init(NukiWrapper* nuki)
|
||||
void Gpio::init()
|
||||
{
|
||||
_nuki = nuki;
|
||||
|
||||
for(const auto& entry : _inst->_pinConfiguration)
|
||||
{
|
||||
const auto it = std::find(_inst->availablePins().begin(), _inst->availablePins().end(), entry.pin);
|
||||
@@ -118,6 +115,19 @@ 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)
|
||||
@@ -147,6 +157,7 @@ void Gpio::getConfigurationText(String& text, const std::vector<PinEntry>& pinCo
|
||||
{
|
||||
if(entry.role != PinRole::Disabled)
|
||||
{
|
||||
text.concat("GPIO ");
|
||||
text.concat(entry.pin);
|
||||
if(entry.pin < 10)
|
||||
{
|
||||
@@ -164,23 +175,41 @@ const std::vector<PinRole>& Gpio::getAllRoles() const
|
||||
return _allRoles;
|
||||
}
|
||||
|
||||
void Gpio::notify(const GpioAction &action)
|
||||
{
|
||||
for(auto& callback : _callbacks)
|
||||
{
|
||||
callback(action);
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio::addCallback(std::function<void(const GpioAction&)> callback)
|
||||
{
|
||||
_callbacks.push_back(callback);
|
||||
}
|
||||
|
||||
void Gpio::isrLock()
|
||||
{
|
||||
if(millis() < _lockedTs) return;
|
||||
_nuki->lock();
|
||||
_lockedTs = millis() + _debounceTime;
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Lock);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrUnlock()
|
||||
{
|
||||
if(millis() < _lockedTs) return;
|
||||
_nuki->unlock();
|
||||
_lockedTs = millis() + _debounceTime;
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Unlock);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrUnlatch()
|
||||
{
|
||||
if(millis() < _lockedTs) return;
|
||||
_nuki->unlatch();
|
||||
_lockedTs = millis() + _debounceTime;
|
||||
}
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Unlatch);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::setPinOutput(const uint8_t& pin, const uint8_t& state)
|
||||
{
|
||||
digitalWrite(pin, state);
|
||||
}
|
||||
|
||||
28
Gpio.h
28
Gpio.h
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "NukiWrapper.h"
|
||||
#include <functional>
|
||||
#include <Preferences.h>
|
||||
#include <vector>
|
||||
|
||||
enum class PinRole
|
||||
{
|
||||
@@ -13,6 +14,13 @@ enum class PinRole
|
||||
OutputHighUnlocked,
|
||||
};
|
||||
|
||||
enum class GpioAction
|
||||
{
|
||||
Lock,
|
||||
Unlock,
|
||||
Unlatch
|
||||
};
|
||||
|
||||
struct PinEntry
|
||||
{
|
||||
uint8_t pin = 0;
|
||||
@@ -22,8 +30,10 @@ struct PinEntry
|
||||
class Gpio
|
||||
{
|
||||
public:
|
||||
Gpio(Preferences* preferences, NukiWrapper* nuki);
|
||||
static void init(NukiWrapper* nuki);
|
||||
Gpio(Preferences* preferences);
|
||||
static void init();
|
||||
|
||||
void addCallback(std::function<void(const GpioAction&)> callback);
|
||||
|
||||
void loadPinConfiguration();
|
||||
void savePinConfiguration(const std::vector<PinEntry>& pinConfiguration);
|
||||
@@ -31,12 +41,17 @@ 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;
|
||||
|
||||
const std::vector<PinRole>& getAllRoles() const;
|
||||
|
||||
void setPinOutput(const uint8_t& pin, const uint8_t& state);
|
||||
|
||||
private:
|
||||
void notify(const GpioAction& action);
|
||||
|
||||
const std::vector<uint8_t> _availablePins = { 2, 4, 5, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, 33 };
|
||||
const std::vector<PinRole> _allRoles =
|
||||
{
|
||||
@@ -55,9 +70,10 @@ private:
|
||||
static void IRAM_ATTR isrUnlock();
|
||||
static void IRAM_ATTR isrUnlatch();
|
||||
|
||||
std::vector<std::function<void(const GpioAction&)>> _callbacks;
|
||||
|
||||
static Gpio* _inst;
|
||||
static NukiWrapper* _nuki;
|
||||
static unsigned long _lockedTs;
|
||||
static unsigned long _debounceTs;
|
||||
|
||||
Preferences* _preferences = nullptr;
|
||||
};
|
||||
|
||||
@@ -8,11 +8,12 @@
|
||||
|
||||
NukiWrapper* nukiInst;
|
||||
|
||||
NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkLock* network, Preferences* preferences)
|
||||
NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkLock* network, Gpio* gpio, Preferences* preferences)
|
||||
: _deviceName(deviceName),
|
||||
_bleScanner(scanner),
|
||||
_nukiLock(deviceName, id),
|
||||
_network(network),
|
||||
_gpio(gpio),
|
||||
_preferences(preferences)
|
||||
{
|
||||
nukiInst = this;
|
||||
@@ -26,6 +27,8 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner:
|
||||
network->setLockActionReceivedCallback(nukiInst->onLockActionReceivedCallback);
|
||||
network->setConfigUpdateReceivedCallback(nukiInst->onConfigUpdateReceivedCallback);
|
||||
network->setKeypadCommandReceivedCallback(nukiInst->onKeypadCommandReceivedCallback);
|
||||
|
||||
_gpio->addCallback(NukiWrapper::gpioActionCallback);
|
||||
}
|
||||
|
||||
|
||||
@@ -307,6 +310,7 @@ void NukiWrapper::updateKeyTurnerState()
|
||||
_retryLockstateCount = 0;
|
||||
|
||||
_network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState);
|
||||
updateGpioOutputs();
|
||||
|
||||
char lockStateStr[20];
|
||||
lockstateToString(_keyTurnerState.lockState, lockStateStr);
|
||||
@@ -446,6 +450,22 @@ void NukiWrapper::onKeypadCommandReceivedCallback(const char *command, const uin
|
||||
nukiInst->onKeypadCommandReceived(command, id, name, code, enabled);
|
||||
}
|
||||
|
||||
void NukiWrapper::gpioActionCallback(const GpioAction &action)
|
||||
{
|
||||
switch(action)
|
||||
{
|
||||
case GpioAction::Lock:
|
||||
nukiInst->lock();
|
||||
break;
|
||||
case GpioAction::Unlock:
|
||||
nukiInst->unlock();
|
||||
break;
|
||||
case GpioAction::Unlatch:
|
||||
nukiInst->unlatch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NukiWrapper::onConfigUpdateReceived(const char *topic, const char *value)
|
||||
{
|
||||
if(strcmp(topic, mqtt_topic_config_button_enabled) == 0)
|
||||
@@ -719,3 +739,26 @@ void NukiWrapper::disableWatchdog()
|
||||
{
|
||||
_restartBeaconTimeout = -1;
|
||||
}
|
||||
|
||||
void NukiWrapper::updateGpioOutputs()
|
||||
{
|
||||
using namespace NukiLock;
|
||||
|
||||
const auto& pinConfiguration = _gpio->pinConfiguration();
|
||||
|
||||
const LockState& lockState = _keyTurnerState.lockState;
|
||||
|
||||
for(const auto& entry : pinConfiguration)
|
||||
{
|
||||
switch(entry.role)
|
||||
{
|
||||
case PinRole::OutputHighLocked:
|
||||
_gpio->setPinOutput(entry.pin, lockState == LockState::Locked || lockState == LockState::Locking ? HIGH : LOW);
|
||||
break;
|
||||
case PinRole::OutputHighUnlocked:
|
||||
_gpio->setPinOutput(entry.pin, lockState == LockState::Locked || lockState == LockState::Locking ? LOW : HIGH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
#include "NukiDataTypes.h"
|
||||
#include "BleScanner.h"
|
||||
#include "NukiLock.h"
|
||||
#include "Gpio.h"
|
||||
|
||||
class NukiWrapper : public Nuki::SmartlockEventHandler
|
||||
{
|
||||
public:
|
||||
NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkLock* network, Preferences* preferences);
|
||||
NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkLock* network, Gpio* gpio, Preferences* preferences);
|
||||
virtual ~NukiWrapper();
|
||||
|
||||
void initialize(const bool& firstStart);
|
||||
@@ -42,6 +43,8 @@ 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);
|
||||
|
||||
@@ -52,6 +55,8 @@ private:
|
||||
void updateKeypad();
|
||||
void postponeBleWatchdog();
|
||||
|
||||
void updateGpioOutputs();
|
||||
|
||||
void readConfig();
|
||||
void readAdvancedConfig();
|
||||
|
||||
@@ -63,8 +68,9 @@ private:
|
||||
|
||||
std::string _deviceName;
|
||||
NukiLock::NukiLock _nukiLock;
|
||||
BleScanner::Scanner* _bleScanner;
|
||||
NetworkLock* _network;
|
||||
BleScanner::Scanner* _bleScanner = nullptr;
|
||||
NetworkLock* _network = nullptr;
|
||||
Gpio* _gpio = nullptr;
|
||||
Preferences* _preferences;
|
||||
int _intervalLockstate = 0; // seconds
|
||||
int _intervalBattery = 0; // seconds
|
||||
|
||||
12
main.cpp
12
main.cpp
@@ -208,16 +208,18 @@ void setup()
|
||||
bleScanner->initialize("NukiHub");
|
||||
bleScanner->setScanDuration(10);
|
||||
|
||||
gpio = new Gpio(preferences);
|
||||
String gpioDesc;
|
||||
gpio->getConfigurationText(gpioDesc, gpio->pinConfiguration());
|
||||
Serial.print(gpioDesc.c_str());
|
||||
|
||||
Log->println(lockEnabled ? F("NUKI Lock enabled") : F("NUKI Lock disabled"));
|
||||
if(lockEnabled)
|
||||
{
|
||||
nuki = new NukiWrapper("NukiHub", deviceId, bleScanner, networkLock, preferences);
|
||||
nuki = new NukiWrapper("NukiHub", deviceId, bleScanner, networkLock, gpio, preferences);
|
||||
nuki->initialize(firstStart);
|
||||
|
||||
gpio = new Gpio(preferences, nuki);
|
||||
String gpioDesc;
|
||||
gpio->getConfigurationText(gpioDesc, gpio->pinConfiguration());
|
||||
Serial.print(gpioDesc.c_str());
|
||||
|
||||
|
||||
// if(preferences->getBool(preference_gpio_locking_enabled))
|
||||
// {
|
||||
|
||||
Reference in New Issue
Block a user