value-types.js 5.2 KB

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