| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- import { getAssets } from '@/api/asset'
- import store from '@/store'
- import {
- State,
- AssetType
- } from '@/constant'
- import {
- createClient,
- decodePayload,
- sm4
- } from '@/utils/mqtt'
- const NAMESPACE = 'asset'
- export const Topic = {
- PRELOAD: 'preload',
- DEL: 'delete',
- PULL: 'pull',
- PLAY: 'play',
- STOP: 'stop',
- DOWNLOAD: 'download'
- }
- export const MediaType = {
- IMAGE: 1,
- VIDEO: 2,
- WEB: 3
- }
- export const MediaStatus = {
- ERROR: -1,
- WAITING: 0,
- LOADING: 1,
- LOADED: 2
- }
- export function takeOver (device, { onMessage, onCreated, onClose, debug }) {
- const { id, productId } = device
- debug('正在连接...')
- let force = false
- const prefix = `${productId}/${id}/${NAMESPACE}`
- let client = createClient({
- clientId: `${store.getters.account}_takeover_${id}`,
- reconnectPeriod: 0,
- will: {
- topic: `${prefix}/${Topic.STOP}`,
- payload: createPayload(createMessageId()),
- qos: 2,
- retain: false
- }
- })
- const messageMap = new Map()
- const onMqttMessage = (event, paylaod) => {
- const needMessageId = event !== Topic.DOWNLOAD
- const messageId = paylaod.messageId
- if (needMessageId && !messageMap.has(messageId)) {
- return
- }
- console.log('Take Over MQTT', event, paylaod)
- const requestPayload = needMessageId ? messageMap.get(messageId) : null
- needMessageId && messageMap.delete(messageId)
- switch (event) {
- case Topic.PRELOAD:
- debug('预加载资源接收成功')
- break
- case Topic.DEL:
- debug('删除资源成功')
- break
- case Topic.PULL:
- debug('资源拉取成功')
- break
- case Topic.PLAY:
- debug(`播放${requestPayload.asset.name}成功`)
- break
- case Topic.STOP:
- debug('结束')
- break
- case Topic.DOWNLOAD:
- if (!paylaod.complete) {
- return
- }
- debug('有资源状态更新')
- break
- default:
- return
- }
- onMessage(event, paylaod, requestPayload)
- }
- const mock = {
- do (event, messageId, payload) {
- this[event](messageId, payload)
- },
- preload (messageId, payload) {
- onMqttMessage(Topic.PRELOAD, { messageId })
- setTimeout(() => {
- payload.assets.forEach(asset => {
- if (asset.type !== MediaType.WEB) {
- onMqttMessage(Topic.DOWNLOAD, {
- messageId: createMessageId,
- asset,
- complete: true,
- success: [true, false][Math.random() * 2 | 0]
- })
- }
- })
- }, 2000)
- },
- delete (messageId) {
- onMqttMessage(Topic.DEL, { messageId, failures: [] })
- },
- pull (messageId) {
- getAssets({ pageNum: 1, pageSize: 10, type: [AssetType.IMAGE, AssetType.VIDEO][Math.random() * 2 | 0], status: State.RESOLVED }).then(({ data }) => {
- onMqttMessage(Topic.PULL, {
- messageId,
- assets: data.map(({ type, originalName, keyName, size, md5 }) => {
- return {
- type,
- name: originalName,
- keyName,
- size,
- md5,
- status: [MediaStatus.ERROR, MediaStatus.LOADING, MediaStatus.LOADED, MediaStatus.WAITING][Math.random() * 3 | 0]
- }
- })
- }, true, true)
- })
- },
- play (messageId) {
- onMqttMessage(Topic.PLAY, { messageId })
- },
- stop (messageId) {
- onMqttMessage(Topic.STOP, { messageId })
- }
- }
- const send = (event, paylaod) => {
- const messageId = createMessageId()
- messageMap.set(messageId, paylaod)
- if (__DEV__) {
- mock.do(event, messageId, paylaod)
- } else {
- client.publish(`${prefix}/${event}`, createPayload(messageId, paylaod))
- }
- }
- client.on('error', e => {
- console.log('Take Over MQTT error: ', e)
- })
- client.on('connect', () => {
- console.log('Take Over MQTT connected')
- debug('连接成功')
- client.subscribe(`${prefix}/+/#`)
- onCreated(createProxy(device, send, () => {
- force = true
- client.end(true)
- }, debug))
- })
- client.on('close', () => {
- console.log('Take Over MQTT closed')
- if (!force) {
- debug('连接发生异常,已断开')
- client.end(true)
- }
- })
- client.on('end', () => {
- console.log('Take Over MQTT end')
- client = null
- messageMap.clear()
- force && debug('连接已断开')
- onClose()
- })
- client.on('message', (topic, payload) => {
- const result = /^\d+\/\d+\/asset\/(.+)\/reply$/.exec(topic)
- if (result) {
- onMqttMessage(result[1], JSON.parse(decodePayload(null, payload)))
- }
- })
- return client
- }
- function createMessageId () {
- return `${store.getters.account}_${Math.random().toString(16).slice(2)}`
- }
- function createPayload (messageId, payload) {
- return sm4.encrypt(JSON.stringify({
- messageId,
- timestamp: `${Date.now()}`,
- ...payload
- }))
- }
- function createProxy (device, send, close, debug) {
- const { wide, high } = device
- return {
- close,
- send,
- preload (assets) {
- debug('预加载资源...')
- send(Topic.PRELOAD, { assets })
- },
- del (assets) {
- debug('删除资源...')
- send(Topic.DEL, { assets })
- },
- pull () {
- debug('资源拉取...')
- send(Topic.PULL)
- },
- play (asset, rect) {
- debug(`播放${asset.name}...`)
- send(Topic.PLAY, {
- asset,
- top: 0,
- left: 0,
- width: wide,
- height: high,
- ...rect
- })
- },
- stop () {
- debug('结束播放...')
- send(Topic.STOP)
- }
- }
- }
|