index.ts 5.4 KB
import { isObject } from '@wry-smile/utils-is'
import { toRaw, unref } from 'vue'
import { EntityType } from '../enum'
import { SubscriptionUpdate, TelemetrySubscriber, TelemetryWebsockerService } from '../telemetry'
import type { SubscriptionUpdateMsg, WebsocketDataMsg } from '../type/message'
import { MessageHandler } from './messageHandler'
import { EventHandler } from './eventHandler'
import type { DrawApp } from '@/fitCore/types'
import { NodeUtils } from '@/hooks/business/useNodeUtils'
import type { NodeDataActJsonType, NodeDataDataSourceJsonType, NodeDataEventJsonType, NodeDataType } from '@/api/node/model'
import type { EventTypeEnum } from '@/enums/datasource'
import { ActTypeEnum, DataSourceTypeEnum } from '@/enums/datasource'
import { fetchComponentDataSubscribers } from '@/core/Library'
import { useContentDataStoreWithOut } from '@/store/modules/contentData'

export type NodeDataActJsonItemType = NodeDataActJsonType[keyof NodeDataActJsonType]
export type NodeDataEventJsonItemType = NodeDataEventJsonType[keyof NodeDataEventJsonType]

export interface CommandSource {
  node: string
  dataType: DataSourceTypeEnum
  type?: EventTypeEnum | ActTypeEnum
  data: NodeDataDataSourceJsonType | NodeDataActJsonItemType | NodeDataEventJsonItemType
}

export class LightboxModeWebsocketService extends TelemetryWebsockerService {
  dataSource: NodeDataType[]

  nodeUtils: NodeUtils

  messageHandler: MessageHandler

  eventHandler: EventHandler

  constructor(public App: DrawApp) {
    super()
    this.nodeUtils = new NodeUtils(App)
    this.dataSource = []
    this.messageHandler = new MessageHandler(this)
    this.eventHandler = new EventHandler(this)
  }

  init() {
    this.openSocket()
    this.onSelectPageChange()
  }

  getAllDataSubscribers() {
    const subscribers = this.dataSource.map(item => this.getNodeDataSubscribers(item)).flat(Infinity) as TelemetrySubscriber[]
    subscribers.forEach(subscribe => subscribe.subscribe())
  }

  /**
   * @description 根据节点绑定数据创建订阅者
   * @param nodeData
   * @returns
   */
  getNodeDataSubscribers(nodeData: NodeDataType) {
    const { dataSourceJson, actJson, configurationNodeId } = nodeData
    const cell = this.nodeUtils.getCellById(configurationNodeId)
    if (!cell) return []
    const componentKey = this.nodeUtils.getNodeComponentKey(cell)
    const categoryKey = this.nodeUtils.getNodeCategory(cell)

    // 自定义数据节点订阅者
    if (componentKey && categoryKey) {
      const getDataSubscribersMethod = fetchComponentDataSubscribers({ key: componentKey, category: categoryKey })
      if (getDataSubscribersMethod)
        return getDataSubscribersMethod(this, nodeData)
    }

    const subscribers: TelemetrySubscriber[] = []
    // 有效的数据动效keys
    const effectActKeys = Object.keys(ActTypeEnum)
    for (const key of Object.keys(actJson || {})) {
      if (actJson[key as ActTypeEnum] && effectActKeys.includes(key)) {
        const { deviceId, attr } = actJson[key as ActTypeEnum]
        // 无entityId及属性时不订阅
        if (deviceId && attr) {
          const subscribe = TelemetrySubscriber.createTimeseriesSubscription(this, { id: deviceId, entityType: EntityType.DEVICE }, attr, this.getCommandSource(configurationNodeId, DataSourceTypeEnum.ACT, actJson[key as ActTypeEnum], key as ActTypeEnum))
          subscribers.push(subscribe)
        }
      }
    }

    const { deviceId, attr } = dataSourceJson || {}

    if (deviceId && attr) {
      const subscribe = TelemetrySubscriber.createTimeseriesSubscription(this, { id: deviceId, entityType: EntityType.DEVICE }, attr, this.getCommandSource(configurationNodeId, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
      subscribers.push(subscribe)
    }

    return subscribers
  }

  getCommandSource(node: string, dataType: DataSourceTypeEnum, data: NodeDataDataSourceJsonType | NodeDataActJsonItemType | NodeDataEventJsonItemType, type?: EventTypeEnum | ActTypeEnum): CommandSource {
    return {
      node, dataType, type, data,
    }
  }

  processOnMessage(message: WebsocketDataMsg): void {
    if ((message as SubscriptionUpdateMsg).subscriptionId) {
      const subscriber = this.subscribersMap.get((message as SubscriptionUpdateMsg).subscriptionId)
      if (subscriber) {
        subscriber.onData(new SubscriptionUpdate(message as SubscriptionUpdateMsg))
        this.messageHandler.distribute(message as SubscriptionUpdateMsg)
      }
    }
  }

  unsubscribeCurrentPageData() {
    const subscribers = Array.from(this.subscribersMap.values())
    subscribers.forEach(subscriber => this.unsubscribe(subscriber))
  }

  getSelectPageNodeData() {
    const contentDataStore = useContentDataStoreWithOut()
    const contentId = this.App.currentPage.getId()
    this.dataSource = toRaw(unref(contentDataStore.contentData)).filter(item => item.contentId === contentId)
  }

  onSelectPageChange() {
    this.unsubscribeCurrentPageData()
    this.getSelectPageNodeData()
    this.getAllDataSubscribers()
  }

  checkDataSourceNeedSubscribe(dataSource?: NodeDataDataSourceJsonType): dataSource is NodeDataDataSourceJsonType {
    return !!(dataSource && isObject(dataSource) && dataSource.deviceId && dataSource.attr)
  }

  checkActNeedSubscribe(actJson?: NodeDataActJsonType): actJson is NodeDataActJsonType {
    return !!(actJson && isObject(actJson) && Object.keys(actJson).length)
  }

  checkEventNeedSubscribe(_eventJson?: NodeDataEventJsonType): _eventJson is NodeDataEventJsonType {
    return true
  }
}