mirror of
https://github.com/Fishwaldo/qt-openzwave.git
synced 2025-03-15 11:31:33 +00:00
Polling Commands and Network Key Support (#21)
* Add Methods to enable/disable Polling on a ValueID * add enablePoll/disablePoll MQTT comamnds * Read Network Key from either Environment or docker secrets file * Update Docs
This commit is contained in:
parent
72a55e5b38
commit
14453f555e
10 changed files with 141 additions and 12 deletions
54
docs/MQTT.md
54
docs/MQTT.md
|
@ -3,14 +3,25 @@ MQTT Client for OpenZWave
|
|||
|
||||
Docker Repo: https://hub.docker.com/r/openzwave/ozwdaemon
|
||||
|
||||
Copy the "config" folder from OZW to `/tmp/ozw/`.
|
||||
Make sure you have create a local folder where ozwdaemon can store the config files etc for your installation. In this example, /home/ozw/config/ is on your local machine.
|
||||
|
||||
If you are using Secure Communications, setup a Docker Secret:
|
||||
```
|
||||
printf "0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0b,0x0c,0x0d,0x0e,0x0f,0x10" | docker secret create OZW_Network_Key -
|
||||
```
|
||||
* replace the Hex String with 16 Bytes to use as your Network Key.
|
||||
|
||||
Start a container with the following command line:
|
||||
```
|
||||
docker run -it --security-opt seccomp=unconfined --device=/dev/ttyUSB0 -v /tmp/ozw:/opt/ozw/config -e MQTT_SERVER="10.100.200.102" -e USBPATH=/dev/ttyUSB0 openzwave/ozwdaemon:latest
|
||||
docker run -it --security-opt seccomp=unconfined --device=/dev/ttyUSB0 -v /home/ozw/config:/opt/ozw/config -e MQTT_SERVER="10.100.200.102" -e USBPATH=/dev/ttyUSB0 --secret OZW_Network_Key openzwave/ozwdaemon:latest
|
||||
```
|
||||
|
||||
(replace `MQTT_SERVER` with the IP address of the MQTT Server and all `/dev/ttyUSB0` entries with the path to your USB Stick.
|
||||
* Update `MQTT_SERVER` with the IP address of the MQTT Server and all `/dev/ttyUSB0` entries with the path to your USB Stick.
|
||||
* If you are not running with a ZWave Network Key, remove the `--secret OZW_Network_Key` command
|
||||
|
||||
|
||||
(Alternatively, you can specify the Network Key via a Docker Enviroment, but this is less secure:
|
||||
`-e OZW_NETWORK_KEY="0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0b,0x0c,0x0d,0x0e,0x0f,0x10"`)
|
||||
|
||||
## MQTT Topic Structure
|
||||
The MQTT Client for OZW will send messages to a MQTT Broker with a predifined topic structure. The structure of the messages are detailed in the sections below.
|
||||
|
@ -1230,3 +1241,40 @@ This allows a MQTT Client to set a value on a Device. As OZW supports many diffe
|
|||
|
||||
[addAssociation](#addAssociation)
|
||||
|
||||
## enablePoll
|
||||
|
||||
**Params**:
|
||||
|
||||
"ValueIDKey" - uint64: The ValueID Key
|
||||
|
||||
"Intensity" - uint8: The Intensity we should poll the value at
|
||||
|
||||
**Returns**:
|
||||
|
||||
"enablePoll" - if OZW accepted the command
|
||||
|
||||
**Notification**:
|
||||
|
||||
The appropriate value key in the MQTT Topic should be updated with a updated IsPolled Value
|
||||
|
||||
**See Also**:
|
||||
|
||||
[disablePoll](#disablePoll)
|
||||
|
||||
## disablePoll
|
||||
|
||||
**Params**:
|
||||
|
||||
"ValueIDKey" - uint64: The ValueID Key
|
||||
|
||||
**Returns**:
|
||||
|
||||
"disablePoll" - if OZW accepted the command
|
||||
|
||||
**Notification**:
|
||||
|
||||
The appropriate value key in the MQTT Topic should be updated with a updated IsPolled Value
|
||||
|
||||
**See Also**:
|
||||
|
||||
[enablePoll](#enablePoll)
|
||||
|
|
|
@ -144,6 +144,9 @@ public:
|
|||
bool AddAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target);
|
||||
bool RemoveAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target);
|
||||
|
||||
bool enablePoll(quint64 vidKey, quint8 intensity);
|
||||
bool disablePoll(quint64 vidKey);
|
||||
|
||||
/* Property Methods */
|
||||
QDir OZWDatabasePath() { return this->m_ozwdatabasepath; }
|
||||
QDir OZWUserPath() { return this->m_ozwuserpath; }
|
||||
|
|
|
@ -156,7 +156,8 @@ class QTOZWManager {
|
|||
|
||||
SLOT(qint32 getPollInterval())
|
||||
SLOT(void setPollInterval(qint32 interval, bool intervalBetweenPolls))
|
||||
|
||||
SLOT(bool enablePoll(quint64 vidKey, quint8 intensity))
|
||||
SLOT(bool disablePoll(quint64 vidKey))
|
||||
SLOT(void syncroniseNodeNeighbors(quint8 node))
|
||||
|
||||
}
|
|
@ -138,6 +138,8 @@ public Q_SLOTS:
|
|||
bool AddAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target);
|
||||
bool RemoveAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target);
|
||||
|
||||
bool enablePoll(quint64 vidKey, quint8 intensity);
|
||||
bool disablePoll(quint64 vidKey);
|
||||
|
||||
/* these slots are called from our OZWNotification Class. Applications should not call them */
|
||||
void pvt_valueAdded(quint64 vidKey);
|
||||
|
|
|
@ -459,7 +459,12 @@ bool QTOZWManager::AddAssociation (quint8 const _nodeId, quint8 const _groupIdx,
|
|||
bool QTOZWManager::RemoveAssociation (quint8 const _nodeId, quint8 const _groupIdx, QString const target) {
|
||||
CALL_DPTR_RTN(RemoveAssociation(_nodeId, _groupIdx, target), bool);
|
||||
}
|
||||
|
||||
bool QTOZWManager::enablePoll(quint64 vidKey, quint8 intensity) {
|
||||
CALL_DPTR_RTN(enablePoll(vidKey, intensity), bool);
|
||||
}
|
||||
bool QTOZWManager::disablePoll(quint64 vidKey) {
|
||||
CALL_DPTR_RTN(disablePoll(vidKey), bool);
|
||||
}
|
||||
|
||||
void QTOZWManager::setOZWDatabasePath(QDir path) {
|
||||
if (path.exists())
|
||||
|
|
|
@ -811,6 +811,36 @@ void QTOZWManager_Internal::setPollInterval(qint32 interval, bool intervalBetwee
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool QTOZWManager_Internal::enablePoll(quint64 vidKey, quint8 intensity) {
|
||||
if (!this->checkValueKey(vidKey))
|
||||
return false;
|
||||
try {
|
||||
OpenZWave::ValueID vid(this->homeId(), vidKey);
|
||||
bool ret = this->m_manager->EnablePoll(vid, intensity);
|
||||
this->m_valueModel->setValueFlags(vidKey, QTOZW_ValueIds::ValueIDFlags::ValuePolled, this->m_manager->IsValuePolled(vid), false);
|
||||
return ret;
|
||||
} catch (OpenZWave::OZWException &e) {
|
||||
emit this->error(QTOZWManagerErrorCodes::OZWException);
|
||||
this->setErrorString(e.GetMsg().c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool QTOZWManager_Internal::disablePoll(quint64 vidKey) {
|
||||
if (!this->checkValueKey(vidKey))
|
||||
return false;
|
||||
try {
|
||||
OpenZWave::ValueID vid(this->homeId(), vidKey);
|
||||
bool ret = this->m_manager->DisablePoll(vid);
|
||||
this->m_valueModel->setValueFlags(vidKey, QTOZW_ValueIds::ValueIDFlags::ValuePolled, this->m_manager->IsValuePolled(vid), false);
|
||||
return ret;
|
||||
} catch (OpenZWave::OZWException &e) {
|
||||
emit this->error(QTOZWManagerErrorCodes::OZWException);
|
||||
this->setErrorString(e.GetMsg().c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QTOZWManager_Internal::syncroniseNodeNeighbors(quint8 node) {
|
||||
if (!this->checkHomeId())
|
||||
return;
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
MqttCommand_EnablePoll::MqttCommand_EnablePoll(QObject *parent) :
|
||||
MqttCommand(parent)
|
||||
{
|
||||
this->m_requiredIntFields << "ValueIDKey";
|
||||
this->m_requiredIntFields << "ValueIDKey" << "Intensity";
|
||||
}
|
||||
MqttCommand* MqttCommand_EnablePoll::Create(QObject *parent) {
|
||||
return new MqttCommand_SyncroniseNodeNeighbors(parent);
|
||||
return new MqttCommand_EnablePoll(parent);
|
||||
}
|
||||
|
||||
bool MqttCommand_EnablePoll::processMessage(rapidjson::Document &msg) {
|
||||
|
@ -15,6 +15,5 @@ bool MqttCommand_EnablePoll::processMessage(rapidjson::Document &msg) {
|
|||
}
|
||||
|
||||
QTOZWManager *mgr = getOZWManager();
|
||||
//mgr->syncroniseNodeNeighbors(msg["node"].GetInt());
|
||||
return this->sendSimpleStatus(true);
|
||||
return this->sendSimpleStatus(mgr->enablePoll(msg["ValueIdKey"].GetUint64(), msg["Intensity"].GetUint()));
|
||||
}
|
|
@ -37,6 +37,7 @@
|
|||
#include "mqttcommands/setPollInterval.h"
|
||||
#include "mqttcommands/syncroniseNodeNeighbors.h"
|
||||
#include "mqttcommands/enablePoll.h"
|
||||
#include "mqttcommands/disablePoll.h"
|
||||
#include "mqttcommands/refreshValue.h"
|
||||
#include "mqttcommands/addAssociation.h"
|
||||
#include "mqttcommands/removeAssociation.h"
|
||||
|
@ -251,7 +252,8 @@ void MqttCommands::setupCommands() {
|
|||
this->Register(MqttCommand_GetPollInterval::StaticGetCommand(), &MqttCommand_GetPollInterval::Create);
|
||||
this->Register(MqttCommand_SetPollInterval::StaticGetCommand(), &MqttCommand_SetPollInterval::Create);
|
||||
this->Register(MqttCommand_SyncroniseNodeNeighbors::StaticGetCommand(), &MqttCommand_SyncroniseNodeNeighbors::Create);
|
||||
// this->Register(MqttCommand_EnablePoll::StaticGetCommand(), &MqttCommand_EnablePoll::Create);
|
||||
this->Register(MqttCommand_EnablePoll::StaticGetCommand(), &MqttCommand_EnablePoll::Create);
|
||||
this->Register(MqttCommand_DisablePoll::StaticGetCommand(), &MqttCommand_DisablePoll::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);
|
||||
|
|
|
@ -61,7 +61,9 @@ qtHaveModule(mqtt) {
|
|||
mqttcommands/syncroniseNodeNeighbors.cpp \
|
||||
mqttcommands/refreshValue.cpp \
|
||||
mqttcommands/addAssociation.cpp \
|
||||
mqttcommands/removeAssociation.cpp
|
||||
mqttcommands/removeAssociation.cpp \
|
||||
mqttcommands/enablePoll.cpp \
|
||||
mqttcommands/disablePoll.cpp
|
||||
|
||||
HEADERS += mqttpublisher.h \
|
||||
qtrj.h \
|
||||
|
@ -105,7 +107,9 @@ qtHaveModule(mqtt) {
|
|||
mqttcommands/syncroniseNodeNeighbors.h \
|
||||
mqttcommands/refreshValue.h \
|
||||
mqttcommands/addAssociation.h \
|
||||
mqttcommands/removeAssociation.h
|
||||
mqttcommands/removeAssociation.h \
|
||||
mqttcommands/enablePoll.h \
|
||||
mqttcommands/disablePoll.h
|
||||
|
||||
|
||||
} else {
|
||||
|
|
|
@ -4,10 +4,45 @@
|
|||
|
||||
qtozwdaemon::qtozwdaemon(QObject *parent) : QObject(parent)
|
||||
{
|
||||
QRegularExpression re("^(0[xX][a-fA-F0-9]{2}[ ,]*){16}$");
|
||||
|
||||
QString NetworkKeyTest = qgetenv("OZW_NETWORK_KEY");
|
||||
QString NetworkKey;
|
||||
QRegularExpressionMatch match = re.match(NetworkKeyTest);
|
||||
if (match.hasMatch()) {
|
||||
NetworkKey = NetworkKeyTest;
|
||||
qInfo() << "Network Key Specified in Enviroment is Valid";
|
||||
} else {
|
||||
qWarning() << "Network Key Specified in Enviroment is Invalid";
|
||||
}
|
||||
|
||||
QFile nwk_file("/run/secrets/OZW_Network_Key");
|
||||
if (nwk_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
NetworkKeyTest = nwk_file.readLine().trimmed();
|
||||
nwk_file.close();
|
||||
match = re.match(NetworkKeyTest);
|
||||
if (match.hasMatch()) {
|
||||
NetworkKey = NetworkKeyTest;
|
||||
qInfo() << "Network Key From File is Valid - Using File";
|
||||
} else {
|
||||
if (NetworkKey.isEmpty()) {
|
||||
qWarning() << "Network Key From File in Invalid - No Valid Network Key Found in Enviroment or File";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qInfo() << "Didn't Find Network Key File. Skipping";
|
||||
}
|
||||
if (!NetworkKey.isEmpty()) {
|
||||
qInfo() << "We Have what appears to be a valid Network Key - Passing to OZW";
|
||||
}
|
||||
|
||||
this->m_openzwave = new QTOpenZwave(this);
|
||||
this->m_qtozwmanager = this->m_openzwave->GetManager();
|
||||
QObject::connect(this->m_qtozwmanager, &QTOZWManager::ready, this, &qtozwdaemon::QTOZW_Ready);
|
||||
this->m_qtozwmanager->initilizeSource(true);
|
||||
if (!NetworkKey.isEmpty()) {
|
||||
this->m_qtozwmanager->getOptions()->setNetworkKey(NetworkKey);
|
||||
}
|
||||
}
|
||||
|
||||
void qtozwdaemon::QTOZW_Ready() {
|
||||
|
|
Loading…
Add table
Reference in a new issue