useCommandDelivery.ts 5.53 KB
import { ref } from 'vue';
import { commandIssuanceApi, getDeviceDetail } from '/@/api/device/deviceManager';
import { RpcCommandType } from '/@/api/device/model/deviceConfigModel';
import { DeviceProfileModel } from '/@/api/device/model/deviceModel';
import { EdgeDeviceItemType } from '/@/api/edgeManage/model/edgeInstance';
import { Tsl } from '/@/api/device/model/modelOfMatterModel';
import { getModelTsl } from '/@/api/device/modelOfMatter';
import {
  CommandDeliveryWayEnum,
  CommandTypeEnum,
  RPCCommandMethodEnum,
  ServiceCallTypeEnum,
  TCPProtocolTypeEnum,
  TransportTypeEnum,
} from '/@/enums/deviceEnum';
import { FunctionTypeEnum } from '/@/enums/objectModelEnum';
import { isFunction, isNullOrUnDef } from '/@/utils/is';
import { getDeviceActiveTime } from '/@/api/alarm/position';
import { useMessage } from '/@/hooks/web/useMessage';
import { useCoverModbusCommand } from './useCoverModbusCommand';

interface SetupType {
  entityId: string;
  transportType: TransportTypeEnum;
  isTCPModbus: boolean;
  deviceCode: string | undefined;
  deviceDetail: EdgeDeviceItemType;
  objectModel: Tsl | undefined;
  identifier: string;
}

interface DoCommandDeliverParamsType {
  value: any;
  deviceDetail?: EdgeDeviceItemType;
  deviceId?: string;
  identifier?: string;
  objectModel?: Tsl;
  deviceProfileId?: string;
  deviceProfileDetail?: DeviceProfileModel;
  way?: CommandDeliveryWayEnum;
  cmdType?: CommandTypeEnum;
  transportType?: TransportTypeEnum;
  beforeFetch?: (
    rpcCommand: RpcCommandType,
    setup: SetupType
  ) =>
    | { rpcCommand: RpcCommandType; way?: CommandDeliveryWayEnum }
    | Promise<{ rpcCommand: RpcCommandType; way?: CommandDeliveryWayEnum }>;
}

export function useCommandDelivery() {
  const loading = ref(false);
  async function doSetup(params: DoCommandDeliverParamsType) {
    let { deviceDetail, identifier, deviceProfileId, objectModel, transportType } = params;
    const { deviceId } = params;

    const entityId = deviceId || deviceDetail?.id?.id;
    if (!entityId) {
      throw new Error('not found entityId');
    }

    identifier = identifier || objectModel?.identifier;

    if (!identifier) {
      throw new Error('not found identifier');
    }

    transportType = transportType || (deviceDetail?.transportType as TransportTypeEnum);

    if (
      !transportType ||
      (transportType === TransportTypeEnum.TCP && !deviceDetail) ||
      !deviceDetail?.deviceProfile
    ) {
      deviceDetail = (await getDeviceDetail(entityId)) as any as EdgeDeviceItemType;
      transportType = deviceDetail?.transportType as TransportTypeEnum;
    }

    const isTCPModbus =
      transportType === TransportTypeEnum.TCP &&
      deviceDetail?.deviceProfile?.profileData?.transportConfiguration?.protocol ===
        TCPProtocolTypeEnum.MODBUS_RTU;

    if (isTCPModbus && !objectModel?.extensionDesc) {
      // deviceProfileId = deviceDetail?.deviceProfileId || deviceProfileId || deviceProfileDetail?.id;
      deviceProfileId = deviceDetail?.deviceProfileId?.id;
      if (!deviceProfileId) {
        throw new Error('not found deviceProfile');
      }

      const objectModels = await getModelTsl({ deviceProfileId });
      objectModel = objectModels.find((item) => item.identifier === identifier);
    }

    const deviceCode = deviceDetail?.code;

    return {
      entityId,
      transportType,
      isTCPModbus,
      deviceCode,
      deviceDetail,
      objectModel,
      identifier,
    };
  }

  async function doCommandDelivery(params: DoCommandDeliverParamsType) {
    try {
      loading.value = true;

      const setupResult = await doSetup(params);

      const { entityId, transportType, isTCPModbus, deviceCode, objectModel, identifier } =
        setupResult;

      let command = params.value;

      if (transportType === TransportTypeEnum.TCP) {
        command = params.value;
        if (isTCPModbus) {
          const { doCoverCommand } = useCoverModbusCommand();
          command = await doCoverCommand(params.value, objectModel!, deviceCode, entityId);
        }
      } else {
        command = {
          [identifier]: command,
        };
      }

      let rpcCommand: RpcCommandType = {
        persistent: true,
        method: RPCCommandMethodEnum.THINGSKIT,
        additionalInfo: {
          cmdType: params.cmdType ?? CommandTypeEnum.API,
        },
        params: command,
      };

      let way = params.way ?? CommandDeliveryWayEnum.ONE_WAY;

      if (objectModel?.functionType === FunctionTypeEnum.SERVICE) {
        rpcCommand.additionalInfo.cmdType = CommandTypeEnum.SERVICE;
        way =
          objectModel.callType === ServiceCallTypeEnum.ASYNC
            ? CommandDeliveryWayEnum.ONE_WAY
            : CommandDeliveryWayEnum.TWO_WAY;
      }

      const sendApi = commandIssuanceApi;

      if (params.beforeFetch && isFunction(params.beforeFetch)) {
        const { rpcCommand: _rpcCommand, way: _way } = await params.beforeFetch(
          rpcCommand,
          setupResult
        );
        !isNullOrUnDef(rpcCommand) && (rpcCommand = _rpcCommand);
        if (_way) way = _way;
      }

      if (way === CommandDeliveryWayEnum.TWO_WAY) {
        const result = await getDeviceActiveTime(entityId);
        const [firsetItem] = result || [];

        if (!firsetItem.value) {
          const { createMessage } = useMessage();
          const message = '当前设备不在线';
          createMessage.warning(message);
          throw Error(message);
        }
      }
      await sendApi(way, entityId, rpcCommand);
    } finally {
      loading.value = false;
    }
  }

  return {
    loading,
    doCommandDelivery,
  };
}