From a5c4a4498712751c9b73175ad488df6a29151540 Mon Sep 17 00:00:00 2001 From: cheetah Date: Mon, 29 Mar 2021 21:47:15 +0000 Subject: [PATCH] added Device Data Collection and Ack Handling --- index.js | 8 ++++ types/DeviceRegistry.js | 7 ++++ types/MessageManager.js | 12 ++++-- types/connectors/DummyConnector.js | 2 +- types/connectors/POCSAGConnector.js | 2 +- types/devices/BirdySlim.js | 62 +++++++++++++++++++---------- 6 files changed, 67 insertions(+), 26 deletions(-) diff --git a/index.js b/index.js index 0776131..d979408 100644 --- a/index.js +++ b/index.js @@ -47,4 +47,12 @@ app.get('/api/message/ack/recv/:id', async (req, res) => { //TODO: make this fan return res.json(true) }) +app.get('/api/device/:id', async (req, res) => { + return res.json( + req.params.id.length == 1 + ? Object.keys(types.DeviceRegistry.DeviceStates) + : types.DeviceRegistry.DeviceStates[ req.params.id ] + ) +}) + app.listen(3000) \ No newline at end of file diff --git a/types/DeviceRegistry.js b/types/DeviceRegistry.js index 9c04d07..3f8de72 100644 --- a/types/DeviceRegistry.js +++ b/types/DeviceRegistry.js @@ -1,6 +1,7 @@ class DeviceRegistry { constructor() { this.Devices = {} + this.DeviceStates = {} // for keeping device states } register(device) { this.Devices[ device.name ] = device @@ -8,6 +9,12 @@ class DeviceRegistry { getDevices() { return Object.values(this.Devices) } + stateSet(deviceType, deviceId, stateData) { + const key = `${ deviceType }:${ deviceId }` + if (!this.DeviceStates[ key ]) + this.DeviceStates[ key ] = {} + Object.assign(this.DeviceStates[ key], stateData) + } /*tryReceive(deviceName, data) { return this.Devices[ deviceName ].tryReceive(data) }*/ diff --git a/types/MessageManager.js b/types/MessageManager.js index afc1576..31cd147 100644 --- a/types/MessageManager.js +++ b/types/MessageManager.js @@ -32,7 +32,7 @@ class MessageManager { deliveryLog: {}, }) console.log(`Type:\t\t${ type }\nDevice:\t\t${ routingParams.device }`) - console.log(`Message UUID:\t${ msgObj.id }`) + console.log(`Message UUID:\t${ msgObj.id } HEX: ${ Buffer.from(msgObj.id, 'utf-8').toString('hex') }`) console.log(`Connectors:\t${ JSON.parse(JSON.stringify(routingParams.connectors)).map(x=>`${x[0]}=${x.splice(1).join(',')}`).join('&') }`) console.log(`Message Original Payload:\t"${ payload }"`) console.log(`Processed Device Payload:\t"${ msgObj.payload }"`) @@ -56,6 +56,12 @@ class MessageManager { } this.messages[ msgId ]._routerData.metadata.push(metadata) } + markMessageRead(msgId) { + this.messages[ msgId ]._routerData.readAck = true + } + respondToMessage(msgId, response) { + this.messages[ msgId ]._routerData.response = response + } _clearEventHandlers4MsgID(msgId) { ConnectorRegistry.events.removeAllListeners(`msg:status:${ msgId }:delivered`) ConnectorRegistry.events.removeAllListeners(`msg:status:${ msgId }:failed`) @@ -109,7 +115,7 @@ class MessageManager { }) .catch(($) => { this._clearEventHandlers4MsgID(msgId) - console.log('DELIVERY WAS A TOTAL FAILURE , FUCK THIS PLANET', $) + console.log('DELIVERY WAS A TOTAL FAILURE', $) }) return true } @@ -152,7 +158,7 @@ class MessageManager { }) .catch(($) => { this._clearEventHandlers4MsgID(msgId) - console.log('ROUTING WAS A TOTAL FAILURE , FUCK THIS PLANET', $) + console.log('ROUTING WAS A TOTAL FAILURE', $) }) } async BindMsg(msg) { diff --git a/types/connectors/DummyConnector.js b/types/connectors/DummyConnector.js index f1a6aaf..9a64762 100644 --- a/types/connectors/DummyConnector.js +++ b/types/connectors/DummyConnector.js @@ -13,7 +13,7 @@ class DummyConnector extends Connector { await new Promise((res)=>setTimeout(res,3e3)) // set Routed this.connectorRegistry.reportState(msg, UUID, 'routed') - await new Promise((res)=>setTimeout(res,6e3)) + await new Promise((res)=>setTimeout(res,16e3)) this.connectorRegistry.events.emit('response', { //reconstruct the response coming from a lorawan connector type: 'ack', ack: 'recv', diff --git a/types/connectors/POCSAGConnector.js b/types/connectors/POCSAGConnector.js index a50bad0..9ae1c86 100644 --- a/types/connectors/POCSAGConnector.js +++ b/types/connectors/POCSAGConnector.js @@ -6,7 +6,7 @@ class POCSAGConnector extends Connector { constructor (amqpConnMngr) { super(amqpConnMngr) this.name = "pocsag" - this.duplexCapable = true + this.duplexCapable = false this.channelWrapper = this.amqpConnMngr.createChannel({ json: false, setup: function(channel) { diff --git a/types/devices/BirdySlim.js b/types/devices/BirdySlim.js index 200cda4..cb91d85 100644 --- a/types/devices/BirdySlim.js +++ b/types/devices/BirdySlim.js @@ -9,21 +9,6 @@ class BirdySlim extends PagerDevice { super() this.duplex = true this.name = "birdyslim" - /*this.birdyParamMapper = { - //'A': ['beaconIDinstant'], // It is the ID of current localisation beacon. - //'B': ['beaconIDstored'], // It is the ID of the last localisation beacon seen by the BIRDY - 'C': ['rssi', 2], // It is the POCSAG carrier received level (in dBm) transmitted by the POCSAG emitter and received by the pager. - //'D': ['date'], // Timestamp in seconds from 01/01/2014. - //'E': ['beaconRoundIDstored'], // It is the ID of the last round beacon seen by the pager - 'G': ['gps', (1+3+1+5)+(1+2+1+5)+2], // Longitude and latitude in decimal degrees and last acquisition time in minutes. - 'I': ['identityRIC'], // BIRDY first RIC code - 'N': ['messageNumber', 5], // To display message number message must begin with ***Mxxx*** where xxx is the message number. - 'S': ['serial', 13], // BIRDY serial number - //'T': ['receivedRIC'], // Message receipt RIC code - 'V': ['batteryVoltage', 2], // BIRDY battery voltage in HEX - //'X': ['lowBattBeacon'], // It is the ID of a beacon with a low battery voltage - '5': ['msgId', 5], // It is to recall first 5 characters of received message in an acknowledgement. - }*/ } RandID() { return `B${ Str.random(4) }` @@ -34,20 +19,55 @@ class BirdySlim extends PagerDevice { msg.payload = msg.type === 'duplex' ? `${ msg.id }${ msg.payload }` : msg.payload // only if duplex wanted we add the id } async tryReceive(data, connector) { - console.log(data) if (typeof(data) === 'object' && !!data.type) { + const stateSet = { + lastSeen: data.date + } + // If we have a Battery Measurement, we should store it + if (!!data.battery) stateSet.battery = data.battery/1e1 + // the same if we have an rssi measurement + if (!!data.rssi) stateSet.rssi = data.rssi + // and if we have the 3 components of a GPS Block + if (!!data.latitude && !!data.longitude && !!data.lastGPSAcquisition) stateSet.gps = { + gps: { + lastGPSAcquisition: data.lastGPSAcquisition, + latitude: data.latitude, + longitude: data.longitude, + }, + } + switch (data.type) { - case 'ack': - if (data.ack === 'recv') { - require('../ConnectorRegistry').reportDelivered({ id: data.msgid }, `lorawan:${ data.device_id }`) // cheating lol - require('../MessageManager').attachMetadata(data.msgid, data) + case 'ack': { + switch (data.ack) { + case 'recv': + require('../ConnectorRegistry').reportDelivered({ id: data.msgid }, `lorawan:${ data.device_id }`) + break; + case 'read': + require('../MessageManager').markMessageRead(data.msgid) + break; + case 'operational': + require('../MessageManager').respondToMessage(data.msgid, data.operationalData) + break; + } + // If we have had a Ack. Event, we should store some Metadate about it too + require('../MessageManager').attachMetadata(data.msgid, { + ack: data.ack, + rssi: data.rssi, + date: data.date + }) } break; + case 'sos': + stateSet.sos = { + sos: data.sos, + date: data.date, + } + break; } + require('../DeviceRegistry').stateSet(this.name, data.device_id, stateSet) return true } return false - // config.pagers.birdyslim.formatRecvAck } } module.exports = BirdySlim \ No newline at end of file