diff --git a/lib/extension/deviceReceive.js b/lib/extension/deviceReceive.js index 20ceeb17..c2c2a589 100644 --- a/lib/extension/deviceReceive.js +++ b/lib/extension/deviceReceive.js @@ -158,16 +158,8 @@ class DeviceReceive { // Add last seen timestamp const now = Date.now(); - switch (settings.get().advanced.last_seen) { - case 'ISO_8601': - payload.last_seen = new Date(now).toISOString(); - break; - case 'ISO_8601_local': - payload.last_seen = utils.toLocalISOString(new Date(now)); - break; - case 'epoch': - payload.last_seen = now; - break; + if (settings.get().advanced.last_seen !== 'disable') { + payload.last_seen = utils.formatDate(now, settings.get().advanced.last_seen); } if (settings.get().advanced.elapsed) { diff --git a/lib/extension/networkMap.js b/lib/extension/networkMap.js index 8cc38bd3..e3089561 100644 --- a/lib/extension/networkMap.js +++ b/lib/extension/networkMap.js @@ -7,10 +7,15 @@ class NetworkMap { this.zigbee = zigbee; this.mqtt = mqtt; this.state = state; + this.lastSeenMap = {}; // Subscribe to topic. this.topic = `${settings.get().mqtt.base_topic}/bridge/networkmap`; + // Bind + this.raw = this.raw.bind(this); + this.graphviz = this.graphviz.bind(this); + // Set supported formats this.supportedFormats = { 'raw': this.raw, @@ -18,6 +23,12 @@ class NetworkMap { }; } + onZigbeeMessage(message, device, mappedDevice) { + if (device) { + this.lastSeenMap[device.ieeeAddr] = Date.now(); + } + } + onMQTTConnected() { this.mqtt.subscribe(this.topic); } @@ -67,8 +78,20 @@ class NetworkMap { labels.push(zigbeeModel ? zigbeeModel : 'No model information available'); } - // Add the device status (online/offline) - labels.push(device.status); + // Add the device status (online/offline) and last_seen timestamp + let lastSeen = 'unknown'; + if (device.type == 'Coordinator') { + lastSeen = utils.formatDate(Date.now(), settings.get().advanced.last_seen, + utils.toLocalISOString(new Date(Date.now()))); + } else { + if (this.lastSeenMap[device.ieeeAddr]) { + const lastSeenAgo = + `${new Date(Date.now() - this.lastSeenMap[device.ieeeAddr]).toISOString().substr(11, 8)}s ago`; + lastSeen = utils.formatDate(this.lastSeenMap[device.ieeeAddr], + settings.get().advanced.last_seen, lastSeenAgo); + } + } + labels.push(`${device.status} (${lastSeen})`); // Shape the record according to device type if (deviceType == 'Coordinator') { diff --git a/lib/util/utils.js b/lib/util/utils.js index 18aef3d4..c2f812ee 100644 --- a/lib/util/utils.js +++ b/lib/util/utils.js @@ -100,6 +100,27 @@ function getZigbee2mqttVersion(callback) { }); } +function formatDate(date, type, _default) { + let result; + + switch (type) { + case 'ISO_8601': + result = new Date(date).toISOString(); + break; + case 'ISO_8601_local': + result = toLocalISOString(new Date(date)); + break; + case 'epoch': + result = date; + break; + default: + result = _default; + break; + } + + return result; +} + module.exports = { millisecondsToSeconds: (milliseconds) => milliseconds / 1000, secondsToMilliseconds: (seconds) => seconds * 1000, @@ -113,6 +134,7 @@ module.exports = { isNumeric: (string) => /^\d+$/.test(string), toLocalISOString: (dDate) => toLocalISOString(dDate), getPostfixes: () => postfixes, + formatDate: (date, type, _default=null) => formatDate(date, type, _default), correctDeviceType: (device) => { if (device) { if (forceEndDevice.includes(device.modelId)) { diff --git a/test/controller.test.js b/test/controller.test.js index f1295198..7048788d 100644 --- a/test/controller.test.js +++ b/test/controller.test.js @@ -45,6 +45,7 @@ describe('Controller', () => { }, advanced: { cache_state: false, + last_seen: 'disable', }, experimental: { output: 'json', diff --git a/test/deviceReceive.test.js b/test/deviceReceive.test.js index f8cb810d..8465fdeb 100644 --- a/test/deviceReceive.test.js +++ b/test/deviceReceive.test.js @@ -41,7 +41,7 @@ describe('DeviceReceive', () => { }); it('Should handle a zigbee message and counter it when Home Assistant integration is enabled', () => { - jest.spyOn(settings, 'get').mockReturnValue({homeassistant: true, advanced: {last_seen: 'disabled'}}); + jest.spyOn(settings, 'get').mockReturnValue({homeassistant: true, advanced: {last_seen: 'disable'}}); const device = {ieeeAddr: '0x12345678'}; const message = utils.zigbeeMessage(device, 'genOnOff', 'attReport', {onOff: 1}, 1); deviceReceive.onZigbeeMessage(message, device, WXKG11LM);