diff --git a/src/mqtt.js b/src/mqtt.js
index 6b8d86f..3052b19 100644
--- a/src/mqtt.js
+++ b/src/mqtt.js
@@ -604,37 +604,6 @@ client.on("connect", () => {
// handle message received
client.on("message", async (topic, message) => {
try {
-
- // handle node status
- if(topic.includes("/stat/!")){
- try {
-
- // get node id and status
- const nodeIdHex = topic.split("/").pop();
- const mqttConnectionState = message.toString();
-
- // convert node id hex to int value
- const nodeId = convertHexIdToNumericId(nodeIdHex);
-
- // update mqtt connection state for node
- await prisma.node.updateMany({
- where: {
- node_id: nodeId,
- },
- data: {
- mqtt_connection_state: mqttConnectionState,
- mqtt_connection_state_updated_at: new Date(),
- },
- });
-
- // no need to continue with this mqtt message
- return;
-
- } catch(e) {
- console.error(e);
- }
- }
-
// decode service envelope
const envelope = ServiceEnvelope.decode(message);
if(!envelope.packet){
@@ -661,6 +630,16 @@ client.on("message", async (topic, message) => {
}
}
+ // Update Node MQTT status based on Last Packet Received time
+ const ret = await prisma.node.updateMany({
+ where: {
+ node_id: convertHexIdToNumericId(envelope.gatewayId),
+ },
+ data: {
+ mqtt_connection_state_updated_at: new Date(),
+ },
+ });
+
// attempt to decrypt encrypted packets
const isEncrypted = envelope.packet.encrypted?.length > 0;
if(isEncrypted){
diff --git a/src/public/index.html b/src/public/index.html
index b6f2340..aff629e 100644
--- a/src/public/index.html
+++ b/src/public/index.html
@@ -1485,6 +1485,30 @@
+
+
+
+
Nodes that have not uploaded to MQTT in this time will show as blue icons. Reload to update map.
+
+
+
@@ -1777,6 +1801,19 @@
}
}
+ function getConfigNodesDisconnectedAgeInSeconds() {
+ const value = localStorage.getItem("config_nodes_disconnected_age_in_seconds");
+ return value != null ? parseInt(value) : null;
+ }
+
+ function setConfigNodesDisconnectedAgeInSeconds(value) {
+ if(value != null){
+ return localStorage.setItem("config_nodes_disconnected_age_in_seconds", value);
+ } else {
+ return localStorage.removeItem("config_nodes_disconnected_age_in_seconds");
+ }
+ }
+
function getConfigNodesOfflineAgeInSeconds() {
const value = localStorage.getItem("config_nodes_offline_age_in_seconds");
return value != null ? parseInt(value) : null;
@@ -1836,6 +1873,7 @@
isShowingAnnouncement: this.shouldShowAnnouncement(),
configNodesMaxAgeInSeconds: window.getConfigNodesMaxAgeInSeconds(),
+ configNodesDisconnectedAgeInSeconds: window.getConfigNodesDisconnectedAgeInSeconds(),
configNodesOfflineAgeInSeconds: window.getConfigNodesOfflineAgeInSeconds(),
configWaypointsMaxAgeInSeconds: window.getConfigWaypointsMaxAgeInSeconds(),
configNeighboursMaxDistanceInMeters: window.getConfigNeighboursMaxDistanceInMeters(),
@@ -2791,6 +2829,9 @@
configNodesMaxAgeInSeconds() {
window.setConfigNodesMaxAgeInSeconds(this.configNodesMaxAgeInSeconds);
},
+ configNodesDisconnectedAgeInSeconds() {
+ window.setConfigNodesDisconnectedAgeInSeconds(this.configNodesDisconnectedAgeInSeconds);
+ },
configNodesOfflineAgeInSeconds() {
window.setConfigNodesOfflineAgeInSeconds(this.configNodesOfflineAgeInSeconds);
},
@@ -3500,12 +3541,15 @@
// icon based on mqtt connection state
var icon = iconMqttDisconnected;
- if(node.mqtt_connection_state === "online"){
- icon = iconMqttConnected;
+ const now = moment();
+ const configNodesDisconnectedAgeInSeconds = getConfigNodesDisconnectedAgeInSeconds();
+ if(configNodesDisconnectedAgeInSeconds){
+ if(now.diff(moment(node.mqtt_connection_state_updated_at)) > configNodesDisconnectedAgeInSeconds * 1000){
+ icon = iconMqttConnected;
+ }
}
// use offline icon for nodes older than configured node offline age
- const now = moment();
const configNodesOfflineAgeInSeconds = getConfigNodesOfflineAgeInSeconds();
if(configNodesOfflineAgeInSeconds){
const lastUpdatedAgeInMillis = now.diff(moment(node.updated_at));
@@ -3519,7 +3563,7 @@
icon: icon,
tagName: node.node_id,
// we want to show online nodes above offline, but without needing to use separate layer groups
- zIndexOffset: node.mqtt_connection_state === "online" ? 1000 : -1000,
+ zIndexOffset: now.diff(moment(node.mqtt_connection_state_updated_at)) > configNodesDisconnectedAgeInSeconds * 1000 ? 1000 : -1000,
}).on('click', function(event) {
// close tooltip on click to prevent tooltip and popup showing at same time
event.target.closeTooltip();
@@ -3937,13 +3981,13 @@
// human friendly connection state
var mqttStatus = "";
- var mqttStatusLastUpdated = node.mqtt_connection_state_updated_at ? `(${moment(new Date(node.mqtt_connection_state_updated_at)).fromNow()})` : "";
- if(node.mqtt_connection_state === "online"){
- mqttStatus = `Connected ${mqttStatusLastUpdated}`;
- } else if(node.mqtt_connection_state === "offline"){
- mqttStatus = `Disconnected ${mqttStatusLastUpdated}`;
+ var mqttStatusLastUpdated = node.mqtt_connection_state_updated_at ? `${moment(new Date(node.mqtt_connection_state_updated_at)).fromNow()}` : "";
+ if(moment().diff(moment(node.mqtt_connection_state_updated_at)) > getConfigNodesDisconnectedAgeInSeconds() * 1000){
+ mqttStatus = `Heard ${mqttStatusLastUpdated}`;
+ } else if(moment().diff(moment(node.mqtt_connection_state_updated_at)) < getConfigNodesDisconnectedAgeInSeconds() * 1000){
+ mqttStatus = `Last Heard ${mqttStatusLastUpdated}`;
} else {
- mqttStatus = `Disconnected`;
+ mqttStatus = `Not heard`;
}
var loraFrequencyRange = getRegionFrequencyRange(node.region_name);