| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- import mqtt from 'mqtt'
- import SM4 from '@/utils/sm4'
- const willTopic = 'web/offline'
- const sm4 = new SM4({
- // encrypt/decypt main key; cannot be omitted
- // key: 'fELIMxLsdoSgRZnX',
- key: [102, 69, 76, 73, 77, 120, 76, 115, 100, 111, 83, 103, 82, 90, 110, 88],
- // optional; can be 'cbc' or 'ecb'
- // default is ecb
- mode: 'ecb',
- // optional; can be 'uint8array' or 'text'
- // default is uint8array
- outType: 'uint8array'
- })
- const host = process.env.VUE_APP_MQTT_URL || `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/mqtt`
- const username = process.env.VUE_APP_MQTT_USER_NAME
- const password = process.env.VUE_APP_MQTT_PASSWORD
- const options = {
- username,
- password,
- clientId: 'mqttjs_' + Math.random().toString(16).slice(2),
- keepalive: 60,
- protocolId: 'MQTT',
- protocolVersion: 4,
- clean: true,
- reconnectPeriod: 1000,
- connectTimeout: 30 * 1000,
- will: {
- topic: willTopic,
- payload: 'Connection Closed abnormally..!',
- qos: 0,
- retain: false
- }
- }
- const whiteList = [
- {
- type: 'topic',
- val: /^\$SYS/
- }, {
- type: 'topic',
- eq: true,
- val: willTopic
- }, {
- type: 'topic',
- val: /^\d+\/\d+\/(status|screenshot)/
- }, {
- val: /messageId/
- }
- ]
- function isWhite (item, topic, message) {
- switch (item.type) {
- case 'topic':
- return item.eq ? topic === item.val : item.val.test(topic)
- default:
- return item.val.test(message)
- }
- }
- let mqttClient
- function changeState (state) {
- mqttClient && (mqttClient.state = state)
- }
- function start () {
- console.log('Connecting mqtt client...')
- const client = mqtt.connect(host, options)
- client.on('error', err => {
- console.log('MQTT connection error: ', err)
- client.end(true)
- mqttClient = null
- })
- client.on('connect', () => {
- console.log('MQTT connected')
- changeState('connect')
- })
- client.on('reconnect', () => {
- console.log('MQTT reconnecting...')
- changeState('reconnect')
- })
- client.on('close', () => {
- console.log('MQTT closed')
- changeState('close')
- })
- client.on('disconnect', () => {
- console.log('MQTT disconnect')
- changeState('disconnect')
- })
- client.on('offline', () => {
- console.log('MQTT offline')
- changeState('offline')
- })
- client.on('end', () => {
- console.log('MQTT end')
- mqttClient = null
- })
- client.on('message', (topic, message) => {
- console.log('MQTT topic', topic)
- try {
- const s = utf8ArrayBufferToString(message)
- if (s) {
- if (whiteList.some(item => isWhite(item, topic, s))) {
- console.log('white list')
- message = s
- } else {
- const decodeStr = sm4.decrypt(message)
- if (decodeStr) {
- console.log('sm4')
- message = decodeStr
- } else {
- console.log('unencrypted')
- message = s
- }
- }
- } else {
- console.log('null')
- message = s
- }
- } catch (e) {
- console.warn(e)
- message = utf8ArrayBufferToString(message)
- }
- console.log(message)
- cbs.forEach(cb => cb(topic, message))
- })
- return client
- }
- const decoder = new TextDecoder('utf-8')
- function utf8ArrayBufferToString (buffer) {
- return decoder.decode(buffer)
- }
- function inst () {
- if (!mqttClient) {
- mqttClient = {
- state: 'init',
- client: start()
- }
- }
- return mqttClient
- }
- export function close () {
- if (mqttClient) {
- mqttClient.client.end(true)
- mqttClient = null
- }
- }
- export function subscribe (topic, fn) {
- if (topic) {
- console.info(`MQTT subscribe ${topic}`)
- inst().client.subscribe(topic, e => {
- e && console.warn('MQTT subscribe', e)
- })
- }
- listen(fn)
- }
- export function unsubscribe (topic, fn) {
- if (topic && mqttClient) {
- console.info(`MQTT unsubscribe ${topic}`)
- mqttClient.client.unsubscribe(topic, e => {
- e && console.warn('MQTT unsubscribe', e)
- })
- }
- unlisten(fn)
- }
- const cbs = []
- export function listen (fn) {
- fn && cbs.push(fn)
- }
- export function unlisten (fn) {
- if (fn) {
- const index = cbs.findIndex(item => item === fn)
- if (~index) {
- cbs.splice(index, 1)
- }
- }
- }
- export function publish (topic, message, encode) {
- return new Promise((resolve, reject) => {
- const mqttInst = inst()
- if (mqttInst && mqttInst.state === 'connect') {
- mqttInst.client.publish(topic, message && encode ? sm4.encrypt(message) : message, err => {
- if (err) {
- console.warn(err)
- reject(err)
- } else {
- resolve()
- }
- })
- } else {
- reject('not connected')
- }
- })
- }
|