value-types.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. const {
  2. DATA_TYPE_OPTIONS,
  3. DEFAULT_DATA_TYPE,
  4. DEFAULT_TEXT_BYTE_LENGTH,
  5. GROUP_LAYOUT_STRUCT,
  6. MAX_TEXT_BYTE_LENGTH
  7. } = require('./constants.js')
  8. function getDataType(dataType) {
  9. return DATA_TYPE_OPTIONS.find((item) => item.key === dataType)
  10. || DATA_TYPE_OPTIONS.find((item) => item.key === DEFAULT_DATA_TYPE)
  11. || DATA_TYPE_OPTIONS[0]
  12. }
  13. function getDataTypeIndex(dataType) {
  14. return Math.max(0, DATA_TYPE_OPTIONS.findIndex((item) => item.key === getDataType(dataType).key))
  15. }
  16. function normalizeTextByteLength(value, fallback = DEFAULT_TEXT_BYTE_LENGTH) {
  17. const numberValue = Number(value)
  18. const rounded = Number.isFinite(numberValue) ? Math.round(numberValue) : fallback
  19. return Math.min(Math.max(rounded, 1), MAX_TEXT_BYTE_LENGTH)
  20. }
  21. function alignEvenByteLength(byteLength) {
  22. const length = Math.max(1, Math.round(Number(byteLength) || 1))
  23. return length % 2 === 0 ? length : length + 1
  24. }
  25. function getRegisterTextByteLength(register = {}) {
  26. return normalizeTextByteLength(register.textByteLength, DEFAULT_TEXT_BYTE_LENGTH)
  27. }
  28. function getRegisterRawByteLength(register = {}) {
  29. const candidates = [
  30. register.sourceByteLength,
  31. register.rawByteLength,
  32. register.textByteLength,
  33. register.byteLength
  34. ]
  35. for (const value of candidates) {
  36. const numberValue = Number(value)
  37. if (Number.isFinite(numberValue) && numberValue > 0) {
  38. return Math.max(1, Math.floor(numberValue))
  39. }
  40. }
  41. return 1
  42. }
  43. function isStructLayout(layout) {
  44. return layout === GROUP_LAYOUT_STRUCT
  45. }
  46. function isBitFieldRegister(register = {}) {
  47. return !!register.isBitField
  48. }
  49. function normalizeBitOffset(value) {
  50. const numberValue = Math.floor(Number(value) || 0)
  51. return Math.min(Math.max(numberValue, 0), 7)
  52. }
  53. function normalizeBitWidth(value) {
  54. const numberValue = Math.round(Number(value) || 1)
  55. return Math.min(Math.max(numberValue, 1), 32)
  56. }
  57. function getBitFieldByteLength(register = {}) {
  58. const bitOffset = normalizeBitOffset(register.bitOffset)
  59. const bitWidth = normalizeBitWidth(register.bitWidth)
  60. return Math.max(1, Math.ceil((bitOffset + bitWidth) / 8))
  61. }
  62. function getBitFieldMaxValue(register = {}) {
  63. const bitWidth = normalizeBitWidth(register.bitWidth)
  64. return bitWidth >= 32 ? 0xFFFFFFFF : Math.pow(2, bitWidth) - 1
  65. }
  66. function getRegisterByteLength(dataType, register = {}) {
  67. if (isBitFieldRegister(register)) return getBitFieldByteLength(register)
  68. const type = getDataType(dataType)
  69. if (type.kind === 'raw') return getRegisterRawByteLength(register)
  70. if (type.kind === 'text') {
  71. const byteLength = getRegisterTextByteLength(register)
  72. return isStructLayout(register.layout) ? byteLength : alignEvenByteLength(byteLength)
  73. }
  74. return type.byteLength || ((type.wordCount || 1) * 2)
  75. }
  76. function getRegisterWordCount(dataType, register = {}) {
  77. return Math.max(1, Math.ceil(getRegisterByteLength(dataType, register) / 2))
  78. }
  79. function getByteSpanWordCount(byteOffset, byteLength) {
  80. return Math.max(1, Math.ceil((Math.max(0, Number(byteOffset) || 0) + Math.max(1, Number(byteLength) || 1)) / 2))
  81. }
  82. function getRegisterWordCountAtOffset(dataType, byteOffset, register = {}) {
  83. const byteLength = getRegisterByteLength(dataType, register)
  84. return getByteSpanWordCount(byteOffset, byteLength)
  85. }
  86. function isTextRegister(dataType) {
  87. return getDataType(dataType).kind === 'text'
  88. }
  89. function getEncodeByteLimit(register) {
  90. return isTextRegister(register.dataType) ? getRegisterTextByteLength(register) : getRegisterByteLength(register.dataType, register)
  91. }
  92. function isByteRegister(dataType) {
  93. const key = getDataType(dataType).key
  94. return key === 'int8_t' || key === 'uint8_t'
  95. }
  96. function isBitRegisterType(registerType) {
  97. return registerType === 'coil' || registerType === 'discrete'
  98. }
  99. function isHexRegister(dataType) {
  100. return getDataType(dataType).key === 'hex'
  101. }
  102. function isRawRegister(dataType) {
  103. return getDataType(dataType).kind === 'raw'
  104. }
  105. function isNumericRegister(dataType) {
  106. return getDataType(dataType).kind === 'number'
  107. }
  108. function supportsRange(dataType) {
  109. return isNumericRegister(dataType) || isHexRegister(dataType)
  110. }
  111. function supportsUnit(dataType) {
  112. return isNumericRegister(dataType)
  113. }
  114. function getRegisterValueTypeLabel(dataType) {
  115. return getDataType(dataType).label
  116. }
  117. module.exports = {
  118. alignEvenByteLength,
  119. getBitFieldByteLength,
  120. getBitFieldMaxValue,
  121. getDataType,
  122. getDataTypeIndex,
  123. getEncodeByteLimit,
  124. getRegisterByteLength,
  125. getRegisterRawByteLength,
  126. getRegisterTextByteLength,
  127. getRegisterValueTypeLabel,
  128. getRegisterWordCount,
  129. getRegisterWordCountAtOffset,
  130. isBitFieldRegister,
  131. isBitRegisterType,
  132. isByteRegister,
  133. isHexRegister,
  134. isNumericRegister,
  135. isRawRegister,
  136. isTextRegister,
  137. normalizeBitOffset,
  138. normalizeBitWidth,
  139. normalizeTextByteLength,
  140. supportsRange,
  141. supportsUnit
  142. }