diff --git a/.gitignore b/.gitignore index 2be016c..6e63376 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build cmake-build-debug cmake-build-release +cmake-build-release-s3 diff --git a/CMakeLists.txt b/CMakeLists.txt index 03386c4..d52a687 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,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 diff --git a/Gpio.cpp b/Gpio.cpp index e3680cc..0a00697 100644 --- a/Gpio.cpp +++ b/Gpio.cpp @@ -5,6 +5,7 @@ #include "Logger.h" #include "PreferencesKeys.h" #include "RestartReason.h" +#include "lib/gpio2go/src/Gpio2Go.h" Gpio* Gpio::_inst = nullptr; unsigned long Gpio::_debounceTs = 0; @@ -65,10 +66,24 @@ 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::GeneralInput: + Gpio2Go::configurePin(entry.pin, PinMode::InputPullup, InterruptMode::Change, 300); + break; default: pinMode(entry.pin, OUTPUT); break; } + + Gpio2Go::subscribe(Gpio::inputCallback); } } @@ -169,6 +184,10 @@ 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::GeneralInput: + return "General input (Pull-up)"; default: return "Unknown"; } @@ -198,15 +217,20 @@ const std::vector& 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 callback) +void Gpio::inputCallback(const int &pin) +{ + _inst->notify(GpioAction::GeneralInput, pin); +} + +void Gpio::addCallback(std::function callback) { _callbacks.push_back(callback); } @@ -214,49 +238,49 @@ void Gpio::addCallback(std::function 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; } diff --git a/Gpio.h b/Gpio.h index 768d717..8bdb9f3 100644 --- a/Gpio.h +++ b/Gpio.h @@ -19,7 +19,9 @@ enum class PinRole OutputHighMotorBlocked, OutputHighRtoActive, OutputHighCmActive, - OutputHighRtoOrCmActive + OutputHighRtoOrCmActive, + GeneralOutput, + GeneralInput }; enum class GpioAction @@ -30,7 +32,8 @@ enum class GpioAction ElectricStrikeActuation, ActivateRTO, ActivateCM, - DeactivateRtoCm + DeactivateRtoCm, + GeneralInput }; struct PinEntry @@ -47,7 +50,7 @@ public: void migrateObsoleteSetting(); - void addCallback(std::function callback); + void addCallback(std::function callback); void loadPinConfiguration(); void savePinConfiguration(const std::vector& pinConfiguration); @@ -63,7 +66,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 _availablePins = { 2, 4, 5, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, 33 }; const std::vector _allRoles = @@ -94,7 +98,7 @@ private: static void IRAM_ATTR isrActivateCM(); static void IRAM_ATTR isrDeactivateRtoCm(); - std::vector> _callbacks; + std::vector> _callbacks; static Gpio* _inst; static unsigned long _debounceTs; diff --git a/MqttTopics.h b/MqttTopics.h index b80feee..0c0c81a 100644 --- a/MqttTopics.h +++ b/MqttTopics.h @@ -60,4 +60,6 @@ #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" \ No newline at end of file +#define mqtt_topic_network_device "/maintenance/networkDevice" + +#define mqtt_topic_gpio_prefix "/gpio/" diff --git a/Network.cpp b/Network.cpp index 4156a88..9b77546 100644 --- a/Network.cpp +++ b/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) { @@ -137,6 +138,9 @@ void Network::setupDevice() void Network::initialize() { + _networkGpio->initialize(); + registerMqttReceiver(_networkGpio); + _restartOnDisconnect = _preferences->getBool(preference_restart_on_disconnect); _rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000; @@ -204,6 +208,20 @@ void Network::initialize() } _publishDebugInfo = _preferences->getBool(preference_publish_debug_info); + + for(const auto& pinEntry : _gpio->pinConfiguration()) + { + switch(pinEntry.role) + { + case PinRole::GeneralInput: + String inp = "input_"; + inp.concat(pinEntry.pin); + initTopic(mqtt_topic_gpio_prefix, inp.c_str(), ) + break; + case PinRole::GeneralOutput: + break; + } + } } bool Network::update() @@ -303,6 +321,8 @@ bool Network::update() _lastMaintenanceTs = ts; } + _networkGpio->update(); + return true; } @@ -1238,3 +1258,8 @@ void Network::disableMqtt() _device->disableMqtt(); _mqttEnabled = false; } + +NetworkDevice *Network::device() +{ + return _device; +} diff --git a/Network.h b/Network.h index 1ef54fc..daf8594 100644 --- a/Network.h +++ b/Network.h @@ -7,6 +7,8 @@ #include "MqttReceiver.h" #include "networkDevices/IPConfiguration.h" #include "MqttTopics.h" +#include "Gpio.h" +#include "NetworkGpio.h" enum class NetworkDeviceType { @@ -23,7 +25,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,6 +72,8 @@ public: void setKeepAliveCallback(std::function reconnectTick); void addReconnectedCallback(std::function 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); @@ -105,6 +109,7 @@ private: char _mqttConnectionStateTopic[211] = {0}; Preferences* _preferences; + Gpio* _gpio; IPConfiguration* _ipConfiguration = nullptr; String _hostname; char _hostnameArr[101] = {0}; diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index df4df28..fd0bc55 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -482,7 +482,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) { diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index da80621..276c3cc 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -46,7 +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); + 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); diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 8b527f8..c4946d4 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -450,7 +450,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) { diff --git a/NukiWrapper.h b/NukiWrapper.h index e553f15..5572354 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -43,7 +43,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); + 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); diff --git a/lib/BleScanner/src/BleScanner.cpp b/lib/BleScanner/src/BleScanner.cpp index be78ddb..4fdba82 100644 --- a/lib/BleScanner/src/BleScanner.cpp +++ b/lib/BleScanner/src/BleScanner.cpp @@ -36,6 +36,8 @@ void Scanner::update() { return; } + bleScan->clearResults(); + bool result = bleScan->start(scanDuration, nullptr, false); if (!result) { scanErrors++; diff --git a/lib/gpio2go/CMakeLists.txt b/lib/gpio2go/CMakeLists.txt new file mode 100644 index 0000000..6fbd13c --- /dev/null +++ b/lib/gpio2go/CMakeLists.txt @@ -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}) + diff --git a/lib/gpio2go/LICENSE b/lib/gpio2go/LICENSE new file mode 100644 index 0000000..cef1a2b --- /dev/null +++ b/lib/gpio2go/LICENSE @@ -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. diff --git a/lib/gpio2go/README.md b/lib/gpio2go/README.md new file mode 100644 index 0000000..b173d34 --- /dev/null +++ b/lib/gpio2go/README.md @@ -0,0 +1 @@ +# gpio2go \ No newline at end of file diff --git a/lib/gpio2go/main.cpp b/lib/gpio2go/main.cpp new file mode 100644 index 0000000..0c6330b --- /dev/null +++ b/lib/gpio2go/main.cpp @@ -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); + } +} \ No newline at end of file diff --git a/lib/gpio2go/src/Gpio2Go.cpp b/lib/gpio2go/src/Gpio2Go.cpp new file mode 100644 index 0000000..e3e4965 --- /dev/null +++ b/lib/gpio2go/src/Gpio2Go.cpp @@ -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 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> Gpio2Go::subscriptions; \ No newline at end of file diff --git a/lib/gpio2go/src/Gpio2Go.h b/lib/gpio2go/src/Gpio2Go.h new file mode 100644 index 0000000..1339119 --- /dev/null +++ b/lib/gpio2go/src/Gpio2Go.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#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 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> DRAM_ATTR subscriptions; +}; diff --git a/lib/gpio2go/src/InterruptMode.h b/lib/gpio2go/src/InterruptMode.h new file mode 100644 index 0000000..15517c8 --- /dev/null +++ b/lib/gpio2go/src/InterruptMode.h @@ -0,0 +1,10 @@ +#pragma once + +enum class InterruptMode +{ + Rising = 0x01, + Falling = 0x02, + Change = 0x03, + OnLow = 0x04, + OnHigh = 0x05 +}; \ No newline at end of file diff --git a/lib/gpio2go/src/PinMode.h b/lib/gpio2go/src/PinMode.h new file mode 100644 index 0000000..9753e38 --- /dev/null +++ b/lib/gpio2go/src/PinMode.h @@ -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 \ No newline at end of file diff --git a/lib/nuki_ble b/lib/nuki_ble index 1de6290..d23f6d7 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit 1de629002a03e6fffc9acd8b746baf498b50f77b +Subproject commit d23f6d794ab0cfffeb838af3eea197197287b984 diff --git a/main.cpp b/main.cpp index 97dc63b..b9119df 100644 --- a/main.cpp +++ b/main.cpp @@ -180,11 +180,16 @@ void setup() restartTs = preferences->getInt(preference_restart_timer) * 60 * 1000; } + 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); @@ -209,11 +214,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) { diff --git a/networkDevices/NetworkDevice.h b/networkDevices/NetworkDevice.h index 6d55e3c..8c87246 100644 --- a/networkDevices/NetworkDevice.h +++ b/networkDevices/NetworkDevice.h @@ -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; }; \ No newline at end of file