screenshot.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import { Message } from 'element-ui'
  2. import {
  3. listen,
  4. unlisten,
  5. publish,
  6. subscribe,
  7. unsubscribe
  8. } from '@/utils/mqtt'
  9. const cache = new Map()
  10. let listening = false
  11. export function watch ({ productId, id }, cb, expired) {
  12. if (!listening) {
  13. listen(onMessage)
  14. listening = true
  15. }
  16. let inst = cache.get(id)
  17. if (!inst || !inst.cb) {
  18. subscribe(`${productId}/${id}/screenshot/reply`)
  19. console.log('screenshot subscribe', id, '-> success')
  20. }
  21. if (inst) {
  22. inst.cb = cb
  23. } else {
  24. cache.set(id, inst = createInst(productId, id, cb))
  25. }
  26. if (retry(inst, expired)) {
  27. screenshot(id, true)
  28. } else {
  29. cb(inst)
  30. }
  31. }
  32. export function check (deviceId, expired) {
  33. const inst = cache.get(deviceId)
  34. if (retry(inst, expired)) {
  35. screenshot(deviceId, true)
  36. }
  37. }
  38. function retry (inst, expired = 30000) {
  39. if (!inst) {
  40. return false
  41. }
  42. if (inst.waiting && inst.timestamp + 10000 >= Date.now()) {
  43. return false
  44. }
  45. if (inst.base64 && inst.timestamp + expired >= Date.now()) {
  46. return false
  47. }
  48. return true
  49. }
  50. export function unwatch (deviceId) {
  51. const inst = cache.get(deviceId)
  52. if (inst) {
  53. inst.cb = null
  54. const { productId, deviceId } = inst
  55. unsubscribe(`${productId}/${deviceId}/screenshot/reply`)
  56. console.log('screenshot unsubscribe', deviceId, '-> success')
  57. }
  58. }
  59. export function screenshot (deviceId, silence) {
  60. const inst = cache.get(deviceId)
  61. if (inst && !inst.waiting) {
  62. inst.waiting = true
  63. inst.timestamp = Date.now()
  64. inst.base64 = null
  65. publish(`${inst.productId}/${inst.deviceId}/screenshot/ask`, JSON.stringify({ timestamp: `${inst.timestamp}` })).then(
  66. () => {
  67. startTimer(inst)
  68. },
  69. () => {
  70. inst.waiting = false
  71. if (!silence) {
  72. Message({
  73. type: 'warning',
  74. message: '正在连接,请稍后重试'
  75. })
  76. }
  77. }
  78. ).finally(() => {
  79. emit(inst)
  80. })
  81. }
  82. }
  83. function createInst (productId, deviceId, cb) {
  84. return {
  85. productId,
  86. deviceId,
  87. cb,
  88. timer: -1,
  89. waiting: false,
  90. timestamp: Date.now(),
  91. base64: null
  92. }
  93. }
  94. function startTimer (inst) {
  95. clearTimeout(inst.timer)
  96. inst.timer = setTimeout(() => {
  97. inst.waiting = false
  98. emit(inst)
  99. }, 20000)
  100. }
  101. function emit (inst) {
  102. inst.cb && inst.cb(inst)
  103. }
  104. function onMessage (topic, message) {
  105. const result = /^(\d+)\/(\d+)\/screenshot\/reply$/.exec(topic)
  106. if (result) {
  107. const inst = cache.get(result[2])
  108. if (inst) {
  109. clearTimeout(inst.timer)
  110. inst.waiting = false
  111. inst.timestamp = Date.now()
  112. inst.base64 = `data:image/jpeg;base64,${message.replace(/\s/g, '')}`
  113. emit(inst)
  114. }
  115. }
  116. }
  117. export function clear () {
  118. if (listening) {
  119. cache.forEach(({ deviceId }) => {
  120. unwatch(deviceId)
  121. })
  122. unlisten(onMessage)
  123. listening = false
  124. }
  125. cache.clear()
  126. }