diff --git a/libnymea-gpio/gpio.cpp b/libnymea-gpio/gpio.cpp index c47ba0b..3b49755 100644 --- a/libnymea-gpio/gpio.cpp +++ b/libnymea-gpio/gpio.cpp @@ -7,7 +7,7 @@ Gpio::Gpio(int gpio, QObject *parent) : QObject(parent), m_gpio(gpio), m_direction(Gpio::DirectionInvalid), - m_gpioDirectory(QDir(QString("/sys/class/gpio/gpio%1/").arg(QString::number(gpio)))) + m_gpioDirectory(QDir(QString("/sys/class/gpio/gpio%1").arg(QString::number(gpio)))) { } @@ -39,9 +39,12 @@ int Gpio::gpioNumber() const /*! Returns true if this \l{Gpio} could be exported in the system file \tt {/sys/class/gpio/export}. If this Gpio is already exported, this function will return true. */ bool Gpio::exportGpio() { + qCDebug(dcGpio()) << "Export GPIO" << m_gpio; // Check if already exported - if (m_gpioDirectory.exists()) + if (m_gpioDirectory.exists()) { + qCDebug(dcGpio()) << "GPIO" << m_gpio << "already exported."; return true; + } QFile exportFile("/sys/class/gpio/export"); if (!exportFile.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -58,6 +61,8 @@ bool Gpio::exportGpio() /*! Returns true if this \l{Gpio} could be unexported in the system file \tt {/sys/class/gpio/unexport}. */ bool Gpio::unexportGpio() { + qCDebug(dcGpio()) << "Unexport GPIO" << m_gpio; + QFile unexportFile("/sys/class/gpio/unexport"); if (!unexportFile.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO unexport file:" << unexportFile.errorString(); @@ -73,12 +78,13 @@ bool Gpio::unexportGpio() /*! Returns true if the \a direction of this GPIO could be set. \sa Gpio::Direction, */ bool Gpio::setDirection(Gpio::Direction direction) { + qCDebug(dcGpio()) << "Set GPIO" << m_gpio << "direction" << direction; if (direction == Gpio::DirectionInvalid) { qCWarning(dcGpio()) << "Setting an invalid direction is forbidden."; return false; } - QFile directionFile(m_gpioDirectory.path() + "/direction"); + QFile directionFile(m_gpioDirectory.path() + QDir::separator() + "direction"); if (!directionFile.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO" << m_gpio << "direction file:" << directionFile.errorString(); return false; @@ -105,7 +111,7 @@ bool Gpio::setDirection(Gpio::Direction direction) /*! Returns the direction of this \l{Gpio}. */ Gpio::Direction Gpio::direction() { - QFile directionFile(m_gpioDirectory.path() + "/direction"); + QFile directionFile(m_gpioDirectory.path() + QDir::separator() + "direction"); if (!directionFile.open(QIODevice::ReadOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO" << m_gpio << "direction file:" << directionFile.fileName() << directionFile.errorString(); return Gpio::DirectionInvalid; @@ -130,6 +136,8 @@ Gpio::Direction Gpio::direction() /*! Returns true if the digital \a value of this \l{Gpio} could be set correctly. */ bool Gpio::setValue(Gpio::Value value) { + qCDebug(dcGpio()) << "Set GPIO" << m_gpio << "value" << value; + // Check given value if (value == Gpio::ValueInvalid) { qCWarning(dcGpio()) << "Setting an invalid value is forbidden."; @@ -147,7 +155,7 @@ bool Gpio::setValue(Gpio::Value value) return false; } - QFile valueFile(m_gpioDirectory.path() + "/value"); + QFile valueFile(m_gpioDirectory.path() + QDir::separator() + "value"); if (!valueFile.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO" << m_gpio << "value file:" << valueFile.errorString(); return false; @@ -173,7 +181,7 @@ bool Gpio::setValue(Gpio::Value value) /*! Returns the current digital value of this \l{Gpio}. */ Gpio::Value Gpio::value() { - QFile valueFile(m_gpioDirectory.path() + "/value"); + QFile valueFile(m_gpioDirectory.path() + QDir::separator() + "value"); if (!valueFile.open(QIODevice::ReadOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO" << m_gpio << "value file:" << valueFile.errorString(); return Gpio::ValueInvalid; @@ -196,7 +204,9 @@ Gpio::Value Gpio::value() /*! This method allows to invert the logic of this \l{Gpio}. Returns true, if the GPIO could be set \a activeLow. */ bool Gpio::setActiveLow(bool activeLow) { - QFile activeLowFile(m_gpioDirectory.path() + "/active_low"); + qCDebug(dcGpio()) << "Set GPIO" << m_gpio << "active low" << activeLow; + + QFile activeLowFile(m_gpioDirectory.path() + QDir::separator() + "active_low"); if (!activeLowFile.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO" << m_gpio << "active_low file:" << activeLowFile.errorString(); return false; @@ -216,7 +226,7 @@ bool Gpio::setActiveLow(bool activeLow) /*! Returns true if the logic of this \l{Gpio} is inverted (1 = low, 0 = high). */ bool Gpio::activeLow() { - QFile activeLowFile(m_gpioDirectory.path() + "/active_low"); + QFile activeLowFile(m_gpioDirectory.path() + QDir::separator() + "active_low"); if (!activeLowFile.open(QIODevice::ReadOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO" << m_gpio << "active_low file:" << activeLowFile.errorString(); return false; @@ -237,12 +247,14 @@ bool Gpio::activeLow() * when an interrupt occurs. */ bool Gpio::setEdgeInterrupt(Gpio::Edge edge) { + if (m_direction == Gpio::DirectionOutput) { qCWarning(dcGpio()) << "Could not set edge interrupt, GPIO is configured as an output."; return false; } - QFile edgeFile(m_gpioDirectory.path() + "/edge"); + qCDebug(dcGpio()) << "Set GPIO" << m_gpio << "edge interrupt" << edge; + QFile edgeFile(m_gpioDirectory.path() + QDir::separator() + "edge"); if (!edgeFile.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO" << m_gpio << "edge file:" << edgeFile.errorString(); return false; @@ -271,7 +283,7 @@ bool Gpio::setEdgeInterrupt(Gpio::Edge edge) /*! Returns the edge interrupt of this \l{Gpio}. */ Gpio::Edge Gpio::edgeInterrupt() { - QFile edgeFile(m_gpioDirectory.path() + "/edge"); + QFile edgeFile(m_gpioDirectory.path() + QDir::separator() + "edge"); if (!edgeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { qCWarning(dcGpio()) << "Could not open GPIO" << m_gpio << "edge file:" << edgeFile.errorString(); return Gpio::EdgeNone; @@ -301,41 +313,43 @@ QDebug operator<<(QDebug debug, Gpio *gpio) { debug.nospace() << "Gpio(" << gpio->gpioNumber() << ", "; if (gpio->direction() == Gpio::DirectionInput) { - debug.nospace() << "Input, "; - } else if (gpio->direction() == Gpio::DirectionOutput) { - debug.nospace() << "Output, "; - } else { - debug.nospace() << "Invalid, "; - } + debug.nospace() << "input, "; - switch (gpio->edgeInterrupt()) { - case Gpio::EdgeFalling: - debug.nospace() << "Ir: Falling, "; - break; - case Gpio::EdgeRising: - debug.nospace() << "Ir: Rising, "; - break; - case Gpio::EdgeBoth: - debug.nospace() << "Ir: Both, "; - break; - case Gpio::EdgeNone: - debug.nospace() << "Ir: None, "; - break; + switch (gpio->edgeInterrupt()) { + case Gpio::EdgeFalling: + debug.nospace() << "edge: falling, "; + break; + case Gpio::EdgeRising: + debug.nospace() << "edge: rising, "; + break; + case Gpio::EdgeBoth: + debug.nospace() << "edge: both, "; + break; + case Gpio::EdgeNone: + debug.nospace() << "edge: none, "; + break; + } + } else if (gpio->direction() == Gpio::DirectionOutput) { + debug.nospace() << "output, "; + } else { + debug.nospace() << "invalid, "; } if (gpio->activeLow()) { - debug.nospace() << "Active Low: 1, "; + debug.nospace() << "active low: 1, "; } else { - debug.nospace() << "Active Low: 0, "; + debug.nospace() << "active low: 0, "; } if (gpio->value() == Gpio::ValueHigh) { - debug.nospace() << "Value: 1)"; + debug.nospace() << "value: 1"; } else if (gpio->value() == Gpio::ValueLow) { - debug.nospace() << "Value: 0)"; + debug.nospace() << "value: 0"; } else { - debug.nospace() << "Value: Invalid)"; + debug.nospace() << "value: invalid"; } - return debug; + debug.nospace() << ")"; + + return debug.space(); } diff --git a/libnymea-gpio/gpiomonitor.cpp b/libnymea-gpio/gpiomonitor.cpp index 22d4975..b8589d7 100644 --- a/libnymea-gpio/gpiomonitor.cpp +++ b/libnymea-gpio/gpiomonitor.cpp @@ -1,20 +1,47 @@ #include "gpiomonitor.h" +#include #include -GpioMonitor::GpioMonitor(int gpio, Gpio::Edge edge, QObject *parent) : +GpioMonitor::GpioMonitor(int gpio, QObject *parent) : QThread(parent), - m_edge(edge) + m_gpioNumber(gpio) { - m_gpio = new Gpio(gpio, this); - connect(this, &GpioMonitor::started, this, &GpioMonitor::onThreadStarted); - connect(this, &GpioMonitor::finished, this, &GpioMonitor::onThreadFinished); + // Inform about the thread status + connect(this, &GpioMonitor::started, this, &GpioMonitor::onThreadStarted, Qt::DirectConnection); + connect(this, &GpioMonitor::finished, this, &GpioMonitor::onThreadFinished, Qt::DirectConnection); } GpioMonitor::~GpioMonitor() { disable(); - wait(); + wait(200); +} + +Gpio::Edge GpioMonitor::edge() const +{ + return m_edge; +} + +void GpioMonitor::setEdge(Gpio::Edge edge) +{ + if (m_edge == edge) + return; + + m_edge = edge; +} + +bool GpioMonitor::activeLow() const +{ + return m_activeLow; +} + +void GpioMonitor::setActiveLow(bool activeLow) +{ + if (m_activeLow == activeLow) + return; + + m_activeLow = activeLow; } Gpio::Value GpioMonitor::value() @@ -31,11 +58,18 @@ bool GpioMonitor::enabled() const void GpioMonitor::setValue(Gpio::Value value) { QMutexLocker valueLocker(&m_valueMutex); - if (m_value == value) - return; - m_value = value; - emit valueChanged(m_value); + + switch (m_value) { + case Gpio::ValueLow: + emit interruptOccured(false); + break; + case Gpio::ValueHigh: + emit interruptOccured(true); + break; + default: + break; + } } void GpioMonitor::setEnabled(bool enabled) @@ -49,70 +83,129 @@ void GpioMonitor::setEnabled(bool enabled) void GpioMonitor::run() { - // Initialize the current value - setValue(m_gpio->value()); + // Create GPIO in the thread for initialisation + Gpio *inputGpio = new Gpio(m_gpioNumber); + if (!inputGpio->exportGpio()) { + qCWarning(dcGpio()) << "Could not enable GPIO monitor."; + delete inputGpio; + return; + } - // Poll the GPIO value until the stop is true + if (!inputGpio->setDirection(Gpio::DirectionInput)) { + qCWarning(dcGpio()) << "Could not enable GPIO monitor."; + delete inputGpio; + return; + } + + if (!inputGpio->setEdgeInterrupt(m_edge)) { + qCWarning(dcGpio()) << "Could not set interrupt for the GPIO monitor."; + delete inputGpio; + return; + } + + if (!inputGpio->setActiveLow(m_activeLow)) { + qCWarning(dcGpio()) << "Could not set active low for the GPIO monitor."; + delete inputGpio; + return; + } + + + // In order to do correctly, use poll (2) according to the kernel documentation + // https://www.kernel.org/doc/Documentation/gpio/sysfs.txt + QFile valueFile(inputGpio->gpioDirectory() + QDir::separator() + "value"); + if (!valueFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qCWarning(dcGpio()) << "Could not open GPIO" << inputGpio << "value file:" << valueFile.errorString(); + delete inputGpio; + return; + } + + struct pollfd fdset[1]; + int rc = -1; + uint nfds = 1; + int timeout = 100; // ms + fdset[0].fd = valueFile.handle(); + fdset[0].events = POLLPRI; + + // Poll the GPIO value until stop is true while (true) { + // Poll the value file + rc = poll(fdset, nfds, timeout); - // Note: the setValue() method takes care about the mutex locking - setValue(m_gpio->value()); + // Poll failed... + if (rc < 0) { + qCWarning(dcGpio()) << "Failed to poll" << inputGpio; + break; + } // Check if we should stop the thread QMutexLocker stopLocker(&m_stopMutex); if (m_stop) break; - msleep(50); + + // No interrupt occured + if (rc == 0) + continue; + + // Interrupt occured + if (fdset[0].revents & POLLPRI) { + QString valueString; + QTextStream readStream(&valueFile); + if (!readStream.seek(0)) { + qCWarning(dcGpio()) << "Failed to seek value file of" << inputGpio; + continue; + } + + // Notify the main thread about the interrupt + readStream >> valueString; + if (valueString == "0") { + setValue(Gpio::ValueLow); + } else { + setValue(Gpio::ValueHigh); + } + } } + + // Clean up once done + valueFile.close(); + delete inputGpio; } void GpioMonitor::onThreadStarted() { + qCDebug(dcGpio()) << "Monitor thread started"; setEnabled(true); } void GpioMonitor::onThreadFinished() { + qCDebug(dcGpio()) << "Monitor thread finished"; setEnabled(false); } bool GpioMonitor::enable() { + qCDebug(dcGpio()) << "Enable gpio monitor"; if (isRunning()) { qCWarning(dcGpio()) << "This GPIO monitor is already running."; return true; } // Init the GPIO - if (!m_gpio->isAvailable()) { - qCWarning(dcGpio()) << "Could not enable GPIO monitor."; - return false; - } - - if (!m_gpio->exportGpio()) { - qCWarning(dcGpio()) << "Could not enable GPIO monitor."; - return false; - } - - if (!m_gpio->setDirection(Gpio::DirectionInput)) { - qCWarning(dcGpio()) << "Could not enable GPIO monitor."; - return false; - } - - if (!m_gpio->setEdgeInterrupt(m_edge)) { - qCWarning(dcGpio()) << "Could not set interrupt for the GPIO monitor."; + if (!Gpio::isAvailable()) { + qCWarning(dcGpio()) << "Could not enable GPIO monitor. There are no GPIOs available on this platform."; return false; } QMutexLocker locker(&m_stopMutex); m_stop = false; - // Everything went fine, lets start the poll thread and inform about the result + // Everything looks good, lets start the poll thread and inform about the result start(); return true; } void GpioMonitor::disable() { + qCDebug(dcGpio()) << "Disable gpio monitor"; // Stop the thread if not already disabled QMutexLocker locker(&m_stopMutex); if (m_stop) return; diff --git a/libnymea-gpio/gpiomonitor.h b/libnymea-gpio/gpiomonitor.h index 1cc4a59..bb109dd 100644 --- a/libnymea-gpio/gpiomonitor.h +++ b/libnymea-gpio/gpiomonitor.h @@ -11,15 +11,23 @@ class GpioMonitor : public QThread { Q_OBJECT public: - explicit GpioMonitor(int gpio, Gpio::Edge edge = Gpio::EdgeBoth, QObject *parent = nullptr); + explicit GpioMonitor(int gpio, QObject *parent = nullptr); ~GpioMonitor() override; + Gpio::Edge edge() const; + void setEdge(Gpio::Edge edge); + + bool activeLow() const; + void setActiveLow(bool activeLow); + Gpio::Value value(); + bool enabled() const; private: - Gpio *m_gpio = nullptr; + int m_gpioNumber = -1; Gpio::Edge m_edge = Gpio::EdgeBoth; + bool m_activeLow = true; bool m_enabled = false; // Thread stuff @@ -36,7 +44,7 @@ protected: void run() override; signals: - void valueChanged(bool value); + void interruptOccured(bool value); void enabledChanged(bool enabled); private slots: diff --git a/libnymea-gpio/libnymea-gpio.pro b/libnymea-gpio/libnymea-gpio.pro index bd37280..033393e 100644 --- a/libnymea-gpio/libnymea-gpio.pro +++ b/libnymea-gpio/libnymea-gpio.pro @@ -3,14 +3,14 @@ include(../nymea-gpio.pri) TARGET = nymea-gpio TEMPLATE = lib -SOURCES += \ - gpio.cpp \ - gpiomonitor.cpp - HEADERS += \ gpio.h \ gpiomonitor.h +SOURCES += \ + gpio.cpp \ + gpiomonitor.cpp + target.path = $$[QT_INSTALL_LIBS] INSTALLS += target diff --git a/nymea-gpio-tool/application.cpp b/nymea-gpio-tool/application.cpp new file mode 100644 index 0000000..73c1d21 --- /dev/null +++ b/nymea-gpio-tool/application.cpp @@ -0,0 +1,46 @@ +#include "application.h" + +#include +#include + +static void catchUnixSignals(const std::vector& quitSignals, const std::vector& ignoreSignals = std::vector()) +{ + auto handler = [](int sig) ->void { + switch (sig) { + case SIGQUIT: + qDebug() << "Cought SIGQUIT quit signal..."; + break; + case SIGINT: + qDebug() << "Cought SIGINT quit signal..."; + break; + case SIGTERM: + qDebug() << "Cought SIGTERM quit signal..."; + break; + case SIGHUP: + qDebug() << "Cought SIGHUP quit signal..."; + break; + case SIGSEGV: { + qCritical() << "Cought SIGSEGV signal. Segmentation fault!"; + exit(EXIT_FAILURE); + } + default: + break; + } + + Application::quit(); + }; + + // all these signals will be ignored. + for (int sig : ignoreSignals) + signal(sig, SIG_IGN); + + for (int sig : quitSignals) + signal(sig, handler); + +} + +Application::Application(int &argc, char **argv) : + QCoreApplication(argc, argv) +{ + catchUnixSignals({SIGQUIT, SIGINT, SIGTERM, SIGHUP, SIGSEGV}); +} diff --git a/nymea-gpio-tool/application.h b/nymea-gpio-tool/application.h new file mode 100644 index 0000000..64941bc --- /dev/null +++ b/nymea-gpio-tool/application.h @@ -0,0 +1,15 @@ +#ifndef APPLICATION_H +#define APPLICATION_H + +#include +#include + +class Application : public QCoreApplication +{ + Q_OBJECT +public: + explicit Application(int &argc, char **argv); + +}; + +#endif // APPLICATION_H diff --git a/nymea-gpio-tool/main.cpp b/nymea-gpio-tool/main.cpp index 85f7ec0..6aeb4d3 100644 --- a/nymea-gpio-tool/main.cpp +++ b/nymea-gpio-tool/main.cpp @@ -1,11 +1,11 @@ -#include #include +#include "application.h" #include "gpiomonitor.h" int main(int argc, char *argv[]) { - QCoreApplication application(argc, argv); + Application application(argc, argv); application.setOrganizationName("guh"); application.setApplicationName("nymea-gpio-tool"); application.setApplicationVersion(VERSION_STRING); @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) QCommandLineOption valueOption(QStringList() << "s" << "set-value", "Configure the GPIO to output and set the value. Allowerd values are: [0, 1].", "VALUE"); parser.addOption(valueOption); - QCommandLineOption monitorOption(QStringList() << "m" << "monitor", "Monitor the given gpio. The GPIO wil automatically configured as input and print any change regarding to the given interrupt behaviour."); + QCommandLineOption monitorOption(QStringList() << "m" << "monitor", "Monitor the given GPIO. The GPIO will automatically configured as input and print any change regarding to the given interrupt behaviour."); parser.addOption(monitorOption); QCommandLineOption activeLowOption(QStringList() << "a" << "active-low", "Set the GPIO to active low. Allowerd values are: [0, 1]", "VALUE"); @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) // Make sure there is a GPIO number passed if (!parser.isSet(gpioOption)) { qCritical() << "No GPIO number specified. Please specify a valid GPIO number using -g, --gpio GPIO"; - parser.showHelp(1); + parser.showHelp(EXIT_FAILURE); } // Verify GPIO number @@ -47,13 +47,13 @@ int main(int argc, char *argv[]) int gpioNumber = parser.value(gpioOption).toInt(&gpioNumberOk); if (!gpioNumberOk || gpioNumber < 0) { qCritical() << "Invalid GPIO number" << parser.value(gpioOption) << "passed. The GPIO number has to be a positiv integer."; - application.exit(1); + return EXIT_FAILURE; } // Verify input output operations if ((parser.isSet(interruptOption) || parser.isSet(monitorOption)) && parser.isSet(valueOption)) { qCritical() << "Invalid parameter combination. The set value can only be used for output GPIO, the monitor and interrupt parameter can only be used for input GPIO."; - application.exit(1); + return EXIT_FAILURE; } Gpio::Edge edge = Gpio::EdgeBoth; @@ -68,19 +68,19 @@ int main(int argc, char *argv[]) edge = Gpio::EdgeBoth; } else { qCritical() << "Invalid interrupt parameter" << parser.value(interruptOption) << "passed. Valid options are [rising, falling, both, none]."; - application.exit(1); + return EXIT_FAILURE; } } - bool activeLow = false; + bool activeLow = true; if (parser.isSet(activeLowOption)) { if (parser.value(activeLowOption) == "1") { - activeLow = true; - } else if (parser.value(activeLowOption) == "0") { activeLow = false; + } else if (parser.value(activeLowOption) == "0") { + activeLow = true; } else { qCritical() << "Invalid active low parameter" << parser.value(activeLowOption) << "passed. Valid options are [0, 1]."; - application.exit(1); + return EXIT_FAILURE; } } @@ -92,13 +92,13 @@ int main(int argc, char *argv[]) value = Gpio::ValueLow; } else { qCritical() << "Invalid set value parameter" << parser.value(valueOption) << "passed. Valid options are [0, 1]."; - application.exit(1); + return EXIT_FAILURE; } } if (!Gpio::isAvailable()) { qCritical() << "There are no GPIOs available on this platform."; - application.exit(2); + return EXIT_FAILURE; } // Configure the GPIO @@ -106,42 +106,54 @@ int main(int argc, char *argv[]) Gpio *gpio = new Gpio(gpioNumber); if (!gpio->exportGpio()) { qCritical() << "Could not export GPIO" << gpioNumber; - exit(1); + return EXIT_FAILURE; } if (!gpio->setDirection(Gpio::DirectionOutput)) { qCritical() << "Could not configure GPIO" << gpioNumber << "as output."; - exit(1); + return EXIT_FAILURE; } if (parser.isSet(activeLowOption)) { if (!gpio->setActiveLow(activeLow)) { qCritical() << "Could not set GPIO" << gpioNumber << "to active low" << activeLow; - exit(1); + return EXIT_FAILURE; } } // Finally set the value if (!gpio->setValue(value)) { qCritical() << "Could not set GPIO" << gpioNumber << "value to" << value; - exit(1); + return EXIT_FAILURE; } - application.exit(); + delete gpio; + return EXIT_SUCCESS; } else { - GpioMonitor *monitor = new GpioMonitor(gpioNumber, edge); + GpioMonitor *monitor = new GpioMonitor(gpioNumber); + monitor->setEdge(edge); + monitor->setActiveLow(activeLow); + + // Inform about enabled changed QObject::connect(monitor, &GpioMonitor::enabledChanged, [gpioNumber](bool enabled) { qDebug() << "GPIO" << gpioNumber << "monitor" << (enabled ? "enabled" : "disabled"); }); - QObject::connect(monitor, &GpioMonitor::valueChanged, [gpioNumber](bool value) { - qDebug() << "GPIO" << gpioNumber << "value changed" << (value ? "1" : "0"); + // Inform about interrupt + QObject::connect(monitor, &GpioMonitor::interruptOccured, [gpioNumber](bool value) { + qDebug() << "GPIO" << gpioNumber << "interrupt occured. Current value:" << (value ? "1" : "0"); }); + // Enable the monitor if (!monitor->enable()) { qCritical() << "Could not enable GPIO" << gpioNumber << "monitor."; - exit(1); + return EXIT_FAILURE; } + + // Clean up the gpio once done + QObject::connect(&application, &Application::aboutToQuit, [monitor](){ + delete monitor; + }); } return application.exec(); diff --git a/nymea-gpio-tool/nymea-gpio-tool.pro b/nymea-gpio-tool/nymea-gpio-tool.pro index 880ba19..2e6a605 100644 --- a/nymea-gpio-tool/nymea-gpio-tool.pro +++ b/nymea-gpio-tool/nymea-gpio-tool.pro @@ -9,9 +9,11 @@ TEMPLATE = app INCLUDEPATH += $$top_srcdir/libnymea-gpio/ LIBS += -L$$top_builddir/libnymea-gpio/ -lnymea-gpio +HEADERS += \ + application.h + SOURCES += main.cpp \ + application.cpp target.path = /usr/bin INSTALLS += target - -HEADERS += diff --git a/nymea-gpio.pri b/nymea-gpio.pri index 9fb5920..f6dcac7 100644 --- a/nymea-gpio.pri +++ b/nymea-gpio.pri @@ -1,7 +1,8 @@ -QT -= gui -QMAKE_CXXFLAGS *= -Werror -std=c++11 -g -QMAKE_LFLAGS *= -std=c++11 +QMAKE_CXXFLAGS += -Werror -std=c++11 -g +QMAKE_LFLAGS += -std=c++11 + +QT -= gui top_srcdir=$$PWD top_builddir=$$shadowed($$PWD)