added emessage api

master
cheetah 3 years ago
parent c950dba5a5
commit 3bce300c70

@ -1,49 +0,0 @@
#!/bin/bash
## Bash Library for sending out Pages and/or getting their State
# dependencies: curl, jq
# echo "Bericht" | send_page "http://127.0.0.1:3000" "duplex" "birdyslim" "dapnet=dl-all#DXxxx"
send_page() {
text=$(cat -)
endpoint=$1
msgType=$2
deviceType=$3
argArr=("$@")
connectorJSON=$(for arg in "${argArr[@]}"; do echo $arg; done | jq -Rcs '{array:split("\n")|.[3:-1]|map(split("=")|[(.[0]),.[1]]?)}.array')
echo $connectorJSON |\
jq -c --arg t "$msgType" --arg d "$deviceType" --arg p "$text" '{type:$t, routing: {connectors:.,device:$d}, payload:$p}' |\
curl -s -XPOST -H "Content-type: application/json" "$endpoint/api/message/advanced" -d @- |\
jq -r .
}
msg_status() {
endpoint=$1
msgid=$2
curl -s "$endpoint/api/message/status/$msgid" |\
jq -r ._routerData
}
is_msg_recv() {
msg_status $* | jq .recvAck | grep -q "true"
return $?
}
is_msg_read() {
msg_status $* | jq .readAck | grep -q "true"
return $?
}
is_msg_resp() {
msg_status $* | jq .response | grep -vq "false"
return $?
}
ENDPOINT="http://127.0.0.1:3000"
#echo "Test" | send_page "$ENDPOINT" "duplex" "birdyslim" "pocsag=133701D" "test=123"
msgid=$(echo "Test" | send_page "$ENDPOINT" "duplex" "birdyslim" "pocsag=133701D" "test=123")
#msgid="Bznka"
msg_status "$ENDPOINT" "$msgid"
if is_msg_recv "$ENDPOINT" "$msgid"; then
echo "message is recv"
fi
if is_msg_read "$ENDPOINT" "$msgid"; then
echo "message is read"
fi

@ -21,10 +21,14 @@ if (!!config.connectors.dapnet && config.connectors.dapnet.enabled === true) {
if (!!config.connectors.ecityruf && config.connectors.ecityruf.enabled === true) {
types.ConnectorRegistry.register(new types.Connectors.eCityrufConnector(connection))
}
if (!!config.connectors.emessage && config.connectors.emessage.enabled === true) {
types.ConnectorRegistry.register(new types.Connectors.eMessageConnector(connection))
}
types.ConnectorRegistry.register(new types.Connectors.DummyConnector())
types.DeviceRegistry.register(new types.devices.GenericPager())
types.DeviceRegistry.register(new types.devices.BirdySlim())
types.DeviceRegistry.register(new types.devices.EMessage2Ways())
types.DeviceRegistry.register(new types.devices.Skyper())
const express = require('express')

@ -0,0 +1,142 @@
const Connector = require("./Connector")
const config = require('../../config.json')
const md5 = require('md5')
const axios = require('axios')
// [ "ecityruf", "123456789" ]
class eCityrufConnector extends Connector {
constructor (amqpConnMngr) {
super(amqpConnMngr)
this.name = "emessage"
this.duplexCapable = true
this.supportBOSkrypt = true
}
async transmitMessage(msg, params) {
const UUID = this.name+':'+md5(JSON.stringify([this.name,...params]))
const target = params[0]
if (target.split('#').length !== 2) throw 'No valid eMessage Parameter <serviceName#identifier>'
const serviceName = target.split('#')[ 0 ], identifier = target.split('#')[ 1 ]
// eCityruf#8907737
let jwtToken = '', msgTrackID = ''
// login
axios.post('https://api.emessage.de/auth/login', {
username: config.connectors.emessage.username,
password: config.connectors.emessage.password
})
.then((loginReq) => { // extract jwt
if (loginReq.data.apiStatusCode != 200) { throw loginReq }
jwtToken = loginReq.data.data.jwt
return jwtToken
})
.then(() => { // send Message Request
return axios.post('https://api.emessage.de/rs/eSendMessages', {
messageText: msg.payload,
recipients: [{ serviceName, identifier }]
}, {
headers: {
'Authorization': `Bearer ${ jwtToken }`
}
})
})
.then((sndMessageReq) => { // extract tracking ID from response
if (sndMessageReq.data.apiStatusCode != 200) { throw sndMessageReq }
this.connectorRegistry.reportState(msg, UUID, 'routed') // since we queued the message, we shall mark it was routed
msgTrackID = sndMessageReq.data.data.trackingId
console.log('TRACKING ID', msgTrackID)
return msgTrackID
})
/*.then((_) => { // extract tracking ID from response
this.connectorRegistry.reportState(msg, UUID, 'routed')
msgTrackID = '04872f70-9029-11ec-b877-e5935093b691'
return msgTrackID
})*/
.then(async () => { // check for response til duplexTimeout
const delaySeconds = (timeout) => new Promise(r=>setTimeout(r, timeout * 1e3))
const checkDelivery = async () => {
try {
let res = await axios.get('https://api.emessage.de/rs/eGetMessages/External/' + msgTrackID, {
headers: {
'Authorization': `Bearer ${ jwtToken }`
}
})
let deliveryState = res.data.data.recipients[ 0 ].status[ 0 ].answer
if (deliveryState == 'INTRANSIT') this.connectorRegistry.reportState(msg, UUID, 'transit')
if (deliveryState == 'SENT') this.connectorRegistry.reportState(msg, UUID, 'sent')
if (deliveryState == 'RECEIVED' || +deliveryState > 0) {
this.connectorRegistry.reportDelivered(msg, UUID)
return true
}
console.log(JSON.stringify(res.data.data))
//this.connectorRegistry.reportState(msg, UUID, deliveryState)
return false
//if (res.data.data.recipients.filter(rec=>))
} catch (e) {
throw e
}
}
const checkResponse = async () => {
try {
let res = await axios.get('https://api.emessage.de/rs/eGetMessages/External/' + msgTrackID, {
headers: {
'Authorization': `Bearer ${ jwtToken }`
}
})
let status = res.data.data.recipients[ 0 ].status[ 0 ]
//if (deliveryState == 'INTRANSIT') this.connectorRegistry.reportState(msg, UUID, 'transit')
/*if (deliveryState == 'RECEIVED' || +deliveryState > 0) {
this.connectorRegistry.reportDelivered(msg, UUID)
return true
}*/
if (+status.answerNo == 1 && +status.answer > -1 ) {
//this.connectorRegistry.response(msg, status.answer)
require('../MessageManager').markMessageRead(msg.id)
require('../MessageManager').respondToMessage(msg.id, +status.answer)
return true
}
return false
//if (res.data.data.recipients.filter(rec=>))
} catch (e) {
throw e
}
}
const deliveryProcess = new Promise(async (res, rej) => {
const { startInterval, duplexTimeout } = config.connectors.emessage
let nextDelay = startInterval + 0
do {
let resultCheck = await checkDelivery()
if (resultCheck == true) return res()
await delaySeconds(nextDelay)
nextDelay *= 2 // wait 2x longer than before
} while (nextDelay <= duplexTimeout)
return rej()
})
const responseProcess = new Promise(async (res, rej) => {
const { startInterval, responseTimeout } = config.connectors.emessage
let nextDelay = startInterval + 0
do {
let resultCheck = await checkResponse()
if (resultCheck == true) return res()
await delaySeconds(nextDelay)
nextDelay *= 2 // wait 2x longer than before
} while (nextDelay <= responseTimeout)
return rej()
})
return Promise.race([
new Promise((res, rej) => { // exit pattern after duplexTimeout
setTimeout(rej, config.connectors.emessage.duplexTimeout * 1e3)
}),
deliveryProcess.then(responseProcess)
])
})
.catch((err) => {
console.error(err)
this.connectorRegistry.reportFail(msg, UUID)
return false
})
}
}
module.exports = eCityrufConnector

@ -1,6 +1,7 @@
module.exports = {
DAPNETConnector: require("./DAPNETConnector"),
eCityrufConnector: require('./eCityrufConnector'),
eMessageConnector: require('./eMessageConnector'),
LoRaWANConnector: require("./LoRaWANConnector"),
POCSAGConnector: require("./POCSAGConnector"),
DummyConnector: require("./DummyConnector"),

@ -0,0 +1,92 @@
const MessageManager = require("../MessageManager")
const PagerDevice = require("./Device")
const Str = require('@supercharge/strings')
const config = require('../../config.json')
// Birdy Slim (IoT) Device
class EMessage2Ways extends PagerDevice {
constructor () {
super()
this.duplex = true
this.supportBOSkrypt = false
this.name = "emessage2WayS"
}
RandID() {
return `E${ Str.random(8) }`
}
async formatTX(msg) {
msg.id = this.RandID()
await MessageManager.BindMsg(msg)
//msg.payload = msg.type === 'duplex' ? `${ msg.id }${ msg.payload }` : msg.payload // only if duplex wanted we add the id
}
async tryReceive(data, connector) {
if (typeof(data) === 'object' && !!data.type) {
const stateSet = {
lastSeen: data.date
}
// If we have a Battery Measurement or other Power Events, we should store it
if (!!data.battery) stateSet.battery = data.battery/1e1
if (data.hasOwnProperty('isCharging')) stateSet.isCharging = data.isCharging
if (data.hasOwnProperty('poweredOn')) stateSet.poweredOn = data.poweredOn
// 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 = {
lastGPSAcquisition: data.lastGPSAcquisition,
latitude: data.latitude,
longitude: data.longitude,
}
stateSet.lastLoRaPacket = data.metadata
console.log(data, stateSet)
/*if (!!data.metadata && !!data.metadata.uplink_message.rx_metadata) {
const rx_metadata = data.metadata.uplink_message.rx_metadata
}*/
switch (data.type) {
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 Metadata about it too
require('../MessageManager').attachMetadata(data.msgid, {
ack: data.ack,
rssi: data.rssi,
date: data.date,
metadata: data.metadata,
})
}
break;
case 'sos':
stateSet.sos = {
sos: data.sos,
date: data.date,
}
break;
case 'status':
case 'cannedMessage':
case 'low_battery':
case 'power':
case 'battery':
case 'sos':
case 'gps':
require('../DeviceRegistry').deviceEvent(this.name, data.device_id, data)
break;
}
require('../DeviceRegistry').stateSet(this.name, data.device_id, stateSet)
return true
}
return false
}
}
module.exports = EMessage2Ways

@ -1,6 +1,7 @@
module.exports = {
GenericPager: require("./GenericPager"),
BirdySlim: require("./BirdySlim"),
EMessage2Ways: require("./EMessage2Ways"),
Skyper: require("./Skyper"),
Device: require("./Device"),
}
Loading…
Cancel
Save