initial import from ozwadmin

This commit is contained in:
Justin Hammond 2019-05-22 17:17:22 +08:00
parent 5b92a8d71b
commit 832ec8f36f
35 changed files with 4396 additions and 0 deletions

2
qt-openzwave.pri Normal file
View file

@ -0,0 +1,2 @@
top_srcdir=$$PWD
top_builddir=$$shadowed($$PWD)

16
qt-openzwave.pro Normal file
View file

@ -0,0 +1,16 @@
#-------------------------------------------------
#
# Project created by QtCreator 2016-04-27T16:10:29
#
#-------------------------------------------------
TEMPLATE = subdirs
CONFIG += ordered silent
#SUBDIRS = qt-openzwave simpleclient ozwadmin-widgets devicedb-lib ozwadmin-main
SUBDIRS = qt-openzwave simpleclient
ozwadmin-main.depends = qt-openzwave ozwadmin-widgets devicedb-lib

View file

@ -0,0 +1,108 @@
#-------------------------------------------------
#
# Project created by QtCreator 2019-05-10T15:07:50
#
#-------------------------------------------------
include(../qt-openzwave.pri)
QT -= gui
QT += remoteobjects
#QT += websockets
TEMPLATE = lib
VERSION = 1.0.0
CONFIG += silent
!versionAtLeast(QT_VERSION, 5.11.2):error("Use at least Qt version 5.11.2")
qtConfig(static) {
# this is a static build
}
mac {
PKG_CONFIG = /usr/local/bin/pkg-config
}
unix {
isEmpty(OZW_LIB_PATH) {
QT_CONFIG -= no-pkg-config
CONFIG += link_pkgconfig
packagesExist(libopenzwave) {
message("Using Distribution copy of OpenZWave")
PKGCONFIG += openzwave
} else {
exists( $$top_srcdir/../open-zwave/cpp/src/) {
message("Found Openzwave in $$absolute_path($$top_srcdir/../open-zwave/cpp/src)")
OZW_LIB_PATH = $$absolute_path($$top_srcdir/../open-zwave/)
INCLUDEPATH += $$absolute_path($$top_srcdir/../open-zwave/cpp/src/)
LIBS += -L$$absolute_path($$top_srcdir/../open-zwave/) -lopenzwave
} else {
message("Can't Find a copy of OpenZwave")
}
}
} else {
exists($$OZW_LIB_PATH/cpp/src/) {
INCLUDEPATH += $$absolute_path($$OZW_LIB_PATH/cpp/src/)
LIBS += -L$$absolute_path($$OZW_LIB_PATH) -lopenzwave
message("Using OZW from Path Supplied in OZW_LIB_PATH varible: $$OZW_LIB_PATH" )
} else {
error("Unable to find a copy of OZW in $$OZW_LIB_PATH")
}
}
}
DEFINES += QTOPENZWAVE_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
qtopenzwave.cpp \
qtozwassociations.cpp \
qtozwmanager.cpp \
qtozwnotification.cpp \
qtozwproxymodels.cpp \
qtozwnodemodel.cpp \
qtozwvalueidmodel.cpp
HEADERS += \
qtopenzwave.h \
qt-openzwave_global.h \ \
qtozwassociations.h \
qtozwproxymodels.h \
qtozwmanager.h \
qtozwnotification.h \
qtozwnodemodel.h \
qtozwvalueidmodel.h
REPC_SOURCE = qtozwmanager.rep
REPC_REPLICA = qtozwmanager.rep
unix {
target.path = /usr/local/lib
INSTALLS += target
}
macx {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
}
message(" ")
message("Summary:")
message(" OpenZWave Path: $$OZW_LIB_PATH")
message(" Include Path: $$INCLUDEPATH")
message(" Library Path: $$LIBS")
message(" ")

View file

@ -0,0 +1,12 @@
#ifndef QTOPENZWAVE_GLOBAL_H
#define QTOPENZWAVE_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(QTOPENZWAVE_LIBRARY)
# define QTOPENZWAVESHARED_EXPORT Q_DECL_EXPORT
#else
# define QTOPENZWAVESHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // QTOPENZWAVE_GLOBAL_H

View file

@ -0,0 +1,27 @@
#include "qtopenzwave.h"
QTOpenZwave::QTOpenZwave
(
QObject *parent
) :
QObject (parent),
m_manager(nullptr)
{
//qRegisterMetaType<uint32_t>("uint32_t");
qRegisterMetaType<QTOZW_ValueIDList>("QTOZW_ValueIDList");
qRegisterMetaTypeStreamOperators<QTOZW_ValueIDList>("QTOZW_ValueIDList");
qRegisterMetaType<QTOZW_ValueIDBitSet>("QTOZW_ValueIDBitSet");
qRegisterMetaTypeStreamOperators<QTOZW_ValueIDBitSet>("QTOZW_ValueIDBitSet");
}
QTOZWManager *QTOpenZwave::GetManager
(
)
{
if (m_manager == nullptr) {
this->m_manager = new QTOZWManager(this);
}
return this->m_manager;
}

View file

@ -0,0 +1,26 @@
#ifndef QTOPENZWAVE_H
#define QTOPENZWAVE_H
#include <QObject>
#include <QtRemoteObjects>
#include "qt-openzwave_global.h"
#include "qtozwmanager.h"
#include "websocketiodevice.h"
class QTOPENZWAVESHARED_EXPORT QTOpenZwave : public QObject
{
Q_OBJECT
public:
QTOpenZwave(QObject *parent = nullptr);
QTOZWManager *GetManager();
private Q_SLOT:
void newWSConnection();
private:
QTOZWManager *m_manager;
};
#endif // QTOPENZWAVE_H

View file

@ -0,0 +1,301 @@
#include <QDebug>
#include <QBitArray>
#include "qtozwassociations.h"
#include "qtopenzwave.h"
QTOZW_Associations::QTOZW_Associations(QObject *parent)
: QAbstractTableModel(parent)
{
}
int QTOZW_Associations::rowCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return this->m_associationData.count();
}
int QTOZW_Associations::columnCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return QTOZW_Associations::associationColumns::Count;
}
QVariant QTOZW_Associations::data(const QModelIndex &index, int role) const {
if (!index.isValid())
return QVariant();
if (index.row() >= this->rowCount(index.parent()) || index.row() < 0)
return QVariant();
if (role == Qt::DisplayRole) {
QMap<associationColumns, QVariant> node = this->m_associationData[index.row()];
if (node.size() == 0) {
qWarning() << "data: Cant find any Node on Row " << index.row();
return QVariant();
}
return node[static_cast<associationColumns>(index.column())];
}
return QVariant();
}
QVariant QTOZW_Associations::headerData(int section, Qt::Orientation orientation, int role) const {
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (static_cast<associationColumns>(section)) {
case NodeID:
return tr("NodeID");
case GroupID:
return tr("Group ID");
case GroupName:
return tr("Group Name");
case GroupHelp:
return tr("Help");
case MaxAssocations:
return tr("Max Assocations");
case MemberNodeID:
return tr("Member");
case MemberNodeInstance:
return tr("Member Node Instance");
case Flags:
return tr("Flags");
case Count:
return QVariant();
}
}
return QVariant();
}
QVariant QTOZW_Associations::getassocationData(uint8_t _node, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance, associationColumns _column) {
int32_t row = this->getassocationRow(_node, _groupIDX, _targetNodeId, _targetNodeInstance);
if (row >= 0)
return this->m_associationData[row][_column];
qWarning() << "Can't find Group " << _groupIDX << " for node " << _node << " with Target Node: " << _targetNodeId << ":" << _targetNodeInstance << " in m_associationData";
return QVariant();
}
int32_t QTOZW_Associations::getassocationRow(uint8_t _node, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance) {
if (this->m_associationData.count() == 0) {
return -1;
}
QMap<int32_t, QMap<associationColumns, QVariant> >::iterator it;
for (it = m_associationData.begin(); it != m_associationData.end(); ++it) {
QMap<associationColumns, QVariant> group = it.value();
if (group.value(associationColumns::NodeID) == _node) {
if (group.value(associationColumns::GroupID) == _groupIDX) {
if (group.value(associationColumns::MemberNodeID) == _targetNodeId) {
if (group.value(associationColumns::MemberNodeInstance) == _targetNodeInstance) {
return it.key();
}
}
}
}
}
qWarning() << "Can't Find Group " << _groupIDX << " for node " << _node << " with Target Node: " << _targetNodeId << ":" << _targetNodeInstance << " in m_associationData";
return -1;
}
QTOZW_Associations_internal::QTOZW_Associations_internal(QObject *parent)
: QTOZW_Associations(parent)
{
}
void QTOZW_Associations_internal::addAssociation(uint8_t _nodeID, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance)
{
if (this->getassocationRow(_nodeID, _groupIDX, _targetNodeId, _targetNodeInstance) >= 0) {
qWarning() << "Association Group " << _groupIDX << " for node " << _nodeID << " with Target Node: " << _targetNodeId << ":" << _targetNodeInstance << " Already Exists";
return;
}
QMap<associationColumns, QVariant> newNode;
newNode[associationColumns::NodeID] = _nodeID;
newNode[associationColumns::GroupID] = _groupIDX;
newNode[associationColumns::MemberNodeID] = _targetNodeId;
newNode[associationColumns::MemberNodeInstance] = _targetNodeInstance;
if (this->m_defaultData.count(_nodeID) && this->m_defaultData[_nodeID].count(_groupIDX)) {
QMap<QTOZW_Associations::associationColumns, QVariant>::iterator it;
for (it = this->m_defaultData[_nodeID][_groupIDX].begin(); it != this->m_defaultData[_nodeID][_groupIDX].end(); ++it) {
newNode[it.key()] = it.value();
}
}
if (newNode[associationColumns::Flags].toBitArray().size() == 0) {
QBitArray flags(static_cast<int>(associationColumns::Count));
newNode[associationColumns::Flags] = flags;
}
this->beginInsertRows(QModelIndex(), this->rowCount(QModelIndex()), this->rowCount(QModelIndex()));
this->m_associationData[this->rowCount(QModelIndex())] = newNode;
this->endInsertRows();
}
void QTOZW_Associations_internal::delAssociation(uint8_t _nodeID, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance) {
QMap<int32_t, QMap<associationColumns, QVariant> >::iterator it;
QMap<int32_t, QMap<associationColumns, QVariant> > newAssociationMap;
int32_t newrow = 0;
for (it = this->m_associationData.begin(); it != this->m_associationData.end(); ++it) {
if (it.value()[associationColumns::NodeID] == _nodeID) {
if (it.value()[associationColumns::GroupID] == _groupIDX) {
if (it.value()[associationColumns::MemberNodeID] == _targetNodeId) {
if (it.value()[associationColumns::MemberNodeInstance] == _targetNodeInstance) {
qDebug() << "Removing Node " << it.value()[associationColumns::NodeID] << it.key();
this->beginRemoveRows(QModelIndex(), it.key(), it.key());
this->m_associationData.erase(it);
this->endRemoveRows();
continue;
}
}
}
}
newAssociationMap[newrow] = it.value();
newrow++;
}
this->m_associationData.swap(newAssociationMap);
}
void QTOZW_Associations_internal::setAssociationData(uint8_t _nodeID, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance, QTOZW_Associations::associationColumns column, QVariant data)
{
int row = this->getassocationRow(_nodeID, _groupIDX, _targetNodeId, _targetNodeInstance);
if (row == -1) {
qWarning() << "setAssocationData: Group " << _groupIDX << "for node " << _nodeID << " does not exist";
return;
}
if (this->m_associationData[row][column] != data) {
this->m_associationData[row][column] = data;
QVector<int> roles;
roles << Qt::DisplayRole;
this->dataChanged(this->createIndex(row, column), this->createIndex(row, column), roles);
}
}
void QTOZW_Associations_internal::setAssociationFlags(uint8_t _nodeID, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance, QTOZW_Associations::associationFlags _flags, bool _value)
{
int row = this->getassocationRow(_nodeID, _groupIDX, _targetNodeId, _targetNodeInstance);
if (row == -1) {
qWarning() << "setAssocationFlags: Group " << _groupIDX << " for node " << _nodeID << " does not exist";
return;
}
QBitArray flag = this->m_associationData[row][associationColumns::Flags].toBitArray();
if (flag.at(_flags) != _value) {
flag.setBit(_flags, _value);
this->m_associationData[row][associationColumns::Flags] = flag;
QVector<int> roles;
roles << Qt::DisplayRole;
this->dataChanged(this->createIndex(row, associationColumns::Flags), this->createIndex(row, associationColumns::Flags), roles);
}
}
void QTOZW_Associations_internal::delNode(uint8_t _nodeID) {
QMap<int32_t, QMap<associationColumns, QVariant> >::iterator it;
QMap<int32_t, QMap<associationColumns, QVariant> > newAssociationMap;
int32_t newrow = 0;
for (it = this->m_associationData.begin(); it != this->m_associationData.end(); ++it) {
if (it.value()[associationColumns::NodeID] == _nodeID) {
qDebug() << "Removing Node " << it.value()[associationColumns::NodeID] << it.key();
this->beginRemoveRows(QModelIndex(), it.key(), it.key());
this->m_associationData.erase(it);
this->endRemoveRows();
continue;
} else {
newAssociationMap[newrow] = it.value();
newrow++;
}
}
this->m_associationData.swap(newAssociationMap);
}
void QTOZW_Associations_internal::delGroup(uint8_t _nodeID, uint8_t _groupIDX) {
QMap<int32_t, QMap<associationColumns, QVariant> >::iterator it;
QMap<int32_t, QMap<associationColumns, QVariant> > newAssociationMap;
int32_t newrow = 0;
for (it = this->m_associationData.begin(); it != this->m_associationData.end(); ++it) {
if (it.value()[associationColumns::NodeID] == _nodeID) {
if (it.value()[associationColumns::GroupID] == _groupIDX) {
qDebug() << "Removing Node " << it.value()[associationColumns::NodeID] << it.key();
this->beginRemoveRows(QModelIndex(), it.key(), it.key());
this->m_associationData.erase(it);
this->endRemoveRows();
continue;
}
}
newAssociationMap[newrow] = it.value();
newrow++;
}
this->m_associationData.swap(newAssociationMap);
}
void QTOZW_Associations_internal::resetModel() {
this->beginRemoveRows(QModelIndex(), 0, this->m_associationData.count());
this->m_associationData.clear();
this->endRemoveRows();
}
void QTOZW_Associations_internal::setDefaultGroupData(uint8_t _nodeID, uint8_t _groupIDX, QTOZW_Associations::associationColumns column, QVariant data) {
switch (column) {
case NodeID:
case GroupID:
case MemberNodeID:
case MemberNodeInstance:
{
qWarning() << "Can Not Set Default Data for " << static_cast<associationColumns>(column);
return;
}
default:
break;
}
if (this->m_defaultData.count(_nodeID) == 0) {
QMap<uint8_t, QMap<QTOZW_Associations::associationColumns, QVariant> > newNode;
this->m_defaultData.insert(_nodeID, newNode);
}
if (this->m_defaultData[_nodeID].count(_groupIDX) == 0) {
QBitArray flags(static_cast<int>(QTOZW_Nodes::flagCount));
this->m_defaultData[_nodeID][_groupIDX][associationColumns::Flags] = flags;
}
this->m_defaultData[_nodeID][_groupIDX][column] = data;
QMap<int32_t, QMap<QTOZW_Associations::associationColumns, QVariant> >::iterator it;
for (it = this->m_associationData.begin(); it != this->m_associationData.end(); ++it) {
if (it.value()[associationColumns::NodeID] == _nodeID) {
if (it.value()[associationColumns::GroupID] == _groupIDX) {
this->setAssociationData(_nodeID, _groupIDX, it.value()[associationColumns::MemberNodeID].value<uint8_t>(), it.value()[associationColumns::MemberNodeInstance].value<uint8_t>(), column, data);
}
}
}
}
void QTOZW_Associations_internal::setDefaultGroupFlags(uint8_t _nodeID, uint8_t _groupIDX, QTOZW_Associations::associationFlags flag, bool data) {
if (this->m_defaultData.count(_nodeID) == 0) {
QMap<uint8_t, QMap<QTOZW_Associations::associationColumns, QVariant> > newNode;
this->m_defaultData.insert(_nodeID, newNode);
}
if (this->m_defaultData[_nodeID].count(_groupIDX) == 0) {
QBitArray flags(static_cast<int>(QTOZW_Nodes::flagCount));
this->m_defaultData[_nodeID][_groupIDX][associationColumns::Flags] = flags;
}
QBitArray flags = this->m_defaultData[_nodeID][_groupIDX][associationColumns::Flags].toBitArray();
flags.setBit(flag, data);
this->m_defaultData[_nodeID][_groupIDX][associationColumns::Flags].toBitArray() = flags;
QMap<int32_t, QMap<QTOZW_Associations::associationColumns, QVariant> >::iterator it;
for (it = this->m_associationData.begin(); it != this->m_associationData.end(); ++it) {
if (it.value()[associationColumns::NodeID] == _nodeID) {
if (it.value()[associationColumns::GroupID] == _groupIDX) {
this->setAssociationFlags(_nodeID, _groupIDX, it.value()[associationColumns::MemberNodeID].value<uint8_t>(), it.value()[associationColumns::MemberNodeInstance].value<uint8_t>(), flag, data);
}
}
}
}
bool QTOZW_Associations_internal::isAssociationExists(uint8_t _node, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance) {
return this->getassocationRow(_node, _groupIDX, _targetNodeId, _targetNodeInstance) == -1 ? false : true;
}

View file

@ -0,0 +1,64 @@
#ifndef QTOZWASSOCIATIONS_H
#define QTOZWASSOCIATIONS_H
#include <QObject>
#include <QAbstractItemModel>
class QTOZW_Associations : public QAbstractTableModel {
Q_OBJECT
public:
enum associationColumns {
NodeID,
GroupID,
GroupName,
GroupHelp,
MaxAssocations,
MemberNodeID,
MemberNodeInstance,
Flags,
Count
};
Q_ENUM(associationColumns)
enum associationFlags {
isMultiInstance
};
Q_ENUM(associationFlags)
friend class QTOZWManager_Internal;
QTOZW_Associations(QObject *parent=nullptr);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
protected:
QVariant getassocationData(uint8_t _node, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance, QTOZW_Associations::associationColumns _column);
int32_t getassocationRow(uint8_t _node, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance);
QMap<int32_t, QMap<QTOZW_Associations::associationColumns, QVariant> > m_associationData;
};
class QTOZW_Associations_internal : public QTOZW_Associations {
Q_OBJECT
public:
QTOZW_Associations_internal(QObject *parent=nullptr);
public Q_SLOTS:
void addAssociation(uint8_t _nodeID, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance);
void delAssociation(uint8_t _nodeID, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance);
void setAssociationData(uint8_t _nodeID, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance, QTOZW_Associations::associationColumns column, QVariant data);
void setAssociationFlags(uint8_t _nodeID, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance, QTOZW_Associations::associationFlags _flags, bool _value);
bool isAssociationExists(uint8_t _node, uint8_t _groupIDX, uint8_t _targetNodeId, uint8_t _targetNodeInstance);
void setDefaultGroupData(uint8_t _nodeID, uint8_t _groupIDX, QTOZW_Associations::associationColumns column, QVariant data);
void setDefaultGroupFlags(uint8_t _nodeID, uint8_t _groupIDX, QTOZW_Associations::associationFlags _flags, bool _value);
void delNode(uint8_t _nodeID);
void delGroup(uint8_t _nodeID, uint8_t _groupIDX);
void resetModel();
private:
QMap<uint8_t, QMap<uint8_t, QMap<QTOZW_Associations::associationColumns, QVariant> > > m_defaultData;
};
#endif // QTOZWASSOCIATIONS_H

File diff suppressed because it is too large Load diff

256
qt-openzwave/qtozwmanager.h Normal file
View file

@ -0,0 +1,256 @@
#ifndef QTOZWMANAGER_H
#define QTOZWMANAGER_H
#include <QObject>
#include <QUrl>
#include "rep_qtozwmanager_source.h"
#include "rep_qtozwmanager_replica.h"
#include "qtozwnotification.h"
#include "qtozwnodemodel.h"
#include "qtozwvalueidmodel.h"
#include "qtozwassociations.h"
void setupOZW();
enum QTOZW_UserRoles {
ModelDataChanged = Qt::UserRole
};
namespace OpenZWave {
/* forward Declaration */
class Manager;
class Options;
class Notification;
}
class QTOZWManager_Internal : public QTOZWManagerSimpleSource
{
Q_OBJECT
public:
friend class OZWNotification;
QTOZWManager_Internal(QObject *parent = nullptr);
QTOZW_Nodes *getNodeModel();
QTOZW_ValueIds *getValueModel();
QTOZW_Associations *getAssociationModel();
public Q_SLOTS:
bool open(QString serialPort);
bool refreshNodeInfo(uint8_t _node);
bool requestNodeState(uint8_t _node);
bool requestNodeDynamic(uint8_t _node);
bool setConfigParam(uint8_t _node, uint8_t _param, int32_t _value, uint8_t const _size);
void requestConfigParam(uint8_t _node, uint8_t _param);
void requestAllConfigParam(uint8_t _node);
void softResetController();
void hardResetController();
bool cancelControllerCommand();
void testNetworkNode(uint8_t _node, uint32_t const _count);
void testNetwork(uint32_t const _count);
void healNetworkNode(uint8_t _node, bool _doRR);
void healNetwork(bool _doRR);
bool addNode(bool _doSecure);
bool removeNode();
bool removeFailedNode(uint8_t _node);
bool hasNodeFailed(uint8_t _node);
bool requestNodeNeighborUpdate(uint8_t _node);
bool assignReturnRoute(uint8_t _node);
bool deleteAllReturnRoute(uint8_t _node);
bool sendNodeInfomation(uint8_t _node);
bool replaceFailedNode(uint8_t _node);
bool requestNetworkUpdate(uint8_t _node);
bool checkLatestConfigFileRevision(uint8_t const _node);
bool checkLatestMFSRevision();
bool downloadLatestConfigFileRevision(uint8_t const _node);
bool downloadLatestMFSRevision();
/* these slots are called from our OZWNotification Class. Applications should not call them */
void pvt_valueAdded(uint64_t vidKey);
void pvt_valueRemoved(uint64_t vidKey);
void pvt_valueChanged(uint64_t vidKey);
void pvt_valueRefreshed(uint64_t vidKey);
void pvt_valuePollingEnabled(uint64_t vidKey);
void pvt_valuePollingDisabled(uint64_t vidKey);
void pvt_nodeGroupChanged(uint8_t node, uint8_t group);
void pvt_nodeNew(uint8_t node);
void pvt_nodeAdded(uint8_t node);
void pvt_nodeRemoved(uint8_t node);
void pvt_nodeReset(uint8_t node);
void pvt_nodeNaming(uint8_t node);
void pvt_nodeEvent(uint8_t node, uint8_t event);
void pvt_nodeProtocolInfo(uint8_t node);
void pvt_nodeEssentialNodeQueriesComplete(uint8_t node);
void pvt_nodeQueriesComplete(uint8_t node);
void pvt_driverReady(uint32_t homeID);
void pvt_driverFailed(uint32_t homeID);
void pvt_driverReset(uint32_t homeID);
void pvt_driverRemoved(uint32_t homeID);
void pvt_driverAllNodesQueriedSomeDead();
void pvt_driverAllNodesQueried();
void pvt_driverAwakeNodesQueried();
void pvt_controllerCommand(uint8_t command);
void pvt_ozwNotification(OpenZWave::Notification::NotificationCode event);
void pvt_ozwUserAlert(OpenZWave::Notification::UserAlertNotification event);
void pvt_manufacturerSpecificDBReady();
void pvt_nodeModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
void pvt_valueModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
private:
bool Lock();
bool Unlock();
private:
bool checkHomeId();
bool checkNodeId(uint8_t _node);
bool checkValueKey(uint64_t _vidKey);
bool convertValueID(uint64_t vidKey);
OpenZWave::Options *m_options;
OpenZWave::Manager *m_manager;
QTOZW_Nodes_internal *m_nodeModel;
QTOZW_ValueIds_internal *m_valueModel;
QTOZW_Associations_internal *m_associationsModel;
pthread_mutex_t m_manager_mutex;
QVector<uint8_t> m_validNodes;
QVector<uint64_t> m_validValues;
QMap<uint8_t, QMap<uint8_t, bool > > m_associationDefaultsSet;
};
class QTOZWManager : public QObject {
Q_OBJECT
public:
enum connectionType {
Local,
Remote,
Invalid
};
Q_ENUM(connectionType)
QTOZWManager(QObject *parent = nullptr);
bool initilizeBase();
bool initilizeSource(bool enableServer);
bool initilizeReplica(QUrl remoteaddress);
bool isRunning();
QAbstractItemModel *getNodeModel();
QAbstractItemModel *getValueModel();
QAbstractItemModel *getAssociationModel();
/* OpenZWave::Manager methods */
bool open(QString serialPort);
bool refreshNodeInfo(uint8_t _node);
bool requestNodeState(uint8_t _node);
bool requestNodeDynamic(uint8_t _node);
bool setConfigParam(uint8_t _node, uint8_t _param, int32_t _value, uint8_t const _size);
void requestConfigParam(uint8_t _node, uint8_t _param);
void requestAllConfigParam(uint8_t _node);
void softResetController();
void hardResetController();
bool cancelControllerCommand();
void testNetworkNode(uint8_t _node, uint32_t const _count);
void testNetwork(uint32_t const _count);
void healNetworkNode(uint8_t _node, bool _doRR);
void healNetwork(bool _doRR);
bool addNode(bool _doSecure);
bool removeNode();
bool removeFailedNode(uint8_t _node);
bool hasNodeFailed(uint8_t _node);
bool requestNodeNeighborUpdate(uint8_t _node);
bool assignReturnRoute(uint8_t _node);
bool deleteAllReturnRoute(uint8_t _node);
bool sendNodeInfomation(uint8_t _node);
bool replaceFailedNode(uint8_t _node);
bool requestNetworkUpdate(uint8_t _node);
bool checkLatestConfigFileRevision(uint8_t const _node);
bool checkLatestMFSRevision();
bool downloadLatestConfigFileRevision(uint8_t const _node);
bool downloadLatestMFSRevision();
Q_SIGNALS:
void ready();
void valueAdded(uint64_t vidKey);
void valueRemoved(uint64_t vidKey);
void valueChanged(uint64_t vidKey);
void valueRefreshed(uint64_t vidKey);
void nodeNew(uint8_t node);
void nodeAdded(uint8_t node);
void nodeRemoved(uint8_t node);
void nodeReset(uint8_t node);
void nodeNaming(uint8_t node);
void nodeEvent(uint8_t node, uint8_t event);
void nodeProtocolInfo(uint8_t node);
void nodeEssentialNodeQueriesComplete(uint8_t node);
void nodeQueriesComplete(uint8_t node);
void driverReady(uint32_t homeID);
void driverFailed(uint32_t homeID);
void driverReset(uint32_t homeID);
void driverRemoved(uint32_t homeID);
void driverAllNodesQueriedSomeDead();
void driverAllNodesQueried();
void driverAwakeNodesQueried();
void controllerCommand(uint8_t command);
// void ozwNotification(OpenZWave::Notification::NotificationCode event);
// void ozwUserAlert(OpenZWave::Notification::UserAlertNotification event);
void manufacturerSpecificDBReady();
void starting();
void started(uint32_t homeID);
void stopped(uint32_t homeID);
// void error(QTOZWErrorCodes errorcode);
private Q_SLOTS:
void onReplicaError(QRemoteObjectNode::ErrorCode);
void onSourceError(QRemoteObjectHost::ErrorCode);
void onManagerStateChange(QRemoteObjectReplica::State);
void onNodeInitialized();
void onValueInitialized();
void onAssociationInitialized();
void setStarted();
void setStopped();
private:
void checkReplicaReady();
void connectSignals();
connectionType m_connectionType;
QRemoteObjectNode *m_replicaNode;
QRemoteObjectHost *m_sourceNode;
QTOZWManager_Internal *d_ptr_internal;
QTOZWManagerReplica *d_ptr_replica;
QRemoteObjectReplica::State m_managerState;
bool m_nodeState;
bool m_valuesState;
bool m_associationsState;
QAbstractItemModel *m_nodeModel;
QAbstractItemModel *m_valueModel;
QAbstractItemModel *m_associationModel;
bool m_running;
};
#endif // QTOZWMANAGER_H

View file

@ -0,0 +1,81 @@
#include <QtCore>
class QTOZWManager {
ENUM QTOZWErrorCodes {
homeId_Invalid,
nodeId_Invalid,
valueIDKey_Invalid,
Manager_Not_Started,
OZWException,
setupFailed,
NoError
};
PROP(bool running SOURCEONLYSETTER)
PROP(uint32_t homeId SOURCEONLYSETTER)
PROP(QString errorString SOURCEONLYSETTER)
SIGNAL(valueAdded(uint64_t vidKey))
SIGNAL(valueRemoved(uint64_t vidKey))
SIGNAL(valueChanged(uint64_t vidKey))
SIGNAL(valueRefreshed(uint64_t vidKey))
SIGNAL(nodeNew(uint8_t node))
SIGNAL(nodeAdded(uint8_t node))
SIGNAL(nodeRemoved(uint8_t node))
SIGNAL(nodeReset(uint8_t node))
SIGNAL(nodeNaming(uint8_t node))
SIGNAL(nodeEvent(uint8_t node, uint8_t event))
SIGNAL(nodeProtocolInfo(uint8_t node))
SIGNAL(nodeEssentialNodeQueriesComplete(uint8_t node))
SIGNAL(nodeQueriesComplete(uint8_t node))
SIGNAL(driverReady(uint32_t homeID))
SIGNAL(driverFailed(uint32_t homeID))
SIGNAL(driverReset(uint32_t homeID))
SIGNAL(driverRemoved(uint32_t homeID))
SIGNAL(driverAllNodesQueriedSomeDead())
SIGNAL(driverAllNodesQueried())
SIGNAL(driverAwakeNodesQueried())
SIGNAL(controllerCommand(uint8_t command))
// SIGNAL(ozwNotification(OpenZWave::Notification::NotificationCode event))
// SIGNAL(ozwUserAlert(OpenZWave::Notification::UserAlertNotification event))
SIGNAL(manufacturerSpecificDBReady())
SIGNAL(starting());
SIGNAL(started(uint32_t homeID))
SIGNAL(stopped(uint32_t homeID))
SIGNAL(error(QTOZWErrorCodes errorcode))
SLOT(bool open(QString serialPort))
SLOT(bool refreshNodeInfo(uint8_t _node))
SLOT(bool requestNodeState(uint8_t _node))
SLOT(bool requestNodeDynamic(uint8_t _node))
SLOT(bool setConfigParam(uint8_t _node, uint8_t _param, int32_t _value, uint8_t const _size))
SLOT(void requestConfigParam(uint8_t _node, uint8_t _param))
SLOT(void requestAllConfigParam(uint8_t _node))
SLOT(void softResetController())
SLOT(void hardResetController())
SLOT(bool cancelControllerCommand())
SLOT(void testNetworkNode(uint8_t _node, uint32_t const _count))
SLOT(void testNetwork(uint32_t const _count))
SLOT(void healNetworkNode(uint8_t _node, bool _doRR))
SLOT(void healNetwork(bool _doRR))
SLOT(bool addNode(bool _doSecure))
SLOT(bool removeNode())
SLOT(bool removeFailedNode(uint8_t _node))
SLOT(bool hasNodeFailed(uint8_t _node))
SLOT(bool requestNodeNeighborUpdate(uint8_t _node))
SLOT(bool assignReturnRoute(uint8_t _node))
SLOT(bool deleteAllReturnRoute(uint8_t _node))
SLOT(bool sendNodeInfomation(uint8_t _node))
SLOT(bool replaceFailedNode(uint8_t _node))
SLOT(bool requestNetworkUpdate(uint8_t _node))
SLOT(bool checkLatestConfigFileRevision(uint8_t const _node))
SLOT(bool checkLatestMFSRevision())
SLOT(bool downloadLatestConfigFileRevision(uint8_t const _node))
SLOT(bool downloadLatestMFSRevision())
}

View file

@ -0,0 +1,258 @@
#include <QDebug>
#include <QBitArray>
#include "qtozwnodemodel.h"
#include "qtopenzwave.h"
QTOZW_Nodes::QTOZW_Nodes(QObject *parent)
: QAbstractTableModel(parent)
{
}
int QTOZW_Nodes::rowCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return this->m_nodeData.count();
}
int QTOZW_Nodes::columnCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return QTOZW_Nodes::NodeCount;
}
QVariant QTOZW_Nodes::data(const QModelIndex &index, int role) const {
if (!index.isValid())
return QVariant();
if (index.row() >= this->rowCount(index.parent()) || index.row() < 0)
return QVariant();
if (role == Qt::DisplayRole) {
QMap<NodeColumns, QVariant> node = this->m_nodeData[index.row()];
if (node.size() == 0) {
qWarning() << "data: Cant find any Node on Row " << index.row();
return QVariant();
}
return node[static_cast<NodeColumns>(index.column())];
}
return QVariant();
}
QVariant QTOZW_Nodes::headerData(int section, Qt::Orientation orientation, int role) const {
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (static_cast<NodeColumns>(section)) {
case NodeID:
return tr("NodeID");
case NodeName:
return tr("Node Name");
case NodeLocation:
return tr("Location");
case NodeManufacturerName:
return tr("Manufacturer");
case NodeProductName:
return tr("Product");
case NodeBasicString:
return tr("Basic Type");
case NodeBasic:
return tr("Basic Type");
case NodeGenericString:
return tr("Generic Type");
case NodeGeneric:
return tr("Generic Type");
case NodeSpecificString:
return tr("Specific Type");
case NodeSpecific:
return tr("Specific Type");
case NodeDeviceTypeString:
return tr("Device Type");
case NodeDeviceType:
return tr("Device Type");
case NodeRole:
return tr("Node Role");
case NodeRoleString:
return tr("Node Role");
case NodePlusType:
return tr("Node Plus Type");
case NodePlusTypeString:
return tr("Node Plus Type");
case NodeQueryStage:
return tr("Query Stage");
case NodeManufacturerID:
return tr("Manufacturer ID");
case NodeProductID:
return tr("Product ID");
case NodeProductType:
return tr("Product Type");
case NodeBaudRate:
return tr("Node Baud Rate");
case NodeVersion:
return tr("Node Version");
case NodeGroups:
return tr("Node Groups Supported");
case NodeFlags:
return tr("Node Flags");
case NodeCount:
return QVariant();
}
}
return QVariant();
}
Qt::ItemFlags QTOZW_Nodes::flags(const QModelIndex &index) const {
if (!index.isValid())
return Qt::ItemIsEnabled;
switch (static_cast<NodeColumns>(index.column())) {
case NodeName:
case NodeLocation:
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
default:
return QAbstractTableModel::flags(index);
}
}
bool QTOZW_Nodes::setData(const QModelIndex &index, const QVariant &value, int role) {
if (role != Qt::EditRole) {
return false;
}
switch (static_cast<NodeColumns>(index.column())) {
case NodeName:
case NodeLocation:
if (this->m_nodeData[index.row()][static_cast<NodeColumns>(index.column())] != value) {
this->m_nodeData[index.row()][static_cast<NodeColumns>(index.column())] = value;
QVector<int> roles;
roles << Qt::DisplayRole << QTOZW_UserRoles::ModelDataChanged;
this->dataChanged(index, index, roles);
}
break;
default:
return false;
}
return true;
}
QVariant QTOZW_Nodes::getNodeData(uint8_t _node, QTOZW_Nodes::NodeColumns _column) {
int32_t row = this->getNodeRow(_node);
if (row >= 0)
return this->m_nodeData[row][_column];
qWarning() << "Can't find NodeData for Node " << _node;
return QVariant();
}
int32_t QTOZW_Nodes::getNodeRow(uint8_t _node) {
if (this->m_nodeData.count() == 0) {
return -1;
}
QMap<int32_t, QMap<NodeColumns, QVariant> >::iterator it;
for (it = m_nodeData.begin(); it != m_nodeData.end(); ++it) {
QMap<NodeColumns, QVariant> node = it.value();
if (node.value(QTOZW_Nodes::NodeID) == _node) {
return it.key();
}
}
qWarning() << "Can't Find NodeID " << _node << " in NodeData";
return -1;
}
QTOZW_Nodes_internal::QTOZW_Nodes_internal(QObject *parent)
: QTOZW_Nodes(parent)
{
}
void QTOZW_Nodes_internal::addNode(uint8_t _nodeID)
{
if (this->getNodeRow(_nodeID) >= 0) {
qWarning() << "Node " << _nodeID << " Already Exists";
return;
}
QMap<QTOZW_Nodes::NodeColumns, QVariant> newNode;
newNode[QTOZW_Nodes::NodeID] = _nodeID;
QBitArray flags(static_cast<int>(QTOZW_Nodes::flagCount));
newNode[QTOZW_Nodes::NodeFlags] = flags;
this->beginInsertRows(QModelIndex(), this->rowCount(QModelIndex()), this->rowCount(QModelIndex()));
this->m_nodeData[this->rowCount(QModelIndex())] = newNode;
this->endInsertRows();
}
void QTOZW_Nodes_internal::setNodeData(uint8_t _nodeID, QTOZW_Nodes::NodeColumns column, QVariant data)
{
int row = this->getNodeRow(_nodeID);
if (row == -1) {
qWarning() << "setNodeData: Node " << _nodeID << " does not exist";
return;
}
if (this->m_nodeData[row][column] != data) {
this->m_nodeData[row][column] = data;
QVector<int> roles;
roles << Qt::DisplayRole;
this->dataChanged(this->createIndex(row, column), this->createIndex(row, column), roles);
}
}
void QTOZW_Nodes_internal::setNodeFlags(uint8_t _nodeID, QTOZW_Nodes::nodeFlags _flags, bool _value)
{
int row = this->getNodeRow(_nodeID);
if (row == -1) {
qWarning() << "setNodeData: Node " << _nodeID << " does not exist";
return;
}
QBitArray flag = this->m_nodeData[row][QTOZW_Nodes::NodeFlags].toBitArray();
if (flag.at(_flags) != _value) {
flag.setBit(_flags, _value);
this->m_nodeData[row][QTOZW_Nodes::NodeFlags] = flag;
QVector<int> roles;
roles << Qt::DisplayRole;
this->dataChanged(this->createIndex(row, QTOZW_Nodes::NodeFlags), this->createIndex(row, QTOZW_Nodes::NodeFlags), roles);
}
}
void QTOZW_Nodes_internal::delNode(uint8_t _nodeID) {
QMap<int32_t, QMap<NodeColumns, QVariant> >::iterator it;
QMap<int32_t, QMap<NodeColumns, QVariant> > newNodeMap;
int32_t newrow = 0;
for (it = this->m_nodeData.begin(); it != this->m_nodeData.end(); ++it) {
if (it.value()[QTOZW_Nodes::NodeColumns::NodeID] == _nodeID) {
qDebug() << "Removing Node " << it.value()[QTOZW_Nodes::NodeColumns::NodeID] << it.key();
this->beginRemoveRows(QModelIndex(), it.key(), it.key());
this->m_nodeData.erase(it);
this->endRemoveRows();
continue;
} else {
newNodeMap[newrow] = it.value();
newrow++;
}
}
this->m_nodeData.swap(newNodeMap);
}
void QTOZW_Nodes_internal::resetModel() {
this->beginRemoveRows(QModelIndex(), 0, this->m_nodeData.count());
this->m_nodeData.clear();
this->endRemoveRows();
}

View file

@ -0,0 +1,83 @@
#ifndef QTOZWNODEMODEL_H
#define QTOZWNODEMODEL_H
#include <QObject>
#include <QAbstractItemModel>
class QTOZW_Nodes : public QAbstractTableModel {
Q_OBJECT
public:
enum NodeColumns {
NodeID,
NodeName,
NodeLocation,
NodeManufacturerName,
NodeProductName,
NodeBasicString,
NodeBasic,
NodeGenericString,
NodeGeneric,
NodeSpecificString,
NodeSpecific,
NodeDeviceTypeString,
NodeDeviceType,
NodeRole,
NodeRoleString,
NodePlusType,
NodePlusTypeString,
NodeQueryStage,
NodeManufacturerID,
NodeProductType,
NodeProductID,
NodeBaudRate,
NodeVersion,
NodeGroups,
NodeFlags,
NodeCount
};
Q_ENUM(NodeColumns)
enum nodeFlags {
isListening,
isFlirs,
isBeaming,
isRouting,
isSecurityv1,
isZWavePlus,
isNIFRecieved,
isAwake,
isFailed,
flagCount
};
Q_ENUM(nodeFlags);
QTOZW_Nodes(QObject *parent=nullptr);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole);
protected:
QVariant getNodeData(uint8_t, NodeColumns);
int32_t getNodeRow(uint8_t _node);
QMap<int32_t, QMap<NodeColumns, QVariant> > m_nodeData;
};
class QTOZW_Nodes_internal : public QTOZW_Nodes {
Q_OBJECT
public:
QTOZW_Nodes_internal(QObject *parent=nullptr);
public Q_SLOTS:
void addNode(uint8_t _nodeID);
void setNodeData(uint8_t _nodeID, QTOZW_Nodes::NodeColumns column, QVariant data);
void setNodeFlags(uint8_t _nodeID, QTOZW_Nodes::nodeFlags _flags, bool _value);
void delNode(uint8_t _nodeID);
void resetModel();
};
#endif // QTOZWNODEMODEL_H

View file

@ -0,0 +1,226 @@
#include <QtDebug>
#include "qtozwnotification.h"
OZWNotification *OZWNotification::s_Instance = nullptr;
OZWNotification *OZWNotification::Get()
{
if (OZWNotification::s_Instance == nullptr) {
OZWNotification::s_Instance = new OZWNotification();
}
return OZWNotification::s_Instance;
}
//-----------------------------------------------------------------------------
// <OZWNotification::processNotification>
// Callback that is triggered when a value, group or node changes
//-----------------------------------------------------------------------------
void OZWNotification::processNotification
(
OpenZWave::Notification const* _notification,
void* _context
)
{
Q_UNUSED(_context);
//qDebug() << QString(_notification->GetAsString().c_str());
//qDebug() << _notification;
#if 0
void valueAdded(uint64_t vidKey);
void valueRemoved(uint64_t vidKey);
void valueChanged(uint64_t vidKey);
void valueRefreshed(uint64_t vidKey);
void valuePollingEnabled(uint64_t vidKey);
void valuePollingDisabled(uint64_t vidKey);
#endif
switch( _notification->GetType() )
{
case OpenZWave::Notification::Type_ValueAdded:
{
emit Get()->valueAdded(_notification->GetValueID().GetId());
break;
}
case OpenZWave::Notification::Type_ValueRemoved:
{
emit Get()->valueRemoved(_notification->GetValueID().GetId());
break;
}
case OpenZWave::Notification::Type_ValueChanged:
{
emit Get()->valueChanged(_notification->GetValueID().GetId());
break;
}
case OpenZWave::Notification::Type_ValueRefreshed:
{
emit Get()->valueRefreshed(_notification->GetValueID().GetId());
break;
}
case OpenZWave::Notification::Type_PollingDisabled:
{
emit Get()->valuePollingDisabled(_notification->GetValueID().GetId());
break;
}
case OpenZWave::Notification::Type_PollingEnabled:
{
emit Get()->valuePollingEnabled(_notification->GetValueID().GetId());
break;
}
case OpenZWave::Notification::Type_Group:
{
emit Get()->nodeGroupChanged(_notification->GetNodeId(), _notification->GetGroupIdx());
break;
}
case OpenZWave::Notification::Type_NodeNew:
{
emit Get()->nodeNew(_notification->GetNodeId());
break;
}
case OpenZWave::Notification::Type_NodeAdded:
{
emit Get()->nodeAdded(_notification->GetNodeId());
break;
}
case OpenZWave::Notification::Type_NodeRemoved:
{
emit Get()->nodeRemoved(_notification->GetNodeId());
break;
}
case OpenZWave::Notification::Type_NodeReset:
{
emit Get()->nodeReset(_notification->GetNodeId());
break;
}
case OpenZWave::Notification::Type_NodeEvent:
{
emit Get()->nodeEvent(_notification->GetNodeId(), _notification->GetEvent());
break;
}
case OpenZWave::Notification::Type_DriverReady:
{
emit Get()->driverReady(_notification->GetHomeId());
break;
}
case OpenZWave::Notification::Type_DriverFailed:
{
emit Get()->driverFailed(_notification->GetHomeId());
break;
}
case OpenZWave::Notification::Type_DriverRemoved:
{
emit Get()->driverRemoved(_notification->GetHomeId());
break;
}
case OpenZWave::Notification::Type_DriverReset:
{
emit Get()->driverReset(_notification->GetHomeId());
break;
}
case OpenZWave::Notification::Type_ControllerCommand:
{
emit Get()->controllerCommand(_notification->GetEvent());
break;
}
case OpenZWave::Notification::Type_AwakeNodesQueried:
{
emit Get()->driverAwakeNodesQueried();
break;
}
case OpenZWave::Notification::Type_AllNodesQueried:
{
emit Get()->driverAllNodesQueried();
break;
}
case OpenZWave::Notification::Type_EssentialNodeQueriesComplete:
{
emit Get()->nodeEssentialNodeQueriesComplete(_notification->GetNodeId());
break;
}
case OpenZWave::Notification::Type_AllNodesQueriedSomeDead:
{
emit Get()->driverAllNodesQueriedSomeDead();
break;
}
case OpenZWave::Notification::Type_Notification:
{
//emit Get()->ozwNotification(_notification->GetNotification());
break;
}
case OpenZWave::Notification::Type_NodeNaming:
{
emit Get()->nodeNaming(_notification->GetNodeId());
break;
}
case OpenZWave::Notification::Type_NodeQueriesComplete:
{
emit Get()->nodeQueriesComplete(_notification->GetNodeId());
break;
}
case OpenZWave::Notification::Type_NodeProtocolInfo:
{
emit Get()->nodeProtocolInfo(_notification->GetNodeId());
break;
}
case OpenZWave::Notification::Type_UserAlerts:
{
break;
}
case OpenZWave::Notification::Type_ManufacturerSpecificDBReady:
{
emit Get()->manufacturerSpecificDBReady();
break;
}
case OpenZWave::Notification::Type_SceneEvent:
{
break;
}
case OpenZWave::Notification::Type_CreateButton:
{
break;
}
case OpenZWave::Notification::Type_DeleteButton:
{
break;
}
case OpenZWave::Notification::Type_ButtonOn:
{
break;
}
case OpenZWave::Notification::Type_ButtonOff:
{
break;
}
}
};

View file

@ -0,0 +1,54 @@
#ifndef QTOZWNOTIFICATION_H
#define QTOZWNOTIFICATION_H
#include <QObject>
#include "Notification.h"
class OZWNotification : public QObject {
Q_OBJECT
public:
static OZWNotification *Get();
//-----------------------------------------------------------------------------
// All our Signals that we emit - one for each type of Notification
//-----------------------------------------------------------------------------
signals:
void valueAdded(uint64_t vidKey);
void valueRemoved(uint64_t vidKey);
void valueChanged(uint64_t vidKey);
void valueRefreshed(uint64_t vidKey);
void valuePollingEnabled(uint64_t vidKey);
void valuePollingDisabled(uint64_t vidKey);
void nodeGroupChanged(uint8_t node, uint8_t group);
void nodeNew(uint8_t node);
void nodeAdded(uint8_t node);
void nodeRemoved(uint8_t node);
void nodeReset(uint8_t node);
void nodeNaming(uint8_t node);
void nodeEvent(uint8_t node, uint8_t event);
void nodeProtocolInfo(uint8_t node);
void nodeEssentialNodeQueriesComplete(uint8_t node);
void nodeQueriesComplete(uint8_t node);
void driverReady(uint32_t homeID);
void driverFailed(uint32_t homeID);
void driverReset(uint32_t homeID);
void driverRemoved(uint32_t homeID);
void driverAllNodesQueriedSomeDead();
void driverAwakeNodesQueried();
void driverAllNodesQueried();
void controllerCommand(uint8_t command);
void ozwNotification(OpenZWave::Notification::NotificationCode event);
void ozwUserAlert(OpenZWave::Notification::UserAlertNotification event);
void manufacturerSpecificDBReady();
//-----------------------------------------------------------------------------
// <OZWNotification::processNotification>
// Callback that is triggered when a value, group or node changes
//-----------------------------------------------------------------------------
public:
static void processNotification(OpenZWave::Notification const* _notification, void* _context);
private:
static OZWNotification *s_Instance;
};
#endif // QTOZWNOTIFICATION_H

View file

@ -0,0 +1,74 @@
#include <QDebug>
#include "qtozwproxymodels.h"
#include "qtozwvalueidmodel.h"
#include "qtozwnodemodel.h"
#include "qtozwassociations.h"
QTOZW_proxyNodeModel::QTOZW_proxyNodeModel(QObject *parent) : QSortFilterProxyModel(parent)
{
}
QTOZW_proxyValueModel::QTOZW_proxyValueModel(QObject *parent) :
QSortFilterProxyModel (parent),
m_genreFilter(QTOZW_ValueIds::ValueIdGenres::GenreCount)
{
}
void QTOZW_proxyValueModel::setSelectionModel(QItemSelectionModel *model) {
this->m_selectionmodel = model;
QObject::connect(this->m_selectionmodel, &QItemSelectionModel::currentRowChanged, this, &QTOZW_proxyValueModel::currentSelectedRowChanged);
}
void QTOZW_proxyValueModel::currentSelectedRowChanged(const QModelIndex &current, const QModelIndex &previous) {
Q_UNUSED(previous);
this->m_nodeFilter = current.siblingAtColumn(QTOZW_Nodes::NodeColumns::NodeID).data().value<uint8_t>();
invalidateFilter();
}
void QTOZW_proxyValueModel::setFilterGenre(QTOZW_ValueIds::ValueIdGenres genre)
{
this->m_genreFilter = genre;
invalidateFilter();
}
bool QTOZW_proxyValueModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
if (this->m_genreFilter != QTOZW_ValueIds::ValueIdGenres::GenreCount) {
QModelIndex genreIndex = sourceModel()->index(sourceRow, QTOZW_ValueIds::ValueIdColumns::Genre, sourceParent);
if (genreIndex.data().value<QTOZW_ValueIds::ValueIdGenres>() != this->m_genreFilter)
return false;
}
if (this->m_nodeFilter > 0) {
QModelIndex nodeIDIndex = sourceModel()->index(sourceRow, QTOZW_ValueIds::ValueIdColumns::Node, sourceParent);
if (nodeIDIndex.data().value<uint8_t>() != this->m_nodeFilter)
return false;
}
return true;
}
QTOZW_proxyAssociationModel::QTOZW_proxyAssociationModel(QObject *parent) :
QSortFilterProxyModel (parent)
{
}
void QTOZW_proxyAssociationModel::setSelectionModel(QItemSelectionModel *model) {
this->m_selectionmodel = model;
QObject::connect(this->m_selectionmodel, &QItemSelectionModel::currentRowChanged, this, &QTOZW_proxyAssociationModel::currentSelectedRowChanged);
}
void QTOZW_proxyAssociationModel::currentSelectedRowChanged(const QModelIndex &current, const QModelIndex &previous) {
this->m_nodeFilter = current.siblingAtColumn(QTOZW_Nodes::NodeColumns::NodeID).data().value<uint8_t>();
invalidateFilter();
}
bool QTOZW_proxyAssociationModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
if (this->m_nodeFilter > 0) {
QModelIndex nodeIDIndex = sourceModel()->index(sourceRow, QTOZW_Associations::associationColumns::NodeID, sourceParent);
if (nodeIDIndex.data().value<uint8_t>() != this->m_nodeFilter)
return false;
}
return true;
}

View file

@ -0,0 +1,66 @@
#ifndef QTOZWPROXYMODELS_H
#define QTOZWPROXYMODELS_H
#include <QObject>
#include <QSortFilterProxyModel>
#include <QItemSelectionModel>
#include "qtozwnodemodel.h"
#include "qtozwvalueidmodel.h"
class QTOZW_proxyNodeModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit QTOZW_proxyNodeModel(QObject *parent = nullptr);
signals:
public slots:
};
class QTOZW_proxyValueModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit QTOZW_proxyValueModel(QObject *parent = nullptr);
void setSelectionModel(QItemSelectionModel *);
void setFilterGenre(QTOZW_ValueIds::ValueIdGenres genre);
// setNodeView(QAbstractItemView *);
public slots:
void currentSelectedRowChanged(const QModelIndex &current, const QModelIndex &previous);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private:
QItemSelectionModel *m_selectionmodel;
QTOZW_ValueIds::ValueIdGenres m_genreFilter;
uint8_t m_nodeFilter;
};
class QTOZW_proxyAssociationModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit QTOZW_proxyAssociationModel(QObject *parent = nullptr);
void setSelectionModel(QItemSelectionModel *);
public slots:
void currentSelectedRowChanged(const QModelIndex &current, const QModelIndex &previous);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private:
QItemSelectionModel *m_selectionmodel;
uint8_t m_nodeFilter;
};
#endif // QTOZWPROXYMODELS_H

View file

@ -0,0 +1,265 @@
#include <QDebug>
#include <QBitArray>
#include <QDataStream>
#include "qtozwvalueidmodel.h"
#include "qtozwmanager.h"
QDataStream & operator<<( QDataStream & dataStream, const QTOZW_ValueIDList & list )
{
dataStream << list.values << list.labels << list.selectedItem;
return dataStream;
}
QDataStream & operator>>(QDataStream & dataStream, QTOZW_ValueIDList & list) {
dataStream >> list.values >> list.labels >> list.selectedItem;
return dataStream;
}
QDataStream & operator<<( QDataStream & dataStream, const QTOZW_ValueIDBitSet & list )
{
dataStream << list.values << list.mask << list.label << list.help;
return dataStream;
}
QDataStream & operator>>(QDataStream & dataStream, QTOZW_ValueIDBitSet & list) {
dataStream >> list.values >> list.mask >> list.label >> list.help;
return dataStream;
}
QTOZW_ValueIds::QTOZW_ValueIds(QObject *parent)
: QAbstractTableModel(parent)
{
}
int QTOZW_ValueIds::rowCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return this->m_valueData.count();
}
int QTOZW_ValueIds::columnCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return ValueIdColumns::ValueIdCount;
}
QVariant QTOZW_ValueIds::data(const QModelIndex &index, int role) const {
if (!index.isValid())
return QVariant();
if (index.row() >= this->rowCount(index.parent()) || index.row() < 0)
return QVariant();
if (role == Qt::DisplayRole) {
QMap<ValueIdColumns, QVariant> node = this->m_valueData[index.row()];
if (node.size() == 0) {
qWarning() << "data: Cant find any Node on Row " << index.row();
return QVariant();
}
return node[static_cast<ValueIdColumns>(index.column())];
}
return QVariant();
}
QVariant QTOZW_ValueIds::headerData(int section, Qt::Orientation orientation, int role) const {
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (static_cast<ValueIdColumns>(section)) {
case Label:
return tr("Label");
case Value:
return tr("Value");
case Units:
return tr("Units");
case Min:
return tr("Min");
case Max:
return tr("Max");
case Type:
return tr("Type");
case Instance:
return tr("Instance");
case CommandClass:
return tr("CommandClass");
case Index:
return tr("Index");
case Node:
return tr("Node");
case Genre:
return tr("Genre");
case Help:
return tr("Help");
case ValueIDKey:
return tr("ValueID Key");
case ValueFlags:
return tr("Flags");
case ValueIdCount:
return QVariant();
}
}
return QVariant();
}
Qt::ItemFlags QTOZW_ValueIds::flags(const QModelIndex &index) const {
if (!index.isValid())
return Qt::ItemIsEnabled;
switch (static_cast<ValueIdColumns>(index.column())) {
case Value:
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
default:
return QAbstractTableModel::flags(index);
}
}
bool QTOZW_ValueIds::setData(const QModelIndex &index, const QVariant &value, int role) {
if (role != Qt::EditRole) {
return false;
}
switch (static_cast<ValueIdColumns>(index.column())) {
case Value:
if (this->m_valueData[index.row()][static_cast<ValueIdColumns>(index.column())] != 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:
return false;
}
return true;
}
QVariant QTOZW_ValueIds::getValueData(uint64_t _vidKey, ValueIdColumns _column) {
int32_t row = this->getValueRow(_vidKey);
if (row >= 0)
return this->m_valueData[row][_column];
qWarning() << "Can't find ValueData for ValueID " << _vidKey;
return QVariant();
}
int32_t QTOZW_ValueIds::getValueRow(uint64_t _vidKey) {
if (this->m_valueData.count() == 0) {
return -1;
}
QMap<int32_t, QMap<ValueIdColumns, QVariant> >::iterator it;
for (it = m_valueData.begin(); it != m_valueData.end(); ++it) {
QMap<ValueIdColumns, QVariant> node = it.value();
if (node.value(ValueIdColumns::ValueIDKey) == _vidKey) {
return it.key();
}
}
qWarning() << "Can't Find ValueID " << _vidKey << " in valueData";
return -1;
}
QTOZW_ValueIds_internal::QTOZW_ValueIds_internal(QObject *parent)
: QTOZW_ValueIds(parent)
{
}
void QTOZW_ValueIds_internal::addValue(uint64_t _vidKey)
{
if (this->getValueRow(_vidKey) >= 0) {
qWarning() << "ValueID " << _vidKey << " Already Exists";
return;
}
// QMap<int32_t, QMap<ValueIdColumns, QVariant> >
QMap<ValueIdColumns, QVariant> newValue;
newValue[QTOZW_ValueIds::ValueIDKey] = _vidKey;
QBitArray flags(static_cast<int>(ValueIDFlags::FlagCount));
newValue[QTOZW_ValueIds::ValueFlags] = flags;
this->beginInsertRows(QModelIndex(), this->rowCount(QModelIndex()), this->rowCount(QModelIndex()));
this->m_valueData[this->rowCount(QModelIndex())] = newValue;
this->endInsertRows();
}
void QTOZW_ValueIds_internal::setValueData(uint64_t _vidKey, QTOZW_ValueIds::ValueIdColumns column, QVariant data)
{
int row = this->getValueRow(_vidKey);
if (row == -1) {
qWarning() << "setValueData: Value " << _vidKey << " does not exist";
return;
}
if (this->m_valueData[row][column] != data) {
this->m_valueData[row][column] = data;
this->dataChanged(this->createIndex(row, column), this->createIndex(row, column));
}
}
void QTOZW_ValueIds_internal::setValueFlags(uint64_t _vidKey, QTOZW_ValueIds::ValueIDFlags _flags, bool _value)
{
int row = this->getValueRow(_vidKey);
if (row == -1) {
qWarning() << "setValueFlags: Value " << _vidKey << " does not exist";
return;
}
QBitArray flag = this->m_valueData[row][QTOZW_ValueIds::ValueFlags].toBitArray();
if (flag.at(_flags) != _value) {
flag.setBit(_flags, _value);
this->m_valueData[row][QTOZW_ValueIds::ValueFlags] = flag;
this->dataChanged(this->createIndex(row, QTOZW_ValueIds::ValueFlags), this->createIndex(row, QTOZW_ValueIds::ValueFlags));
}
}
void QTOZW_ValueIds_internal::delValue(uint64_t _vidKey) {
QMap<int32_t, QMap<ValueIdColumns, QVariant> >::iterator it;
QMap<int32_t, QMap<ValueIdColumns, QVariant> > newValueMap;
int32_t newrow = 0;
for (it = this->m_valueData.begin(); it != this->m_valueData.end(); ++it) {
if (it.value()[QTOZW_ValueIds::ValueIdColumns::ValueIDKey] == _vidKey) {
qDebug() << "Removing Value " << it.value()[QTOZW_ValueIds::ValueIdColumns::Label] << it.key();
this->beginRemoveRows(QModelIndex(), it.key(), it.key());
this->m_valueData.erase(it);
this->endRemoveRows();
continue;
} else {
newValueMap[newrow] = it.value();
newrow++;
}
}
this->m_valueData.swap(newValueMap);
}
void QTOZW_ValueIds_internal::delNodeValues(uint8_t _node) {
QMap<int32_t, QMap<ValueIdColumns, QVariant> >::iterator it;
QMap<int32_t, QMap<ValueIdColumns, QVariant> > newValueMap;
int32_t newrow = 0;
for (it = this->m_valueData.begin(); it != this->m_valueData.end(); ++it) {
if (it.value()[QTOZW_ValueIds::ValueIdColumns::Node] == _node) {
qDebug() << "Removing Value " << it.value()[QTOZW_ValueIds::ValueIdColumns::Label] << it.key();
this->beginRemoveRows(QModelIndex(), it.key(), it.key());
this->m_valueData.erase(it);
this->endRemoveRows();
continue;
} else {
newValueMap[newrow] = it.value();
newrow++;
}
}
this->m_valueData.swap(newValueMap);
}
void QTOZW_ValueIds_internal::resetModel() {
this->beginRemoveRows(QModelIndex(), 0, this->m_valueData.count());
this->m_valueData.clear();
this->endRemoveRows();
}

View file

@ -0,0 +1,114 @@
#ifndef QTOZWVALUEIDMODEL_H
#define QTOZWVALUEIDMODEL_H
#include <QObject>
#include <QAbstractItemModel>
#include <QAbstractListModel>
#include <QBitArray>
struct QTOZW_ValueIDList {
QList< uint32_t > values;
QStringList labels;
QString selectedItem;
};
QDataStream & operator<<( QDataStream & dataStream, const QTOZW_ValueIDList & list );
QDataStream & operator>>(QDataStream & dataStream, QTOZW_ValueIDList & list);
Q_DECLARE_METATYPE(QTOZW_ValueIDList);
struct QTOZW_ValueIDBitSet {
QBitArray values;
QBitArray mask;
QMap<uint32_t, QString> label;
QMap<uint32_t, QString> help;
};
QDataStream & operator<<( QDataStream & dataStream, const QTOZW_ValueIDBitSet & list );
QDataStream & operator>>(QDataStream & dataStream, QTOZW_ValueIDBitSet & list);
Q_DECLARE_METATYPE(QTOZW_ValueIDBitSet);
class QTOZW_ValueIds : public QAbstractTableModel {
Q_OBJECT
public:
enum ValueIdColumns {
Label,
Value,
Units,
Min,
Max,
Type,
Instance,
CommandClass,
Index,
Node,
Genre,
Help,
ValueIDKey,
ValueFlags,
ValueIdCount
};
Q_ENUM(ValueIdColumns)
enum ValueIdGenres {
Basic,
User,
Config,
System,
GenreCount
};
Q_ENUM(ValueIdGenres)
enum ValueIdTypes {
Bool,
Byte,
Decimal,
Int,
List,
Schedule,
Short,
String,
Button,
Raw,
BitSet,
TypeCount
};
Q_ENUM(ValueIdTypes)
enum ValueIDFlags {
ReadOnly,
WriteOnly,
ValueSet,
ValuePolled,
ChangeVerified,
FlagCount
};
Q_ENUM(ValueIDFlags)
QTOZW_ValueIds(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole);
protected:
QVariant getValueData(uint64_t, ValueIdColumns);
int32_t getValueRow(uint64_t _node);
QMap<int32_t, QMap<ValueIdColumns, QVariant> > m_valueData;
};
class QTOZW_ValueIds_internal : public QTOZW_ValueIds {
Q_OBJECT
public:
QTOZW_ValueIds_internal(QObject *parent=nullptr);
public Q_SLOTS:
void addValue(uint64_t _vidKey);
void setValueData(uint64_t _vidKey, QTOZW_ValueIds::ValueIdColumns column, QVariant data);
void setValueFlags(uint64_t _vidKey, QTOZW_ValueIds::ValueIDFlags _flags, bool _value);
void delValue(uint64_t _vidKey);
void delNodeValues(uint8_t _node);
void resetModel();
};
#endif // QTOZWVALUEIDMODEL_H

View file

@ -0,0 +1,203 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "websocketiodevice.h"
#include <QtCore/QDebug>
void WebSocketIODevice::print() {
qDebug() << m_socket->errorString();
qDebug() << m_socket->state();
}
WebSocketIODevice::WebSocketIODevice(QObject *parent)
: QIODevice(parent)
{
m_socket = new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this);
connect(m_socket, &QWebSocket::connected, this, &WebSocketIODevice::onSocketConnected);
connect(m_socket, &QWebSocket::disconnected, this, &WebSocketIODevice::onSocketDisconnected);
connect(m_socket, &QWebSocket::binaryMessageReceived, this, &WebSocketIODevice::handleBinaryMessage);
connect(m_socket, &QWebSocket::stateChanged, this, &WebSocketIODevice::print);
connect(m_socket, &QWebSocket::aboutToClose, this, &WebSocketIODevice::onAboutToClose);
connect(this, &WebSocketIODevice::readyRead, this, &WebSocketIODevice::print);
}
WebSocketIODevice::WebSocketIODevice(QWebSocket *socket, QObject *parent)
:QIODevice (parent),
m_socket(socket)
{
m_socket = socket;
m_socket->setParent(this);
connect(m_socket, &QWebSocket::connected, this, &WebSocketIODevice::onSocketConnected);
connect(m_socket, &QWebSocket::disconnected, this, &WebSocketIODevice::onSocketDisconnected);
connect(m_socket, &QWebSocket::binaryMessageReceived, this, &WebSocketIODevice::handleBinaryMessage);
connect(m_socket, &QWebSocket::stateChanged, this, &WebSocketIODevice::print);
connect(m_socket, &QWebSocket::aboutToClose, this, &WebSocketIODevice::onAboutToClose);
}
bool WebSocketIODevice::open(QIODevice::OpenMode mode)
{
// Cannot use an URL because of missing sub protocol support
// Have to use QNetworkRequest, see QTBUG-38742
QNetworkRequest request;
request.setUrl(m_url);
request.setRawHeader("Sec-WebSocket-Protocol", m_protocol.constData());
qDebug() << m_url;
m_socket->open(request);
qDebug() << "Made Request";
return QIODevice::open(mode);
}
void WebSocketIODevice::close()
{
m_socket->close();
QIODevice::close();
}
qint64 WebSocketIODevice::readData(char *data, qint64 maxlen)
{
qint64 bytesToRead = qMin(maxlen, (qint64)m_buffer.size());
memcpy(data, m_buffer.constData(), bytesToRead);
m_buffer = m_buffer.right(m_buffer.size() - bytesToRead);
qDebug() << "readData";
return bytesToRead;
}
qint64 WebSocketIODevice::writeData(const char *data, qint64 len)
{
QByteArray msg(data, len);
const int length = m_socket->sendBinaryMessage(msg);
qDebug() << "writeData " << msg;
return length;
}
void WebSocketIODevice::setUrl(const QUrl &url)
{
m_url = url;
}
void WebSocketIODevice::setProtocol(const QByteArray &data)
{
m_protocol = data;
}
void WebSocketIODevice::handleBinaryMessage(const QByteArray &msg)
{
m_buffer.append(msg);
qDebug() << "binaryMessage" << msg;
emit readyRead();
}
void WebSocketIODevice::onSocketConnected()
{
emit connected();
}
void WebSocketIODevice::onSocketDisconnected()
{
emit disconnected();
}
void WebSocketIODevice::onAboutToClose()
{
emit aboutToClose();
}
WebSocketServer::WebSocketServer(quint16 port, QObject *parent) :
QObject(parent),
m_pWebSocketServer(new QWebSocketServer(QStringLiteral("OpenZWave"),
QWebSocketServer::NonSecureMode, this))
{
if (m_pWebSocketServer->listen(QHostAddress::Any, port)) {
qDebug() << "WebSocketServer "<< m_pWebSocketServer->serverName() << " listening on port" << port;
connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &WebSocketServer::onNewConnection);
connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &WebSocketServer::closed);
connect(m_pWebSocketServer, &QWebSocketServer::closed, this, [this]() {
qDebug() << "WebSocket closed.";
});
connect(m_pWebSocketServer, &QWebSocketServer::serverError, this, [this]() {
qDebug() << "WebSocket Error.";
});
connect(m_pWebSocketServer, &QWebSocketServer::acceptError, this, [this]() {
qDebug() << "WebSocket acceptError.";
});
connect(m_pWebSocketServer, &QWebSocketServer::acceptError, this, [this]() {
qDebug() << "WebSocket acceptError.";
});
}
}
WebSocketServer::~WebSocketServer()
{
m_pWebSocketServer->close();
qDeleteAll(m_clients.begin(), m_clients.end());
}
void WebSocketServer::onNewConnection()
{
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
m_clients << new WebSocketIODevice(pSocket, this);
qDebug() << "New Connection" << pSocket;
emit newConnection();
}
WebSocketIODevice *WebSocketServer::nextPendingConnection()
{
if (!m_clients.isEmpty())
return m_clients.takeLast();
qDebug() << "nextPendingConnection called with Empty List";
return nullptr;
}

View file

@ -0,0 +1,118 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef WEBSOCKETIODEVICE_H
#define WEBSOCKETIODEVICE_H
#include <QtCore/QIODevice>
#include <QtWebSockets/QWebSocket>
#include <QtWebSockets/QWebSocketServer>
class WebSocketIODevice : public QIODevice
{
Q_OBJECT
public:
WebSocketIODevice(QObject *parent = nullptr);
WebSocketIODevice(QWebSocket *socket, QObject *parent = nullptr);
bool open(OpenMode mode) override;
void close() override;
void print();
qint64 readData(char *data, qint64 maxlen) override;
qint64 writeData(const char *data, qint64 len) override;
qint64 write(const char *data, qint64 len) {return writeData(data, len);}
void setUrl(const QUrl &url);
void setProtocol(const QByteArray &data);
bool isOpen() const { qDebug() << "IsOpen" << QIODevice::isOpen(); return QIODevice::isOpen(); }
Q_SIGNALS:
void connected();
void disconnected();
void aboutToClose();
void readyRead();
public slots:
void handleBinaryMessage(const QByteArray &msg);
private slots:
void onSocketConnected();
void onSocketDisconnected();
void onAboutToClose();
private:
QByteArray m_protocol;
QByteArray m_buffer;
QWebSocket *m_socket;
QUrl m_url;
};
class WebSocketServer : public QObject
{
Q_OBJECT
public:
WebSocketServer(quint16 port, QObject *parent = nullptr);
~WebSocketServer();
WebSocketIODevice *nextPendingConnection();
Q_SIGNALS:
void closed();
void newConnection();
private Q_SLOTS:
void onNewConnection();
private:
QWebSocketServer *m_pWebSocketServer;
QList<WebSocketIODevice *> m_clients;
};
#endif // WEBSOCKETIODEVICE_H

84
simpleclient/main.cpp Normal file
View file

@ -0,0 +1,84 @@
/****************************************************************************
**
** Copyright (C) 2017 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QTreeView>
#include <QApplication>
#include <QRemoteObjectNode>
#include <QAbstractItemModelReplica>
#include "qtozwmanager.h"
#include "mainwindow.h"
int main(int argc, char **argv)
{
#if 0
QLoggingCategory::setFilterRules("qt.remoteobjects.debug=true\n"
"qt.remoteobjects.warning=true\n"
"qt.remoteobjects.models.debug=true\n"
"qt.remoteobjects.models.debug=true\n"
"qt.remoteobjects.io.debug=true\n"
"default.debug=true");
#else
QLoggingCategory::setFilterRules("default.debug=true");
#endif
QApplication app(argc, argv);
QIcon icon(":res/ozw_SF2_notext.png");
MainWindow window;
window.setWindowIcon(icon);
window.resize(640, 480);
window.show();
window.start();
return app.exec();
}

111
simpleclient/mainwindow.cpp Normal file
View file

@ -0,0 +1,111 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "startup.h"
#include "qtozw_itemdelegate.h"
#include <qtozwproxymodels.h>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->m_openzwave = new QTOpenZwave(this);
this->m_qtozwmanager = this->m_openzwave->GetManager();
QObject::connect(this->m_qtozwmanager, &QTOZWManager::ready, this, &MainWindow::QTOZW_Ready);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::start() {
Startup win(this);
win.setModal(true);
QObject::connect(&win, &Startup::startLocal, this, &MainWindow::startLocal);
QObject::connect(&win, &Startup::startRemote, this, &MainWindow::startRemote);
win.exec();
}
void MainWindow::startRemote(QString url) {
QUrl server;
server.setHost(url);
server.setPort(1983);
server.setScheme("tcp");
qDebug() << server;
this->m_qtozwmanager->initilizeReplica(server);
}
void MainWindow::startLocal(QString serialPort, bool startServer) {
this->m_serialPort = serialPort;
this->m_qtozwmanager->initilizeSource(startServer);
qDebug() << "startLocal: " << this->m_serialPort;
}
void MainWindow::QTOZW_Ready() {
qDebug() << "OZW Ready " << this->m_serialPort;
if (this->m_qtozwmanager->isRunning() == false) {
this->m_qtozwmanager->open(this->m_serialPort);
}
QTOZW_proxyNodeModel *proxyNodeModel = new QTOZW_proxyNodeModel(this);
proxyNodeModel->setSourceModel(this->m_qtozwmanager->getNodeModel());
this->ui->nodeView->setModel(proxyNodeModel);
this->ui->nodeView->setSortingEnabled(true);
this->ui->nodeView->horizontalHeader()->setSectionsMovable(true);
this->ui->nodeView->verticalHeader()->hide();
this->ui->nodeView->setSelectionBehavior(QAbstractItemView::SelectRows);
this->ui->nodeView->setSelectionMode(QAbstractItemView::SingleSelection);
QItemSelectionModel *selectNodeModel = this->ui->nodeView->selectionModel();
QTOZW_proxyValueModel *proxyUserValueModel = new QTOZW_proxyValueModel(this);
proxyUserValueModel->setSourceModel(this->m_qtozwmanager->getValueModel());
proxyUserValueModel->setSelectionModel(selectNodeModel);
proxyUserValueModel->setFilterGenre(QTOZW_ValueIds::ValueIdGenres::User);
QTOZW_ItemDelegate *delegate = new QTOZW_ItemDelegate(this);
this->ui->userView->setItemDelegateForColumn(QTOZW_ValueIds::ValueIdColumns::Value, delegate);
this->ui->userView->setModel(proxyUserValueModel);
this->ui->userView->setSortingEnabled(true);
this->ui->userView->horizontalHeader()->setSectionsMovable(true);
this->ui->userView->verticalHeader()->hide();
this->ui->userView->setSelectionBehavior(QAbstractItemView::SelectRows);
this->ui->userView->setSelectionMode(QAbstractItemView::SingleSelection);
QTOZW_proxyValueModel *proxyConfigValueModel = new QTOZW_proxyValueModel(this);
proxyConfigValueModel->setSourceModel(this->m_qtozwmanager->getValueModel());
proxyConfigValueModel->setSelectionModel(selectNodeModel);
proxyConfigValueModel->setFilterGenre(QTOZW_ValueIds::ValueIdGenres::Config);
this->ui->configView->setModel(proxyConfigValueModel);
this->ui->configView->setSortingEnabled(true);
this->ui->configView->horizontalHeader()->setSectionsMovable(true);
this->ui->configView->verticalHeader()->hide();
this->ui->configView->setSelectionBehavior(QAbstractItemView::SelectRows);
this->ui->configView->setSelectionMode(QAbstractItemView::SingleSelection);
QTOZW_proxyValueModel *proxySystemValueModel = new QTOZW_proxyValueModel(this);
proxySystemValueModel->setSourceModel(this->m_qtozwmanager->getValueModel());
proxySystemValueModel->setSelectionModel(selectNodeModel);
proxySystemValueModel->setFilterGenre(QTOZW_ValueIds::ValueIdGenres::System);
this->ui->systemView->setModel(proxySystemValueModel);
this->ui->systemView->setSortingEnabled(true);
this->ui->systemView->horizontalHeader()->setSectionsMovable(true);
this->ui->systemView->verticalHeader()->hide();
this->ui->systemView->setSelectionBehavior(QAbstractItemView::SelectRows);
this->ui->systemView->setSelectionMode(QAbstractItemView::SingleSelection);
QTOZW_proxyAssociationModel *proxyAssociationModel = new QTOZW_proxyAssociationModel(this);
proxyAssociationModel->setSourceModel(this->m_qtozwmanager->getAssociationModel());
proxyAssociationModel->setSelectionModel(selectNodeModel);
this->ui->AssociationView->setModel(proxyAssociationModel);
this->ui->AssociationView->setSortingEnabled(true);
this->ui->AssociationView->horizontalHeader()->setSectionsMovable(true);
this->ui->AssociationView->verticalHeader()->hide();
this->ui->AssociationView->setSelectionBehavior(QAbstractItemView::SelectRows);
this->ui->AssociationView->setSelectionMode(QAbstractItemView::SingleSelection);
}

32
simpleclient/mainwindow.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qtopenzwave.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void start();
public Q_SLOTS:
void startRemote(QString);
void startLocal(QString, bool);
void QTOZW_Ready();
private:
Ui::MainWindow *ui;
QTOpenZwave *m_openzwave;
QTOZWManager *m_qtozwmanager;
QString m_serialPort;
};
#endif // MAINWINDOW_H

View file

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle">
<string>OpenZWave Sample Client</string>
</property>
<property name="windowIcon">
<iconset resource="simpleclient.qrc">
<normaloff>:/res/ozw_SF2_notext.png</normaloff>:/res/ozw_SF2_notext.png</iconset>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableView" name="nodeView"/>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>User</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTableView" name="userView"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>System</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTableView" name="systemView"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Config</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTableView" name="configView"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Associations</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QTableView" name="AssociationView"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources>
<include location="simpleclient.qrc"/>
</resources>
<connections/>
</ui>

View file

@ -0,0 +1,41 @@
#include <QLabel>
#include <QFrame>
#include <QHBoxLayout>
#include <QPainter>
#include <QDebug>
#include "qtozw_itemdelegate.h"
#include "qtozwvalueidmodel.h"
QTOZW_ItemDelegate::QTOZW_ItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
this->m_comboBox = new QComboBox();
this->m_comboBox->setFrame(false);
}
void QTOZW_ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QModelIndex typeIndex = index.sibling(index.row(), QTOZW_ValueIds::ValueIdColumns::Type);
if (typeIndex.data() != QTOZW_ValueIds::ValueIdTypes::List) {
return QStyledItemDelegate::paint(painter, option, index);
}
QModelIndex flagsIndex = index.sibling(index.row(), QTOZW_ValueIds::ValueIdColumns::ValueFlags);
QTOZW_ValueIDBitSet flags = flagsIndex.data().value<QTOZW_ValueIDBitSet>();
QTOZW_ValueIDList val = index.data().value<QTOZW_ValueIDList>();
this->m_comboBox->addItems(val.labels);
this->m_comboBox->setCurrentText(val.selectedItem);
this->m_comboBox->resize(option.rect.size());
qDebug() << flags.values;
// if (flags.values.at(QTOZW_ValueIds::ValueIDFlags::ReadOnly) == true)
// this->m_comboBox->setEnabled(false);
painter->save();
painter->translate(option.rect.topLeft());
this->m_comboBox->render(painter, QPoint(), QRegion(), QWidget::DrawChildren);
painter->restore();
}
QSize QTOZW_ItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
return this->m_comboBox->minimumSizeHint();
}

View file

@ -0,0 +1,25 @@
#ifndef QTOZW_ITEMDELEGATE_H
#define QTOZW_ITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <QComboBox>
class QTOZW_ItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit QTOZW_ItemDelegate(QObject *parent = nullptr);
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
signals:
public slots:
private:
QComboBox* m_comboBox;
};
#endif // QTOZW_ITEMDELEGATE_H

Binary file not shown.

After

(image error) Size: 40 KiB

Binary file not shown.

Binary file not shown.

After

(image error) Size: 32 KiB

View file

@ -0,0 +1,38 @@
QT += widgets remoteobjects websockets
SOURCES = main.cpp \
mainwindow.cpp \
qtozw_itemdelegate.cpp \
startup.cpp
#CONFIG -= app_bundle
#CONFIG += static
CONFIG += silent
DEFINES += remote
LIBS += -L../qt-openzwave/ -lqt-openzwave -L../open-zwave/ -lopenzwave -lresolv
INCLUDEPATH += ../qt-openzwave ../open-zwave/cpp/src
requires(qtConfig(treeview))
macx {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
ICON = res/ozw_logo.icns
}
win32 {
RC_ICONS += res/ozw_logo.ico
}
FORMS += \
mainwindow.ui \
startup.ui
HEADERS += \
mainwindow.h \
qtozw_itemdelegate.h \
startup.h
DISTFILES +=
RESOURCES += \
simpleclient.qrc

View file

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>res/ozw_logo.icns</file>
<file>res/ozw_logo.ico</file>
<file>res/ozw_SF2_notext.png</file>
</qresource>
</RCC>

38
simpleclient/startup.cpp Normal file
View file

@ -0,0 +1,38 @@
#include "startup.h"
#include "ui_startup.h"
#include <QMessageBox>
Startup::Startup(QWidget *parent) :
QDialog(parent),
ui(new Ui::Startup)
{
ui->setupUi(this);
QObject::connect(ui->startlocal, &QPushButton::clicked, this, &Startup::localPressed);
QObject::connect(ui->startremote, &QPushButton::clicked, this, &Startup::remotePressed);
}
Startup::~Startup()
{
delete ui;
}
void Startup::localPressed() {
QString serialport = ui->serialport->text();
if (serialport.length() == 0) {
QMessageBox::critical(this, tr("Error"), tr("You Must Specify a Serial Port"), QMessageBox::Ok);
}
emit this->startLocal(serialport, ui->enableserver->isChecked());
this->close();
}
void Startup::remotePressed() {
QString remotehost = ui->remotehost->text();
if (remotehost.length() == 0) {
QMessageBox::critical(this, tr("Error"), tr("You Must Specify a Remote Host"), QMessageBox::Ok);
}
emit this->startRemote(remotehost);
this->close();
}

33
simpleclient/startup.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef STARTUP_H
#define STARTUP_H
#include <QDialog>
#include <QObject>
namespace Ui {
class Startup;
}
class Startup : public QDialog
{
Q_OBJECT
public Q_SLOTS:
void localPressed();
void remotePressed();
Q_SIGNALS:
void startLocal(QString, bool);
void startRemote(QString);
public:
explicit Startup(QWidget *parent = nullptr);
~Startup();
private:
Ui::Startup *ui;
};
#endif // STARTUP_H

98
simpleclient/startup.ui Normal file
View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Startup</class>
<widget class="QDialog" name="Startup">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Lets Get Started!</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Local Client</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Serial Port</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Enable Server</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="enableserver">
<property name="text">
<string>Enabled</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="startlocal">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="serialport">
<property name="text">
<string>/dev/cu.usbmodem14101</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Remote Client</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Remote Host</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="remotehost">
<property name="text">
<string>127.0.0.1</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="startremote">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>