useObjectFormData.ts 6.85 KB
import { DataTypeForm } from './DataTypeForm';
import { ExtendDescFormFieldsValueType } from './ExtendDesc';
import { isFloatType, useParseOperationType } from './ExtendDesc/useParseOperationType';
import { FormFieldsEnum } from './config';
import { ObjectModelFormGetFieldsValueType, ObjectModelFormPropsType } from './types';
import { DefineComponentsBasicExpose } from '/#/utils';
import { ModelOfMatterParams, Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel';
import { FormActionType } from '/@/components/Form';
import { TCPProtocolTypeEnum, TransportTypeEnum } from '/@/enums/deviceEnum';
import {
  BuiltInIdentifierEnum,
  DataTypeEnum,
  FunctionTypeEnum,
  ObjectModelAccessModeEnum,
  OriginalDataTypeEnum,
} from '/@/enums/objectModelEnum';
import { Ref, computed, toRaw, unref } from 'vue';

interface UseObjectFormDataParamsType {
  formActionType: FormActionType;
  dataTypeFormRef: Ref<InstanceType<typeof DataTypeForm> | undefined>;
  propsRef?: ObjectModelFormPropsType;
}

export function getDataTypeByOriginalDataType(
  originalDataType: OriginalDataTypeEnum,
  identifier: string
) {
  if (identifier === BuiltInIdentifierEnum.SOURCE) return DataTypeEnum.STRING;

  if (isFloatType(originalDataType)) return DataTypeEnum.NUMBER_DOUBLE;
  else if (originalDataType === OriginalDataTypeEnum.STRING) return DataTypeEnum.STRING;
  else if ([OriginalDataTypeEnum.BOOLEAN, OriginalDataTypeEnum.BITS].includes(originalDataType))
    return DataTypeEnum.BOOL;
  else return DataTypeEnum.NUMBER_INT;
}

function handleTCPModbusProductPropertiesType(
  value: ObjectModelFormGetFieldsValueType
): ModelOfMatterParams {
  const { functionName, identifier, functionType, remark, extensionDesc, unit, unitName } = value;

  const {
    operationType,
    originalDataType,
    bitMask,
    valueRange,
    registerAddress,
    scaling,
    registerCount,
    valueMapping,
  } = extensionDesc! || {};

  const { writeOnly, accessMode } = useParseOperationType(operationType);

  const dataType = getDataTypeByOriginalDataType(originalDataType, identifier);

  return {
    functionType,
    functionName,
    identifier,
    functionJson: {
      dataType: {
        type: dataType,
        specs: {
          unit,
          unitName,
          valueRange,
        },
        specsList: valueMapping || [],
      },
    },
    accessMode:
      identifier === BuiltInIdentifierEnum.SOURCE ? ObjectModelAccessModeEnum.READ : accessMode,
    remark,
    extensionDesc: {
      writeOnly,
      bitMask,
      operationType,
      originalDataType,
      registerAddress,
      scaling,
      registerCount,
    },
  };
}

function handlePropertiesType(
  value: ObjectModelFormGetFieldsValueType,
  dataTypeFormValue: StructJSON
): ModelOfMatterParams {
  const { functionType, accessMode, remark } = value;
  const { functionName, identifier, dataType } = dataTypeFormValue || {};

  const result: ModelOfMatterParams = {
    functionType,
    functionName,
    identifier,
    functionJson: {
      dataType,
    },
    accessMode,
    remark,
  };

  return result;
}

function handleServiceType(
  value: ObjectModelFormGetFieldsValueType,
  transportType?: TransportTypeEnum
): ModelOfMatterParams {
  const {
    functionName,
    identifier,
    functionType,
    remark,
    inputData = [],
    outputData = [],
    serviceCommand,
    callType,
  } = value;

  return {
    callType,
    functionType,
    functionName,
    identifier,
    remark,
    functionJson: {
      inputData:
        transportType === TransportTypeEnum.TCP
          ? [
              {
                [FormFieldsEnum.SERVICE_COMMAND]: serviceCommand?.replaceAll(/\s/g, ''),
              } as unknown as StructJSON,
            ]
          : inputData,
      outputData,
    },
  };
}

function handleEventType(value: ObjectModelFormGetFieldsValueType): ModelOfMatterParams {
  const { functionName, identifier, functionType, remark, eventType, outputData = [] } = value;

  return {
    functionType,
    functionName,
    identifier,
    remark,
    eventType,
    functionJson: {
      outputData,
    },
  };
}

export const useObjectFormData = ({
  formActionType,
  dataTypeFormRef,
  propsRef,
}: UseObjectFormDataParamsType): DefineComponentsBasicExpose<ModelOfMatterParams> => {
  const getTCPModbusProductFlag = computed(
    () =>
      propsRef?.deviceRecord?.profileData?.transportConfiguration?.protocol ===
      TCPProtocolTypeEnum.MODBUS_RTU
  );

  const getTransportType = computed(
    () => propsRef?.deviceRecord?.transportType as TransportTypeEnum
  );

  const getFieldsValue = (): ModelOfMatterParams => {
    const value = formActionType.getFieldsValue() as ObjectModelFormGetFieldsValueType;
    const { functionType } = value;
    if (functionType === FunctionTypeEnum.PROPERTIES) {
      const dataTypeFormValue = unref(dataTypeFormRef)?.getFieldsValue?.();
      if (unref(getTCPModbusProductFlag)) return handleTCPModbusProductPropertiesType(value);
      return handlePropertiesType(value, dataTypeFormValue!);
    }

    if (functionType === FunctionTypeEnum.EVENTS) {
      return handleEventType(value);
    }

    return handleServiceType(value, unref(getTransportType));
  };

  const setFieldsValue = (values: ModelOfMatterParams) => {
    values = toRaw(unref(values));
    const transportType = unref(getTransportType);
    const {
      functionName,
      identifier,
      functionJson,
      functionType,
      accessMode,
      callType,
      remark,
      extensionDesc,
      eventType,
    } = values;
    const { dataType, inputData = [], outputData = [] } = functionJson || {};

    const setValue = {
      identifier,
      functionName,
      functionType,
      accessMode,
      callType,
      inputData,
      outputData,
      remark,
      eventType,
      serviceCommand: transportType === TransportTypeEnum.TCP ? inputData?.[0]?.serviceCommand : '',
      extensionDesc,
    } as ObjectModelFormGetFieldsValueType;

    if (unref(getTCPModbusProductFlag)) {
      const { specs, type, specsList } = dataType || {};
      const { unit, unitName, valueRange } = (specs as Specs) || {};
      Object.assign(setValue, { unit, unitName } as ObjectModelFormGetFieldsValueType);
      Object.assign(setValue.extensionDesc || {}, {
        valueRange,
        dataType: type,
        valueMapping: specsList,
      } as Partial<ExtendDescFormFieldsValueType>);
    }

    formActionType.setFieldsValue(setValue);

    if (functionType === FunctionTypeEnum.PROPERTIES) {
      unref(dataTypeFormRef)?.setFieldsValue({
        functionName,
        identifier,
        dataType,
      } as StructJSON);
    }
  };

  const validate = async () => {
    await formActionType.validate();
    await unref(dataTypeFormRef)?.validate?.();
  };

  const resetFieldsValue = async () => {
    formActionType.resetFields();
    unref(dataTypeFormRef)?.resetFieldsValue?.();
  };

  return { getFieldsValue, setFieldsValue, validate, resetFieldsValue };
};