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