Fixes after testing/review
This commit is contained in:
parent
322bcf56a6
commit
82703de061
@ -343,6 +343,35 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (requestPath.startsWith("/debug/settings/ioconnections")) {
|
||||
QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleIOConnections).fileName();
|
||||
qCDebug(dcDebugServer()) << "Loading" << settingsFileName;
|
||||
QFile settingsFile(settingsFileName);
|
||||
if (!settingsFile.exists()) {
|
||||
qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist.";
|
||||
HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName)));
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (!settingsFile.open(QFile::ReadOnly)) {
|
||||
qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName;
|
||||
HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName)));
|
||||
return reply;
|
||||
}
|
||||
|
||||
QByteArray settingsFileData = settingsFile.readAll();
|
||||
settingsFile.close();
|
||||
|
||||
HttpReply *reply = HttpReply::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/plain");
|
||||
reply->setPayload(settingsFileData);
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (requestPath.startsWith("/debug/ping")) {
|
||||
// Only one ping process should run
|
||||
if (m_pingProcess || m_pingReply)
|
||||
@ -1608,6 +1637,56 @@ QByteArray DebugServerHandler::createDebugXmlDocument()
|
||||
|
||||
writer.writeEndElement(); // div download-row
|
||||
|
||||
|
||||
// Download row IO connections
|
||||
writer.writeStartElement("div");
|
||||
writer.writeAttribute("class", "download-row");
|
||||
|
||||
writer.writeStartElement("div");
|
||||
writer.writeAttribute("class", "download-name-column");
|
||||
//: The MQTT policies download description of the debug interface
|
||||
writer.writeTextElement("p", tr("IO Connections"));
|
||||
writer.writeEndElement(); // div download-name-column
|
||||
|
||||
writer.writeStartElement("div");
|
||||
writer.writeAttribute("class", "download-path-column");
|
||||
writer.writeTextElement("p", NymeaSettings(NymeaSettings::SettingsRoleIOConnections).fileName());
|
||||
writer.writeEndElement(); // div download-path-column
|
||||
|
||||
writer.writeStartElement("div");
|
||||
writer.writeAttribute("class", "download-button-column");
|
||||
writer.writeStartElement("form");
|
||||
writer.writeAttribute("class", "download-button");
|
||||
writer.writeStartElement("button");
|
||||
writer.writeAttribute("class", "button");
|
||||
writer.writeAttribute("type", "button");
|
||||
if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleMqttPolicies).fileName())) {
|
||||
writer.writeAttribute("disabled", "true");
|
||||
}
|
||||
writer.writeAttribute("onClick", "downloadFile('/debug/settings/ioconnections', 'ioconnections.conf')");
|
||||
writer.writeCharacters(tr("Download"));
|
||||
writer.writeEndElement(); // button
|
||||
writer.writeEndElement(); // form
|
||||
writer.writeEndElement(); // div download-button-column
|
||||
|
||||
writer.writeStartElement("div");
|
||||
writer.writeAttribute("class", "show-button-column");
|
||||
writer.writeStartElement("form");
|
||||
writer.writeAttribute("class", "show-button");
|
||||
writer.writeStartElement("button");
|
||||
writer.writeAttribute("class", "button");
|
||||
writer.writeAttribute("type", "button");
|
||||
if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleMqttPolicies).fileName())) {
|
||||
writer.writeAttribute("disabled", "true");
|
||||
}
|
||||
writer.writeAttribute("onClick", "showFile('/debug/settings/ioconnections')");
|
||||
writer.writeCharacters(tr("Show"));
|
||||
writer.writeEndElement(); // button
|
||||
writer.writeEndElement(); // form
|
||||
writer.writeEndElement(); // div show-button-column
|
||||
|
||||
writer.writeEndElement(); // div download-row
|
||||
|
||||
writer.writeEndElement(); // downloads-section
|
||||
|
||||
|
||||
|
||||
@ -2039,6 +2039,12 @@ void ThingManagerImplementation::loadIOConnections()
|
||||
IOConnection ioConnection(id, inputThingId, inputStateTypeId, outputThingId, outputStateTypeId, inverted);
|
||||
m_ioConnections.insert(id, ioConnection);
|
||||
connectionSettings.endGroup();
|
||||
|
||||
Thing *inputThing = m_configuredThings.value(inputThingId);
|
||||
if (!inputThing) {
|
||||
continue;
|
||||
}
|
||||
syncIOConnection(inputThing, inputStateTypeId);
|
||||
}
|
||||
connectionSettings.endGroup();
|
||||
}
|
||||
|
||||
@ -420,7 +420,7 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
||||
});
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Emitted whenever a IO connection is added.";
|
||||
description = "Emitted whenever an IO connection has been added.";
|
||||
params.insert("ioConnection", objectRef<IOConnection>());
|
||||
registerNotification("IOConnectionAdded", description, params);
|
||||
connect(m_thingManager, &ThingManager::ioConnectionAdded, this, [this](const IOConnection &connection) {
|
||||
@ -430,7 +430,7 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
||||
});
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Emitted whenever a IO connection is removed.";
|
||||
description = "Emitted whenever an IO connection has been removed.";
|
||||
params.insert("ioConnectionId", enumValueName(Uuid));
|
||||
registerNotification("IOConnectionRemoved", description, params);
|
||||
connect(m_thingManager, &ThingManager::ioConnectionRemoved, this, [this](const IOConnectionId &ioConnectionId) {
|
||||
|
||||
@ -1,3 +1,47 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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 IOConnection
|
||||
\brief The IOConnection class stores information about generic IO connections.
|
||||
|
||||
\ingroup things
|
||||
\inmodule libnymea
|
||||
|
||||
Generic IO connections allow a user to connect states of two devices so they'll be synced whenever
|
||||
those states change.
|
||||
|
||||
\sa ThingManager::connectIO
|
||||
|
||||
*/
|
||||
|
||||
#include "ioconnection.h"
|
||||
|
||||
IOConnection::IOConnection()
|
||||
@ -5,6 +49,7 @@ IOConnection::IOConnection()
|
||||
|
||||
}
|
||||
|
||||
/*! Constructs a new IOConnection object. */
|
||||
IOConnection::IOConnection(const IOConnectionId &id, const ThingId &inputThing, const StateTypeId &inputState, const ThingId &outputThing, const StateTypeId &outputState, bool inverted):
|
||||
m_id(id),
|
||||
m_inputThingId(inputThing),
|
||||
@ -16,31 +61,37 @@ IOConnection::IOConnection(const IOConnectionId &id, const ThingId &inputThing,
|
||||
|
||||
}
|
||||
|
||||
/*! Returns the ID of this connection object. */
|
||||
IOConnectionId IOConnection::id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/*! Returns the ID of the input thing for this connection. */
|
||||
ThingId IOConnection::inputThingId() const
|
||||
{
|
||||
return m_inputThingId;
|
||||
}
|
||||
|
||||
/*! Returns the input state type ID for this connection. */
|
||||
StateTypeId IOConnection::inputStateTypeId() const
|
||||
{
|
||||
return m_inputStateTypeId;
|
||||
}
|
||||
|
||||
/*! Returns the ID of the output thing for this connection. */
|
||||
ThingId IOConnection::outputThingId() const
|
||||
{
|
||||
return m_outputThingId;
|
||||
}
|
||||
|
||||
/*! Returns the output state type ID for this connection. */
|
||||
StateTypeId IOConnection::outputStateTypeId() const
|
||||
{
|
||||
return m_outputStateTypeId;
|
||||
}
|
||||
|
||||
/*! Returns whether the connection is inverted or not. */
|
||||
bool IOConnection::inverted() const
|
||||
{
|
||||
return m_inverted;
|
||||
|
||||
@ -1,3 +1,33 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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 IOCONNECTION_H
|
||||
#define IOCONNECTION_H
|
||||
|
||||
|
||||
@ -51,6 +51,18 @@ ThingManager::ThingManager(QObject *parent) : QObject(parent)
|
||||
qRegisterMetaType<ParamTypes>();
|
||||
}
|
||||
|
||||
/*! Connect two states.
|
||||
When two states are connected, any state changes will be synced between those. A connection
|
||||
is made from an \a inputThing and its \a inputState to an \a outputThing and its \a outputState.
|
||||
Whenever the input state changes, the output state is set accordingly. If the input state is
|
||||
writable, the connection will be bidirectional, that is, a change of the output state will also
|
||||
reflect on the input state.
|
||||
Connections can be logically inverted.
|
||||
Connections need to be compatible. This means, only states which have a defined ioState of type "input"
|
||||
can be connected to states which habe a defined ioState of type "output". Additionally, the digital/analog
|
||||
type needs to match. In other words, states with ioType "digitalInput" can be connected to states with ioType
|
||||
"digitaOutput" and states with ioType "analogInput" can be connected to states with ioType "analogOutput".
|
||||
*/
|
||||
IOConnectionResult ThingManager::connectIO(const ThingId &inputThing, const StateTypeId &inputState, const ThingId &outputThing, const StateTypeId &outputState, bool inverted)
|
||||
{
|
||||
IOConnection connection(IOConnectionId::createIOConnectionId(), inputThing, inputState, outputThing, outputState, inverted);
|
||||
|
||||
@ -60,6 +60,10 @@
|
||||
This role will create the \b{device-states.conf} file and is used to store the configured \l{Device} \l{State}{States}.
|
||||
\value SettingsRoleTags
|
||||
This role will create the \b{tags.conf} file and is used to store the \l{Tag}{Tags}.
|
||||
\value SettingsRoleMqttPolicies
|
||||
This role will create the \b{mqttpolicies.conf} file and is used to store the \l{MqttPolicy}{MqttPolicies}.
|
||||
\value SettingsRoleIOConnections
|
||||
This role will create the \b{ioconnections.conf} file and is used to store the \l{IOConnection}{IOConnections}.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@ -720,12 +720,13 @@ void IntegrationPluginMock::executeAction(ThingActionInfo *info)
|
||||
|
||||
if (info->thing()->thingClassId() == genericIoMockThingClassId) {
|
||||
if (info->action().actionTypeId() == genericIoMockDigitalOutput1ActionTypeId) {
|
||||
info->thing()->setStateValue(genericIoMockDigitalOutput1StateTypeId, info->action().param(genericIoMockDigitalOutput1ActionDigitalOutput1ParamTypeId).value());
|
||||
qCDebug(dcMock()) << "Setting digital output 1 to" << info->action().param(genericIoMockDigitalOutput1ActionDigitalOutput1ParamTypeId).value().toBool();
|
||||
info->thing()->setStateValue(genericIoMockDigitalOutput1StateTypeId, info->action().param(genericIoMockDigitalOutput1ActionDigitalOutput1ParamTypeId).value().toBool());
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
if (info->action().actionTypeId() == genericIoMockDigitalOutput2ActionTypeId) {
|
||||
info->thing()->setStateValue(genericIoMockDigitalOutput2StateTypeId, info->action().param(genericIoMockDigitalOutput2ActionDigitalOutput2ParamTypeId).value());
|
||||
info->thing()->setStateValue(genericIoMockDigitalOutput2StateTypeId, info->action().param(genericIoMockDigitalOutput2ActionDigitalOutput2ParamTypeId).value().toBool());
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2055,13 +2055,13 @@
|
||||
}
|
||||
},
|
||||
"Integrations.IOConnectionAdded": {
|
||||
"description": "Emitted whenever a IO connection is added.",
|
||||
"description": "Emitted whenever an IO connection has been added.",
|
||||
"params": {
|
||||
"ioConnection": "$ref:IOConnection"
|
||||
}
|
||||
},
|
||||
"Integrations.IOConnectionRemoved": {
|
||||
"description": "Emitted whenever a IO connection is removed.",
|
||||
"description": "Emitted whenever an IO connection has been removed.",
|
||||
"params": {
|
||||
"ioConnectionId": "Uuid"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user