diff --git a/debian/control b/debian/control
index ea89a128..34fb91cd 100644
--- a/debian/control
+++ b/debian/control
@@ -986,11 +986,15 @@ Description: nymea.io plugin for keba
This package will install the nymea.io plugin for keba
-Package: nymea-plugin-remotessh
+Package: nymea-plugin-reversessh
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
+ sshpass,
nymea-plugins-translations,
+Recommends: openssh-server
+Replaces: nymea-plugin-remotessh
+Conflicts: nymea-plugin-remotessh
Description: nymea.io plugin to configure remotessh for your nymea:core
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
diff --git a/debian/nymea-plugin-remotessh.install.in b/debian/nymea-plugin-reversessh.install.in
similarity index 77%
rename from debian/nymea-plugin-remotessh.install.in
rename to debian/nymea-plugin-reversessh.install.in
index 294ceb70..b4d37fbd 100644
--- a/debian/nymea-plugin-remotessh.install.in
+++ b/debian/nymea-plugin-reversessh.install.in
@@ -1 +1 @@
-usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginremotessh.so
+usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginreversessh.so
diff --git a/nymea-plugins.pro b/nymea-plugins.pro
index e32bd80e..91c50e3b 100644
--- a/nymea-plugins.pro
+++ b/nymea-plugins.pro
@@ -48,7 +48,7 @@ PLUGIN_DIRS = \
shelly \
solarlog \
systemmonitor \
- remotessh \
+ reversessh \
senic \
serialportcommander \
simulation \
diff --git a/remotessh/README.md b/remotessh/README.md
deleted file mode 100644
index 226ed8d7..00000000
--- a/remotessh/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Remote ssh
-
-This plugin allowes to to establish a reverse SSH tunnel to the device where nymea is running. This requires a reverse ssh proxy running somewhere accessable from the system.
-
-## Supported Things
-
-* Remote SSH
- * Reverse SSH connection
- * Config target IP-address, local and remote port
- * Username and Password login
-
-## Requirements
-
-* The package “nymea-plugin-remotessh” must be installed
-* Reverse SSH proxy server
-
-## More
-
-https://www.howtogeek.com/428413/what-is-reverse-ssh-tunneling-and-how-to-use-it/
diff --git a/remotessh/integrationpluginremotessh.cpp b/remotessh/integrationpluginremotessh.cpp
deleted file mode 100644
index 76340441..00000000
--- a/remotessh/integrationpluginremotessh.cpp
+++ /dev/null
@@ -1,217 +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 .
-*
-* 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
-*
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#include "integrationpluginremotessh.h"
-#include "plugininfo.h"
-
-#include
-#include
-
-IntegrationPluginRemoteSsh::IntegrationPluginRemoteSsh()
-{
-
-}
-
-void IntegrationPluginRemoteSsh::init()
-{
- m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
- connect(m_pluginTimer, &PluginTimer::timeout, this, &IntegrationPluginRemoteSsh::onPluginTimeout);
-}
-
-void IntegrationPluginRemoteSsh::setupThing(ThingSetupInfo *info)
-{
- Thing *thing = info->thing();
-
- qCDebug(dcRemoteSsh()) << "Setup" << thing->name() << thing->params();
-
- if (thing->thingClassId() == reverseSshThingClassId) {
- m_identityFilePath = QString("%1/.ssh/id_rsa_guh").arg(QDir::homePath());
- return info->finish(Thing::ThingErrorNoError);
- }
-}
-
-void IntegrationPluginRemoteSsh::executeAction(ThingActionInfo *info)
-{
- Thing *thing = info->thing();
- Action action = info->action();
- if (thing->thingClassId() == reverseSshThingClassId ) {
-
- if (action.actionTypeId() == reverseSshConnectedActionTypeId) {
-
- if (action.param(reverseSshConnectedActionConnectedParamTypeId).value().toBool() == true) {
- QProcess *process = startReverseSSHProcess(thing);
- m_reverseSSHProcess.insert(process, thing);
- m_startingProcess.insert(process, info);
- // in case action call is cancelled, detach result reporting
- connect(info, &ThingActionInfo::destroyed, process, [this, process]{
- m_startingProcess.remove(process);
- });
- return;
- } else {
- QProcess *process = m_reverseSSHProcess.key(thing);
-
- // Check if the application is running...
- if (!process)
- return info->finish(Thing::ThingErrorNoError);
-
- if (process->state() == QProcess::NotRunning)
- return info->finish(Thing::ThingErrorNoError);
-
- process->kill();
- m_killingProcess.insert(process, info);
- // in case action call is cancelled, detach result reporting
- connect(info, &ThingActionInfo::destroyed, process, [this, process]{
- m_killingProcess.remove(process);
- });
- return;
- }
- }
- }
-}
-
-
-void IntegrationPluginRemoteSsh::thingRemoved(Thing *thing)
-{
- if (thing->thingClassId() == reverseSshThingClassId) {
- QProcess *process = m_reverseSSHProcess.key(thing);
- if (!process)
- return;
-
- m_reverseSSHProcess.remove(process);
- if (process->state() != QProcess::NotRunning) {
- process->kill();
- }
- process->deleteLater();
- }
-}
-
-void IntegrationPluginRemoteSsh::processReadyRead()
-{
- QByteArray data = static_cast(sender())->readAll();
- qCWarning(dcRemoteSsh()) << "process read" << data;
-}
-
-
-QProcess * IntegrationPluginRemoteSsh::startReverseSSHProcess(Thing *thing)
-{
- qCDebug(dcRemoteSsh()) << "Start reverse SSH";
- QProcess *process = new QProcess(this);
- process->setProcessChannelMode(QProcess::MergedChannels);
-
- connect(process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
- connect(process, &QProcess::stateChanged, this, &IntegrationPluginRemoteSsh::processStateChanged);
- connect(process, &QProcess::readyRead, this, &IntegrationPluginRemoteSsh::processReadyRead);
-
- QStringList arguments;
- int localPort = thing->paramValue(reverseSshThingLocalPortParamTypeId).toInt();
- int remotePort = thing->paramValue(reverseSshThingRemotePortParamTypeId).toInt();
- QString user = thing->paramValue(reverseSshThingUserParamTypeId).toString();
- QString password = thing->paramValue(reverseSshThingPasswordParamTypeId).toString();
- QString address = thing->paramValue(reverseSshThingAddressParamTypeId).toString();
-
- arguments << "-p" << password;
- arguments << "ssh" << "-o StrictHostKeyChecking=no" << "-oUserKnownHostsFile=/dev/null";
- arguments << "-TN" << "-R" << QString("%1:localhost:%2").arg(remotePort).arg(localPort) << QString("%1@%2").arg(user, address);
- process->start(QStringLiteral("sshpass"), arguments);
- qCDebug(dcRemoteSsh()) << "Command:" << process->program() << process->arguments();
- return process;
-}
-
-void IntegrationPluginRemoteSsh::onPluginTimeout()
-{
- foreach(QProcess *process, m_reverseSSHProcess.keys()) {
- if (process->state() == QProcess::NotRunning)
- qCDebug(dcRemoteSsh()) << "SSH Process not running";
- }
-}
-
-
-void IntegrationPluginRemoteSsh::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
-{
- Q_UNUSED(exitCode);
- QProcess *process = static_cast(sender());
-
- if(exitStatus != QProcess::NormalExit || exitCode != 0) {
- qCWarning(dcRemoteSsh()) << "Error:" << process->readAllStandardError();
- }
-
- if (m_reverseSSHProcess.contains(process)) {
- qCDebug(dcRemoteSsh()) << "SSH process finished";
- Thing *thing = m_reverseSSHProcess.value(process);
- thing->setStateValue(reverseSshConnectedStateTypeId, false);
- m_reverseSSHProcess.remove(process);
-
- } else if (m_sshKeyGenProcess.contains(process)) {
- qCDebug(dcRemoteSsh()) << "SSH Key generation process finished" << process->readAll();
- Thing *thing = m_sshKeyGenProcess.value(process);
- QFile file(QString(m_identityFilePath + ".pub"));
- if(!file.open(QIODevice::ReadOnly))
- qCWarning(dcRemoteSsh()) << "error" << file.errorString();
-
- QTextStream in(&file);
- QString sshKey = in.readLine();
- thing->setStateValue(reverseSshSshKeyStateTypeId, sshKey);
- process->kill();
- m_sshKeyGenProcess.remove(process);
- file.close();
- }
-}
-
-
-void IntegrationPluginRemoteSsh::processStateChanged(QProcess::ProcessState state)
-{
- QProcess *process = static_cast(sender());
- Thing *thing = m_reverseSSHProcess.value(process);
-
- switch (state) {
- case QProcess::Running:
- thing->setStateValue(reverseSshConnectedStateTypeId, true);
- if (m_startingProcess.contains(process)) {
- m_startingProcess.take(process)->finish(Thing::ThingErrorNoError);
- }
- break;
-
- case QProcess::NotRunning:
- if (thing)
- thing->setStateValue(reverseSshConnectedStateTypeId, false);
-
- if (m_startingProcess.contains(process)) {
- m_startingProcess.take(process)->finish(Thing::ThingErrorInvalidParameter);
- }
-
- if (m_killingProcess.contains(process)) {
- m_killingProcess.take(process)->finish(Thing::ThingErrorNoError);
- m_reverseSSHProcess.remove(process);
- }
- break;
- default:
- break;
- }
-}
diff --git a/remotessh/remotessh.pro b/remotessh/remotessh.pro
deleted file mode 100644
index 55234390..00000000
--- a/remotessh/remotessh.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-include(../plugins.pri)
-
-TARGET = $$qtLibraryTarget(nymea_integrationpluginremotessh)
-
-SOURCES += \
- integrationpluginremotessh.cpp \
-
-HEADERS += \
- integrationpluginremotessh.h \
-
diff --git a/reversessh/README.md b/reversessh/README.md
new file mode 100644
index 00000000..a895efc3
--- /dev/null
+++ b/reversessh/README.md
@@ -0,0 +1,51 @@
+# Reverse ssh
+
+This plugin allows to establish a reverse SSH tunnel to the device where nymea is running.
+
+This is useful when maintaining remote nymea setups which may be hidden behind a firewall
+and cannot be accessed from the public internet. A user can easily enable SSH access for
+a nymea setup by adding a Thing using the app without having to deal with DNS and NAT.
+
+## Requirements
+
+In order to establish a reverse SSH tunnel, a SSH server is required to be accessible from
+both, the nymea instance and the client log in from. Also a SSH server is required
+to run on the system where nymea is running (If using the nymea images, this is already the case).
+
+## Setup
+
+### SSH Server setup
+
+The SSH server can be hosted anywhere, for instance on a vserver somewhere in the internet.
+The following settings must be enabled on the SSH server for it to work (assuming openssh):
+
+* AllowTcpForwarding yes (To allow this sort of forwarding generally)
+* GatewayPorts yes (To allow reverse ssh from other hosts than the reverse proxy itself - it would listen to localhost only otherwise)
+
+Create a user on the SSH server. Note that if sharing the credentials with someone else it
+might be advisable to confine the SSH server in a container, however, such a setup is beyond
+the scope of this manual. This will assume that both ends are trusted and SSH credentials
+for the server can be shared.
+
+### Nymea setup
+
+During the thing setup, enter the server connection information for SSH server:
+
+* SSH server address: The hostname or IP of the SSH server
+* SSH server port: The SSH port of the SSH server (22 by default)
+* Local SSH server port: The SSH port of the local SSH server running on the nymea system (22 by default)
+* Remote port to be opened: This is the port on which the nymea system will be reachable. This can be any port number which isn't in use already, and, unless you intend to log in as root (not advisable) this must be a port higher than 1024
+
+In the next step, provide the SSH credentials for the user on the SSH server which has been created before. Once the login succeeds, the thing should become connected.
+
+### Connecting with an SSH client
+
+Once the above setup succeeded, the nymea system can be reached via SSH using:
+
+ ssh @ -p
+
+where `user` is a user on the nymea system, server is the IP or hostname of the SSH server and `remote open port` is the port that has been picked during the thing setup.
+
+## More
+
+https://www.howtogeek.com/428413/what-is-reverse-ssh-tunneling-and-how-to-use-it/
diff --git a/reversessh/integrationpluginreversessh.cpp b/reversessh/integrationpluginreversessh.cpp
new file mode 100644
index 00000000..a3d7c7db
--- /dev/null
+++ b/reversessh/integrationpluginreversessh.cpp
@@ -0,0 +1,196 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* 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 .
+*
+* 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
+*
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "integrationpluginreversessh.h"
+#include "plugininfo.h"
+
+#include
+#include
+
+IntegrationPluginReverseSsh::IntegrationPluginReverseSsh()
+{
+
+}
+
+IntegrationPluginReverseSsh::~IntegrationPluginReverseSsh()
+{
+ foreach (QProcess *process, m_processes) {
+ process->terminate();
+ }
+}
+
+void IntegrationPluginReverseSsh::startPairing(ThingPairingInfo *info)
+{
+ info->finish(Thing::ThingErrorNoError, QString(QT_TR_NOOP("Please enter your login credentials for %1.")).arg(info->params().paramValue(reverseSshThingAddressParamTypeId).toString()));
+}
+
+void IntegrationPluginReverseSsh::confirmPairing(ThingPairingInfo *info, const QString &user, const QString &secret)
+{
+ // Perform a test login on the remote server
+ QString address = info->params().paramValue(reverseSshThingAddressParamTypeId).toString();
+ int remotePort = info->params().paramValue(reverseSshThingRemotePortParamTypeId).toInt();
+
+ QStringList arguments;
+ arguments << "-p" << secret << "ssh" << "-o StrictHostKeyChecking=no" << "-oUserKnownHostsFile=/dev/null";
+ arguments << QString("%1@%2").arg(user, address) << "-p" << QString::number(remotePort) << "whoami";
+
+ QProcess *process = new QProcess(this);
+ process->setProgram("sshpass");
+ process->setArguments(arguments);
+
+ arguments.replace(1, "xxxxxx");
+ qCInfo(dcReverseSsh()) << "Testing SSH connection:" << process->program() << arguments.join(" ");
+
+ typedef void (QProcess:: *finishedSignal)(int exitCode, QProcess::ExitStatus exitStatus);
+ connect(process, static_cast(&QProcess::finished), this, [=](int exitCode, QProcess::ExitStatus exitStatus){
+ process->deleteLater();
+ qCDebug(dcReverseSsh()) << "Testing process finished. Exit code:" << exitCode << "Exit status:" << exitStatus;
+
+ switch (exitCode) {
+ case 0:
+ pluginStorage()->beginGroup(info->thingId().toString());
+ pluginStorage()->setValue("username", user);
+ pluginStorage()->setValue("password", secret);
+ pluginStorage()->endGroup();
+ qCInfo(dcReverseSsh()) << "Reverse SSH test login successful.";
+ info->finish(Thing::ThingErrorNoError);
+ break;
+ case 5:
+ qCWarning(dcReverseSsh()) << "Reverse SSH test login failed.";
+ info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Login error on remote SSH server."));
+ break;
+ default:
+ qCWarning(dcReverseSsh()) << "Reverse SSH test login unable to connect to SSH server.";
+ info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Cannot connect to remote SSH server."));
+ }
+
+ });
+ process->start();
+}
+
+void IntegrationPluginReverseSsh::setupThing(ThingSetupInfo *info)
+{
+ Thing *thing = info->thing();
+
+
+ QStringList arguments;
+ int localPort = thing->paramValue(reverseSshThingLocalPortParamTypeId).toInt();
+ int remoteOpenPort = thing->paramValue(reverseSshThingRemoteOpenPortParamTypeId).toInt();
+ int remotePort = thing->paramValue(reverseSshThingRemotePortParamTypeId).toInt();
+ QString address = thing->paramValue(reverseSshThingAddressParamTypeId).toString();
+
+ pluginStorage()->beginGroup(thing->id().toString());
+ QString user = pluginStorage()->value("username").toString();
+ QString password = pluginStorage()->value("password").toString();
+ pluginStorage()->endGroup();
+
+ arguments << "-p" << password << "ssh" << "-o StrictHostKeyChecking=no" << "-oUserKnownHostsFile=/dev/null";
+ arguments << "-TN" << "-R" << QString("%1:localhost:%2").arg(remoteOpenPort).arg(localPort) << QString("%1@%2").arg(user, address) << "-p" << QString::number(remotePort);
+ QProcess *process = new QProcess(thing);
+ process->setProgram("sshpass");
+ process->setArguments(arguments);
+ process->setProcessChannelMode(QProcess::MergedChannels);
+ arguments.replace(1, "xxxxxx");
+ qCDebug(dcReverseSsh()) << "Reverse SSH command:" << process->program() << arguments;
+
+ m_processes.insert(info->thing(), process);
+
+ connect(process, &QProcess::stateChanged, thing, [=](QProcess::ProcessState newState){
+ switch (newState) {
+ case QProcess::Starting:
+ qCDebug(dcReverseSsh()) << "Connection starting for" << thing->name();
+ return ;
+ case QProcess::Running:
+ qCInfo(dcReverseSsh()) << "Reverse SSH connected for" << thing->name();
+ thing->setStateValue(reverseSshConnectedStateTypeId, true);
+ return;
+ case QProcess::NotRunning:
+ qCInfo(dcReverseSsh()) << "Reverse SSH disconnected for" << thing->name();
+ thing->setStateValue(reverseSshConnectedStateTypeId, false);
+ return;
+ }
+ });
+ connect(process, &QProcess::readyRead, thing, [=](){
+ QByteArray data = process->readAll();
+ qCWarning(dcReverseSsh()) << "Reverse SSH connection data for" << thing->name() << data;
+ });
+
+
+ // Start up now if enabled
+ bool enabled = thing->setting(reverseSshSettingsActiveParamTypeId).toBool();
+ if (enabled) {
+ process->start();
+ }
+
+ // And connect to the enabled setting
+ connect(thing, &Thing::settingChanged, this, [=](const ParamTypeId &settingId, const QVariant &value){
+ if (settingId == reverseSshSettingsActiveParamTypeId) {
+ if (value.toBool()) {
+ process->start();
+ } else {
+ process->terminate();
+ }
+ }
+ });
+
+ info->finish(Thing::ThingErrorNoError);
+
+
+ // Create a watchdog to reconnect if a connection drops...
+ if (!m_watchdog) {
+ m_watchdog = hardwareManager()->pluginTimerManager()->registerTimer(10);
+ connect(m_watchdog, &PluginTimer::timeout, this, [this](){
+ foreach (Thing *thing, m_processes.keys()) {
+ QProcess *process = m_processes.value(thing);
+ if (thing->setting(reverseSshSettingsActiveParamTypeId).toBool() && process->state() == QProcess::NotRunning) {
+ qCInfo(dcReverseSsh()) << "Reconnecting reverse SSH for" << thing->name();
+ process->start();
+ }
+ }
+ });
+ }
+}
+
+
+void IntegrationPluginReverseSsh::thingRemoved(Thing *thing)
+{
+ if (thing->thingClassId() == reverseSshThingClassId) {
+ QProcess *process = m_processes.take(thing);
+ if (process->state() != QProcess::NotRunning) {
+ process->terminate();
+ process->waitForFinished();
+ }
+ }
+
+ if (myThings().isEmpty()) {
+ hardwareManager()->pluginTimerManager()->unregisterTimer(m_watchdog);
+ m_watchdog = nullptr;
+ }
+}
diff --git a/remotessh/integrationpluginremotessh.h b/reversessh/integrationpluginreversessh.h
similarity index 70%
rename from remotessh/integrationpluginremotessh.h
rename to reversessh/integrationpluginreversessh.h
index 03c52e64..5f8b16db 100644
--- a/remotessh/integrationpluginremotessh.h
+++ b/reversessh/integrationpluginreversessh.h
@@ -33,43 +33,29 @@
#include "plugintimer.h"
#include "integrations/integrationplugin.h"
+#include "extern-plugininfo.h"
#include
-class IntegrationPluginRemoteSsh : public IntegrationPlugin
+class IntegrationPluginReverseSsh : public IntegrationPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginremotessh.json")
+ Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginreversessh.json")
Q_INTERFACES(IntegrationPlugin)
public:
- explicit IntegrationPluginRemoteSsh();
+ explicit IntegrationPluginReverseSsh();
+ ~IntegrationPluginReverseSsh();
- void init() override;
+ void startPairing(ThingPairingInfo *info) override;
+ void confirmPairing(ThingPairingInfo *info, const QString &user, const QString &secret) override;
void setupThing(ThingSetupInfo *info) override;
void thingRemoved(Thing *thing) override;
- void executeAction(ThingActionInfo *info) override;
private:
- QHash m_reverseSSHProcess;
- QHash m_sshKeyGenProcess;
-
- QHash m_startingProcess;
- QHash m_killingProcess;
-
- PluginTimer *m_pluginTimer = nullptr;
-
- bool m_aboutToQuit = false;
- QString m_identityFilePath;
-
- QProcess *startReverseSSHProcess(Thing *thing);
-
-private slots:
- void onPluginTimeout();
- void processReadyRead();
- void processStateChanged(QProcess::ProcessState state);
- void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ QHash m_processes;
+ PluginTimer *m_watchdog = nullptr;
};
#endif // INTEGRATIONPLUGINREMOTESSH_H
diff --git a/remotessh/integrationpluginremotessh.json b/reversessh/integrationpluginreversessh.json
similarity index 50%
rename from remotessh/integrationpluginremotessh.json
rename to reversessh/integrationpluginreversessh.json
index a5dea82c..3cf231ef 100644
--- a/remotessh/integrationpluginremotessh.json
+++ b/reversessh/integrationpluginreversessh.json
@@ -1,7 +1,7 @@
{
"id": "cd75d899-3f53-43fa-9ee8-f6b36646a27d",
- "name": "RemoteSsh",
- "displayName": "Remote SSH",
+ "name": "ReverseSsh",
+ "displayName": "Reverse SSH",
"vendors": [
{
"id": "e87ad7b1-1705-46b1-a962-282126646b4d",
@@ -13,73 +13,57 @@
"name": "reverseSsh",
"displayName": "Reverse SSH",
"createMethods": ["user"],
+ "setupMethod": "userandpassword",
"interfaces": ["connectable"],
+ "settingsTypes": [
+ {
+ "id": "478aea93-68c4-4527-ac91-15b8da77f1e5",
+ "name": "active",
+ "displayName": "Active",
+ "type": "bool",
+ "defaultValue": true
+ }
+ ],
"paramTypes": [
{
"id": "92747d75-d18a-4915-bd48-0edd5cc5f19a",
"name": "address",
- "displayName": "Address",
+ "displayName": "SSH server address",
"type": "QString",
- "inputType": "IPv4Address",
- "defaultValue": "127.0.0.1"
- },
- {
- "id": "7f7aa198-c719-415e-b31c-7a676b9d8e01",
- "name": "localPort",
- "displayName": "Local Port",
- "type": "int",
- "defaultValue": 22
+ "defaultValue": ""
},
{
"id": "988aec42-1026-4aef-85d1-329ee1a34208",
"name": "remotePort",
- "displayName": "Remote Port",
+ "displayName": "SSH server port",
"type": "int",
- "defaultValue": 2022
+ "defaultValue": 22
},
{
- "id": "c675f7ea-f94a-46e9-bf0f-92682182d6dd",
- "name": "user",
- "displayName": "User Name",
- "type": "QString",
- "inputType": "TextLine",
- "defaultValue": "Enter your user"
+ "id": "7f7aa198-c719-415e-b31c-7a676b9d8e01",
+ "name": "localPort",
+ "displayName": "Local SSH server port",
+ "type": "int",
+ "defaultValue": 22
},
{
- "id": "d8cc7177-bf35-4394-ab7b-881184bd8c8b",
- "name": "password",
- "displayName": "Password",
- "type": "QString",
- "inputType": "TextLine",
- "defaultValue": "Enter your password"
+ "id": "e999ce4b-bc8c-4664-8c1c-d502a1589e78",
+ "name": "remoteOpenPort",
+ "displayName": "Remote port to be opened",
+ "type": "int",
+ "defaultValue": 2201,
+ "minValue": 0,
+ "maxValue": 65535
}
],
"stateTypes":[
- {
- "id": "19f079f0-1654-44c3-ab10-e7d7f9742e09",
- "name": "reachable",
- "displayName": "Server Reachable",
- "displayNameEvent": "reachable status changed",
- "type": "bool",
- "defaultValue": true
- },
{
"id": "1ae425b2-d642-42ca-be41-4d06dff5c5cd",
"name": "connected",
"displayName": "Connected",
"type": "bool",
"defaultValue": false,
- "displayNameEvent": "Connected changed",
- "displayNameAction": "Connect to Server",
- "writable": true
- },
- {
- "id": "d8bb619e-6602-4c89-8654-85e111520561",
- "name": "sshKey",
- "displayName": "SSH public key",
- "displayNameEvent": "SSH key changed",
- "type": "QString",
- "defaultValue": "-"
+ "displayNameEvent": "Connected changed"
}
]
}
diff --git a/remotessh/meta.json b/reversessh/meta.json
similarity index 100%
rename from remotessh/meta.json
rename to reversessh/meta.json
diff --git a/reversessh/reversessh.pro b/reversessh/reversessh.pro
new file mode 100644
index 00000000..8746ec49
--- /dev/null
+++ b/reversessh/reversessh.pro
@@ -0,0 +1,10 @@
+include(../plugins.pri)
+
+TARGET = $$qtLibraryTarget(nymea_integrationpluginreversessh)
+
+SOURCES += \
+ integrationpluginreversessh.cpp \
+
+HEADERS += \
+ integrationpluginreversessh.h \
+
diff --git a/remotessh/remotessh.svg b/reversessh/reversessh.svg
similarity index 100%
rename from remotessh/remotessh.svg
rename to reversessh/reversessh.svg
diff --git a/remotessh/translations/cd75d899-3f53-43fa-9ee8-f6b36646a27d-en_US.ts b/reversessh/translations/cd75d899-3f53-43fa-9ee8-f6b36646a27d-en_US.ts
similarity index 52%
rename from remotessh/translations/cd75d899-3f53-43fa-9ee8-f6b36646a27d-en_US.ts
rename to reversessh/translations/cd75d899-3f53-43fa-9ee8-f6b36646a27d-en_US.ts
index 7206c033..fa483b46 100644
--- a/remotessh/translations/cd75d899-3f53-43fa-9ee8-f6b36646a27d-en_US.ts
+++ b/reversessh/translations/cd75d899-3f53-43fa-9ee8-f6b36646a27d-en_US.ts
@@ -2,45 +2,32 @@
- RemoteSsh
+ IntegrationPluginReverseSsh
- Remote Access
- The name of the vendor ({e87ad7b1-1705-46b1-a962-282126646b4d})
+ Please enter your login credentials for %1.
- Reverse SSH
- The name of the ThingClass ({a4f12741-4f30-40ca-a319-7f15e9c0c43a})
+ Login error on remote SSH server.
- Address
- The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {92747d75-d18a-4915-bd48-0edd5cc5f19a})
+ Cannot connect to remote SSH server.
+
+
+
+
+ ReverseSsh
+
+ Active
+ The name of the ParamType (ThingClass: reverseSsh, Type: settings, ID: {478aea93-68c4-4527-ac91-15b8da77f1e5})
- Local Port
- The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {7f7aa198-c719-415e-b31c-7a676b9d8e01})
-
-
-
- Remote Port
- The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {988aec42-1026-4aef-85d1-329ee1a34208})
-
-
-
- User Name
- The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {c675f7ea-f94a-46e9-bf0f-92682182d6dd})
-
-
-
- Password
- The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {d8cc7177-bf35-4394-ab7b-881184bd8c8b})
-
-
-
- reachable status changed
- The name of the EventType ({19f079f0-1654-44c3-ab10-e7d7f9742e09}) of ThingClass reverseSsh
+ Connected
+ The name of the ParamType (ThingClass: reverseSsh, EventType: connected, ID: {1ae425b2-d642-42ca-be41-4d06dff5c5cd})
+----------
+The name of the StateType ({1ae425b2-d642-42ca-be41-4d06dff5c5cd}) of ThingClass reverseSsh
@@ -49,41 +36,35 @@
- Connect to Server
- The name of the ActionType ({1ae425b2-d642-42ca-be41-4d06dff5c5cd}) of ThingClass reverseSsh
+ Local SSH server port
+ The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {7f7aa198-c719-415e-b31c-7a676b9d8e01})
- SSH key changed
- The name of the EventType ({d8bb619e-6602-4c89-8654-85e111520561}) of ThingClass reverseSsh
+ Remote Access
+ The name of the vendor ({e87ad7b1-1705-46b1-a962-282126646b4d})
- Remote SSH
- The name of the plugin RemoteSsh ({cd75d899-3f53-43fa-9ee8-f6b36646a27d})
+ Remote port to be opened
+ The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {e999ce4b-bc8c-4664-8c1c-d502a1589e78})
- Server Reachable
- The name of the ParamType (ThingClass: reverseSsh, EventType: reachable, ID: {19f079f0-1654-44c3-ab10-e7d7f9742e09})
+ Reverse SSH
+ The name of the ThingClass ({a4f12741-4f30-40ca-a319-7f15e9c0c43a})
----------
-The name of the StateType ({19f079f0-1654-44c3-ab10-e7d7f9742e09}) of ThingClass reverseSsh
+The name of the plugin ReverseSsh ({cd75d899-3f53-43fa-9ee8-f6b36646a27d})
- Connected
- The name of the ParamType (ThingClass: reverseSsh, ActionType: connected, ID: {1ae425b2-d642-42ca-be41-4d06dff5c5cd})
-----------
-The name of the ParamType (ThingClass: reverseSsh, EventType: connected, ID: {1ae425b2-d642-42ca-be41-4d06dff5c5cd})
-----------
-The name of the StateType ({1ae425b2-d642-42ca-be41-4d06dff5c5cd}) of ThingClass reverseSsh
+ SSH server address
+ The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {92747d75-d18a-4915-bd48-0edd5cc5f19a})
- SSH public key
- The name of the ParamType (ThingClass: reverseSsh, EventType: sshKey, ID: {d8bb619e-6602-4c89-8654-85e111520561})
-----------
-The name of the StateType ({d8bb619e-6602-4c89-8654-85e111520561}) of ThingClass reverseSsh
+ SSH server port
+ The name of the ParamType (ThingClass: reverseSsh, Type: thing, ID: {988aec42-1026-4aef-85d1-329ee1a34208})