poller.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. const genericModbusService = require('./service.js')
  2. const POLL_TIMER_ID = '__genericPoll'
  3. const MEMORY_AREA_ORDER = {
  4. DATA: 0,
  5. IDATA: 1,
  6. XDATA: 2,
  7. CODE: 3,
  8. BIT: 4
  9. }
  10. function getMemoryAreaOrder(group = {}) {
  11. const key = String(group.sourceMemoryArea || '').trim().toUpperCase()
  12. return Object.prototype.hasOwnProperty.call(MEMORY_AREA_ORDER, key) ? MEMORY_AREA_ORDER[key] : 99
  13. }
  14. function getGroupAddress(group = {}) {
  15. const sourceAddress = Number(group.sourceAddress)
  16. if (Number.isFinite(sourceAddress)) return Math.max(0, Math.floor(sourceAddress))
  17. const startAddress = Number(group.startAddress)
  18. return Number.isFinite(startAddress) ? Math.max(0, Math.floor(startAddress)) : 0
  19. }
  20. function shouldPoll(data) {
  21. return !!data
  22. && (data.activeParamView === 'genericModbus' || data.activeParamView === 'genericModbusGroup')
  23. && !!data.connectedDevice
  24. && !!data.genericModbusAutoPollEnabled
  25. }
  26. function getPollableGroups(data) {
  27. return (data.genericModbusGroups || [])
  28. .filter((group) => {
  29. if (!group || group.addressOverflow) return false
  30. if ((group.registers || []).some((register) => register && register.isDirty)) return false
  31. if (data.isPrivateProtocol) return !!group.sourceMemoryArea
  32. return group.isReadOnly
  33. })
  34. .sort((left, right) => (
  35. getMemoryAreaOrder(left) - getMemoryAreaOrder(right)
  36. || getGroupAddress(left) - getGroupAddress(right)
  37. || String(left.name || '').localeCompare(String(right.name || ''))
  38. ))
  39. }
  40. function createGenericModbusPoller(getData) {
  41. const timers = {}
  42. function clearTimer(timerId) {
  43. if (!timers[timerId]) return
  44. clearTimeout(timers[timerId])
  45. delete timers[timerId]
  46. }
  47. function clearAll() {
  48. Object.keys(timers).forEach(clearTimer)
  49. }
  50. function schedule(delay) {
  51. clearTimer(POLL_TIMER_ID)
  52. timers[POLL_TIMER_ID] = setTimeout(async () => {
  53. const data = getData()
  54. if (!shouldPoll(data)) {
  55. clearTimer(POLL_TIMER_ID)
  56. return
  57. }
  58. for (const group of getPollableGroups(data)) {
  59. const latestData = getData()
  60. if (!shouldPoll(latestData)) break
  61. await genericModbusService.readGroup(group.id, {
  62. maxPacketLength: latestData.genericModbusMaxPacketLength,
  63. showModal: false
  64. })
  65. }
  66. const latestData = getData()
  67. if (shouldPoll(latestData)) {
  68. schedule(latestData.genericModbusPollInterval || 100)
  69. }
  70. }, delay)
  71. }
  72. function scheduleVisible() {
  73. const data = getData()
  74. if (!shouldPoll(data)) {
  75. clearAll()
  76. return
  77. }
  78. schedule(data.genericModbusPollInterval || 100)
  79. }
  80. return {
  81. clearAll,
  82. clearTimer,
  83. schedule,
  84. scheduleVisible
  85. }
  86. }
  87. module.exports = {
  88. createGenericModbusPoller
  89. }