mirror of https://github.com/nymea/nymea.git
Make use of gpio classes from libnymea-gpio
parent
685450fdb3
commit
f993b0b68e
|
|
@ -12,6 +12,7 @@ Build-Depends: debhelper (>= 9.0.0),
|
|||
libnymea-networkmanager-dev (>= 0.4.0),
|
||||
libnymea-remoteproxyclient-dev (>= 0.1.13),
|
||||
libnymea-zigbee-dev (>= 0.1.0),
|
||||
libnymea-gpio-dev,
|
||||
libpython3-dev,
|
||||
libqt5websockets5-dev,
|
||||
libqt5bluetooth5,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
#include "radio433brennenstuhl.h"
|
||||
#include "loggingcategories.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#include <QDebug>
|
||||
|
||||
#include "libnymea.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "gpio.h"
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ INCLUDEPATH += $$top_srcdir/libnymea $$top_builddir
|
|||
LIBS += -L$$top_builddir/libnymea/ -lnymea -lssl -lcrypto
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += nymea-mqtt nymea-networkmanager nymea-zigbee nymea-remoteproxyclient
|
||||
PKGCONFIG += nymea-mqtt nymea-networkmanager nymea-zigbee nymea-remoteproxyclient nymea-gpio
|
||||
|
||||
CONFIG(withoutpython) {
|
||||
message("Building without python support.")
|
||||
|
|
|
|||
|
|
@ -1,483 +0,0 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*!
|
||||
\class Gpio
|
||||
\brief The Gpio class allows to interact with the GPIOs.
|
||||
|
||||
\ingroup hardware
|
||||
\inmodule libnymea
|
||||
|
||||
A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
|
||||
digital signal. They are provided from many kinds of chip, and are familiar
|
||||
to Linux developers working with embedded and custom hardware. Each GPIO
|
||||
represents a bit connected to a particular pin, or "ball" on Ball Grid Array
|
||||
(BGA) packages. Board schematics show which external hardware connects to
|
||||
which GPIOs. Drivers can be written generically, so that board setup code
|
||||
passes such pin configuration data to drivers
|
||||
(\l{https://www.kernel.org/doc/Documentation/gpio/gpio.txt}{source}).
|
||||
|
||||
General Purpose Input/Output (a.k.a. GPIO) is a generic pin on a chip whose
|
||||
behavior (including whether it is an input or output pin) can be controlled
|
||||
through this class. An object of of the Gpio class represents a pin.
|
||||
|
||||
|
||||
\code
|
||||
Gpio *gpioOut = new Gpio(23, this);
|
||||
|
||||
// Export Gpio
|
||||
if (!gpioOut->exportGpio()) {
|
||||
qWarning() << "Could not export Gpio" << gpioOut->gpioNumber();
|
||||
gpioOut->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure Gpio direction
|
||||
if (!gpioOut->setDirection(PiGpio::DirectionOutput)) {
|
||||
qWarning() << "Could not set direction of Gpio" << gpioOut->gpioNumber();
|
||||
gpioOut->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
gpioOut->setValue(Gpio::ValueHigh)
|
||||
|
||||
\endcode
|
||||
|
||||
\code
|
||||
Gpio *gpioIn = new Gpio(24, this);
|
||||
|
||||
// Export Gpio
|
||||
if (!gpioIn->exportGpio()) {
|
||||
qWarning() << "Could not export Gpio" << gpioIn->gpioNumber();
|
||||
gpioIn->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure Gpio direction
|
||||
if (!gpioIn->setDirection(PiGpio::DirectionInput)) {
|
||||
qWarning() << "Could not set direction of Gpio" << gpioIn->gpioNumber();
|
||||
gpioIn->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Current value" << (bool)gpioIn->value();
|
||||
|
||||
\endcode
|
||||
|
||||
|
||||
\sa GpioMonitor
|
||||
*/
|
||||
|
||||
/*! \enum Gpio::Direction
|
||||
|
||||
This enum type specifies the dirction a \l{Gpio}.
|
||||
|
||||
\value DirectionInput
|
||||
The \l{Gpio} is configured as \b input.
|
||||
\value DirectionOutput
|
||||
The \l{Gpio} is configured as \b output.
|
||||
\value DirectionInvalid
|
||||
The direction is not valid.
|
||||
*/
|
||||
|
||||
/*! \enum Gpio::Value
|
||||
|
||||
This enum type specifies the value a \l{Gpio}.
|
||||
|
||||
\value ValueLow
|
||||
The \l{Gpio} is low.
|
||||
\value ValueHigh
|
||||
The \l{Gpio} is high.
|
||||
\value ValueInvalid
|
||||
The value is not valid.
|
||||
*/
|
||||
|
||||
/*! \enum Gpio::Edge
|
||||
|
||||
This enum type specifies the edge interrupt type of a \l{Gpio}.
|
||||
|
||||
\value EdgeFalling
|
||||
The \l{Gpio} reacts on falling edge interrupt.
|
||||
\value EdgeRising
|
||||
The \l{Gpio} reacts on rising edge interrupt.
|
||||
\value EdgeBoth
|
||||
The \l{Gpio} reacts on both, rising and falling edge interrupt.
|
||||
\value EdgeNone
|
||||
The \l{Gpio} does not react on interrupts.
|
||||
|
||||
*/
|
||||
|
||||
#include "gpio.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
/*! Constructs a \l{Gpio} object to represent a GPIO with the given \a gpio number and \a parent. */
|
||||
Gpio::Gpio(const 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_direction = direction();
|
||||
}
|
||||
|
||||
/*! Destroys and unexports the \l{Gpio}. */
|
||||
Gpio::~Gpio()
|
||||
{
|
||||
unexportGpio();
|
||||
}
|
||||
|
||||
/*! Returns the directory \tt {/sys/class/gpio/gpio<number>} of this Gpio. */
|
||||
QString Gpio::gpioDirectory() const
|
||||
{
|
||||
return m_gpioDirectory.canonicalPath();
|
||||
}
|
||||
|
||||
/*! Returns the number of this \l{Gpio}. \note The Gpio number is mostly not equivalent with the pin number. */
|
||||
int Gpio::gpioNumber() const
|
||||
{
|
||||
return m_gpio;
|
||||
}
|
||||
|
||||
|
||||
/*! Returns true if the directories \tt {/sys/class/gpio} and \tt {/sys/class/gpio/export} do exist. */
|
||||
bool Gpio::isAvailable()
|
||||
{
|
||||
return QFile("/sys/class/gpio/export").exists();
|
||||
}
|
||||
|
||||
/*! 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()
|
||||
{
|
||||
// Check if already exported
|
||||
if (m_gpioDirectory.exists())
|
||||
return true;
|
||||
|
||||
QFile exportFile("/sys/class/gpio/export");
|
||||
if (!exportFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO export file:" << exportFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&exportFile);
|
||||
out << m_gpio;
|
||||
exportFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{Gpio} could be unexported in the system file \tt {/sys/class/gpio/unexport}. */
|
||||
bool Gpio::unexportGpio()
|
||||
{
|
||||
QFile unexportFile("/sys/class/gpio/unexport");
|
||||
if (!unexportFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO unexport file:" << unexportFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&unexportFile);
|
||||
out << m_gpio;
|
||||
unexportFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Returns true if the \a direction of this GPIO could be set. \sa Gpio::Direction, */
|
||||
bool Gpio::setDirection(Gpio::Direction direction)
|
||||
{
|
||||
if (direction == Gpio::DirectionInvalid) {
|
||||
qCWarning(dcHardware()) << "Gpio: Setting an invalid direction is forbidden.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile directionFile(m_gpioDirectory.path() + "/direction");
|
||||
if (!directionFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO" << m_gpio << "direction file:" << directionFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_direction = direction;
|
||||
|
||||
QTextStream out(&directionFile);
|
||||
switch (m_direction) {
|
||||
case DirectionInput:
|
||||
out << "in";
|
||||
break;
|
||||
case DirectionOutput:
|
||||
out << "out";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
directionFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Returns the direction of this \l{Gpio}. */
|
||||
Gpio::Direction Gpio::direction()
|
||||
{
|
||||
QFile directionFile(m_gpioDirectory.path() + "/direction");
|
||||
if (!directionFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO" << m_gpio << "direction file:" << directionFile.errorString();
|
||||
return Gpio::DirectionInvalid;
|
||||
}
|
||||
|
||||
QString direction;
|
||||
QTextStream in(&directionFile);
|
||||
in >> direction;
|
||||
directionFile.close();
|
||||
|
||||
if (direction == "in") {
|
||||
m_direction = DirectionInput;
|
||||
return Gpio::DirectionInput;
|
||||
} else if (direction == "out") {
|
||||
m_direction = DirectionOutput;
|
||||
return Gpio::DirectionOutput;
|
||||
}
|
||||
|
||||
return Gpio::DirectionInvalid;
|
||||
}
|
||||
|
||||
/*! Returns true if the digital \a value of this \l{Gpio} could be set correctly. */
|
||||
bool Gpio::setValue(Gpio::Value value)
|
||||
{
|
||||
// Check given value
|
||||
if (value == Gpio::ValueInvalid) {
|
||||
qCWarning(dcHardware()) << "Gpio: Setting an invalid value is forbidden.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check current direction
|
||||
if (m_direction == Gpio::DirectionInput) {
|
||||
qCWarning(dcHardware()) << "Gpio: Setting the value of an input GPIO is forbidden.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_direction == Gpio::DirectionInvalid) {
|
||||
qCWarning(dcHardware()) << "Gpio: The direction of GPIO" << m_gpio << "is invalid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile valueFile(m_gpioDirectory.path() + "/value");
|
||||
if (!valueFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO" << m_gpio << "value file:" << valueFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&valueFile);
|
||||
switch (value) {
|
||||
case ValueLow:
|
||||
out << "0";
|
||||
break;
|
||||
case ValueHigh:
|
||||
out << "1";
|
||||
break;
|
||||
default:
|
||||
valueFile.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
valueFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Returns the current digital value of this \l{Gpio}. */
|
||||
Gpio::Value Gpio::value()
|
||||
{
|
||||
QFile valueFile(m_gpioDirectory.path() + "/value");
|
||||
if (!valueFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO" << m_gpio << "value file:" << valueFile.errorString();
|
||||
return Gpio::ValueInvalid;
|
||||
}
|
||||
|
||||
QString value;
|
||||
QTextStream in(&valueFile);
|
||||
in >> value;
|
||||
valueFile.close();
|
||||
|
||||
if (value == "0") {
|
||||
return Gpio::ValueLow;
|
||||
} else if (value == "1") {
|
||||
return Gpio::ValueHigh;
|
||||
}
|
||||
|
||||
return Gpio::ValueInvalid;
|
||||
}
|
||||
|
||||
/*! 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");
|
||||
if (!activeLowFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO" << m_gpio << "active_low file:" << activeLowFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&activeLowFile);
|
||||
if (activeLow) {
|
||||
out << "0";
|
||||
} else {
|
||||
out << "1";
|
||||
}
|
||||
|
||||
activeLowFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! 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");
|
||||
if (!activeLowFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO" << m_gpio << "active_low file:" << activeLowFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QString value;
|
||||
QTextStream in(&activeLowFile);
|
||||
in >> value;
|
||||
activeLowFile.close();
|
||||
|
||||
if (value == "0")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! Returns true if the \a edge of this GPIO could be set correctly. The \a edge parameter specifies,
|
||||
* when an interrupt occurs. */
|
||||
bool Gpio::setEdgeInterrupt(Gpio::Edge edge)
|
||||
{
|
||||
if (m_direction == Gpio::DirectionOutput) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not set edge interrupt, GPIO is configured as an output.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile edgeFile(m_gpioDirectory.path() + "/edge");
|
||||
if (!edgeFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO" << m_gpio << "edge file:" << edgeFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&edgeFile);
|
||||
switch (edge) {
|
||||
case EdgeFalling:
|
||||
out << "falling";
|
||||
break;
|
||||
case EdgeRising:
|
||||
out << "rising";
|
||||
break;
|
||||
case EdgeBoth:
|
||||
out << "both";
|
||||
break;
|
||||
case EdgeNone:
|
||||
out << "none";
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
edgeFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Returns the edge interrupt of this \l{Gpio}. */
|
||||
Gpio::Edge Gpio::edgeInterrupt()
|
||||
{
|
||||
QFile edgeFile(m_gpioDirectory.path() + "/edge");
|
||||
if (!edgeFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qCWarning(dcHardware()) << "Gpio: Could not open GPIO" << m_gpio << "edge file:" << edgeFile.errorString();
|
||||
return Gpio::EdgeNone;
|
||||
}
|
||||
|
||||
QString edge;
|
||||
QTextStream in(&edgeFile);
|
||||
in >> edge;
|
||||
edgeFile.close();
|
||||
|
||||
if (edge.contains("falling")) {
|
||||
return Gpio::EdgeFalling;
|
||||
} else if (edge.contains("rising")) {
|
||||
return Gpio::EdgeRising;
|
||||
} else if (edge.contains("both")) {
|
||||
return Gpio::EdgeBoth;
|
||||
} else if (edge.contains("none")) {
|
||||
return Gpio::EdgeNone;
|
||||
}
|
||||
|
||||
return Gpio::EdgeNone;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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, ";
|
||||
}
|
||||
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (gpio->activeLow()) {
|
||||
debug.nospace() << "Active Low: 1, ";
|
||||
} else {
|
||||
debug.nospace() << "Active Low: 0, ";
|
||||
}
|
||||
|
||||
if (gpio->value() == Gpio::ValueHigh) {
|
||||
debug.nospace() << "Value: 1)";
|
||||
} else if (gpio->value() == Gpio::ValueLow) {
|
||||
debug.nospace() << "Value: 0)";
|
||||
} else {
|
||||
debug.nospace() << "Value: Invalid)";
|
||||
}
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef GPIO_H
|
||||
#define GPIO_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "libnymea.h"
|
||||
|
||||
class LIBNYMEA_EXPORT Gpio : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Direction {
|
||||
DirectionInput,
|
||||
DirectionOutput,
|
||||
DirectionInvalid
|
||||
};
|
||||
|
||||
enum Value {
|
||||
ValueLow = 0,
|
||||
ValueHigh = 1,
|
||||
ValueInvalid = -1
|
||||
};
|
||||
|
||||
enum Edge {
|
||||
EdgeFalling,
|
||||
EdgeRising,
|
||||
EdgeBoth,
|
||||
EdgeNone
|
||||
};
|
||||
|
||||
explicit Gpio(const int &gpio, QObject *parent = nullptr);
|
||||
~Gpio();
|
||||
|
||||
QString gpioDirectory() const;
|
||||
int gpioNumber() const;
|
||||
|
||||
static bool isAvailable();
|
||||
|
||||
bool exportGpio();
|
||||
bool unexportGpio();
|
||||
|
||||
bool setDirection(Gpio::Direction direction);
|
||||
Gpio::Direction direction();
|
||||
|
||||
bool setValue(Gpio::Value value);
|
||||
Gpio::Value value();
|
||||
|
||||
bool setActiveLow(bool activeLow);
|
||||
bool activeLow();
|
||||
|
||||
bool setEdgeInterrupt(Gpio::Edge edge);
|
||||
Gpio::Edge edgeInterrupt();
|
||||
|
||||
|
||||
private:
|
||||
int m_gpio;
|
||||
Gpio::Direction m_direction;
|
||||
QDir m_gpioDirectory;
|
||||
|
||||
};
|
||||
|
||||
QDebug operator<< (QDebug debug, Gpio *gpio);
|
||||
|
||||
#endif // GPIO_H
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*!
|
||||
\class GpioMonitor
|
||||
\brief The GpioMonitor class allows to monitor GPIOs.
|
||||
|
||||
\ingroup hardware
|
||||
\inmodule libnymea
|
||||
|
||||
An instance of this class creates a thread, which monitors each of the added GPIOs. The object
|
||||
emits a signal if one of the added GPIOs changes its value. The GpioMonitor configures a GPIO as an
|
||||
input, with the edge interrupt EDGE_BOTH (\l{Gpio::setEdgeInterrupt()}{setEdgeInterrupt}).
|
||||
|
||||
\chapter Example
|
||||
Following example shows how to use the GpioMonitor class for a button on the Raspberry Pi. There are two possibilitys
|
||||
to connect a button. Following picture shows the schematics:
|
||||
|
||||
\image Raspberry_Pi_Button_Example.png "Raspberry Pi button example"
|
||||
|
||||
Button A represents a clean solutin with a 10 k\unicode{0x2126} resistor (set up as activeLow = false).
|
||||
Button B represents a "dirty" solution, were the 3.3V will be directly connected to the GPIO if the button is pressed (set activeLow = true).
|
||||
|
||||
Here is the code example for a button class:
|
||||
\code
|
||||
Button::Button(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_button = new GpioMonitor(110, this);
|
||||
connect(m_button, &GpioMonitor::valueChanged, this, &Button::stateChanged);
|
||||
}
|
||||
|
||||
bool Button::init()
|
||||
{
|
||||
return m_button->enable();
|
||||
}
|
||||
|
||||
void Button::stateChanged(const bool &value)
|
||||
{
|
||||
if (m_pressed != value) {
|
||||
m_pressed = value;
|
||||
if (value) {
|
||||
emit buttonPressed();
|
||||
} else {
|
||||
emit buttonReleased();
|
||||
}
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
/*! \fn void GpioMonitor::valueChanged(const bool &value);
|
||||
* This signal will be emitted, if the monitored \l{Gpio}{Gpios} changed his \a value. */
|
||||
|
||||
#include "gpiomonitor.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
/*! Constructs a \l{GpioMonitor} object with the given \a gpio number and \a parent. */
|
||||
GpioMonitor::GpioMonitor(int gpio, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_gpioNumber(gpio)
|
||||
{
|
||||
m_valueFile.setFileName("/sys/class/gpio/gpio" + QString::number(m_gpioNumber) + "/value");
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{GpioMonitor} could be enabled successfully. With the \a activeLow parameter the values can be inverted.
|
||||
With the \a edgeInterrupt parameter the interrupt type can be specified. */
|
||||
bool GpioMonitor::enable(bool activeLow, Gpio::Edge edgeInterrupt)
|
||||
{
|
||||
if (!Gpio::isAvailable())
|
||||
return false;
|
||||
|
||||
m_gpio = new Gpio(m_gpioNumber, this);
|
||||
if (!m_gpio->exportGpio() ||
|
||||
!m_gpio->setDirection(Gpio::DirectionInput) ||
|
||||
!m_gpio->setActiveLow(activeLow) ||
|
||||
!m_gpio->setEdgeInterrupt(edgeInterrupt)) {
|
||||
qCWarning(dcHardware()) << "GpioMonitor: Error while initializing GPIO" << m_gpio->gpioNumber();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_valueFile.open(QFile::ReadOnly)) {
|
||||
qWarning(dcHardware()) << "GpioMonitor: Could not open value file for gpio monitor" << m_gpio->gpioNumber();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_notifier = new QSocketNotifier(m_valueFile.handle(), QSocketNotifier::Exception);
|
||||
connect(m_notifier, &QSocketNotifier::activated, this, &GpioMonitor::readyReady);
|
||||
|
||||
m_notifier->setEnabled(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Disables this \l{GpioMonitor}. */
|
||||
void GpioMonitor::disable()
|
||||
{
|
||||
delete m_notifier;
|
||||
delete m_gpio;
|
||||
|
||||
m_notifier = 0;
|
||||
m_gpio = 0;
|
||||
|
||||
m_valueFile.close();
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{GpioMonitor} is running. */
|
||||
bool GpioMonitor::isRunning() const
|
||||
{
|
||||
if (!m_notifier)
|
||||
return false;
|
||||
|
||||
return m_notifier->isEnabled();
|
||||
}
|
||||
|
||||
/*! Returns the current value of this \l{GpioMonitor}. */
|
||||
bool GpioMonitor::value() const
|
||||
{
|
||||
return m_currentValue;
|
||||
}
|
||||
|
||||
/*! Returns the \l{Gpio} of this \l{GpioMonitor}. */
|
||||
Gpio *GpioMonitor::gpio()
|
||||
{
|
||||
return m_gpio;
|
||||
}
|
||||
|
||||
void GpioMonitor::readyReady(const int &ready)
|
||||
{
|
||||
Q_UNUSED(ready)
|
||||
|
||||
m_valueFile.seek(0);
|
||||
QByteArray data = m_valueFile.readAll();
|
||||
|
||||
bool value = false;
|
||||
if (data[0] == '1') {
|
||||
value = true;
|
||||
} else if (data[0] == '0') {
|
||||
value = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentValue = value;
|
||||
emit valueChanged(value);
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef GPIOMONITOR_H
|
||||
#define GPIOMONITOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QSocketNotifier>
|
||||
#include <QFile>
|
||||
|
||||
#include "libnymea.h"
|
||||
#include "gpio.h"
|
||||
|
||||
class LIBNYMEA_EXPORT GpioMonitor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GpioMonitor(int gpio, QObject *parent = nullptr);
|
||||
|
||||
bool enable(bool activeLow = false, Gpio::Edge edgeInterrupt = Gpio::EdgeBoth);
|
||||
void disable();
|
||||
|
||||
bool isRunning() const;
|
||||
bool value() const;
|
||||
|
||||
Gpio* gpio();
|
||||
|
||||
private:
|
||||
int m_gpioNumber;
|
||||
Gpio *m_gpio;
|
||||
QSocketNotifier *m_notifier;
|
||||
QFile m_valueFile;
|
||||
bool m_currentValue;
|
||||
|
||||
signals:
|
||||
void valueChanged(const bool &value);
|
||||
|
||||
private slots:
|
||||
void readyReady(const int &ready);
|
||||
|
||||
};
|
||||
|
||||
#endif // GPIOMONITOR_H
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
#include "radio433.h"
|
||||
#include "loggingcategories.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ QT -= gui
|
|||
DEFINES += LIBNYMEA_LIBRARY
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += nymea-zigbee nymea-mqtt
|
||||
PKGCONFIG += nymea-zigbee nymea-mqtt nymea-gpio
|
||||
|
||||
QMAKE_LFLAGS += -fPIC
|
||||
|
||||
|
|
@ -65,8 +65,6 @@ HEADERS += \
|
|||
typeutils.h \
|
||||
loggingcategories.h \
|
||||
nymeasettings.h \
|
||||
hardware/gpio.h \
|
||||
hardware/gpiomonitor.h \
|
||||
hardware/pwm.h \
|
||||
hardware/radio433/radio433.h \
|
||||
network/upnp/upnpdiscovery.h \
|
||||
|
|
@ -162,8 +160,6 @@ SOURCES += \
|
|||
nymeasettings.cpp \
|
||||
platform/package.cpp \
|
||||
platform/repository.cpp \
|
||||
hardware/gpio.cpp \
|
||||
hardware/gpiomonitor.cpp \
|
||||
hardware/pwm.cpp \
|
||||
hardware/radio433/radio433.cpp \
|
||||
network/upnp/upnpdiscovery.cpp \
|
||||
|
|
|
|||
Loading…
Reference in New Issue