Add ZigBee routing information to topology map
This commit is contained in:
parent
a12ea9775c
commit
4a06e05115
@ -424,4 +424,18 @@ void ZigbeeManager::updateNodeProperties(ZigbeeNode *node, const QVariantMap &no
|
|||||||
neighbors.append(networkAddress);
|
neighbors.append(networkAddress);
|
||||||
}
|
}
|
||||||
node->commitNeighbors(neighbors);
|
node->commitNeighbors(neighbors);
|
||||||
|
|
||||||
|
QList<quint16> routes;
|
||||||
|
foreach (const QVariant &route, nodeMap.value("routingTableRecords").toList()) {
|
||||||
|
QVariantMap routeMap = route.toMap();
|
||||||
|
quint16 destinationAddress = routeMap.value("destinationAddress").toUInt();
|
||||||
|
quint16 nextHopAddress = routeMap.value("nextHopAddress").toUInt();
|
||||||
|
QMetaEnum routeStatusEnum = QMetaEnum::fromType<ZigbeeNode::ZigbeeNodeRouteStatus>();
|
||||||
|
ZigbeeNode::ZigbeeNodeRouteStatus routeStatus = static_cast<ZigbeeNode::ZigbeeNodeRouteStatus>(routeStatusEnum.keyToValue(routeMap.value("status").toByteArray().data()));
|
||||||
|
bool memoryConstrained = routeMap.value("memoryConstrained").toBool();
|
||||||
|
bool manyToOne = routeMap.value("manyToOne").toBool();
|
||||||
|
node->addOrUpdateRoute(destinationAddress, nextHopAddress, routeStatus, memoryConstrained, manyToOne);
|
||||||
|
routes.append(destinationAddress);
|
||||||
|
}
|
||||||
|
node->commitRoutes(routes);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -210,12 +210,17 @@ void ZigbeeNode::addOrUpdateNeighbor(quint16 networkAddress, ZigbeeNodeRelations
|
|||||||
neighbor->setPermitJoining(permitJoining);
|
neighbor->setPermitJoining(permitJoining);
|
||||||
m_neighborsDirty = true;
|
m_neighborsDirty = true;
|
||||||
}
|
}
|
||||||
|
if (neighbor->depth() != depth) {
|
||||||
|
neighbor->setDepth(depth);
|
||||||
|
m_neighborsDirty = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ZigbeeNodeNeighbor *neighbor = new ZigbeeNodeNeighbor(networkAddress, this);
|
ZigbeeNodeNeighbor *neighbor = new ZigbeeNodeNeighbor(networkAddress, this);
|
||||||
neighbor->setRelationship(relationship);
|
neighbor->setRelationship(relationship);
|
||||||
neighbor->setLqi(lqi);
|
neighbor->setLqi(lqi);
|
||||||
|
neighbor->setPermitJoining(permitJoining);
|
||||||
neighbor->setDepth(depth);
|
neighbor->setDepth(depth);
|
||||||
m_neighbors.append(neighbor);
|
m_neighbors.append(neighbor);
|
||||||
m_neighborsDirty = true;
|
m_neighborsDirty = true;
|
||||||
@ -239,6 +244,61 @@ void ZigbeeNode::commitNeighbors(QList<quint16> toBeKept)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<ZigbeeNodeRoute *> ZigbeeNode::routes() const
|
||||||
|
{
|
||||||
|
return m_routes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::addOrUpdateRoute(quint16 destinationAddress, quint16 nextHopAddress, ZigbeeNodeRouteStatus status, bool memoryConstrained, bool manyToOne)
|
||||||
|
{
|
||||||
|
foreach (ZigbeeNodeRoute *route, m_routes) {
|
||||||
|
if (route->destinationAddress() == destinationAddress) {
|
||||||
|
if (route->nextHopAddress() != nextHopAddress) {
|
||||||
|
route->setNextHopAddress(nextHopAddress);
|
||||||
|
m_routesDirty = true;
|
||||||
|
}
|
||||||
|
if (route->status() != status) {
|
||||||
|
route->setStatus(status);
|
||||||
|
m_routesDirty = true;
|
||||||
|
}
|
||||||
|
if (route->memoryConstrained() != memoryConstrained) {
|
||||||
|
route->setMemoryConstrained(memoryConstrained);
|
||||||
|
m_routesDirty = true;
|
||||||
|
}
|
||||||
|
if (route->manyToOne() != manyToOne) {
|
||||||
|
route->setManyToOne(manyToOne);
|
||||||
|
m_routesDirty = true;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ZigbeeNodeRoute *route = new ZigbeeNodeRoute(destinationAddress, this);
|
||||||
|
route->setNextHopAddress(nextHopAddress);
|
||||||
|
route->setStatus(status);
|
||||||
|
route->setMemoryConstrained(memoryConstrained);
|
||||||
|
route->setManyToOne(manyToOne);
|
||||||
|
m_routes.append(route);
|
||||||
|
m_routesDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::commitRoutes(QList<quint16> toBeKept)
|
||||||
|
{
|
||||||
|
QMutableListIterator<ZigbeeNodeRoute*> iter(m_routes);
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
ZigbeeNodeRoute *route = iter.next();
|
||||||
|
if (!toBeKept.contains(route->destinationAddress())) {
|
||||||
|
iter.remove();
|
||||||
|
route->deleteLater();
|
||||||
|
m_routesDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_routesDirty) {
|
||||||
|
emit routesChanged();
|
||||||
|
m_routesDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeNode::ZigbeeNodeState ZigbeeNode::stringToNodeState(const QString &nodeState)
|
ZigbeeNode::ZigbeeNodeState ZigbeeNode::stringToNodeState(const QString &nodeState)
|
||||||
{
|
{
|
||||||
if (nodeState == "ZigbeeNodeStateUninitialized") {
|
if (nodeState == "ZigbeeNodeStateUninitialized") {
|
||||||
@ -326,3 +386,67 @@ void ZigbeeNodeNeighbor::setPermitJoining(bool permitJoining)
|
|||||||
emit permitJoiningChanged();
|
emit permitJoiningChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeNodeRoute::ZigbeeNodeRoute(quint16 destinationAddress, QObject *parent):
|
||||||
|
QObject(parent),
|
||||||
|
m_destinationAddress(destinationAddress)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 ZigbeeNodeRoute::destinationAddress() const
|
||||||
|
{
|
||||||
|
return m_destinationAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 ZigbeeNodeRoute::nextHopAddress() const
|
||||||
|
{
|
||||||
|
return m_nextHopAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNodeRoute::setNextHopAddress(quint16 nextHopAddress)
|
||||||
|
{
|
||||||
|
if (m_nextHopAddress != nextHopAddress) {
|
||||||
|
m_nextHopAddress = nextHopAddress;
|
||||||
|
emit nextHopAddressChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeNode::ZigbeeNodeRouteStatus ZigbeeNodeRoute::status() const
|
||||||
|
{
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNodeRoute::setStatus(ZigbeeNode::ZigbeeNodeRouteStatus status)
|
||||||
|
{
|
||||||
|
if (m_status != status) {
|
||||||
|
m_status = status;
|
||||||
|
emit statusChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeNodeRoute::memoryConstrained() const
|
||||||
|
{
|
||||||
|
return m_memoryConstrained;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNodeRoute::setMemoryConstrained(bool memoryConstrained)
|
||||||
|
{
|
||||||
|
if (m_memoryConstrained != memoryConstrained) {
|
||||||
|
m_memoryConstrained = memoryConstrained;
|
||||||
|
emit memoryConstrainedChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeNodeRoute::manyToOne() const
|
||||||
|
{
|
||||||
|
return m_manyToOne;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNodeRoute::setManyToOne(bool manyToOne)
|
||||||
|
{
|
||||||
|
if (m_manyToOne != manyToOne) {
|
||||||
|
m_manyToOne = manyToOne;
|
||||||
|
emit manyToOneChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -37,6 +37,7 @@
|
|||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
class ZigbeeNodeNeighbor;
|
class ZigbeeNodeNeighbor;
|
||||||
|
class ZigbeeNodeRoute;
|
||||||
|
|
||||||
class ZigbeeNode : public QObject
|
class ZigbeeNode : public QObject
|
||||||
{
|
{
|
||||||
@ -54,6 +55,7 @@ class ZigbeeNode : public QObject
|
|||||||
Q_PROPERTY(uint lqi READ lqi WRITE setLqi NOTIFY lqiChanged)
|
Q_PROPERTY(uint lqi READ lqi WRITE setLqi NOTIFY lqiChanged)
|
||||||
Q_PROPERTY(QDateTime lastSeen READ lastSeen WRITE setLastSeen NOTIFY lastSeenChanged)
|
Q_PROPERTY(QDateTime lastSeen READ lastSeen WRITE setLastSeen NOTIFY lastSeenChanged)
|
||||||
Q_PROPERTY(QList<ZigbeeNodeNeighbor*> neighbors READ neighbors NOTIFY neighborsChanged)
|
Q_PROPERTY(QList<ZigbeeNodeNeighbor*> neighbors READ neighbors NOTIFY neighborsChanged)
|
||||||
|
Q_PROPERTY(QList<ZigbeeNodeRoute*> routes READ routes NOTIFY routesChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum ZigbeeNodeType {
|
enum ZigbeeNodeType {
|
||||||
@ -80,6 +82,15 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(ZigbeeNodeRelationship)
|
Q_ENUM(ZigbeeNodeRelationship)
|
||||||
|
|
||||||
|
enum ZigbeeNodeRouteStatus {
|
||||||
|
ZigbeeNodeRouteStatusActive,
|
||||||
|
ZigbeeNodeRouteStatusDiscoveryUnderway,
|
||||||
|
ZigbeeNodeRouteStatusDiscoveryFailed,
|
||||||
|
ZigbeeNodeRouteStatusInactive,
|
||||||
|
ZigbeeNodeRouteStatusValidationUnderway
|
||||||
|
};
|
||||||
|
Q_ENUM(ZigbeeNodeRouteStatus)
|
||||||
|
|
||||||
explicit ZigbeeNode(const QUuid &networkUuid, const QString &ieeeAddress, QObject *parent = nullptr);
|
explicit ZigbeeNode(const QUuid &networkUuid, const QString &ieeeAddress, QObject *parent = nullptr);
|
||||||
|
|
||||||
QUuid networkUuid() const;
|
QUuid networkUuid() const;
|
||||||
@ -119,6 +130,10 @@ public:
|
|||||||
void addOrUpdateNeighbor(quint16 networkAddress, ZigbeeNodeRelationship relationship, quint8 lqi, quint8 depth, bool permitJoining);
|
void addOrUpdateNeighbor(quint16 networkAddress, ZigbeeNodeRelationship relationship, quint8 lqi, quint8 depth, bool permitJoining);
|
||||||
void commitNeighbors(QList<quint16> toBeKept);
|
void commitNeighbors(QList<quint16> toBeKept);
|
||||||
|
|
||||||
|
QList<ZigbeeNodeRoute*> routes() const;
|
||||||
|
void addOrUpdateRoute(quint16 destinationAddress, quint16 nextHopAddress, ZigbeeNodeRouteStatus status, bool memoryConstrained, bool manyToOne);
|
||||||
|
void commitRoutes(QList<quint16> toBeKept);
|
||||||
|
|
||||||
static ZigbeeNodeState stringToNodeState(const QString &nodeState);
|
static ZigbeeNodeState stringToNodeState(const QString &nodeState);
|
||||||
static ZigbeeNodeType stringToNodeType(const QString &nodeType);
|
static ZigbeeNodeType stringToNodeType(const QString &nodeType);
|
||||||
|
|
||||||
@ -134,6 +149,7 @@ signals:
|
|||||||
void lqiChanged(uint lqi);
|
void lqiChanged(uint lqi);
|
||||||
void lastSeenChanged(const QDateTime &lastSeen);
|
void lastSeenChanged(const QDateTime &lastSeen);
|
||||||
void neighborsChanged();
|
void neighborsChanged();
|
||||||
|
void routesChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUuid m_networkUuid;
|
QUuid m_networkUuid;
|
||||||
@ -150,6 +166,8 @@ private:
|
|||||||
QDateTime m_lastSeen;
|
QDateTime m_lastSeen;
|
||||||
QList<ZigbeeNodeNeighbor*> m_neighbors;
|
QList<ZigbeeNodeNeighbor*> m_neighbors;
|
||||||
bool m_neighborsDirty = false;
|
bool m_neighborsDirty = false;
|
||||||
|
QList<ZigbeeNodeRoute*> m_routes;
|
||||||
|
bool m_routesDirty = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ZigbeeNodeNeighbor: public QObject
|
class ZigbeeNodeNeighbor: public QObject
|
||||||
@ -192,4 +210,44 @@ private:
|
|||||||
bool m_permitJoining = false;
|
bool m_permitJoining = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ZigbeeNodeRoute: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(quint16 destinationAddress READ destinationAddress CONSTANT)
|
||||||
|
Q_PROPERTY(quint16 nextHopAddress READ nextHopAddress NOTIFY nextHopAddressChanged)
|
||||||
|
Q_PROPERTY(ZigbeeNode::ZigbeeNodeRouteStatus status READ status NOTIFY statusChanged)
|
||||||
|
Q_PROPERTY(bool memoryConstrained READ memoryConstrained NOTIFY memoryConstrainedChanged)
|
||||||
|
Q_PROPERTY(bool manyToOne READ manyToOne NOTIFY manyToOneChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ZigbeeNodeRoute(quint16 destinationAddress, QObject *parent);
|
||||||
|
|
||||||
|
quint16 destinationAddress() const;
|
||||||
|
|
||||||
|
quint16 nextHopAddress() const;
|
||||||
|
void setNextHopAddress(quint16 nextHopAddress);
|
||||||
|
|
||||||
|
ZigbeeNode::ZigbeeNodeRouteStatus status() const;
|
||||||
|
void setStatus(ZigbeeNode::ZigbeeNodeRouteStatus status);
|
||||||
|
|
||||||
|
bool memoryConstrained() const;
|
||||||
|
void setMemoryConstrained(bool memoryConstrained);
|
||||||
|
|
||||||
|
bool manyToOne() const;
|
||||||
|
void setManyToOne(bool manyToOne);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void nextHopAddressChanged();
|
||||||
|
void statusChanged();
|
||||||
|
void memoryConstrainedChanged();
|
||||||
|
void manyToOneChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
quint16 m_destinationAddress;
|
||||||
|
quint16 m_nextHopAddress;
|
||||||
|
ZigbeeNode::ZigbeeNodeRouteStatus m_status = ZigbeeNode::ZigbeeNodeRouteStatusInactive;
|
||||||
|
bool m_memoryConstrained = false;
|
||||||
|
bool m_manyToOne = false;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // ZIGBEENODE_H
|
#endif // ZIGBEENODE_H
|
||||||
|
|||||||
@ -16,7 +16,7 @@ Page {
|
|||||||
property ZigbeeManager zigbeeManager: null
|
property ZigbeeManager zigbeeManager: null
|
||||||
property ZigbeeNetwork network: null
|
property ZigbeeNetwork network: null
|
||||||
|
|
||||||
readonly property int nodeDistance: 150
|
readonly property int nodeDistance: Style.iconSize * 2
|
||||||
readonly property int nodeSize: Style.iconSize + Style.margins
|
readonly property int nodeSize: Style.iconSize + Style.margins
|
||||||
readonly property double scale: 1
|
readonly property double scale: 1
|
||||||
|
|
||||||
@ -26,7 +26,12 @@ Page {
|
|||||||
|
|
||||||
reload();
|
reload();
|
||||||
for (var i = 0; i < network.nodes.count; i++) {
|
for (var i = 0; i < network.nodes.count; i++) {
|
||||||
network.nodes.get(i).neighborsChanged.connect(function() {root.reload()})
|
network.nodes.get(i).neighborsChanged.connect(root.reload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component.onDestruction: {
|
||||||
|
for (var i = 0; i < network.nodes.count; i++) {
|
||||||
|
network.nodes.get(i).neighborsChanged.disconnect(root.reload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,12 +39,12 @@ Page {
|
|||||||
target: root.network.nodes
|
target: root.network.nodes
|
||||||
onNodeAdded: {
|
onNodeAdded: {
|
||||||
root.reload()
|
root.reload()
|
||||||
node.neighborsChanged.connect(function() {root.reload()});
|
node.neighborsChanged.connect(root.reload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateNodeList() {
|
function generateNodeList() {
|
||||||
d.nodeItems = []
|
var nodeItems = []
|
||||||
var coordinator = {}
|
var coordinator = {}
|
||||||
var routers = []
|
var routers = []
|
||||||
var endDevices = []
|
var endDevices = []
|
||||||
@ -60,19 +65,20 @@ Page {
|
|||||||
|
|
||||||
var startAngle = -90
|
var startAngle = -90
|
||||||
|
|
||||||
var x = root.nodeDistance * Math.cos(startAngle * Math.PI / 180)
|
var routersCircumference = Math.max(5, routers.length) * (root.nodeSize + root.nodeDistance) * root.scale
|
||||||
var y = root.nodeDistance * Math.sin(startAngle * Math.PI / 180)
|
var distanceFromCenter = routersCircumference / 2 / Math.PI
|
||||||
d.nodeItems.push(createNodeItem(coordinator, x, y, startAngle))
|
|
||||||
|
routers.unshift(coordinator)
|
||||||
|
|
||||||
var handledEndDevices = []
|
var handledEndDevices = []
|
||||||
|
|
||||||
var angle = 360 / (routers.length + 1);
|
var angle = 360 / routers.length;
|
||||||
for (var i = 0; i < routers.length; i++) {
|
for (var i = 0; i < routers.length; i++) {
|
||||||
var router = routers[i]
|
var router = routers[i]
|
||||||
var nodeAngle = startAngle + angle * (i + 1);
|
var nodeAngle = startAngle + angle * i;
|
||||||
var x = root.nodeDistance * Math.cos(nodeAngle * Math.PI / 180)
|
var x = distanceFromCenter * Math.cos(nodeAngle * Math.PI / 180)
|
||||||
var y = root.nodeDistance * Math.sin(nodeAngle * Math.PI / 180)
|
var y = distanceFromCenter * Math.sin(nodeAngle * Math.PI / 180)
|
||||||
d.nodeItems.push(createNodeItem(routers[i], x, y, nodeAngle));
|
nodeItems.push(createNodeItem(routers[i], x, y, nodeAngle));
|
||||||
|
|
||||||
|
|
||||||
var neighborCounter = 0;
|
var neighborCounter = 0;
|
||||||
@ -88,13 +94,12 @@ Page {
|
|||||||
}
|
}
|
||||||
handledEndDevices.push(neighborNode.networkAddress)
|
handledEndDevices.push(neighborNode.networkAddress)
|
||||||
|
|
||||||
|
|
||||||
var neighborAngle = nodeAngle + neighborCounter * 8
|
var neighborAngle = nodeAngle + neighborCounter * 8
|
||||||
var neighborDistance = root.nodeDistance * 1.5 * root.scale + neighborCounter * root.nodeSize * 0.75 * root.scale
|
var neighborDistance = (distanceFromCenter + root.nodeDistance + root.nodeSize) * root.scale + neighborCounter * root.nodeDistance * .5 * root.scale
|
||||||
|
|
||||||
x = neighborDistance * Math.cos(neighborAngle * Math.PI / 180)
|
x = neighborDistance * Math.cos(neighborAngle * Math.PI / 180)
|
||||||
y = neighborDistance * Math.sin(neighborAngle * Math.PI / 180)
|
y = neighborDistance * Math.sin(neighborAngle * Math.PI / 180)
|
||||||
d.nodeItems.push(createNodeItem(neighborNode, x, y, angle))
|
nodeItems.push(createNodeItem(neighborNode, x, y, angle))
|
||||||
|
|
||||||
neighborCounter++
|
neighborCounter++
|
||||||
}
|
}
|
||||||
@ -120,10 +125,10 @@ Page {
|
|||||||
var column = i % columns;
|
var column = i % columns;
|
||||||
var row = Math.floor(i / columns)
|
var row = Math.floor(i / columns)
|
||||||
var x = cellWidth * column + cellWidth / 2 - rowWidth / 2
|
var x = cellWidth * column + cellWidth / 2 - rowWidth / 2
|
||||||
var y = Style.margins + cellHeight * row + root.nodeSize - root.height / 3
|
var y = Style.margins + cellHeight * row + root.nodeSize - canvas.height / 2
|
||||||
var point = root.mapToItem(canvas, x, y)
|
nodeItems.push(createNodeItem(node, x, y, 0))
|
||||||
d.nodeItems.push(createNodeItem(node, point.x, point.y, 0))
|
|
||||||
}
|
}
|
||||||
|
d.nodeItems = nodeItems
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -173,16 +178,13 @@ Page {
|
|||||||
var nodeItem = d.nodeItems.shift()
|
var nodeItem = d.nodeItems.shift()
|
||||||
nodeItem.image.destroy();
|
nodeItem.image.destroy();
|
||||||
}
|
}
|
||||||
// d.selectedNodeItem= null
|
|
||||||
d.minX = 0
|
|
||||||
d.minY = 0
|
|
||||||
d.maxX = 0
|
|
||||||
d.maxY = 0
|
|
||||||
d.size = 0
|
|
||||||
generateNodeList();
|
generateNodeList();
|
||||||
canvas.requestPaint()
|
canvas.requestPaint()
|
||||||
flickable.contentX = (flickable.contentWidth - flickable.width) / 2
|
print("repainting", flickable.contentX, flickable.contentY)
|
||||||
flickable.contentY = (flickable.contentHeight - flickable.height) / 2
|
if (flickable.contentX == 0 && flickable.contentY == 0) {
|
||||||
|
flickable.contentX = (flickable.contentWidth - flickable.width) / 2
|
||||||
|
flickable.contentY = (flickable.contentHeight - flickable.height) / 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
@ -190,6 +192,17 @@ Page {
|
|||||||
property var nodeItems: []
|
property var nodeItems: []
|
||||||
|
|
||||||
property int selectedNodeAddress: -1
|
property int selectedNodeAddress: -1
|
||||||
|
readonly property var selectedNodeItem: {
|
||||||
|
print("selected", selectedNodeAddress)
|
||||||
|
for (var i = 0; i < nodeItems.length; i++) {
|
||||||
|
print("checking", nodeItems[i].node.networkAddress)
|
||||||
|
if (nodeItems[i].node.networkAddress === selectedNodeAddress) {
|
||||||
|
return nodeItems[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
readonly property ZigbeeNode selectedNode: selectedNodeAddress >= 0 ? network.nodes.getNodeByNetworkAddress(selectedNodeAddress) : null
|
readonly property ZigbeeNode selectedNode: selectedNodeAddress >= 0 ? network.nodes.getNodeByNetworkAddress(selectedNodeAddress) : null
|
||||||
|
|
||||||
property int minX: 0
|
property int minX: 0
|
||||||
@ -249,11 +262,69 @@ Page {
|
|||||||
for (var i = 0; i < d.nodeItems.length; i++) {
|
for (var i = 0; i < d.nodeItems.length; i++) {
|
||||||
paintEdges(ctx, d.nodeItems[i], true)
|
paintEdges(ctx, d.nodeItems[i], true)
|
||||||
}
|
}
|
||||||
|
if (d.selectedNodeItem) {
|
||||||
|
paintRoute(ctx, d.selectedNodeItem)
|
||||||
|
}
|
||||||
for (var i = 0; i < d.nodeItems.length; i++) {
|
for (var i = 0; i < d.nodeItems.length; i++) {
|
||||||
paintNode(ctx, d.nodeItems[i])
|
paintNode(ctx, d.nodeItems[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function paintRoute(ctx, nodeItem) {
|
||||||
|
var node = nodeItem.node
|
||||||
|
var nextHop = -1
|
||||||
|
if (node.type === ZigbeeNode.ZigbeeNodeTypeRouter) {
|
||||||
|
for (var i = 0; i < node.routes.length; i++) {
|
||||||
|
if (node.routes[i].destinationAddress === 0) {
|
||||||
|
nextHop = node.routes[i].nextHopAddress
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (node.type === ZigbeeNode.ZigbeeNodeTypeEndDevice) {
|
||||||
|
for (var i = 0; i < network.nodes.count; i++) {
|
||||||
|
for (var j = 0; j < network.nodes.get(i).neighbors.length; j++) {
|
||||||
|
if (network.nodes.get(i).neighbors[j].networkAddress === node.networkAddress) {
|
||||||
|
nextHop = network.nodes.get(i).networkAddress
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("next hop", nextHop)
|
||||||
|
if (nextHop == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var toNodeItem = null
|
||||||
|
for (var i = 0; i < d.nodeItems.length; i++) {
|
||||||
|
if (d.nodeItems[i].node.networkAddress == nextHop) {
|
||||||
|
toNodeItem = d.nodeItems[i]
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!toNodeItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.save()
|
||||||
|
|
||||||
|
ctx.lineWidth = 2
|
||||||
|
ctx.setLineDash([4, 4])
|
||||||
|
ctx.strokeStyle = Style.blue
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(scale * nodeItem.x, scale * nodeItem.y)
|
||||||
|
ctx.lineTo(scale * toNodeItem.x, scale * toNodeItem.y)
|
||||||
|
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.closePath()
|
||||||
|
ctx.setLineDash([1,0])
|
||||||
|
ctx.restore();
|
||||||
|
|
||||||
|
paintRoute(ctx, toNodeItem)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function paintEdges(ctx, nodeItem, selected) {
|
function paintEdges(ctx, nodeItem, selected) {
|
||||||
for (var i = 0; i < nodeItem.node.neighbors.length; i++) {
|
for (var i = 0; i < nodeItem.node.neighbors.length; i++) {
|
||||||
var neighbor = nodeItem.node.neighbors[i]
|
var neighbor = nodeItem.node.neighbors[i]
|
||||||
@ -346,7 +417,11 @@ Page {
|
|||||||
if (Math.abs(root.scale * nodeItem.x - translatedMouseX) < (root.scale * root.nodeSize / 2)
|
if (Math.abs(root.scale * nodeItem.x - translatedMouseX) < (root.scale * root.nodeSize / 2)
|
||||||
&& Math.abs(root.scale * nodeItem.y - translatedMouseY) < (root.scale * root.nodeSize / 2)) {
|
&& Math.abs(root.scale * nodeItem.y - translatedMouseY) < (root.scale * root.nodeSize / 2)) {
|
||||||
d.selectedNodeAddress = nodeItem.node.networkAddress;
|
d.selectedNodeAddress = nodeItem.node.networkAddress;
|
||||||
print("sleecting", nodeItem.node.networkAddress)
|
print("selecting", nodeItem.node.networkAddress)
|
||||||
|
for (var j = 0; j < nodeItem.node.routes.length; j++) {
|
||||||
|
var route = nodeItem.node.routes[j]
|
||||||
|
print("route:", route.destinationAddress, "via", route.nextHopAddress)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,7 +493,7 @@ Page {
|
|||||||
|
|
||||||
contentItem: ListView {
|
contentItem: ListView {
|
||||||
id: tableListView
|
id: tableListView
|
||||||
spacing: app.margins
|
// spacing: app.margins
|
||||||
implicitHeight: Math.min(root.height / 4, count * Style.smallIconSize)
|
implicitHeight: Math.min(root.height / 4, count * Style.smallIconSize)
|
||||||
clip: true
|
clip: true
|
||||||
model: d.selectedNode ? d.selectedNode.neighbors.length : 0
|
model: d.selectedNode ? d.selectedNode.neighbors.length : 0
|
||||||
|
|||||||
Reference in New Issue
Block a user