1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
||||
build
|
||||
cmake-build-debug
|
||||
cmake-build-release
|
||||
cmake-build-release-s3
|
||||
|
||||
@@ -86,6 +86,9 @@ set(SRCFILES
|
||||
lib/nuki_ble/src/NukiUtils.cpp
|
||||
lib/nuki_ble/src/NukiLockUtils.cpp
|
||||
lib/nuki_ble/src/NukiOpenerUtils.cpp
|
||||
lib/gpio2go/src/Gpio2Go.cpp
|
||||
lib/gpio2go/src/InterruptMode.h
|
||||
lib/gpio2go/src/PinMode.h
|
||||
lib/BleScanner/src/BleInterfaces.h
|
||||
lib/BleScanner/src/BleScanner.cpp
|
||||
lib/MqttLogger/src/MqttLogger.cpp
|
||||
|
||||
4
Config.h
4
Config.h
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#define NUKI_HUB_VERSION "8.23"
|
||||
#define NUKI_HUB_VERSION "8.24"
|
||||
|
||||
#define MQTT_QOS_LEVEL 1
|
||||
#define MQTT_CLEAN_SESSIONS false
|
||||
|
||||
#define GPIO_DEBOUNCE_TIME 200
|
||||
65
Gpio.cpp
65
Gpio.cpp
@@ -1,13 +1,15 @@
|
||||
#include <esp32-hal.h>
|
||||
#include "Gpio.h"
|
||||
#include "Config.h"
|
||||
#include "Arduino.h"
|
||||
#include "Logger.h"
|
||||
#include "PreferencesKeys.h"
|
||||
#include "RestartReason.h"
|
||||
#include "lib/gpio2go/src/Gpio2Go.h"
|
||||
|
||||
Gpio* Gpio::_inst = nullptr;
|
||||
unsigned long Gpio::_debounceTs = 0;
|
||||
const uint Gpio::_debounceTime = 1000;
|
||||
const uint Gpio::_debounceTime = GPIO_DEBOUNCE_TIME;
|
||||
|
||||
Gpio::Gpio(Preferences* preferences)
|
||||
: _preferences(preferences)
|
||||
@@ -64,10 +66,27 @@ void Gpio::init()
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrDeactivateRtoCm, FALLING);
|
||||
break;
|
||||
case PinRole::OutputHighLocked:
|
||||
case PinRole::OutputHighUnlocked:
|
||||
case PinRole::OutputHighMotorBlocked:
|
||||
case PinRole::OutputHighRtoActive:
|
||||
case PinRole::OutputHighCmActive:
|
||||
case PinRole::OutputHighRtoOrCmActive:
|
||||
case PinRole::GeneralOutput:
|
||||
pinMode(entry.pin, OUTPUT);
|
||||
break;
|
||||
case PinRole::GeneralInputPullDown:
|
||||
Gpio2Go::configurePin(entry.pin, PinMode::InputPullDown, InterruptMode::Change, 300);
|
||||
break;
|
||||
case PinRole::GeneralInputPullUp:
|
||||
Gpio2Go::configurePin(entry.pin, PinMode::InputPullup, InterruptMode::Change, 300);
|
||||
break;
|
||||
default:
|
||||
pinMode(entry.pin, OUTPUT);
|
||||
break;
|
||||
}
|
||||
|
||||
Gpio2Go::subscribe(Gpio::inputCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +155,18 @@ const std::vector<PinEntry> &Gpio::pinConfiguration() const
|
||||
return _pinConfiguration;
|
||||
}
|
||||
|
||||
const PinRole Gpio::getPinRole(const int &pin) const
|
||||
{
|
||||
for(const auto& pinEntry : _pinConfiguration)
|
||||
{
|
||||
if(pinEntry.pin == pin)
|
||||
{
|
||||
return pinEntry.role;
|
||||
}
|
||||
}
|
||||
return PinRole::Disabled;
|
||||
}
|
||||
|
||||
String Gpio::getRoleDescription(PinRole role) const
|
||||
{
|
||||
switch(role)
|
||||
@@ -168,6 +199,12 @@ String Gpio::getRoleDescription(PinRole role) const
|
||||
return "Output: High when CM active";
|
||||
case PinRole::OutputHighRtoOrCmActive:
|
||||
return "Output: High when RTO or CM active";
|
||||
case PinRole::GeneralOutput:
|
||||
return "General output";
|
||||
case PinRole::GeneralInputPullDown:
|
||||
return "General input (Pull-down)";
|
||||
case PinRole::GeneralInputPullUp:
|
||||
return "General input (Pull-up)";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@@ -197,15 +234,20 @@ const std::vector<PinRole>& Gpio::getAllRoles() const
|
||||
return _allRoles;
|
||||
}
|
||||
|
||||
void Gpio::notify(const GpioAction &action)
|
||||
void Gpio::notify(const GpioAction &action, const int& pin)
|
||||
{
|
||||
for(auto& callback : _callbacks)
|
||||
{
|
||||
callback(action);
|
||||
callback(action, pin);
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio::addCallback(std::function<void(const GpioAction&)> callback)
|
||||
void Gpio::inputCallback(const int &pin)
|
||||
{
|
||||
_inst->notify(GpioAction::GeneralInput, pin);
|
||||
}
|
||||
|
||||
void Gpio::addCallback(std::function<void(const GpioAction&, const int&)> callback)
|
||||
{
|
||||
_callbacks.push_back(callback);
|
||||
}
|
||||
@@ -213,49 +255,49 @@ void Gpio::addCallback(std::function<void(const GpioAction&)> callback)
|
||||
void Gpio::isrLock()
|
||||
{
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Lock);
|
||||
_inst->notify(GpioAction::Lock, -1);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrUnlock()
|
||||
{
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Unlock);
|
||||
_inst->notify(GpioAction::Unlock, -1);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrUnlatch()
|
||||
{
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Unlatch);
|
||||
_inst->notify(GpioAction::Unlatch, -1);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrElectricStrikeActuation()
|
||||
{
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::ElectricStrikeActuation);
|
||||
_inst->notify(GpioAction::ElectricStrikeActuation, -1);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrActivateRTO()
|
||||
{
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::ActivateRTO);
|
||||
_inst->notify(GpioAction::ActivateRTO, -1);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrActivateCM()
|
||||
{
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::ActivateCM);
|
||||
_inst->notify(GpioAction::ActivateCM, -1);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrDeactivateRtoCm()
|
||||
{
|
||||
if(millis() < _debounceTs) return;
|
||||
_inst->notify(GpioAction::DeactivateRtoCm);
|
||||
_inst->notify(GpioAction::DeactivateRtoCm, -1);
|
||||
_debounceTs = millis() + _debounceTime;
|
||||
}
|
||||
|
||||
@@ -291,3 +333,4 @@ void Gpio::migrateObsoleteSetting()
|
||||
delay(200);
|
||||
restartEsp(RestartReason::GpioConfigurationUpdated);
|
||||
}
|
||||
|
||||
|
||||
19
Gpio.h
19
Gpio.h
@@ -19,7 +19,10 @@ enum class PinRole
|
||||
OutputHighMotorBlocked,
|
||||
OutputHighRtoActive,
|
||||
OutputHighCmActive,
|
||||
OutputHighRtoOrCmActive
|
||||
OutputHighRtoOrCmActive,
|
||||
GeneralOutput,
|
||||
GeneralInputPullDown,
|
||||
GeneralInputPullUp
|
||||
};
|
||||
|
||||
enum class GpioAction
|
||||
@@ -30,7 +33,8 @@ enum class GpioAction
|
||||
ElectricStrikeActuation,
|
||||
ActivateRTO,
|
||||
ActivateCM,
|
||||
DeactivateRtoCm
|
||||
DeactivateRtoCm,
|
||||
GeneralInput
|
||||
};
|
||||
|
||||
struct PinEntry
|
||||
@@ -47,13 +51,14 @@ public:
|
||||
|
||||
void migrateObsoleteSetting();
|
||||
|
||||
void addCallback(std::function<void(const GpioAction&)> callback);
|
||||
void addCallback(std::function<void(const GpioAction&, const int&)> callback);
|
||||
|
||||
void loadPinConfiguration();
|
||||
void savePinConfiguration(const std::vector<PinEntry>& pinConfiguration);
|
||||
|
||||
const std::vector<uint8_t>& availablePins() const;
|
||||
const std::vector<PinEntry>& pinConfiguration() const;
|
||||
const PinRole getPinRole(const int& pin) const;
|
||||
|
||||
String getRoleDescription(PinRole role) const;
|
||||
void getConfigurationText(String& text, const std::vector<PinEntry>& pinConfiguration, const String& linebreak = "\n") const;
|
||||
@@ -63,7 +68,8 @@ public:
|
||||
void setPinOutput(const uint8_t& pin, const uint8_t& state);
|
||||
|
||||
private:
|
||||
void notify(const GpioAction& action);
|
||||
void IRAM_ATTR notify(const GpioAction& action, const int& pin);
|
||||
static void inputCallback(const int & pin);
|
||||
|
||||
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 =
|
||||
@@ -81,6 +87,9 @@ private:
|
||||
PinRole::OutputHighRtoActive,
|
||||
PinRole::OutputHighCmActive,
|
||||
PinRole::OutputHighRtoOrCmActive,
|
||||
PinRole::GeneralInputPullDown,
|
||||
PinRole::GeneralInputPullUp,
|
||||
PinRole::GeneralOutput
|
||||
};
|
||||
|
||||
std::vector<PinEntry> _pinConfiguration;
|
||||
@@ -94,7 +103,7 @@ private:
|
||||
static void IRAM_ATTR isrActivateCM();
|
||||
static void IRAM_ATTR isrDeactivateRtoCm();
|
||||
|
||||
std::vector<std::function<void(const GpioAction&)>> _callbacks;
|
||||
std::vector<std::function<void(const GpioAction&, const int&)>> _callbacks;
|
||||
|
||||
static Gpio* _inst;
|
||||
static unsigned long _debounceTs;
|
||||
|
||||
@@ -60,4 +60,9 @@
|
||||
#define mqtt_topic_restart_reason_fw "/maintenance/restartReasonNukiHub"
|
||||
#define mqtt_topic_restart_reason_esp "/maintenance/restartReasonNukiEsp"
|
||||
#define mqtt_topic_mqtt_connection_state "/maintenance/mqttConnectionState"
|
||||
#define mqtt_topic_network_device "/maintenance/networkDevice"
|
||||
#define mqtt_topic_network_device "/maintenance/networkDevice"
|
||||
|
||||
#define mqtt_topic_gpio_prefix "/gpio"
|
||||
#define mqtt_topic_gpio_pin "/pin_"
|
||||
#define mqtt_topic_gpio_role "/role"
|
||||
#define mqtt_topic_gpio_state "/state"
|
||||
|
||||
166
Network.cpp
166
Network.cpp
@@ -14,8 +14,9 @@ bool _versionPublished = false;
|
||||
|
||||
RTC_NOINIT_ATTR char WiFi_fallbackDetect[14];
|
||||
|
||||
Network::Network(Preferences *preferences, const String& maintenancePathPrefix, char* buffer, size_t bufferSize)
|
||||
Network::Network(Preferences *preferences, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize)
|
||||
: _preferences(preferences),
|
||||
_gpio(gpio),
|
||||
_buffer(buffer),
|
||||
_bufferSize(bufferSize)
|
||||
{
|
||||
@@ -35,7 +36,8 @@ Network::Network(Preferences *preferences, const String& maintenancePathPrefix,
|
||||
_maintenancePathPrefix[i] = maintenancePathPrefix.charAt(i);
|
||||
}
|
||||
|
||||
String connectionStateTopic = _preferences->getString(preference_mqtt_lock_path) + mqtt_topic_mqtt_connection_state;
|
||||
_lockPath = _preferences->getString(preference_mqtt_lock_path);
|
||||
String connectionStateTopic = _lockPath + mqtt_topic_mqtt_connection_state;
|
||||
|
||||
memset(_mqttConnectionStateTopic, 0, sizeof(_mqttConnectionStateTopic));
|
||||
len = connectionStateTopic.length();
|
||||
@@ -210,6 +212,45 @@ void Network::initialize()
|
||||
}
|
||||
|
||||
_publishDebugInfo = _preferences->getBool(preference_publish_debug_info);
|
||||
|
||||
char gpioPath[250];
|
||||
bool rebGpio = rebuildGpio();
|
||||
|
||||
if(rebGpio)
|
||||
{
|
||||
Log->println(F("Rebuild MQTT GPIO structure"));
|
||||
}
|
||||
for (const auto &pinEntry: _gpio->pinConfiguration())
|
||||
{
|
||||
switch (pinEntry.role)
|
||||
{
|
||||
case PinRole::GeneralInputPullDown:
|
||||
case PinRole::GeneralInputPullUp:
|
||||
if(rebGpio)
|
||||
{
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role});
|
||||
publishString(_lockPath.c_str(), gpioPath, "input");
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state});
|
||||
publishString(_lockPath.c_str(), gpioPath, std::to_string(digitalRead(pinEntry.pin)).c_str());
|
||||
}
|
||||
break;
|
||||
case PinRole::GeneralOutput:
|
||||
if(rebGpio)
|
||||
{
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role});
|
||||
publishString(_lockPath.c_str(), gpioPath, "output");
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state});
|
||||
publishString(_lockPath.c_str(), gpioPath, "0");
|
||||
}
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state});
|
||||
subscribe(_lockPath.c_str(), gpioPath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_gpio->addCallback([this](const GpioAction& action, const int& pin)
|
||||
{
|
||||
gpioActionCallback(action, pin);
|
||||
});
|
||||
}
|
||||
|
||||
bool Network::update()
|
||||
@@ -309,6 +350,26 @@ bool Network::update()
|
||||
_lastMaintenanceTs = ts;
|
||||
}
|
||||
|
||||
for(const auto& gpioTs : _gpioTs)
|
||||
{
|
||||
uint8_t pin = gpioTs.first;
|
||||
unsigned long ts = gpioTs.second;
|
||||
if(ts != 0 && ((millis() - ts) >= GPIO_DEBOUNCE_TIME))
|
||||
{
|
||||
_gpioTs[pin] = 0;
|
||||
|
||||
uint8_t pinState = digitalRead(pin) == HIGH ? 1 : 0;
|
||||
char gpioPath[250];
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pin)).c_str(), mqtt_topic_gpio_state});
|
||||
publishInt(_lockPath.c_str(), gpioPath, pinState);
|
||||
|
||||
Log->print(F("GPIO "));
|
||||
Log->print(pin);
|
||||
Log->print(F(" (Input) --> "));
|
||||
Log->println(pinState);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -444,36 +505,40 @@ bool Network::reconnect()
|
||||
void Network::subscribe(const char* prefix, const char *path)
|
||||
{
|
||||
char prefixedPath[500];
|
||||
buildMqttPath(prefix, path, prefixedPath);
|
||||
buildMqttPath(prefixedPath, { prefix, path });
|
||||
_subscribedTopics.push_back(prefixedPath);
|
||||
}
|
||||
|
||||
void Network::initTopic(const char *prefix, const char *path, const char *value)
|
||||
{
|
||||
char prefixedPath[500];
|
||||
buildMqttPath(prefix, path, prefixedPath);
|
||||
buildMqttPath(prefixedPath, { prefix, path });
|
||||
String pathStr = prefixedPath;
|
||||
String valueStr = value;
|
||||
_initTopics[pathStr] = valueStr;
|
||||
}
|
||||
|
||||
void Network::buildMqttPath(const char* prefix, const char* path, char* outPath)
|
||||
void Network::buildMqttPath(char* outPath, std::initializer_list<const char*> paths)
|
||||
{
|
||||
int offset = 0;
|
||||
int i=0;
|
||||
while(prefix[i] != 0x00)
|
||||
{
|
||||
outPath[offset] = prefix[i];
|
||||
++offset;
|
||||
++i;
|
||||
}
|
||||
int pathCount = 0;
|
||||
|
||||
i=0;
|
||||
while(path[i] != 0x00)
|
||||
for(const char* path : paths)
|
||||
{
|
||||
outPath[offset] = path[i];
|
||||
++i;
|
||||
++offset;
|
||||
if(pathCount > 0 && path[0] != '/')
|
||||
{
|
||||
outPath[offset] = '/';
|
||||
++offset;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while(path[i] != 0)
|
||||
{
|
||||
outPath[offset] = path[i];
|
||||
++offset;
|
||||
++i;
|
||||
}
|
||||
++pathCount;
|
||||
}
|
||||
|
||||
outPath[offset] = 0x00;
|
||||
@@ -486,11 +551,6 @@ void Network::registerMqttReceiver(MqttReceiver* receiver)
|
||||
|
||||
void Network::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
|
||||
{
|
||||
if(millis() < _ignoreSubscriptionsTs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t value[50] = {0};
|
||||
size_t l = min(len, sizeof(value)-1);
|
||||
|
||||
@@ -502,14 +562,57 @@ void Network::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProper
|
||||
_inst->onMqttDataReceived(properties, topic, value, len, index, total);
|
||||
}
|
||||
|
||||
void Network::onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
|
||||
void Network::onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total)
|
||||
{
|
||||
parseGpioTopics(properties, topic, payload, len, index, total);
|
||||
|
||||
if(millis() < _ignoreSubscriptionsTs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto receiver : _mqttReceivers)
|
||||
{
|
||||
receiver->onMqttDataReceived(topic, (byte*)payload, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Network::parseGpioTopics(const espMqttClientTypes::MessageProperties &properties, const char *topic, const uint8_t *payload, size_t& len, size_t& index, size_t& total)
|
||||
{
|
||||
char gpioPath[250];
|
||||
buildMqttPath(gpioPath, {_lockPath.c_str(), mqtt_topic_gpio_prefix, mqtt_topic_gpio_pin});
|
||||
// /nuki_t/gpio/pin_17/state
|
||||
size_t gpioLen = strlen(gpioPath);
|
||||
if(strncmp(gpioPath, topic, gpioLen) == 0)
|
||||
{
|
||||
char pinStr[3] = {0};
|
||||
pinStr[0] = topic[gpioLen];
|
||||
if(topic[gpioLen+1] != '/')
|
||||
{
|
||||
pinStr[1] = topic[gpioLen+1];
|
||||
}
|
||||
|
||||
int pin = std::atoi(pinStr);
|
||||
|
||||
if(_gpio->getPinRole(pin) == PinRole::GeneralOutput)
|
||||
{
|
||||
const uint8_t pinState = strcmp((const char*)payload, "1") == 0 ? HIGH : LOW;
|
||||
Log->print(F("GPIO "));
|
||||
Log->print(pin);
|
||||
Log->print(F(" (Output) --> "));
|
||||
Log->println(pinState);
|
||||
digitalWrite(pin, pinState);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Network::gpioActionCallback(const GpioAction &action, const int &pin)
|
||||
{
|
||||
_gpioTs[pin] = millis();
|
||||
}
|
||||
|
||||
void Network::reconfigureDevice()
|
||||
{
|
||||
_device->reconfigure();
|
||||
@@ -547,7 +650,7 @@ void Network::publishFloat(const char* prefix, const char* topic, const float va
|
||||
char str[30];
|
||||
dtostrf(value, 0, precision, str);
|
||||
char path[200] = {0};
|
||||
buildMqttPath(prefix, topic, path);
|
||||
buildMqttPath(path, { prefix, topic });
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, true, str);
|
||||
}
|
||||
|
||||
@@ -556,7 +659,7 @@ void Network::publishInt(const char* prefix, const char *topic, const int value)
|
||||
char str[30];
|
||||
itoa(value, str, 10);
|
||||
char path[200] = {0};
|
||||
buildMqttPath(prefix, topic, path);
|
||||
buildMqttPath(path, { prefix, topic });
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, true, str);
|
||||
}
|
||||
|
||||
@@ -565,7 +668,7 @@ void Network::publishUInt(const char* prefix, const char *topic, const unsigned
|
||||
char str[30];
|
||||
utoa(value, str, 10);
|
||||
char path[200] = {0};
|
||||
buildMqttPath(prefix, topic, path);
|
||||
buildMqttPath(path, { prefix, topic });
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, true, str);
|
||||
}
|
||||
|
||||
@@ -574,7 +677,7 @@ void Network::publishULong(const char* prefix, const char *topic, const unsigned
|
||||
char str[30];
|
||||
utoa(value, str, 10);
|
||||
char path[200] = {0};
|
||||
buildMqttPath(prefix, topic, path);
|
||||
buildMqttPath(path, { prefix, topic });
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, true, str);
|
||||
}
|
||||
|
||||
@@ -583,14 +686,14 @@ void Network::publishBool(const char* prefix, const char *topic, const bool valu
|
||||
char str[2] = {0};
|
||||
str[0] = value ? '1' : '0';
|
||||
char path[200] = {0};
|
||||
buildMqttPath(prefix, topic, path);
|
||||
buildMqttPath(path, { prefix, topic });
|
||||
_device->mqttPublish(path, MQTT_QOS_LEVEL, true, str);
|
||||
}
|
||||
|
||||
bool Network::publishString(const char* prefix, const char *topic, const char *value)
|
||||
{
|
||||
char path[200] = {0};
|
||||
buildMqttPath(prefix, topic, path);
|
||||
buildMqttPath(path, { prefix, topic });
|
||||
return _device->mqttPublish(path, MQTT_QOS_LEVEL, true, value) > 0;
|
||||
}
|
||||
|
||||
@@ -1244,3 +1347,8 @@ void Network::disableMqtt()
|
||||
_device->disableMqtt();
|
||||
_mqttEnabled = false;
|
||||
}
|
||||
|
||||
NetworkDevice *Network::device()
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
|
||||
14
Network.h
14
Network.h
@@ -7,6 +7,7 @@
|
||||
#include "MqttReceiver.h"
|
||||
#include "networkDevices/IPConfiguration.h"
|
||||
#include "MqttTopics.h"
|
||||
#include "Gpio.h"
|
||||
|
||||
enum class NetworkDeviceType
|
||||
{
|
||||
@@ -23,7 +24,7 @@ enum class NetworkDeviceType
|
||||
class Network
|
||||
{
|
||||
public:
|
||||
explicit Network(Preferences* preferences, const String& maintenancePathPrefix, char* buffer, size_t bufferSize);
|
||||
explicit Network(Preferences* preferences, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize);
|
||||
|
||||
void initialize();
|
||||
bool update();
|
||||
@@ -70,9 +71,13 @@ public:
|
||||
void setKeepAliveCallback(std::function<void()> reconnectTick);
|
||||
void addReconnectedCallback(std::function<void()> reconnectedCallback);
|
||||
|
||||
NetworkDevice* device();
|
||||
|
||||
private:
|
||||
static void onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
|
||||
void onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
|
||||
void onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
|
||||
void parseGpioTopics(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
|
||||
void gpioActionCallback(const GpioAction& action, const int& pin);
|
||||
void setupDevice();
|
||||
bool reconnect();
|
||||
|
||||
@@ -97,14 +102,16 @@ private:
|
||||
void onMqttConnect(const bool& sessionPresent);
|
||||
void onMqttDisconnect(const espMqttClientTypes::DisconnectReason& reason);
|
||||
|
||||
void buildMqttPath(const char* prefix, const char* path, char* outPath);
|
||||
void buildMqttPath(char* outPath, std::initializer_list<const char*> paths);
|
||||
|
||||
static Network* _inst;
|
||||
|
||||
const char* _lastWillPayload = "offline";
|
||||
char _mqttConnectionStateTopic[211] = {0};
|
||||
String _lockPath;
|
||||
|
||||
Preferences* _preferences;
|
||||
Gpio* _gpio;
|
||||
IPConfiguration* _ipConfiguration = nullptr;
|
||||
String _hostname;
|
||||
char _hostnameArr[101] = {0};
|
||||
@@ -133,6 +140,7 @@ private:
|
||||
bool _mqttEnabled = true;
|
||||
static unsigned long _ignoreSubscriptionsTs;
|
||||
long _rssiPublishInterval = 0;
|
||||
std::map<uint8_t, unsigned long> _gpioTs;
|
||||
|
||||
char* _buffer;
|
||||
const size_t _bufferSize;
|
||||
|
||||
@@ -511,7 +511,7 @@ void NukiOpenerWrapper::onKeypadCommandReceivedCallback(const char *command, con
|
||||
nukiOpenerInst->onKeypadCommandReceived(command, id, name, code, enabled);
|
||||
}
|
||||
|
||||
void NukiOpenerWrapper::gpioActionCallback(const GpioAction &action)
|
||||
void NukiOpenerWrapper::gpioActionCallback(const GpioAction &action, const int& pin)
|
||||
{
|
||||
switch(action)
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ private:
|
||||
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);
|
||||
static void gpioActionCallback(const GpioAction& action, const int& pin);
|
||||
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);
|
||||
|
||||
|
||||
@@ -480,7 +480,7 @@ void NukiWrapper::onKeypadCommandReceivedCallback(const char *command, const uin
|
||||
nukiInst->onKeypadCommandReceived(command, id, name, code, enabled);
|
||||
}
|
||||
|
||||
void NukiWrapper::gpioActionCallback(const GpioAction &action)
|
||||
void NukiWrapper::gpioActionCallback(const GpioAction &action, const int& pin)
|
||||
{
|
||||
switch(action)
|
||||
{
|
||||
|
||||
@@ -46,7 +46,7 @@ private:
|
||||
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);
|
||||
static void gpioActionCallback(const GpioAction& action, const int& pin);
|
||||
|
||||
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);
|
||||
|
||||
@@ -196,6 +196,9 @@ can be configured for a specific role:
|
||||
- Output: High when RTO active: Outputs a high signal when ring-to-open is active (opener)
|
||||
- Output: High when CM active: Outputs a high signal when continuous mode is active (opener)
|
||||
- Output: High when RTO or CM active: Outputs a high signal when either ring-to-open or continuous mode is active (opener)
|
||||
- General input (pull-down): The pin is configured in pull-down configuration and its state is published to the "gpio/pin_x/state" topic
|
||||
- General input (pull-up): The pin is configured in pull-up configuration and its state is published to the "gpio/pin_x/state" topic
|
||||
- Genral output: The pin is set to high or low depending on the "gpio/pin/x/state" topic
|
||||
|
||||
Note: The old setting "Enable control via GPIO" is removed. If you had enabled this setting before upgrading to 8.22, the PINs are automatically configured to be
|
||||
compatible with the previously hard-coded PINs.
|
||||
|
||||
@@ -25,24 +25,37 @@ enum class RestartReason
|
||||
#define RESTART_REASON_VALID_DETECT 0xa00ab00bc00bd00d;
|
||||
|
||||
extern int restartReason;
|
||||
extern uint64_t restartReasonValid;
|
||||
extern uint64_t restartReasonValidDetect;
|
||||
extern bool rebuildGpioRequested;
|
||||
|
||||
extern RestartReason currentRestartReason;
|
||||
|
||||
extern bool restartReason_isValid;
|
||||
|
||||
|
||||
inline static void restartEsp(RestartReason reason)
|
||||
{
|
||||
if(reason == RestartReason::GpioConfigurationUpdated)
|
||||
{
|
||||
rebuildGpioRequested = true;
|
||||
}
|
||||
restartReason = (int)reason;
|
||||
restartReasonValid = RESTART_REASON_VALID_DETECT;
|
||||
restartReasonValidDetect = RESTART_REASON_VALID_DETECT;
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
inline static void initializeRestartReason()
|
||||
{
|
||||
uint64_t cmp = RESTART_REASON_VALID_DETECT;
|
||||
if(restartReasonValid == cmp)
|
||||
restartReason_isValid = (restartReasonValidDetect == cmp);
|
||||
if(restartReason_isValid)
|
||||
{
|
||||
currentRestartReason = (RestartReason)restartReason;
|
||||
memset(&restartReasonValid, 0, sizeof(restartReasonValid));
|
||||
memset(&restartReasonValidDetect, 0, sizeof(restartReasonValidDetect));
|
||||
}
|
||||
else
|
||||
{
|
||||
rebuildGpioRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,4 +134,11 @@ inline static String getEspRestartReason()
|
||||
default:
|
||||
return "Unknown: " + (int)reason;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool rebuildGpio()
|
||||
{
|
||||
bool rebGpio = rebuildGpioRequested;
|
||||
rebuildGpioRequested = false;
|
||||
return restartReason_isValid && rebGpio;
|
||||
}
|
||||
@@ -36,6 +36,8 @@ void Scanner::update() {
|
||||
return;
|
||||
}
|
||||
|
||||
bleScan->clearResults();
|
||||
|
||||
bool result = bleScan->start(scanDuration, nullptr, false);
|
||||
if (!result) {
|
||||
scanErrors++;
|
||||
|
||||
58
lib/gpio2go/CMakeLists.txt
Normal file
58
lib/gpio2go/CMakeLists.txt
Normal file
@@ -0,0 +1,58 @@
|
||||
cmake_minimum_required(VERSION 3.0.0)
|
||||
|
||||
if(NOT ARDUINO_BOARD)
|
||||
set(ARDUINO_BOARD "ESP32 Dev Module [esp32.esp32]")
|
||||
endif()
|
||||
|
||||
project(gpio2go CXX)
|
||||
|
||||
# ARDUHAL_LOG_LEVEL_NONE, define ARDUHAL_LOG_LEVEL_ERROR, define ARDUHAL_LOG_LEVEL_WARN, define ARDUHAL_LOG_LEVEL_INFO,
|
||||
# define ARDUHAL_LOG_LEVEL_DEBUG, define ARDUHAL_LOG_LEVEL_VERBOSE
|
||||
|
||||
set(LOG_LEVEL ARDUHAL_LOG_LEVEL_NONE)
|
||||
|
||||
#add_compile_definitions(DEBUG_SENSE_NUKI)
|
||||
#add_compile_definitions(DEBUG_NUKI_COMMAND)
|
||||
#add_compile_definitions(DEBUG_NUKI_CONNECT)
|
||||
#add_compile_definitions(DEBUG_NUKI_COMMUNICATION)
|
||||
#add_compile_definitions(DEBUG_NUKI_HEX_DATA)
|
||||
#add_compile_definitions(DEBUG_NUKI_READABLE_DATA)
|
||||
|
||||
add_compile_definitions(ESP_PLATFORM)
|
||||
add_compile_definitions(ESP32)
|
||||
add_compile_definitions(ARDUINO_ARCH_ESP32)
|
||||
|
||||
include_directories(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
src
|
||||
)
|
||||
|
||||
set(SRCFILES
|
||||
src/PinMode.h
|
||||
src/Gpio2Go.cpp
|
||||
src/InterruptMode.h
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE SRCFILESREC
|
||||
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
main.cpp
|
||||
${SRCFILES}
|
||||
${SRCFILESREC}
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
ARDUHAL_LOG_LEVEL=${LOG_LEVEL}
|
||||
CORE_DEBUG_LEVEL=${LOG_LEVEL}
|
||||
)
|
||||
|
||||
target_link_arduino_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
core
|
||||
)
|
||||
|
||||
target_enable_arduino_upload(${PROJECT_NAME})
|
||||
|
||||
21
lib/gpio2go/LICENSE
Normal file
21
lib/gpio2go/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Jan-Ole Schümann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1
lib/gpio2go/README.md
Normal file
1
lib/gpio2go/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# gpio2go
|
||||
38
lib/gpio2go/main.cpp
Normal file
38
lib/gpio2go/main.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "Arduino.h"
|
||||
#include "Gpio2Go.h"
|
||||
|
||||
#define INPUT_PIN 21
|
||||
|
||||
bool hasMessage = false;
|
||||
String message;
|
||||
|
||||
void inputCb(const int & pin)
|
||||
{
|
||||
message = "";
|
||||
message.concat("Input, Pin ");
|
||||
message.concat(pin);
|
||||
message.concat(" ");
|
||||
message.concat(", state ");
|
||||
message.concat(digitalRead(INPUT_PIN) ? "High" : "Low");
|
||||
hasMessage = true;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
delay(1100);
|
||||
Serial.println(F("Started"));
|
||||
Gpio2Go::configurePin(INPUT_PIN, PinMode::InputPullup, InterruptMode::Change, 200);
|
||||
Gpio2Go::subscribe(inputCb);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(100);
|
||||
if(hasMessage)
|
||||
{
|
||||
hasMessage = false;
|
||||
Serial.println(message);
|
||||
}
|
||||
}
|
||||
242
lib/gpio2go/src/Gpio2Go.cpp
Normal file
242
lib/gpio2go/src/Gpio2Go.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
#include "Gpio2Go.h"
|
||||
|
||||
|
||||
void Gpio2Go::configurePin(int pin, PinMode pin_Mode, InterruptMode interrupt_Mode, uint16_t timeoutAfterTriggerMS)
|
||||
{
|
||||
timeoutDurations[pin - GPIO2GO_NR_FIRST_PIN] = timeoutAfterTriggerMS;
|
||||
|
||||
switch(pin_Mode)
|
||||
{
|
||||
case PinMode::InputPullup:
|
||||
pinMode(pin, INPUT_PULLUP);
|
||||
attachIsr(pin, interrupt_Mode);
|
||||
break;
|
||||
case PinMode::InputPullDown:
|
||||
pinMode(pin, INPUT_PULLDOWN);
|
||||
attachIsr(pin, interrupt_Mode);
|
||||
break;
|
||||
case PinMode::Output:
|
||||
pinMode(pin, OUTPUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio2Go::subscribe(std::function<void(const int &)> callback)
|
||||
{
|
||||
subscriptions.push_back(callback);
|
||||
}
|
||||
|
||||
unsigned long Gpio2Go::getLastTriggeredMillis(const int &pin)
|
||||
{
|
||||
if(pin >= GPIO2GO_NR_FIRST_PIN && pin <= (GPIO2GO_NR_OF_PINS + GPIO2GO_NR_FIRST_PIN))
|
||||
{
|
||||
return lastTriggeredTimestamps[pin - GPIO2GO_NR_FIRST_PIN];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Gpio2Go::attachIsr(int pin, InterruptMode interruptMode)
|
||||
{
|
||||
switch(pin)
|
||||
{
|
||||
case 2:
|
||||
attachInterrupt(2, isrGpio2, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 4:
|
||||
attachInterrupt(4, isrGpio4, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 5:
|
||||
attachInterrupt(5, isrGpio5, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 13:
|
||||
attachInterrupt(13, isrGpio13, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 14:
|
||||
attachInterrupt(14, isrGpio14, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 15:
|
||||
attachInterrupt(15, isrGpio15, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 16:
|
||||
attachInterrupt(16, isrGpio16, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 17:
|
||||
attachInterrupt(17, isrGpio17, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 18:
|
||||
attachInterrupt(18, isrGpio18, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 19:
|
||||
attachInterrupt(19, isrGpio19, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 20:
|
||||
attachInterrupt(20, isrGpio20, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 21:
|
||||
attachInterrupt(21, isrGpio21, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 22:
|
||||
attachInterrupt(22, isrGpio22, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 23:
|
||||
attachInterrupt(23, isrGpio23, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 24:
|
||||
attachInterrupt(24, isrGpio24, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 25:
|
||||
attachInterrupt(25, isrGpio25, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 26:
|
||||
attachInterrupt(26, isrGpio26, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 27:
|
||||
attachInterrupt(27, isrGpio27, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 32:
|
||||
attachInterrupt(32, isrGpio32, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 33:
|
||||
attachInterrupt(33, isrGpio33, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Gpio2Go: Unsupported pin.");
|
||||
}
|
||||
}
|
||||
|
||||
int Gpio2Go::resolveInterruptMode(InterruptMode interruptMode)
|
||||
{
|
||||
switch(interruptMode)
|
||||
{
|
||||
case InterruptMode::Rising:
|
||||
return RISING;
|
||||
case InterruptMode::Falling:
|
||||
return FALLING;
|
||||
case InterruptMode::Change:
|
||||
return CHANGE;
|
||||
case InterruptMode::OnLow:
|
||||
return ONLOW;
|
||||
case InterruptMode::OnHigh:
|
||||
return ONHIGH;
|
||||
default:
|
||||
throw std::runtime_error("Gpio2Go: Unsupported interrupt mode.");
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio2Go::isrHandler(int pin)
|
||||
{
|
||||
unsigned long timeout = lastTriggeredTimestamps[pin - GPIO2GO_NR_FIRST_PIN];
|
||||
if(timeoutDurations[pin - GPIO2GO_NR_FIRST_PIN] != 0 && (millis() - timeout) < timeoutDurations[pin - GPIO2GO_NR_FIRST_PIN]) return;
|
||||
lastTriggeredTimestamps[pin - GPIO2GO_NR_FIRST_PIN] = millis();
|
||||
|
||||
bool state = digitalRead(pin) == HIGH;
|
||||
|
||||
for(const auto& callback : subscriptions)
|
||||
{
|
||||
callback(pin);
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio2()
|
||||
{
|
||||
isrHandler(2);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio4()
|
||||
{
|
||||
isrHandler(4);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio5()
|
||||
{
|
||||
isrHandler(5);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio13()
|
||||
{
|
||||
isrHandler(13);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio14()
|
||||
{
|
||||
isrHandler(14);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio15()
|
||||
{
|
||||
isrHandler(15);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio16()
|
||||
{
|
||||
isrHandler(16);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio17()
|
||||
{
|
||||
isrHandler(17);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio18()
|
||||
{
|
||||
isrHandler(18);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio19()
|
||||
{
|
||||
isrHandler(19);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio20()
|
||||
{
|
||||
isrHandler(20);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio21()
|
||||
{
|
||||
isrHandler(21);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio22()
|
||||
{
|
||||
isrHandler(22);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio23()
|
||||
{
|
||||
isrHandler(23);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio24()
|
||||
{
|
||||
isrHandler(24);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio25()
|
||||
{
|
||||
isrHandler(25);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio26()
|
||||
{
|
||||
isrHandler(26);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio27()
|
||||
{
|
||||
isrHandler(27);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio32()
|
||||
{
|
||||
isrHandler(32);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio33()
|
||||
{
|
||||
isrHandler(33);
|
||||
}
|
||||
|
||||
unsigned long Gpio2Go::lastTriggeredTimestamps[] = {0};
|
||||
uint16_t Gpio2Go::timeoutDurations[] = {0};
|
||||
std::vector<std::function<void(const int&)>> Gpio2Go::subscriptions;
|
||||
49
lib/gpio2go/src/Gpio2Go.h
Normal file
49
lib/gpio2go/src/Gpio2Go.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <vector>
|
||||
#include "esp_attr.h"
|
||||
#include "PinMode.h"
|
||||
#include "InterruptMode.h"
|
||||
|
||||
#define GPIO2GO_NR_OF_PINS 31
|
||||
#define GPIO2GO_NR_FIRST_PIN 2
|
||||
|
||||
class Gpio2Go
|
||||
{
|
||||
public:
|
||||
static void configurePin(int pin, PinMode pin_Mode, InterruptMode interrupt_Mode, uint16_t timeoutAfterTriggerMS);
|
||||
static void subscribe(std::function<void(const int&)> callback);
|
||||
|
||||
unsigned long getLastTriggeredMillis(const int& pin);
|
||||
|
||||
private:
|
||||
static void attachIsr(int pin, InterruptMode interruptMode);
|
||||
static int resolveInterruptMode(InterruptMode interruptMode);
|
||||
|
||||
static void IRAM_ATTR isrHandler(int pin);
|
||||
static void IRAM_ATTR isrGpio2();
|
||||
static void IRAM_ATTR isrGpio4();
|
||||
static void IRAM_ATTR isrGpio5();
|
||||
static void IRAM_ATTR isrGpio13();
|
||||
static void IRAM_ATTR isrGpio14();
|
||||
static void IRAM_ATTR isrGpio15();
|
||||
static void IRAM_ATTR isrGpio16();
|
||||
static void IRAM_ATTR isrGpio17();
|
||||
static void IRAM_ATTR isrGpio18();
|
||||
static void IRAM_ATTR isrGpio19();
|
||||
static void IRAM_ATTR isrGpio20();
|
||||
static void IRAM_ATTR isrGpio21();
|
||||
static void IRAM_ATTR isrGpio22();
|
||||
static void IRAM_ATTR isrGpio23();
|
||||
static void IRAM_ATTR isrGpio24();
|
||||
static void IRAM_ATTR isrGpio25();
|
||||
static void IRAM_ATTR isrGpio26();
|
||||
static void IRAM_ATTR isrGpio27();
|
||||
static void IRAM_ATTR isrGpio32();
|
||||
static void IRAM_ATTR isrGpio33();
|
||||
|
||||
static unsigned long DRAM_ATTR lastTriggeredTimestamps[GPIO2GO_NR_OF_PINS];
|
||||
static uint16_t DRAM_ATTR timeoutDurations[GPIO2GO_NR_OF_PINS];
|
||||
static std::vector<std::function<void(const int&)>> DRAM_ATTR subscriptions;
|
||||
};
|
||||
10
lib/gpio2go/src/InterruptMode.h
Normal file
10
lib/gpio2go/src/InterruptMode.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
enum class InterruptMode
|
||||
{
|
||||
Rising = 0x01,
|
||||
Falling = 0x02,
|
||||
Change = 0x03,
|
||||
OnLow = 0x04,
|
||||
OnHigh = 0x05
|
||||
};
|
||||
20
lib/gpio2go/src/PinMode.h
Normal file
20
lib/gpio2go/src/PinMode.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
enum class PinMode
|
||||
{
|
||||
Output = 0x03,
|
||||
InputPullup = 0x05,
|
||||
InputPullDown = 0x09
|
||||
};
|
||||
|
||||
//#define INPUT 0x01
|
||||
//// Changed OUTPUT from 0x02 to behave the same as Arduino pinMode(pin,OUTPUT)
|
||||
//// where you can read the state of pin even when it is set as OUTPUT
|
||||
//#define OUTPUT 0x03
|
||||
//#define PULLUP 0x04
|
||||
//#define INPUT_PULLUP 0x05
|
||||
//#define PULLDOWN 0x08
|
||||
//#define INPUT_PULLDOWN 0x09
|
||||
//#define OPEN_DRAIN 0x10
|
||||
//#define OUTPUT_OPEN_DRAIN 0x12
|
||||
//#define ANALOG 0xC0
|
||||
16
main.cpp
16
main.cpp
@@ -34,7 +34,9 @@ bool openerEnabled = false;
|
||||
unsigned long restartTs = (2^32) - 5 * 60000;
|
||||
|
||||
RTC_NOINIT_ATTR int restartReason;
|
||||
RTC_NOINIT_ATTR uint64_t restartReasonValid;
|
||||
RTC_NOINIT_ATTR uint64_t restartReasonValidDetect;
|
||||
RTC_NOINIT_ATTR bool rebuildGpioRequested;
|
||||
bool restartReason_isValid;
|
||||
RestartReason currentRestartReason = RestartReason::NotApplicable;
|
||||
|
||||
TaskHandle_t networkTaskHandle = nullptr;
|
||||
@@ -176,11 +178,16 @@ void setup()
|
||||
preferences->remove(preference_restart_timer);
|
||||
}
|
||||
|
||||
gpio = new Gpio(preferences);
|
||||
String gpioDesc;
|
||||
gpio->getConfigurationText(gpioDesc, gpio->pinConfiguration(), "\n\r");
|
||||
Serial.print(gpioDesc.c_str());
|
||||
|
||||
lockEnabled = preferences->getBool(preference_lock_enabled);
|
||||
openerEnabled = preferences->getBool(preference_opener_enabled);
|
||||
|
||||
const String mqttLockPath = preferences->getString(preference_mqtt_lock_path);
|
||||
network = new Network(preferences, mqttLockPath, CharBuffer::get(), CHAR_BUFFER_SIZE);
|
||||
network = new Network(preferences, gpio, mqttLockPath, CharBuffer::get(), CHAR_BUFFER_SIZE);
|
||||
network->initialize();
|
||||
|
||||
networkLock = new NetworkLock(network, preferences, CharBuffer::get(), CHAR_BUFFER_SIZE);
|
||||
@@ -198,11 +205,6 @@ void setup()
|
||||
bleScanner->initialize("NukiHub");
|
||||
bleScanner->setScanDuration(10);
|
||||
|
||||
gpio = new Gpio(preferences);
|
||||
String gpioDesc;
|
||||
gpio->getConfigurationText(gpioDesc, gpio->pinConfiguration(), "\n\r");
|
||||
Serial.print(gpioDesc.c_str());
|
||||
|
||||
Log->println(lockEnabled ? F("NUKI Lock enabled") : F("NUKI Lock disabled"));
|
||||
if(lockEnabled)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,6 @@ public:
|
||||
virtual uint16_t mqttSubscribe(const char* topic, uint8_t qos) = 0;
|
||||
|
||||
protected:
|
||||
const uint16_t _mqttMaxBufferSize = 6144;
|
||||
const String _hostname;
|
||||
const IPConfiguration* _ipConfiguration = nullptr;
|
||||
};
|
||||
Reference in New Issue
Block a user