mirror of
https://github.com/Fishwaldo/qt-openzwave.git
synced 2025-03-15 19:41:24 +00:00
add Association Management Commands (#14)
* Add AddAssociation and RemoveAssociation Commands - This completes the Association Functionality
This commit is contained in:
parent
78544d6fc2
commit
47f4b61364
16 changed files with 292 additions and 4 deletions
53
docs/MQTT.md
53
docs/MQTT.md
|
@ -1177,3 +1177,56 @@ This allows a MQTT Client to set a value on a Device. As OZW supports many diffe
|
|||
|
||||
[testNetwork](#testNetwork)
|
||||
|
||||
## addAssociation
|
||||
|
||||
**Params**:
|
||||
|
||||
"node" - uint8: The NodeID to test
|
||||
|
||||
"group" - uint8: The Association Group you wish to add a member to
|
||||
|
||||
"target" - string: The Target Node you wish to send notifications to for this group.
|
||||
|
||||
**Returns**:
|
||||
|
||||
"addAssociation" - if OZW accepted the command
|
||||
|
||||
**Notification**:
|
||||
|
||||
topic "nodeGroupChanged" Indicates the Memberships was successfully refreshed from the device
|
||||
|
||||
**Notes**:
|
||||
|
||||
Note - The Target string can be specified as a single NodeID (eg, "1" or "1.0") or a NodeID and Instance as "<nodeid>.<instance>". This allows you to configure a device to send a notification to a different instance on Multi Channel Devices. You should ensure that the target device has a valid instance and supports the commands it will recieve.
|
||||
If you specify a instance (other than 0) for a target node, but the group does not support sending MultiChannel messages, the instance will be removed (or set to 0, which indicates the root node).
|
||||
|
||||
**See Also**:
|
||||
|
||||
[removeAssociation](#removeAssociation)
|
||||
|
||||
## removeAssociation
|
||||
|
||||
**Params**:
|
||||
|
||||
"node" - uint8: The NodeID to test
|
||||
|
||||
"group" - uint8: The Association Group you wish to add a member to
|
||||
|
||||
"target" - string: The Target Node you wish remove from the Group Membership List.
|
||||
|
||||
**Returns**:
|
||||
|
||||
"removeAssociation" - if OZW accepted the command
|
||||
|
||||
**Notification**:
|
||||
|
||||
topic "nodeGroupChanged" Indicates the Memberships was successfully refreshed from the device
|
||||
|
||||
**Notes**:
|
||||
|
||||
Note - The Target string can be specified as a single NodeID (eg, "1" or "1.0") or a NodeID and Instance as "<nodeid>.<instance>". You should first check the membership list via the Association Topics for the device and only attempt to remove existing members. Attempting to remove a member that does exist will result in a error.
|
||||
|
||||
**See Also**:
|
||||
|
||||
[addAssociation](#addAssociation)
|
||||
|
||||
|
|
|
@ -63,6 +63,10 @@ public:
|
|||
int columnCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
#if 0
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
QVariant getassocationData(quint8 _node, quint8 _groupIDX, QTOZW_Associations::associationColumns _column);
|
||||
|
|
|
@ -141,6 +141,8 @@ public:
|
|||
|
||||
bool refreshValue(quint64);
|
||||
|
||||
bool AddAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target);
|
||||
bool RemoveAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target);
|
||||
|
||||
/* Property Methods */
|
||||
QDir OZWDatabasePath() { return this->m_ozwdatabasepath; }
|
||||
|
|
|
@ -149,6 +149,11 @@ class QTOZWManager {
|
|||
SLOT(QString getControllerPath())
|
||||
SLOT(bool refreshValue(quint64))
|
||||
|
||||
SLOT(bool AddAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target))
|
||||
SLOT(bool RemoveAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target))
|
||||
|
||||
|
||||
|
||||
SLOT(qint32 getPollInterval())
|
||||
SLOT(void setPollInterval(qint32 interval, bool intervalBetweenPolls))
|
||||
|
||||
|
|
|
@ -135,6 +135,10 @@ public Q_SLOTS:
|
|||
|
||||
bool refreshValue(quint64);
|
||||
|
||||
bool AddAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target);
|
||||
bool RemoveAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target);
|
||||
|
||||
|
||||
/* these slots are called from our OZWNotification Class. Applications should not call them */
|
||||
void pvt_valueAdded(quint64 vidKey);
|
||||
void pvt_valueRemoved(quint64 vidKey);
|
||||
|
|
|
@ -99,7 +99,41 @@ QVariant QTOZW_Associations::headerData(int section, Qt::Orientation orientation
|
|||
}
|
||||
return QVariant();
|
||||
}
|
||||
#if 0
|
||||
bool QTOZW_Associations::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
if (role != Qt::EditRole) {
|
||||
return false;
|
||||
}
|
||||
switch (static_cast<associationColumns>(index.column())) {
|
||||
case Members:
|
||||
// if (this->m_valueData.at(index.row())[static_cast<ValueIdColumns>(index.column())] != value) {
|
||||
// qCDebug(valueModel) << "setData Called for Row" << index.row() << " With Value" << value;
|
||||
// this->m_valueData[index.row()][static_cast<ValueIdColumns>(index.column())] = value;
|
||||
// QVector<int> roles;
|
||||
// roles << Qt::DisplayRole << QTOZW_UserRoles::ModelDataChanged;
|
||||
// this->dataChanged(index, index, roles);
|
||||
// }
|
||||
break;
|
||||
default:
|
||||
qCWarning(valueModel) << "got a setData for a Column other than Value. Ignoring" << index.column();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags QTOZW_Associations::flags(const QModelIndex &index) const {
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
switch (static_cast<associationColumns>(index.column())) {
|
||||
case Members: {
|
||||
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return QAbstractTableModel::flags(index);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
QVariant QTOZW_Associations::getassocationData(quint8 _node, quint8 _groupIDX, associationColumns _column) {
|
||||
int32_t row = this->getassocationRow(_node, _groupIDX);
|
||||
if (row >= 0)
|
||||
|
|
|
@ -453,6 +453,13 @@ void QTOZWManager::syncroniseNodeNeighbors(quint8 node) {
|
|||
bool QTOZWManager::refreshValue(quint64 vidKey) {
|
||||
CALL_DPTR_RTN(refreshValue(vidKey), bool);
|
||||
}
|
||||
bool QTOZWManager::AddAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target) {
|
||||
CALL_DPTR_RTN(AddAssociation(_nodeId, _groupIdx, target), bool);
|
||||
}
|
||||
bool QTOZWManager::RemoveAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target) {
|
||||
CALL_DPTR_RTN(RemoveAssociation(_nodeId, _groupIdx, target), bool);
|
||||
}
|
||||
|
||||
|
||||
void QTOZWManager::setOZWDatabasePath(QDir path) {
|
||||
if (path.exists())
|
||||
|
|
|
@ -841,6 +841,105 @@ bool QTOZWManager_Internal::refreshValue(quint64 vidKey) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool QTOZWManager_Internal::AddAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target) {
|
||||
if (!this->checkHomeId())
|
||||
return false;
|
||||
if (!this->checkNodeId(_nodeId))
|
||||
return false;
|
||||
quint8 targetnode = 0;
|
||||
quint8 targetinstance = 0;
|
||||
QRegExp rx("^(\\d+)\\.(\\d+)$");
|
||||
if (target.contains(rx)) {
|
||||
targetnode = rx.cap(1).toInt();
|
||||
targetinstance = rx.cap(2).toInt();
|
||||
qCDebug(manager) << "Got a AddAssociation with a instance value" << target << " node: " << targetnode << " instance: " << targetinstance;
|
||||
}
|
||||
rx.setPattern("^(\\d+)$");
|
||||
if (target.contains(rx)) {
|
||||
targetnode = rx.cap(1).toInt();
|
||||
targetinstance = 0;
|
||||
qCDebug(manager) << "Got a AddAssociation with no instance value" << target << " node: " << targetnode;
|
||||
}
|
||||
if (targetnode == 0) {
|
||||
qCWarning(manager) << "Couldn't find a valid Target in AddAssociation: " << target;
|
||||
return false;
|
||||
}
|
||||
if (targetinstance > 0) {
|
||||
try {
|
||||
if (!this->m_manager->IsMultiInstance(this->homeId(), _nodeId, _groupIdx)) {
|
||||
qCWarning(manager) << "AddAssociation: Association Group " << _groupIdx << "for node " << _nodeId << "does not support instances but a instance was specified:" << target << ". Removing";
|
||||
targetinstance = 0;
|
||||
}
|
||||
} catch (OpenZWave::OZWException &e) {
|
||||
emit this->error(QTOZWManagerErrorCodes::OZWException);
|
||||
this->setErrorString(e.GetMsg().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this->m_associationsModel->findAssociation(_nodeId, _groupIdx, targetnode, targetinstance)) {
|
||||
qCWarning(manager) << "AddAssociation: Association Group " << _groupIdx << "for node " << _nodeId << "already has a Assocation to " << target;
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
this->m_manager->AddAssociation(this->homeId(), _nodeId, _groupIdx, targetnode, targetinstance);
|
||||
return true;
|
||||
} catch (OpenZWave::OZWException &e) {
|
||||
emit this->error(QTOZWManagerErrorCodes::OZWException);
|
||||
this->setErrorString(e.GetMsg().c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool QTOZWManager_Internal::RemoveAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target) {
|
||||
if (!this->checkHomeId())
|
||||
return false;
|
||||
if (!this->checkNodeId(_nodeId))
|
||||
return false;
|
||||
quint8 targetnode = 0;
|
||||
quint8 targetinstance = 0;
|
||||
QRegExp rx("^(\\d+)\\.(\\d+)$");
|
||||
if (target.contains(rx)) {
|
||||
targetnode = rx.cap(1).toInt();
|
||||
targetinstance = rx.cap(2).toInt();
|
||||
}
|
||||
rx.setPattern("^(\\d+)$");
|
||||
if (target.contains(rx)) {
|
||||
targetnode = rx.cap(1).toInt();
|
||||
targetinstance = 0;
|
||||
}
|
||||
if (targetnode == 0) {
|
||||
qCWarning(manager) << "Couldn't find a valid Target in RemoveAssocation: " << target;
|
||||
return false;
|
||||
}
|
||||
if (targetinstance > 0) {
|
||||
try {
|
||||
if (!this->m_manager->IsMultiInstance(this->homeId(), _nodeId, _groupIdx)) {
|
||||
qCWarning(manager) << "RemoveAssoication: Association Group " << _groupIdx << "for node " << _nodeId << "does not support instances but a instance was specified:" << target << ". Removing";
|
||||
targetinstance = 0;
|
||||
}
|
||||
} catch (OpenZWave::OZWException &e) {
|
||||
emit this->error(QTOZWManagerErrorCodes::OZWException);
|
||||
this->setErrorString(e.GetMsg().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->m_associationsModel->findAssociation(_nodeId, _groupIdx, targetnode, targetinstance)) {
|
||||
qCWarning(manager) << "RemoveAssociation: Association Group " << _groupIdx << "for node " << _nodeId << "does not have a Assocation to " << target;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
this->m_manager->RemoveAssociation(this->homeId(), _nodeId, _groupIdx, targetnode, targetinstance);
|
||||
return true;
|
||||
} catch (OpenZWave::OZWException &e) {
|
||||
emit this->error(QTOZWManagerErrorCodes::OZWException);
|
||||
this->setErrorString(e.GetMsg().c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QTOZW_Nodes *QTOZWManager_Internal::getNodeModel() {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "qt-openzwave/qtozwmanager.h"
|
||||
#include "mqttAssociations.h"
|
||||
#include "qtrj.h"
|
||||
|
|
19
qt-ozwdaemon/mqttcommands/addAssociation.cpp
Normal file
19
qt-ozwdaemon/mqttcommands/addAssociation.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "mqttcommands/addAssociation.h"
|
||||
|
||||
MqttCommand_AddAssociation::MqttCommand_AddAssociation(QObject *parent) :
|
||||
MqttCommand(parent)
|
||||
{
|
||||
this->m_requiredIntFields << "node" << "group";
|
||||
this->m_requiredStringFields << "target";
|
||||
}
|
||||
MqttCommand* MqttCommand_AddAssociation::Create(QObject *parent) {
|
||||
return new MqttCommand_AddAssociation(parent);
|
||||
}
|
||||
|
||||
bool MqttCommand_AddAssociation::processMessage(rapidjson::Document &msg) {
|
||||
if (!this->checkNode(msg, "node")) {
|
||||
return this->sendSimpleStatus(false, "Invalid Node Number");
|
||||
}
|
||||
QTOZWManager *mgr = getOZWManager();
|
||||
return this->sendSimpleStatus(mgr->AddAssociation(msg["node"].GetUint(), msg["group"].GetUint(), msg["target"].GetString()));
|
||||
}
|
17
qt-ozwdaemon/mqttcommands/addAssociation.h
Normal file
17
qt-ozwdaemon/mqttcommands/addAssociation.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef ADDASSOCIATION_H
|
||||
#define ADDASSOCIATION_H
|
||||
|
||||
#include "mqttcommands/mqttcommands.h"
|
||||
|
||||
class MqttCommand_AddAssociation : public MqttCommand {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static MqttCommand *Create(QObject *parent = nullptr);
|
||||
static QString StaticGetCommand() { return "AddAssociation";};
|
||||
QString GetCommand() override { return StaticGetCommand(); };
|
||||
bool processMessage(rapidjson::Document &) override;
|
||||
private:
|
||||
MqttCommand_AddAssociation(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // PING_H
|
|
@ -38,6 +38,8 @@
|
|||
#include "mqttcommands/syncroniseNodeNeighbors.h"
|
||||
#include "mqttcommands/enablePoll.h"
|
||||
#include "mqttcommands/refreshValue.h"
|
||||
#include "mqttcommands/addAssociation.h"
|
||||
#include "mqttcommands/removeAssociation.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(ozwmc, "ozw.mqtt.commands");
|
||||
|
||||
|
@ -251,6 +253,8 @@ void MqttCommands::setupCommands() {
|
|||
this->Register(MqttCommand_SyncroniseNodeNeighbors::StaticGetCommand(), &MqttCommand_SyncroniseNodeNeighbors::Create);
|
||||
// this->Register(MqttCommand_EnablePoll::StaticGetCommand(), &MqttCommand_EnablePoll::Create);
|
||||
this->Register(MqttCommand_RefreshValue::StaticGetCommand(), &MqttCommand_RefreshValue::Create);
|
||||
this->Register(MqttCommand_AddAssociation::StaticGetCommand(), &MqttCommand_AddAssociation::Create);
|
||||
this->Register(MqttCommand_RemoveAssociation::StaticGetCommand(), &MqttCommand_RemoveAssociation::Create);
|
||||
}
|
||||
|
||||
void MqttCommands::setupSubscriptions(QMqttClient *mqttclient, QString topTopic) {
|
||||
|
|
19
qt-ozwdaemon/mqttcommands/removeAssociation.cpp
Normal file
19
qt-ozwdaemon/mqttcommands/removeAssociation.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "mqttcommands/removeAssociation.h"
|
||||
|
||||
MqttCommand_RemoveAssociation::MqttCommand_RemoveAssociation(QObject *parent) :
|
||||
MqttCommand(parent)
|
||||
{
|
||||
this->m_requiredIntFields << "node" << "group";
|
||||
this->m_requiredStringFields << "target";
|
||||
}
|
||||
MqttCommand* MqttCommand_RemoveAssociation::Create(QObject *parent) {
|
||||
return new MqttCommand_RemoveAssociation(parent);
|
||||
}
|
||||
|
||||
bool MqttCommand_RemoveAssociation::processMessage(rapidjson::Document &msg) {
|
||||
if (!this->checkNode(msg, "node")) {
|
||||
return this->sendSimpleStatus(false, "Invalid Node Number");
|
||||
}
|
||||
QTOZWManager *mgr = getOZWManager();
|
||||
return this->sendSimpleStatus(mgr->RemoveAssociation(msg["node"].GetUint(), msg["group"].GetUint(), msg["target"].GetString()));
|
||||
}
|
17
qt-ozwdaemon/mqttcommands/removeAssociation.h
Normal file
17
qt-ozwdaemon/mqttcommands/removeAssociation.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef REMOVEASSOCIATION_H
|
||||
#define REMOVEASSOCIATION_H
|
||||
|
||||
#include "mqttcommands/mqttcommands.h"
|
||||
|
||||
class MqttCommand_RemoveAssociation : public MqttCommand {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static MqttCommand *Create(QObject *parent = nullptr);
|
||||
static QString StaticGetCommand() { return "RemoveAssociation";};
|
||||
QString GetCommand() override { return StaticGetCommand(); };
|
||||
bool processMessage(rapidjson::Document &) override;
|
||||
private:
|
||||
MqttCommand_RemoveAssociation(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // PING_H
|
|
@ -380,7 +380,7 @@ void mqttpublisher::sendCommandUpdate(QString command, rapidjson::Document &js)
|
|||
|
||||
void mqttpublisher::sendAssociationUpdate(quint8 node, quint8 group, rapidjson::Document &js) {
|
||||
QT2JS::SetUInt64(js, "TimeStamp", QDateTime::currentSecsSinceEpoch());
|
||||
this->m_client->publish(QMqttTopicName(getAssociationTopic(node, group)), QT2JS::getJSON(js), 0, false);
|
||||
this->m_client->publish(QMqttTopicName(getAssociationTopic(node, group)), QT2JS::getJSON(js), 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,9 @@ qtHaveModule(mqtt) {
|
|||
mqttcommands/setPollInterval.cpp \
|
||||
mqttcommands/getPollINterval.cpp \
|
||||
mqttcommands/syncroniseNodeNeighbors.cpp \
|
||||
mqttcommands/refreshValue.cpp
|
||||
mqttcommands/refreshValue.cpp \
|
||||
mqttcommands/addAssociation.cpp \
|
||||
mqttcommands/removeAssociation.cpp
|
||||
|
||||
HEADERS += mqttpublisher.h \
|
||||
qtrj.h \
|
||||
|
@ -101,7 +103,10 @@ qtHaveModule(mqtt) {
|
|||
mqttcommands/setPollInterval.h \
|
||||
mqttcommands/getPollInterval.h\
|
||||
mqttcommands/syncroniseNodeNeighbors.h \
|
||||
mqttcommands/refreshValue.h
|
||||
mqttcommands/refreshValue.h \
|
||||
mqttcommands/addAssociation.h \
|
||||
mqttcommands/removeAssociation.h
|
||||
|
||||
|
||||
} else {
|
||||
warning("MQTT Qt Module Not Found. Not Building MQTT Client Capabilities")
|
||||
|
|
Loading…
Add table
Reference in a new issue