parent
f08e361d2e
commit
4a63a53a3d
16
package.json
16
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@uci/mqtt",
|
"name": "@uci/mqtt",
|
||||||
"version": "0.1.0",
|
"version": "0.1.2",
|
||||||
"description": "mqtt client with json payloads and mqtt custom broker",
|
"description": "mqtt client with json payloads and mqtt custom broker",
|
||||||
"main": "src",
|
"main": "src",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -26,8 +26,8 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/uCOMmandIt/uci-changeme#readme",
|
"homepage": "https://github.com/uCOMmandIt/uci-changeme#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uci/logger": "^0.0.3",
|
"@uci/logger": "0.0.6",
|
||||||
"async-mqtt": "^1.0.1",
|
"async-mqtt": "^2.0.0",
|
||||||
"better-try-catch": "^0.6.2",
|
"better-try-catch": "^0.6.2",
|
||||||
"is-plain-object": "^2.0.4",
|
"is-plain-object": "^2.0.4",
|
||||||
"lodash.merge": "^4.6.1",
|
"lodash.merge": "^4.6.1",
|
||||||
|
@ -35,12 +35,12 @@
|
||||||
"lodash.xor": "^4.5.0"
|
"lodash.xor": "^4.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.2.0",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"codecov": "^3.0.0",
|
"codecov": "^3.1.0",
|
||||||
"esm": "^3.0.21",
|
"esm": "^3.0.84",
|
||||||
"istanbul": "^0.4.5",
|
"istanbul": "^0.4.5",
|
||||||
"mocha": "^4.0.1",
|
"mocha": "^5.2.0",
|
||||||
"nodemon": "^1.14.3"
|
"nodemon": "^1.18.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,27 +8,59 @@ import isPlainObject from 'is-plain-object'
|
||||||
|
|
||||||
let log = {}
|
let log = {}
|
||||||
|
|
||||||
export default class Client {
|
/**
|
||||||
|
* MQTT - Client - An mqtt client that supports UCI packets
|
||||||
|
* it extends the {@link https://github.com/mqttjs/async-mqtt| async version this mqtt client } albiet in a clunky way with a private extend method because it was not written as an extendable class
|
||||||
|
* @extends MQTT.js
|
||||||
|
*/
|
||||||
|
class MQTTClient {
|
||||||
|
/**
|
||||||
|
* constructor - Description
|
||||||
|
*
|
||||||
|
* @param {object} [opts={}] Description
|
||||||
|
*
|
||||||
|
*/
|
||||||
constructor(opts = {}) {
|
constructor(opts = {}) {
|
||||||
this.id = opts.id || opts.name || 'mqtt:' + new Date().getTime()
|
this.id = opts.id || opts.name || 'mqtt:' + new Date().getTime()
|
||||||
|
log = logger({
|
||||||
|
file: 'src/client.js',
|
||||||
|
class: 'Client',
|
||||||
|
name: 'mqtt',
|
||||||
|
id: this.id
|
||||||
|
})
|
||||||
this.url = opts.url || ''
|
this.url = opts.url || ''
|
||||||
// subscription topics can be string of commna delimited or array of strings see object see mqtt.js docs
|
// subscription topics can be string of commna delimited or array of strings see object see mqtt.js docs
|
||||||
this.topics = Array.isArray(opts.topics) ? opts.topics : (opts.topics ? opts.topics.split(',') : [this.id])
|
this.topics = Array.isArray(opts.topics)
|
||||||
|
? opts.topics
|
||||||
|
: opts.topics
|
||||||
|
? opts.topics.split(',')
|
||||||
|
: [this.id]
|
||||||
this.opts = opts.connect || {} // see options for new mqtt.Client
|
this.opts = opts.connect || {} // see options for new mqtt.Client
|
||||||
// self bindings
|
// self bindings
|
||||||
this.connect = this.connect.bind(this)
|
this.connect = this.connect.bind(this)
|
||||||
this.push = this.send
|
this.push = this.send
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* connect - Description
|
||||||
|
*
|
||||||
|
* @returns {type} Description
|
||||||
|
*/
|
||||||
async connect() {
|
async connect() {
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
let mqtt = connect(
|
||||||
let mqtt = connect(this.url,this.opts)
|
this.url,
|
||||||
|
this.opts
|
||||||
|
)
|
||||||
this._extend(mqtt, 'subscribe,unsubscribe') // merge mqtt client into class extend with given functions
|
this._extend(mqtt, 'subscribe,unsubscribe') // merge mqtt client into class extend with given functions
|
||||||
|
console.log('publish,', this.publish)
|
||||||
let timeout = this.opts.connectTimeout || 5000
|
let timeout = this.opts.connectTimeout || 5000
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
reject(`ending mqtt connection attempt, no broker at ${this._client.options.hostname}:${this._client.options.port}`)
|
reject(
|
||||||
|
`ending mqtt connection attempt, no broker at ${
|
||||||
|
this._client.options.hostname
|
||||||
|
}:${this._client.options.port}`
|
||||||
|
)
|
||||||
}, timeout)
|
}, timeout)
|
||||||
|
|
||||||
this.once('connect', () => {
|
this.once('connect', () => {
|
||||||
|
@ -46,10 +78,18 @@ export default class Client {
|
||||||
})
|
})
|
||||||
|
|
||||||
this.subscribe(this.topics)
|
this.subscribe(this.topics)
|
||||||
log.info({options:this._client.options},`mqtt client connected to broker at ${this._client.options.hostname}:${this._client.options.port}`)
|
log.info(
|
||||||
resolve(`mqtt client connected to broker at ${this._client.options.hostname}:${this._client.options.port}`)
|
{ options: this._client.options },
|
||||||
|
`mqtt client connected to broker at ${
|
||||||
|
this._client.options.hostname
|
||||||
|
}:${this._client.options.port}`
|
||||||
|
)
|
||||||
|
resolve(
|
||||||
|
`mqtt client connected to broker at ${
|
||||||
|
this._client.options.hostname
|
||||||
|
}:${this._client.options.port}`
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
}) //end promise
|
}) //end promise
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,17 +114,20 @@ export default class Client {
|
||||||
if (typeof topics !== 'string' && !Array.isArray(topics)) {
|
if (typeof topics !== 'string' && !Array.isArray(topics)) {
|
||||||
options = topics
|
options = topics
|
||||||
topics = this.topics
|
topics = this.topics
|
||||||
} else { if (typeof topics ==='string') topics=topics.split(',') }
|
} else {
|
||||||
|
if (typeof topics === 'string') topics = topics.split(',')
|
||||||
|
}
|
||||||
let payload = {}
|
let payload = {}
|
||||||
if (typeof packet !== 'string') {
|
if (typeof packet !== 'string') {
|
||||||
payload = this._serialize(packet)
|
payload = this._serialize(packet)
|
||||||
if (!payload) payload = this._serialize({ err: 'could not serialze packet'})
|
if (!payload)
|
||||||
|
payload = this._serialize({ err: 'could not serialze packet' })
|
||||||
topics = [packet.cmd] || topics // if payload has a cmd use that as topic
|
topics = [packet.cmd] || topics // if payload has a cmd use that as topic
|
||||||
}
|
} else payload = this._serialize({ data: packet })
|
||||||
else payload = this._serialize({ data:packet })
|
|
||||||
let pubs = []
|
let pubs = []
|
||||||
topics.forEach(async topic => {
|
topics.forEach(async topic => {
|
||||||
log.info(`sending ${payload} to topic ${topic} with options ${options}`)
|
log.info(`sending ${payload} to topic ${topic} with options ${options}`)
|
||||||
|
console.log('publish,', this.publish)
|
||||||
pubs.push(this.publish(topic, payload, options))
|
pubs.push(this.publish(topic, payload, options))
|
||||||
})
|
})
|
||||||
return await Promise.all(pubs)
|
return await Promise.all(pubs)
|
||||||
|
@ -104,15 +147,18 @@ export default class Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
_listen() {
|
_listen() {
|
||||||
log.info(`listening for incoming packets from broker on topics ${this.topics}`)
|
log.info(
|
||||||
|
`listening for incoming packets from broker on topics ${this.topics}`
|
||||||
|
)
|
||||||
this.on('message', messageProcess.bind(this))
|
this.on('message', messageProcess.bind(this))
|
||||||
|
|
||||||
async function messageProcess(topic, payload) {
|
async function messageProcess(topic, payload) {
|
||||||
log.info('incoming message on topic', topic)
|
log.info('incoming message on topic', topic)
|
||||||
let packet = this._handlePayload(payload)
|
let packet = this._handlePayload(payload)
|
||||||
if(packet) packet.cmd = packet.cmd || topic // payload had no command that use topic as cmd
|
if (packet) packet.cmd = packet.cmd || topic
|
||||||
|
// payload had no command that use topic as cmd
|
||||||
else packet = { cmd: topic }
|
else packet = { cmd: topic }
|
||||||
let res = await this._packetProcess(packet,topic) || {}
|
let res = (await this._packetProcess(packet, topic)) || {}
|
||||||
this.send(res)
|
this.send(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,15 +175,22 @@ export default class Client {
|
||||||
// default packet process just a simple console logger. ignores any cmd: prop
|
// default packet process just a simple console logger. ignores any cmd: prop
|
||||||
_packetProcess(packet, topic) {
|
_packetProcess(packet, topic) {
|
||||||
console.log('=========================')
|
console.log('=========================')
|
||||||
console.log('default consumer processor\npacket from broker on topic:',topic)
|
console.log(
|
||||||
|
'default consumer processor\npacket from broker on topic:',
|
||||||
|
topic
|
||||||
|
)
|
||||||
console.dir(packet)
|
console.dir(packet)
|
||||||
console.log(packet.status)
|
console.log(packet.status)
|
||||||
console.log('========================')
|
console.log('========================')
|
||||||
}
|
}
|
||||||
|
|
||||||
async _log() {
|
async _log() {
|
||||||
|
log = logger({
|
||||||
log = logger({file:'src/client.js',class:'Client',name:'mqtt',id:this.id})
|
file: 'src/client.js',
|
||||||
|
class: 'Client',
|
||||||
|
name: 'mqtt',
|
||||||
|
id: this.id
|
||||||
|
})
|
||||||
|
|
||||||
this.on('close', () => {
|
this.on('close', () => {
|
||||||
log.info('connection to broker was closed')
|
log.info('connection to broker was closed')
|
||||||
|
@ -154,7 +207,6 @@ export default class Client {
|
||||||
this.on('packetreceive', packet => {
|
this.on('packetreceive', packet => {
|
||||||
log.info({ packet: packet }, 'incoming packet from mqtt broker')
|
log.info({ packet: packet }, 'incoming packet from mqtt broker')
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_extend(obj, funcs) {
|
_extend(obj, funcs) {
|
||||||
|
@ -169,5 +221,6 @@ export default class Client {
|
||||||
this[func] = temp[func]
|
this[func] = temp[func]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end mqtt client class
|
} // end mqtt client class
|
||||||
|
|
||||||
|
export default MQTTClient
|
||||||
|
|
Loading…
Reference in New Issue