const { migrateLegacyGroupsToProtocol, persistGroups, readStoredGroups } = require('./persistence.js') const { getWxApi } = require('../../utils/platform-utils.js') const { normalizeStorageCodeInfoCard, DATA_TYPE_OPTIONS, REGISTER_TYPE_OPTIONS, normalizeGroup } = require('../../domain/parameter-groups/model.js') const STORAGE_CODE_INFO_KEY = 'parameter-groups-code-info' const PROTOCOL_MODE = { MODBUS_RTU: 'modbus-rtu', STORAGE_ACCESS: 'storage-access' } let initialized = false const subscribers = [] const DEFAULT_STORAGE_CODE_INFO_CARD = normalizeStorageCodeInfoCard(null) let state = { activeProtocolMode: PROTOCOL_MODE.STORAGE_ACCESS, parameterDataTypeOptions: DATA_TYPE_OPTIONS, parameterGroupsByProtocol: { [PROTOCOL_MODE.MODBUS_RTU]: [], [PROTOCOL_MODE.STORAGE_ACCESS]: [] }, parameterRegisterTypeOptions: REGISTER_TYPE_OPTIONS, storageCodeInfoCard: DEFAULT_STORAGE_CODE_INFO_CARD } function normalizeProtocolMode(protocolMode) { return protocolMode === PROTOCOL_MODE.MODBUS_RTU ? PROTOCOL_MODE.MODBUS_RTU : PROTOCOL_MODE.STORAGE_ACCESS } function getActiveProtocolMode() { return normalizeProtocolMode(state.activeProtocolMode) } function getActiveGroups() { return state.parameterGroupsByProtocol[getActiveProtocolMode()] || [] } function getGroupsForProtocol(protocolMode = getActiveProtocolMode()) { return state.parameterGroupsByProtocol[normalizeProtocolMode(protocolMode)] || [] } function getCodeInfoContext(card = state.storageCodeInfoCard) { return card && card.codeInfoContext ? card.codeInfoContext : {} } function normalizeGroupsForProtocol(parameterGroups = [], protocolMode = getActiveProtocolMode(), options = {}) { const codeInfoContext = protocolMode === PROTOCOL_MODE.STORAGE_ACCESS ? getCodeInfoContext(options.storageCodeInfoCard) : {} return Array.isArray(parameterGroups) ? parameterGroups.map((group) => normalizeGroup({ ...group, codeInfoContext })) : [] } function notify() { const nextState = getState() subscribers.slice().forEach((subscriber) => { subscriber(nextState) }) } function persistActiveGroups(options = {}) { if (options.persist === false) return persistGroups(getActiveGroups(), getActiveProtocolMode()) } function setState(changedData, options = {}) { state = { ...state, ...changedData } persistActiveGroups(options) notify() } function setGroups(parameterGroups, options = {}) { const protocolMode = normalizeProtocolMode(options.protocolMode || getActiveProtocolMode()) const normalizedGroups = normalizeGroupsForProtocol(parameterGroups, protocolMode) const parameterGroupsByProtocol = { ...state.parameterGroupsByProtocol, [protocolMode]: normalizedGroups } state = { ...state, parameterGroupsByProtocol } if (options.persist !== false) persistGroups(normalizedGroups, protocolMode) notify() } function persistStorageCodeInfoCard(card) { const wxApi = getWxApi() if (typeof wxApi.setStorageSync !== 'function') return try { wxApi.setStorageSync(STORAGE_CODE_INFO_KEY, JSON.stringify(card || null)) } catch (error) {} } function readStorageCodeInfoCard() { const wxApi = getWxApi() if (typeof wxApi.getStorageSync !== 'function') return DEFAULT_STORAGE_CODE_INFO_CARD try { const jsonText = wxApi.getStorageSync(STORAGE_CODE_INFO_KEY) return jsonText ? normalizeStorageCodeInfoCard(JSON.parse(jsonText)) : DEFAULT_STORAGE_CODE_INFO_CARD } catch (error) { return DEFAULT_STORAGE_CODE_INFO_CARD } } function setStorageCodeInfo(codeInfo, options = {}) { const card = normalizeStorageCodeInfoCard(codeInfo) const storageGroups = state.parameterGroupsByProtocol[PROTOCOL_MODE.STORAGE_ACCESS] || [] const normalizedStorageGroups = normalizeGroupsForProtocol(storageGroups, PROTOCOL_MODE.STORAGE_ACCESS, { storageCodeInfoCard: card }) state = { ...state, parameterGroupsByProtocol: { ...state.parameterGroupsByProtocol, [PROTOCOL_MODE.STORAGE_ACCESS]: normalizedStorageGroups }, storageCodeInfoCard: card } if (options.persist !== false) persistGroups(normalizedStorageGroups, PROTOCOL_MODE.STORAGE_ACCESS) if (options.persist !== false) persistStorageCodeInfoCard(card) notify() } function updateGroups(mapper, options = {}) { if (typeof mapper !== 'function') return const protocolMode = normalizeProtocolMode(options.protocolMode || getActiveProtocolMode()) setGroups(getGroupsForProtocol(protocolMode).map((group, index) => mapper(group, index)), { ...options, protocolMode }) } function switchProtocolMode(protocolMode, options = {}) { const normalizedProtocolMode = normalizeProtocolMode(protocolMode) init(normalizedProtocolMode) if (state.activeProtocolMode === normalizedProtocolMode) { if (options.notify !== false) notify() return } state = { ...state, activeProtocolMode: normalizedProtocolMode } if (options.notify !== false) notify() } function init(protocolMode = state.activeProtocolMode) { const normalizedProtocolMode = normalizeProtocolMode(protocolMode) if (initialized) return const storageCodeInfoCard = readStorageCodeInfoCard() migrateLegacyGroupsToProtocol(normalizedProtocolMode) const protocolOrder = normalizedProtocolMode === PROTOCOL_MODE.MODBUS_RTU ? [PROTOCOL_MODE.MODBUS_RTU, PROTOCOL_MODE.STORAGE_ACCESS] : [PROTOCOL_MODE.STORAGE_ACCESS, PROTOCOL_MODE.MODBUS_RTU] const parameterGroupsByProtocol = { [PROTOCOL_MODE.MODBUS_RTU]: [], [PROTOCOL_MODE.STORAGE_ACCESS]: [] } protocolOrder.forEach((targetProtocolMode) => { parameterGroupsByProtocol[targetProtocolMode] = normalizeGroupsForProtocol( readStoredGroups(targetProtocolMode), targetProtocolMode ) }) state = { ...state, activeProtocolMode: normalizedProtocolMode, storageCodeInfoCard, parameterGroupsByProtocol } initialized = true } function getState() { return { activeProtocolMode: getActiveProtocolMode(), parameterDataTypeOptions: DATA_TYPE_OPTIONS, parameterGroups: getActiveGroups(), parameterRegisterTypeOptions: REGISTER_TYPE_OPTIONS, storageCodeInfoCard: state.storageCodeInfoCard } } function getGroups() { return getActiveGroups() } function findGroup(groupId, protocolMode = getActiveProtocolMode()) { return getGroupsForProtocol(protocolMode).find((group) => group.id === groupId) } function subscribe(subscriber) { if (typeof subscriber !== 'function') return () => {} init() subscribers.push(subscriber) subscriber(getState()) return () => { const index = subscribers.indexOf(subscriber) if (index >= 0) subscribers.splice(index, 1) } } module.exports = { DATA_TYPE_OPTIONS, REGISTER_TYPE_OPTIONS, findGroup, getGroups, getState, init, setGroups, setState, setStorageCodeInfo, switchProtocolMode, subscribe, updateGroups }