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;
|
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")) {
|
if (requestPath.startsWith("/debug/ping")) {
|
||||||
// Only one ping process should run
|
// Only one ping process should run
|
||||||
if (m_pingProcess || m_pingReply)
|
if (m_pingProcess || m_pingReply)
|
||||||
@ -1608,6 +1637,56 @@ QByteArray DebugServerHandler::createDebugXmlDocument()
|
|||||||
|
|
||||||
writer.writeEndElement(); // div download-row
|
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
|
writer.writeEndElement(); // downloads-section
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2039,6 +2039,12 @@ void ThingManagerImplementation::loadIOConnections()
|
|||||||
IOConnection ioConnection(id, inputThingId, inputStateTypeId, outputThingId, outputStateTypeId, inverted);
|
IOConnection ioConnection(id, inputThingId, inputStateTypeId, outputThingId, outputStateTypeId, inverted);
|
||||||
m_ioConnections.insert(id, ioConnection);
|
m_ioConnections.insert(id, ioConnection);
|
||||||
connectionSettings.endGroup();
|
connectionSettings.endGroup();
|
||||||
|
|
||||||
|
Thing *inputThing = m_configuredThings.value(inputThingId);
|
||||||
|
if (!inputThing) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
syncIOConnection(inputThing, inputStateTypeId);
|
||||||
}
|
}
|
||||||
connectionSettings.endGroup();
|
connectionSettings.endGroup();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -420,7 +420,7 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||||||
});
|
});
|
||||||
|
|
||||||
params.clear(); returns.clear();
|
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>());
|
params.insert("ioConnection", objectRef<IOConnection>());
|
||||||
registerNotification("IOConnectionAdded", description, params);
|
registerNotification("IOConnectionAdded", description, params);
|
||||||
connect(m_thingManager, &ThingManager::ioConnectionAdded, this, [this](const IOConnection &connection) {
|
connect(m_thingManager, &ThingManager::ioConnectionAdded, this, [this](const IOConnection &connection) {
|
||||||
@ -430,7 +430,7 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||||||
});
|
});
|
||||||
|
|
||||||
params.clear(); returns.clear();
|
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));
|
params.insert("ioConnectionId", enumValueName(Uuid));
|
||||||
registerNotification("IOConnectionRemoved", description, params);
|
registerNotification("IOConnectionRemoved", description, params);
|
||||||
connect(m_thingManager, &ThingManager::ioConnectionRemoved, this, [this](const IOConnectionId &ioConnectionId) {
|
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"
|
#include "ioconnection.h"
|
||||||
|
|
||||||
IOConnection::IOConnection()
|
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):
|
IOConnection::IOConnection(const IOConnectionId &id, const ThingId &inputThing, const StateTypeId &inputState, const ThingId &outputThing, const StateTypeId &outputState, bool inverted):
|
||||||
m_id(id),
|
m_id(id),
|
||||||
m_inputThingId(inputThing),
|
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
|
IOConnectionId IOConnection::id() const
|
||||||
{
|
{
|
||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the ID of the input thing for this connection. */
|
||||||
ThingId IOConnection::inputThingId() const
|
ThingId IOConnection::inputThingId() const
|
||||||
{
|
{
|
||||||
return m_inputThingId;
|
return m_inputThingId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the input state type ID for this connection. */
|
||||||
StateTypeId IOConnection::inputStateTypeId() const
|
StateTypeId IOConnection::inputStateTypeId() const
|
||||||
{
|
{
|
||||||
return m_inputStateTypeId;
|
return m_inputStateTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the ID of the output thing for this connection. */
|
||||||
ThingId IOConnection::outputThingId() const
|
ThingId IOConnection::outputThingId() const
|
||||||
{
|
{
|
||||||
return m_outputThingId;
|
return m_outputThingId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the output state type ID for this connection. */
|
||||||
StateTypeId IOConnection::outputStateTypeId() const
|
StateTypeId IOConnection::outputStateTypeId() const
|
||||||
{
|
{
|
||||||
return m_outputStateTypeId;
|
return m_outputStateTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns whether the connection is inverted or not. */
|
||||||
bool IOConnection::inverted() const
|
bool IOConnection::inverted() const
|
||||||
{
|
{
|
||||||
return m_inverted;
|
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
|
#ifndef IOCONNECTION_H
|
||||||
#define IOCONNECTION_H
|
#define IOCONNECTION_H
|
||||||
|
|
||||||
|
|||||||
@ -51,6 +51,18 @@ ThingManager::ThingManager(QObject *parent) : QObject(parent)
|
|||||||
qRegisterMetaType<ParamTypes>();
|
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)
|
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);
|
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}.
|
This role will create the \b{device-states.conf} file and is used to store the configured \l{Device} \l{State}{States}.
|
||||||
\value SettingsRoleTags
|
\value SettingsRoleTags
|
||||||
This role will create the \b{tags.conf} file and is used to store the \l{Tag}{Tags}.
|
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->thing()->thingClassId() == genericIoMockThingClassId) {
|
||||||
if (info->action().actionTypeId() == genericIoMockDigitalOutput1ActionTypeId) {
|
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);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (info->action().actionTypeId() == genericIoMockDigitalOutput2ActionTypeId) {
|
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);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2055,13 +2055,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Integrations.IOConnectionAdded": {
|
"Integrations.IOConnectionAdded": {
|
||||||
"description": "Emitted whenever a IO connection is added.",
|
"description": "Emitted whenever an IO connection has been added.",
|
||||||
"params": {
|
"params": {
|
||||||
"ioConnection": "$ref:IOConnection"
|
"ioConnection": "$ref:IOConnection"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Integrations.IOConnectionRemoved": {
|
"Integrations.IOConnectionRemoved": {
|
||||||
"description": "Emitted whenever a IO connection is removed.",
|
"description": "Emitted whenever an IO connection has been removed.",
|
||||||
"params": {
|
"params": {
|
||||||
"ioConnectionId": "Uuid"
|
"ioConnectionId": "Uuid"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user