Add button mode

This commit is contained in:
Simon Stürz 2019-10-08 17:56:14 +02:00
parent 1a369e1845
commit 09c782e3ec
6 changed files with 126 additions and 52 deletions

View File

@ -7,11 +7,15 @@ if the system is currently not connected to any network. Once the system is conn
First you have to install build dependencies:
> Note: the libnymea-networkmanager-dev package can be installed from the [nymea repository](https://nymea.io/en/wiki/nymea/master/install/debian) or built
> Note: the `libnymea-networkmanager-dev` package can be installed from the [nymea repository](https://nymea.io/en/wiki/nymea/master/install/debian) or built
and installed from [source](https://github.com/nymea/libnymea-networkmanager).
> Note: the `libnymea-gpio-dev` package can be installed from the [nymea repository](https://nymea.io/en/wiki/nymea/master/install/debian) or built
and installed from [source](https://github.com/nymea/nymea-gpio).
$ sudo apt update
$ sudo apt install qt5-default qtbase5-dev qtbase5-dev-tools libqt5bluetooth5 qtconnectivity5-dev libnymea-networkmanager-dev git
$ sudo apt install qt5-default qtbase5-dev qtbase5-dev-tools libqt5bluetooth5 qtconnectivity5-dev libnymea-networkmanager-dev libnymea-gpio-dev git
Clone the source code and change into the source directory
@ -63,45 +67,41 @@ this repository and it will be installed to /etc/nymea-networkmanager.conf with
# Command line parameters
$ nymea-networkmanager --help
Usage:nymea-networkmanager [options]
Usage: ./nymea-networkmanager [options]
This daemon allows to configure a wifi network using a bluetooth low energy connection.
Copyright © 2018 - 2019 Simon Stürz <simon.stuerz@nymea.io>
Copyright © 2018-2019 Simon Stürz <simon.stuerz@nymea.io>
Modes:
- offline This mode starts the bluetooth server once the device is offline
and not connected to any LAN network.
- once This mode starts the bluetooth server only if no network configuration exists.
Once a network connection exists the server will never start again.
- button This mode enables the bluetooth server when a GPIO button has been pressed for
the configured timeout periode.
- always This mode enables the bluetooth server as long the application is running.
- start This mode starts the bluetooth server for 3 minutes on start and shuts down after a connection.
Options:
-h, --help Displays this help.
-v, --version Displays version information.
-d, --debug Enable more debug output.
-a, --advertise-name <NAME> The name of the bluetooth
server. Default "BT WLAN setup".
-p, --platform-name <NAME> The name of the platform this
daemon is running. Default
"nymea-box".
-t, --timeout <SECONDS> The timeout of the bluetooth
server. Minimum value is 10.
Default "60".
-m, --mode <offline | once | always | start> Run the daemon in a specific
mode. Default is "offline".
- offline: this mode starts the
bluetooth server once the device
is offline and not connected to
any LAN network.
- once: this mode starts the
bluetooth server only if no
network configuration exists.
Once a network connection exists
the server will never start
again.
- always: this mode enables the
bluetooth server as long the
application is running.
- start: this mode starts the
bluetooth server for 3 minutes
on start and shuts down after a
connection.
-h, --help Displays this help.
-v, --version Displays version information.
-d, --debug Enable more debug output.
-a, --advertise-name <NAME> The name of the bluetooth server. Default "BT
WLAN setup".
-p, --platform-name <NAME> The name of the platform this daemon is running.
Default "nymea-box".
-g, --gpio <GPIO> The GPIO sysfs number for the button GPIO. This
parameter is only needed for the "button" mode.
-t, --timeout <SECONDS> The timeout of the bluetooth server. Minimum
value is 10. Default "60".
-m, --mode <MODE> Run the daemon in a specific mode (offline,
once, always, button, start). Default is
"offline".
# Bluetooth GATT profile
-------------------------------------------

View File

@ -3,3 +3,4 @@ Mode=offline
Timeout=60
AdvertiseName=BT WLAN setup
PlatformName=nymea-box
ButtonGpio=14

View File

@ -62,7 +62,7 @@ Core::Mode Core::mode() const
return m_mode;
}
void Core::setMode(const Core::Mode &mode)
void Core::setMode(Mode mode)
{
m_mode = mode;
}
@ -92,11 +92,21 @@ int Core::advertisingTimeout() const
return m_advertisingTimeout;
}
void Core::setAdvertisingTimeout(const int advertisingTimeout)
void Core::setAdvertisingTimeout(int advertisingTimeout)
{
m_advertisingTimeout = advertisingTimeout;
}
int Core::buttonGpio() const
{
return m_buttonGpio;
}
void Core::setButtonGpio(int buttonGpio)
{
m_buttonGpio = buttonGpio;
}
void Core::run()
{
// Start the networkmanager
@ -243,6 +253,17 @@ void Core::postRun()
qCDebug(dcApplication()) << "Not starting the bluetooth service because of \"once\" mode. There are" << m_networkManager->networkSettings()->connections().count() << "network configurations.";
}
break;
case ModeButton:
// Enable button
m_button = new GpioButton(m_buttonGpio, this);
m_button->setLongPressedTimeout(2000);
connect(m_button, &GpioButton::longPressed, this, &Core::onButtonLongPressed);
if (!m_button->enable()) {
qCCritical(dcApplication()) << "Could not not enable GPIO button for" << m_buttonGpio;
m_button->deleteLater();
m_button = nullptr;
}
break;
}
}
@ -288,6 +309,8 @@ void Core::onBluetoothServerRunningChanged(bool running)
qCDebug(dcApplication()) << "Not starting the bluetooth service because of \"once\" mode. There are" << m_networkManager->networkSettings()->connections().count() << "network configurations.";
}
break;
case ModeButton:
break;
}
}
}
@ -336,6 +359,8 @@ void Core::onNetworkManagerAvailableChanged(bool available)
qCDebug(dcApplication()) << "Not starting the bluetooth service because of \"once\" mode. There are" << m_networkManager->networkSettings()->connections().count() << "network configurations.";
}
break;
case ModeButton:
break;
}
}
@ -344,6 +369,11 @@ void Core::onNetworkManagerStateChanged(NetworkManager::NetworkManagerState stat
evaluateNetworkManagerState(state);
}
void Core::onButtonLongPressed()
{
startService();
}
void Core::onNymeaServiceAvailableChanged(bool available)
{
if (available)

View File

@ -25,6 +25,7 @@
#include <QObject>
#include "nymeadservice.h"
#include "nymea-gpio/gpiobutton.h"
#include "bluetooth/bluetoothserver.h"
#include "nymea-networkmanager/networkmanager.h"
#include "nymea-networkmanager/bluetooth/bluetoothserver.h"
@ -38,7 +39,8 @@ public:
ModeAlways,
ModeOffline,
ModeOnce,
ModeStart
ModeStart,
ModeButton
};
Q_ENUM(Mode)
@ -50,7 +52,7 @@ public:
NymeadService *nymeaService() const;
Mode mode() const;
void setMode(const Mode &mode);
void setMode(Mode mode);
QString advertiseName() const;
void setAdvertiseName(const QString &name);
@ -59,7 +61,10 @@ public:
void setPlatformName(const QString &name);
int advertisingTimeout() const;
void setAdvertisingTimeout(const int advertisingTimeout);
void setAdvertisingTimeout(int advertisingTimeout);
int buttonGpio() const;
void setButtonGpio(int buttonGpio);
void run();
@ -73,6 +78,7 @@ private:
BluetoothServer *m_bluetoothServer = nullptr;
NymeadService *m_nymeaService = nullptr;
WirelessNetworkDevice *m_wirelessDevice = nullptr;
GpioButton *m_button = nullptr;
QTimer *m_advertisingTimer = nullptr;
@ -81,6 +87,7 @@ private:
QString m_platformName;
int m_advertisingTimeout = 60;
bool m_initRunning = true;
int m_buttonGpio = -1;
void evaluateNetworkManagerState(NetworkManager::NetworkManagerState state);
@ -98,6 +105,8 @@ private slots:
void onNetworkManagerAvailableChanged(bool available);
void onNetworkManagerStateChanged(NetworkManager::NetworkManagerState state);
void onButtonLongPressed();
void onNymeaServiceAvailableChanged(bool available);
};

View File

@ -84,6 +84,7 @@ int main(int argc, char *argv[])
// Default configuration:
Core::Mode mode = Core::ModeOffline;
int timeout = 60;
int buttonGpio = -1;
QString advertiseName = "BT WLAN setup";
QString platformName = "nymea-box";
@ -96,8 +97,17 @@ int main(int argc, char *argv[])
QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
parser.setApplicationDescription(QString("\nThis daemon allows to configure a wifi network using a bluetooth low energy connection." \
"\n\nCopyright %1 2018-2019 Simon Stürz <simon.stuerz@nymea.io>").arg(QChar(0xA9)));
parser.setApplicationDescription(QString("\nThis daemon allows to configure a wifi network using a bluetooth low energy connection.\n\n"
"Copyright %1 2018-2019 Simon Stürz <simon.stuerz@nymea.io>\n\n"
"Modes: \n"
" - offline This mode starts the bluetooth server once the device is offline\n"
" and not connected to any LAN network.\n"
" - once This mode starts the bluetooth server only if no network configuration exists.\n"
" Once a network connection exists the server will never start again.\n"
" - button This mode enables the bluetooth server when a GPIO button has been pressed for\n"
" the configured timeout periode.\n"
" - always This mode enables the bluetooth server as long the application is running.\n"
" - start This mode starts the bluetooth server for 3 minutes on start and shuts down after a connection.\n\n").arg(QChar(0xA9)));
QCommandLineOption debugOption(QStringList() << "d" << "debug", "Enable more debug output.");
parser.addOption(debugOption);
@ -110,15 +120,15 @@ int main(int argc, char *argv[])
platformNameOption.setDefaultValue(platformName);
parser.addOption(platformNameOption);
QCommandLineOption gpioOption(QStringList() << "g" << "gpio", QString("The GPIO sysfs number for the button GPIO. This parameter is only needed for the \"button\" mode."), "GPIO");
platformNameOption.setDefaultValue("-1");
parser.addOption(gpioOption);
QCommandLineOption timeoutOption(QStringList() << "t" << "timeout", QString("The timeout of the bluetooth server. Minimum value is 10. Default \"%1\".").arg(timeout), "SECONDS");
timeoutOption.setDefaultValue(QString::number(timeout));
parser.addOption(timeoutOption);
QCommandLineOption modeOption(QStringList() << "m" << "mode", "Run the daemon in a specific mode. Default is \"offline\".\n\n" \
"- offline: this mode starts the bluetooth server once the device is offline and not connected to any LAN network.\n\n" \
"- once: this mode starts the bluetooth server only if no network configuration exists. Once a network connection exists the server will never start again.\n\n" \
"- always: this mode enables the bluetooth server as long the application is running.\n\n" \
"- start: this mode starts the bluetooth server for 3 minutes on start and shuts down after a connection.\n\n", "offline | once | always | start");
QCommandLineOption modeOption(QStringList() << "m" << "mode", "Run the daemon in a specific mode (offline, once, always, button, start). Default is \"offline\".", "MODE");
parser.addOption(modeOption);
parser.process(application);
@ -132,6 +142,7 @@ int main(int argc, char *argv[])
QLoggingCategory::installFilter(loggingCategoryFilter);
bool timeoutValueOk = true;
bool gpioValueOk = true;
// Now read the cofig file, overriding defaults
QStringList configLocations;
@ -152,10 +163,15 @@ int main(int argc, char *argv[])
mode = Core::ModeStart;
} else if (settings.value("Mode").toString().toLower() == "once") {
mode = Core::ModeOnce;
} else if (settings.value("Mode").toString().toLower() == "button") {
mode = Core::ModeButton;
} else {
qCWarning(dcApplication()).noquote() << QString("The config file's mode \"%1\" does not match the allowed modes.").arg(settings.value("Mode").toString());
}
}
if (settings.contains("ButtonGpio")) {
buttonGpio = settings.value("ButtonGpio", -1).toInt(&gpioValueOk);
}
if (settings.contains("Timeout")) {
timeout = settings.value("Timeout").toInt(&timeoutValueOk);
}
@ -179,7 +195,10 @@ int main(int argc, char *argv[])
mode = Core::ModeStart;
} else if (parser.value(modeOption).toLower() == "once") {
mode = Core::ModeOnce;
} else {
} else if (parser.value(modeOption).toLower() == "button") {
mode = Core::ModeButton;
} else {
qCWarning(dcApplication()).noquote() << QString("The given mode \"%1\" does not match the allowed modes.").arg(parser.value(modeOption));
parser.showHelp(1);
}
@ -193,15 +212,27 @@ int main(int argc, char *argv[])
if (parser.isSet(timeoutOption)) {
timeout = parser.value(timeoutOption).toInt(&timeoutValueOk);
}
if (parser.isSet(gpioOption)) {
buttonGpio = parser.value(gpioOption).toInt(&gpioValueOk);
}
// All parsed. Validate input:
if (!timeoutValueOk) {
qCCritical(dcApplication()) << QString("Invalid timeout value passed: \"%1\". Please pass an integer >= 10").arg(parser.value(timeoutOption));
parser.showHelp(1);
return(1);
}
if (!gpioValueOk) {
qCCritical(dcApplication()) << QString("Invalid GPIO number value passed: \"%1\". Please pass an integer > 0").arg(parser.value(gpioOption));
return(1);
}
if (timeout < 10) {
qCCritical(dcApplication()) << QString("Invalid timeout value passed: \"%1\". The minimal timeout is 10 [s].").arg(parser.value(timeoutOption));
parser.showHelp(1);
return(1);
}
if (mode == Core::ModeButton && buttonGpio <= 0) {
qCCritical(dcApplication()) << "Button mode selected but no valid GPIO passed.";
return(1);
}
qCDebug(dcApplication()) << "=====================================";
@ -211,12 +242,15 @@ int main(int argc, char *argv[])
qCDebug(dcApplication()) << "Platform name:" << platformName;
qCDebug(dcApplication()) << "Mode:" << mode;
qCDebug(dcApplication()) << "Timeout:" << timeout;
if (mode == Core::ModeButton)
qCDebug(dcApplication()) << "Button GPIO:" << buttonGpio;
// Start core
Core::instance()->setMode(mode);
Core::instance()->setAdvertisingTimeout(timeout);
Core::instance()->setAdvertiseName(advertiseName);
Core::instance()->setPlatformName(platformName);
Core::instance()->setButtonGpio(buttonGpio);
Core::instance()->run();

View File

@ -9,7 +9,7 @@ CONFIG += console link_pkgconfig
CONFIG -= app_bundle
TEMPLATE = app
PKGCONFIG += nymea-networkmanager
PKGCONFIG += nymea-networkmanager nymea-gpio
HEADERS += \
application.h \