node-red-contrib-motechat
Version:
ultranet topic and payload communication
267 lines (230 loc) • 7.46 kB
JavaScript
const mchat = require('motechat')
const os = require('os')
const { name, version } = require('../package.json')
const { EventEmitter } = require('events')
const debug = require('debug')('nr-motechat')
let config = require('./config.js')
let mcState = false
let mcEvent = new EventEmitter()
mcEvent.setMaxListeners(0)
let settings = {}
debug(`${name} version:${version}`)
class MCClient {
static isOpen(config) {
return new Promise(resolve => {
mchat.Open(config, result => resolve(result.ErrCode == 0))
})
}
static isReg(dSIM) {
return new Promise(resolve => {
mchat.Reg(dSIM, result => resolve(result))
})
}
static updateDevice(result, dSIM) {
if (dSIM.SToken != result.SToken || dSIM.EiToken != result.EiToken) {
dSIM.SToken = result.SToken
dSIM.EiToken = result.EiToken
}
}
static setEiInfo(result, settings) {
let { dSIM, mote } = settings
settings.DDN = result.DDN
mchat.Set({
SToken: dSIM.SToken,
EdgeInfo: {
DDN: result.DDN,
EiOwner: mote.EiOwner,
EiName: mote.EiName,
EiType: mote.EiType,
EiTag: mote.EiTag,
EiLoc: mote.EiLoc
}
}, reply => {
debug('EiInfo setting: ', reply)
if (!mcState) {
config.setDDN(settings.DDN)
config.setMote(settings.mote)
config.setDSIM(settings.dSIM)
config.setConfig(settings.config)
}
mcState = true
})
}
static async setup() {
settings = await config.init()
let isNullDDN = settings.DDN ? false : true
debug(settings)
debug("DC env: ", process.env.DC)
if (mcState) return
if (!await this.isOpen(settings.config)) {
debug('motechat not open')
return
}
let regData = await this.isReg(settings.dSIM)
debug('regData: ', regData)
if (regData.ErrCode != 0) {
debug('motechat reg fail')
return
}
this.updateDevice(regData.result, settings.dSIM)
//if (isNullDDN) {
if (!this.chkMoteInfo(regData.result, settings.mote)){
this.setEiInfo(regData.result, settings)
}
mchat.OnEvent('message', (ch, inctl, data, cb) => {
mcEvent.emit('message', { ch, inctl, data, mcBack: cb })
// cb({ ErrCode: 0, ErrMsg: 'OK' })
}, '')
mchat.OnEvent('state', state => mcEvent.emit('state', { state }), '')
}
static chkMoteInfo(reg, data){
if (reg.EiName != data.EiName || reg.EiType != data.EiType || reg.EiTag != data.EiTag || reg.EiLoc != data.EiLoc) return false
else return true
}
static getMessage({ Topic = '', DDN = '', Data, t1 = 6, t2 = 12 } = {}) {
return {
SToken: settings.dSIM.SToken,
Topic, DDN, Data,
SendTimeout: t1,
WaitReply: t2
}
}
static getRPC({ Topic = '', DDN = '', Func, Data, t1 = 6, t2 = 12 } = {}) {
return {
SToken: settings.dSIM.SToken,
DDN, Topic, Func, Data,
SendTimeout: t1,
WaitReply: t2
}
}
static setEi({ name, tag, location }) {
function isDiffEi({ name, tag, location }) {
const { EiName, EiTag, EiLoc } = settings.mote
if (name !== EiName) return true
if (tag !== EiTag) return true
if (location !== EiLoc) return true
return false
}
if (!isDiffEi({ name, tag, location })) {
return new Promise(resolve => resolve({}))
}
settings.mote.EiName = name
settings.mote.EiTag = tag
settings.mote.EiLoc = location
let { dSIM, mote, DDN } = settings
let info = {
SToken: dSIM.SToken,
EdgeInfo: {
DDN: DDN,
EiOwner: mote.EiOwner,
EiName: mote.EiName,
EiType: mote.EiType,
EiTag: mote.EiTag,
EiLoc: mote.EiLoc
}
}
return new Promise(resolve => {
mchat.Set(info, result => resolve(result))
})
}
}
const checkNormal = (reply) => {
if (!Array.isArray(reply)) {
const { ErrCode } = reply
return ErrCode == 0
}
const [result] = reply
if (result.State) {
const { ErrCode } = result.State
return ErrCode == 0
}
if (result.IN.State) {
const { ErrCode } = result.IN.State
return ErrCode == 0
}
}
MCClient.setup()
module.exports = {
/**
* @summary Send the message to the DDN, and return the promise of the reply
* @function send
* @public
*
* @param {string} topic the topic
* @param {string} DDN the DDN
* @param {*} payload the data that send to the DDN
*
* @returns {Promise<object>} return the send reply
*/
send(topic, DDN, timers = {}, payload) {
let { t1, t2 } = timers
return new Promise((resolve, reject) => {
const message = MCClient.getMessage({
Topic: topic, DDN, Data: payload,
t1, t2
})
mchat.Send(message, reply => {
const isNormal = checkNormal(reply)
if (!isNormal) reject(reply)
resolve(reply)
})
})
},
/**
* @summary Call the function of the DDN, and then return the reply
* @function call
* @public
*
* @param {stirng} topic the topic
* @param {string} DDN the DDN
* @param {string} func the function name
* @param {*} payload the data that send to the called topic
*
* @returns {Promise<object>} return the call reply
*/
call(topic, DDN, func, timers = {}, payload = {}) {
let { t1, t2 } = timers
return new Promise((resolve, reject) => {
let xrpc = MCClient.getRPC({
Topic: topic, DDN, Func: func, Data: payload,
t1, t2
})
mchat.Call(xrpc, reply => {
const isNormal = checkNormal(reply)
if (!isNormal) reject(reply)
resolve(reply)
})
})
},
/**
* @summary set the triggerID signal to the event emitter
* @function setEvent
* @public
*
* @param {string} event the event signal
* @param {function} callback the event callback fucntion
*/
setEvent(event, callback) {
if (event !== "message" && event !== "status") return
debug("setting event")
mcEvent.on(event, callback)
debug(mcEvent)
},
/**
* @summary remove the event listener from the event emitter
* @function removeEvent
* @public
*
* @param {string} event the event signal that removed from the event emitter
* @param {function} callback the event callback that removed
*/
removeEvent(event, callback) {
mcEvent.removeListener(event, callback)
},
getDDN() {
return settings.DDN
},
setEi: MCClient.setEi,
debug: debug
}