register-value-utils.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. const {
  2. toFiniteNumber
  3. } = require('./calculation-context')
  4. function toAddressKey(address) {
  5. if (typeof address === 'number' && Number.isFinite(address)) {
  6. return Math.round(address).toString(16).toUpperCase()
  7. }
  8. const text = String(address || '').trim().toUpperCase()
  9. if (!text) return ''
  10. const hexText = text.startsWith('0X') ? text.slice(2) : text
  11. if (/^[0-9A-F]+$/.test(hexText)) {
  12. return parseInt(hexText, 16).toString(16).toUpperCase()
  13. }
  14. const numberValue = Number(text)
  15. if (Number.isFinite(numberValue)) {
  16. return Math.round(numberValue).toString(16).toUpperCase()
  17. }
  18. return text
  19. }
  20. function wordsToFloat(highWord, lowWord) {
  21. const highValue = Number(highWord)
  22. const lowValue = Number(lowWord)
  23. if (!Number.isInteger(highValue) || !Number.isInteger(lowValue)) return null
  24. const buffer = new ArrayBuffer(4)
  25. const view = new DataView(buffer)
  26. view.setUint16(0, highValue & 0xFFFF, false)
  27. view.setUint16(2, lowValue & 0xFFFF, false)
  28. return view.getFloat32(0, false)
  29. }
  30. function floatToWords(value) {
  31. const numberValue = toFiniteNumber(value, NaN)
  32. if (!Number.isFinite(numberValue)) return null
  33. const buffer = new ArrayBuffer(4)
  34. const view = new DataView(buffer)
  35. view.setFloat32(0, numberValue, false)
  36. return [view.getUint16(0, false), view.getUint16(2, false)]
  37. }
  38. function toRegisterWord(value) {
  39. const numberValue = toFiniteNumber(value, NaN)
  40. if (!Number.isFinite(numberValue)) return null
  41. const word = Math.round(numberValue)
  42. return word >= 0 && word <= 0xFFFF ? word : null
  43. }
  44. function addCoilReadValues(readValues, startAddress, quantity, response) {
  45. if (!readValues || !readValues.coils || !response || !Array.isArray(response.dataBytes)) return
  46. for (let offset = 0; offset < quantity; offset += 1) {
  47. const byte = response.dataBytes[Math.floor(offset / 8)] || 0
  48. const bit = (byte >> (offset % 8)) & 0x01
  49. readValues.coils[toAddressKey(startAddress + offset)] = bit
  50. }
  51. }
  52. function addWordReadValues(readValues, startAddress, response) {
  53. if (!readValues || !readValues.words || !response || !Array.isArray(response.words)) return
  54. response.words.forEach((word, index) => {
  55. readValues.words[toAddressKey(startAddress + index)] = Number(word) & 0xFFFF
  56. })
  57. }
  58. function getRegisterWordCache(startAddress, words) {
  59. if (!Array.isArray(words)) return {}
  60. return words.reduce((result, word, index) => {
  61. result[startAddress + index] = Number(word) & 0xFFFF
  62. return result
  63. }, {})
  64. }
  65. module.exports = {
  66. addCoilReadValues,
  67. addWordReadValues,
  68. floatToWords,
  69. getRegisterWordCache,
  70. toAddressKey,
  71. toRegisterWord,
  72. wordsToFloat
  73. }