Update database and add lqi and timestamp for nodes

pull/7/head
Simon Stürz 2020-07-01 15:14:34 +02:00
parent ed5517fbf1
commit 5cc83bb956
5 changed files with 65 additions and 9 deletions

View File

@ -243,7 +243,7 @@ void ZigbeeNetwork::removeZigbeeNode(const ZigbeeAddress &address)
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, this, [this, zdoReply, node](){
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
qCWarning(dcZigbeeNode()) << "Failed to send management leave request to" << node << zdoReply->error();
qCWarning(dcZigbeeNode()) << "This node is gonna be removed internally and tried to remove once it shows up the next time.";
qCWarning(dcZigbeeNode()) << "This node is gonna be removed internally. TODO: try to remove using ZDO once it shows up the next time.";
}
removeNode(node);
@ -264,7 +264,15 @@ void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
}
// FIXME: check when and how the note will be reachable
//node->setConnected(state() == StateRunning);
// Update database metrics of the node
connect(node, &ZigbeeNode::lqiChanged, this, [this, node](quint8 lqi){
m_database->updateNodeLqi(node, lqi);
});
connect(node, &ZigbeeNode::lastSeenChanged, this, [this, node](const QDateTime &lastSeen){
m_database->updateNodeLastSeen(node, lastSeen);
});
// Note: if a cluster shows up after initialization (out of spec devices), save the cluster and it's attributes
foreach (ZigbeeNodeEndpoint *endpoint, node->endpoints()) {

View File

@ -74,12 +74,16 @@ QList<ZigbeeNode *> ZigbeeNetworkDatabase::loadNodes()
quint16 shortAddress = nodesQuery.value("shortAddress").toUInt();
QByteArray nodeDescriptor = QByteArray::fromBase64(nodesQuery.value("nodeDescriptor").toByteArray());
quint16 powerDescriptor = nodesQuery.value("powerDescriptor").toUInt();
quint8 lqi = nodesQuery.value("lqi").toUInt();
quint64 lastSeen = nodesQuery.value("timestamp").toULongLong();
// Build the node object
ZigbeeNode *node = new ZigbeeNode(m_network, shortAddress, ZigbeeAddress(ieeeAddress), m_network);
node->m_nodeDescriptor = ZigbeeDeviceProfile::parseNodeDescriptor(nodeDescriptor);
node->m_macCapabilities = node->nodeDescriptor().macCapabilities;
node->m_powerDescriptor = ZigbeeDeviceProfile::parsePowerDescriptor(powerDescriptor);
node->m_lqi = lqi;
node->m_lastSeen = QDateTime::fromMSecsSinceEpoch(lastSeen * 1000);
qCDebug(dcZigbeeNetworkDatabase()) << "Loaded" << node;
@ -202,9 +206,9 @@ bool ZigbeeNetworkDatabase::initDatabase()
"(ieeeAddress TEXT PRIMARY KEY, " // ieeeAddress to string
"shortAddress INTEGER NOT NULL, " // uint16
"nodeDescriptor BLOB NOT NULL, " // bytes as received from the node
"powerDescriptor INTEGER NOT NULL, "
"lqi INTEGER,"
"timestamp )"); // uint16
"powerDescriptor INTEGER NOT NULL, " // uint16
"lqi INTEGER NOT NULL," // uint8
"timestamp INTEGER NOT NULL)"); // unix timestamp with the last communication
createIndices("ieeeAddressIndex", "nodes", "ieeeAddress");
}
@ -379,12 +383,14 @@ bool ZigbeeNetworkDatabase::saveAttribute(ZigbeeCluster *cluster, const ZigbeeCl
bool ZigbeeNetworkDatabase::saveNode(ZigbeeNode *node)
{
qCDebug(dcZigbeeNetworkDatabase()) << "Save" << node;
QString queryString = QString("INSERT OR REPLACE INTO nodes (ieeeAddress, shortAddress, nodeDescriptor, powerDescriptor) "
"VALUES (\"%1\", \"%2\", \"%3\", \"%4\");")
QString queryString = QString("INSERT OR REPLACE INTO nodes (ieeeAddress, shortAddress, nodeDescriptor, powerDescriptor, lqi, timestamp) "
"VALUES (\"%1\", \"%2\", \"%3\", \"%4\", \"%5\", \"%6\");")
.arg(node->extendedAddress().toString())
.arg(node->shortAddress())
.arg(node->nodeDescriptor().descriptorRawData.toBase64().data()) // Note: convert to base64 for saving zeros as string
.arg(node->powerDescriptor().powerDescriptoFlag);
.arg(node->powerDescriptor().powerDescriptoFlag)
.arg(node->lqi())
.arg(node->lastSeen().toMSecsSinceEpoch() / 1000);
qCDebug(dcZigbeeNetworkDatabase()) << queryString;
m_db.exec(queryString);
@ -403,6 +409,33 @@ bool ZigbeeNetworkDatabase::saveNode(ZigbeeNode *node)
return true;
}
bool ZigbeeNetworkDatabase::updateNodeLqi(ZigbeeNode *node, quint8 lqi)
{
qCDebug(dcZigbeeNetworkDatabase()) << "Update nod LQI" << node << lqi;
QString queryString = QString("UPDATE nodes SET lqi = \"%1\" WHERE ieeeAddress = \"%2\";").arg(lqi).arg(node->extendedAddress().toString());
m_db.exec(queryString);
if (m_db.lastError().type() != QSqlError::NoError) {
qCWarning(dcZigbeeNetworkDatabase()) << "Could not update node LQI value in the database." << queryString << m_db.lastError().databaseText() << m_db.lastError().driverText();
return false;
}
return true;
}
bool ZigbeeNetworkDatabase::updateNodeLastSeen(ZigbeeNode *node, const QDateTime &lastSeen)
{
quint64 timestamp = lastSeen.toMSecsSinceEpoch() / 1000;
qCDebug(dcZigbeeNetworkDatabase()) << "Update node last seen UTC timestamp" << node << timestamp;
QString queryString = QString("UPDATE nodes SET timestamp = \"%1\" WHERE ieeeAddress = \"%2\";").arg(timestamp).arg(node->extendedAddress().toString());
m_db.exec(queryString);
if (m_db.lastError().type() != QSqlError::NoError) {
qCWarning(dcZigbeeNetworkDatabase()) << "Could not update node timestamp value in the database." << queryString << m_db.lastError().databaseText() << m_db.lastError().driverText();
return false;
}
return true;
}
bool ZigbeeNetworkDatabase::removeNode(ZigbeeNode *node)
{
qCDebug(dcZigbeeNetworkDatabase()) << "Remove" << node;

View File

@ -63,7 +63,8 @@ public slots:
bool saveOutputCluster(ZigbeeCluster *cluster);
bool saveAttribute(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
bool saveNode(ZigbeeNode *node);
bool updateNodeLqi(ZigbeeNode *node, quint8 lqi);
bool updateNodeLastSeen(ZigbeeNode *node, const QDateTime &lastSeen);
bool removeNode(ZigbeeNode *node);
};

View File

@ -92,6 +92,11 @@ quint8 ZigbeeNode::lqi() const
return m_lqi;
}
QDateTime ZigbeeNode::lastSeen() const
{
return m_lastSeen;
}
ZigbeeDeviceProfile::NodeDescriptor ZigbeeNode::nodeDescriptor() const
{
return m_nodeDescriptor;
@ -548,6 +553,11 @@ void ZigbeeNode::handleDataIndication(const Zigbee::ApsdeDataIndication &indicat
emit lqiChanged(m_lqi);
}
// Update the UTC timestamp of last seen for reachable verification
if (m_lastSeen != QDateTime::currentDateTimeUtc()) {
m_lastSeen = QDateTime::currentDateTimeUtc();
emit lastSeenChanged(m_lastSeen);
}
// Check if this indocation is related to any pending reply
if (indication.profileId == Zigbee::ZigbeeProfileDevice) {

View File

@ -29,6 +29,7 @@
#define ZIGBEENODE_H
#include <QObject>
#include <QDateTime>
#include "zigbee.h"
#include "zigbeeaddress.h"
@ -66,6 +67,7 @@ public:
ZigbeeNodeEndpoint *getEndpoint(quint8 endpointId) const;
quint8 lqi() const;
QDateTime lastSeen() const;
// Information from descriptors
ZigbeeDeviceProfile::NodeDescriptor nodeDescriptor() const;
@ -93,6 +95,7 @@ private:
bool m_connected = false;
State m_state = StateUninitialized;
quint8 m_lqi = 0;
QDateTime m_lastSeen;
// Node information
ZigbeeDeviceProfile::NodeDescriptor m_nodeDescriptor;
@ -122,6 +125,7 @@ signals:
void nodeInitializationFailed();
void stateChanged(State state);
void lqiChanged(quint8 lqi);
void lastSeenChanged(const QDateTime &lastSeen);
void connectedChanged(bool connected);
void clusterAdded(ZigbeeCluster *cluster);
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);