persistence.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. const {
  2. formatExportStamp,
  3. isCancelError,
  4. loadSelectedFile,
  5. saveTextFileToChat
  6. } = require('../../repositories/file.js')
  7. const {
  8. getWxApi,
  9. pickFields
  10. } = require('../../utils/base-utils.js')
  11. const {
  12. cloneImportedGroup,
  13. getRegisterJsonValue
  14. } = require('../../domain/parameter-groups/model.js')
  15. const {
  16. SOURCE_GROUP_FIELDS,
  17. SOURCE_REGISTER_FIELDS,
  18. STRUCT_REGISTER_FIELDS
  19. } = require('../../domain/parameter-groups/constants.js')
  20. const {
  21. PROTOCOL_MODE,
  22. isModbusProtocolMode
  23. } = require('../../domain/protocol-mode.js')
  24. const STORAGE_KEY = 'parameter-groups-json'
  25. const JSON_DOCUMENT_TYPE = 'parameter-groups'
  26. const JSON_SCHEMA_VERSION = 2
  27. function toPersistedGroups(groups = []) {
  28. return groups.map((group) => ({
  29. layout: group.layout,
  30. name: group.name,
  31. ...(group.pollEnabled === false ? { pollEnabled: false } : {}),
  32. registerType: group.registerType,
  33. startAddress: group.startAddress,
  34. quantity: group.quantity,
  35. registers: group.registers.map((register) => ({
  36. dataType: register.dataType,
  37. defaultValue: register.defaultValue,
  38. conversionFormula: register.conversionFormula,
  39. isStructField: register.isStructField,
  40. name: register.name,
  41. maxValue: register.maxValue,
  42. minValue: register.minValue,
  43. textByteLength: register.textByteLength,
  44. remark: register.remark,
  45. unit: register.unit,
  46. value: getRegisterJsonValue(register),
  47. ...pickFields(register, STRUCT_REGISTER_FIELDS),
  48. ...pickFields(register, SOURCE_REGISTER_FIELDS)
  49. })),
  50. ...pickFields(group, SOURCE_GROUP_FIELDS)
  51. }))
  52. }
  53. function toJsonData(groups = [], options = {}) {
  54. const jsonData = {
  55. groups: toPersistedGroups(groups),
  56. type: JSON_DOCUMENT_TYPE,
  57. version: JSON_SCHEMA_VERSION
  58. }
  59. if (options.includeExportedAt) {
  60. jsonData.exportedAt = new Date().toISOString()
  61. }
  62. return jsonData
  63. }
  64. function toJsonText(groups = [], options = {}) {
  65. return JSON.stringify(toJsonData(groups, options), null, 2)
  66. }
  67. function normalizeProtocolMode(protocolMode) {
  68. return isModbusProtocolMode(protocolMode)
  69. ? PROTOCOL_MODE.MODBUS_RTU
  70. : PROTOCOL_MODE.STORAGE_ACCESS
  71. }
  72. function getProtocolStorageKey(protocolMode) {
  73. return `${STORAGE_KEY}:${normalizeProtocolMode(protocolMode)}`
  74. }
  75. function parseJsonGroups(jsonText) {
  76. const parsed = typeof jsonText === 'string' ? JSON.parse(jsonText) : jsonText
  77. const groups = Array.isArray(parsed)
  78. ? parsed
  79. : (Array.isArray(parsed && parsed.groups) ? parsed.groups : parsed && parsed.parameterGroups)
  80. if (parsed && parsed.type && parsed.type !== JSON_DOCUMENT_TYPE) {
  81. throw new Error('JSON 文件不是参数组配置')
  82. }
  83. if (parsed && parsed.version && parsed.version !== JSON_SCHEMA_VERSION) {
  84. throw new Error('JSON 版本不兼容')
  85. }
  86. if (!Array.isArray(groups)) {
  87. throw new Error('JSON 中没有找到寄存器组数组')
  88. }
  89. return groups
  90. }
  91. function readStoredGroups(protocolMode = PROTOCOL_MODE.STORAGE_ACCESS) {
  92. const wxApi = getWxApi()
  93. if (typeof wxApi.getStorageSync !== 'function') return []
  94. try {
  95. const storageKey = getProtocolStorageKey(protocolMode)
  96. const jsonText = wxApi.getStorageSync(storageKey)
  97. if (jsonText) return parseJsonGroups(jsonText).map(cloneImportedGroup)
  98. } catch (error) {
  99. return []
  100. }
  101. return []
  102. }
  103. function persistGroups(groups = [], protocolMode = PROTOCOL_MODE.STORAGE_ACCESS) {
  104. const wxApi = getWxApi()
  105. if (typeof wxApi.setStorageSync !== 'function') return
  106. try {
  107. wxApi.setStorageSync(getProtocolStorageKey(protocolMode), toJsonText(groups))
  108. } catch (error) {}
  109. }
  110. function getShareFileName() {
  111. return `parameter-groups-${formatExportStamp()}.json`
  112. }
  113. async function loadGroupsFromMessageFile() {
  114. const file = await loadSelectedFile('auto', {
  115. encoding: 'utf8',
  116. extensionMessage: '请选择 .json 寄存器配置文件',
  117. extensions: ['json'],
  118. fallbackName: 'parameter-groups.json'
  119. })
  120. return parseJsonGroups(file.text).map(cloneImportedGroup)
  121. }
  122. async function saveGroupsToChat(groups = []) {
  123. if (!groups.length) {
  124. throw new Error('没有可保存的寄存器组')
  125. }
  126. const jsonText = toJsonText(groups, {
  127. includeExportedAt: true
  128. })
  129. const result = await saveTextFileToChat(getShareFileName(), jsonText)
  130. return {
  131. count: groups.length,
  132. ...result
  133. }
  134. }
  135. module.exports = {
  136. JSON_DOCUMENT_TYPE,
  137. JSON_SCHEMA_VERSION,
  138. STORAGE_KEY,
  139. isCancelError,
  140. loadGroupsFromMessageFile,
  141. parseJsonGroups,
  142. persistGroups,
  143. readStoredGroups,
  144. saveGroupsToChat,
  145. toJsonData,
  146. toJsonText
  147. }