config.ts 6.24 KB
import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
import { getModelServices } from '/@/api/device/modelOfMatter';
import { FormProps, FormSchema, useComponentRegister } from '/@/components/Form';
import { validateTCPCustomCommand } from '/@/components/Form/src/components/ThingsModelForm';
import { JSONEditor, JSONEditorValidator } from '/@/components/CodeEditor';
import {
  TransportTypeEnum,
  CommandTypeNameEnum,
  CommandTypeEnum,
  ServiceCallTypeEnum,
  CommandDeliveryWayEnum,
  CommandDeliveryWayNameEnum,
  TCPProtocolTypeEnum,
} from '/@/enums/deviceEnum';
import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
import { EdgeDeviceItemType } from '/@/api/edgeManage/model/edgeInstance';

export interface CommandDeliveryFormFieldType {
  [CommandFieldsEnum.COMMAND_TYPE]: CommandTypeEnum;
  [CommandFieldsEnum.TCP_COMMAND_VALUE]?: string;
  [CommandFieldsEnum.COMAND_VALUE]?: string;
  [CommandFieldsEnum.SERVICE]?: string;
  [CommandFieldsEnum.MODEL_INPUT]?: ModelOfMatterParams;
  [CommandFieldsEnum.CALL_TYPE]: CommandDeliveryWayEnum;
}

export enum CommandFieldsEnum {
  COMMAND_TYPE = 'commandType',
  TCP_COMMAND_VALUE = 'tcpCommandValue',
  COMAND_VALUE = 'commandValue',
  SERVICE = 'service',
  MODEL_INPUT = 'modelInput',
  CALL_TYPE = 'callType',

  SERVICE_COMMAND = 'serviceCommand',

  SERVICE_OBJECT_MODEL = 'serviceObjectModel',
}

useComponentRegister('JSONEditor', JSONEditor);

export const CommandSchemas = (deviceRecord: EdgeDeviceItemType): FormSchema[] => {
  const { deviceData, deviceProfileId, deviceType } = deviceRecord;

  const isTCPTransport = deviceData.transportConfiguration.type === TransportTypeEnum.TCP;

  const isTCPModbus =
    isTCPTransport &&
    deviceRecord.deviceProfile?.profileData?.transportConfiguration?.protocol ===
      TCPProtocolTypeEnum.MODBUS_RTU;

  return [
    {
      field: CommandFieldsEnum.COMMAND_TYPE,
      component: 'RadioGroup',
      label: '下发类型',
      defaultValue: CommandTypeEnum.CUSTOM,
      required: true,
      componentProps: ({ formActionType }) => {
        const { setFieldsValue } = formActionType;

        const getOptions = () => {
          const options = [{ label: CommandTypeNameEnum.CUSTOM, value: CommandTypeEnum.CUSTOM }];

          if (isTCPModbus || (isTCPTransport && deviceType === DeviceTypeEnum.SENSOR))
            return options;

          options.push({ label: CommandTypeNameEnum.SERVICE, value: CommandTypeEnum.SERVICE });

          return options;
        };
        return {
          options: getOptions(),
          onChange() {
            setFieldsValue({
              [CommandFieldsEnum.SERVICE]: null,
              [CommandFieldsEnum.MODEL_INPUT]: null,
              [CommandFieldsEnum.COMAND_VALUE]: null,
              [CommandFieldsEnum.TCP_COMMAND_VALUE]: null,
            });
          },
        };
      },
    },
    {
      field: CommandFieldsEnum.CALL_TYPE,
      component: 'RadioGroup',
      label: '单向/双向',
      required: true,
      defaultValue: CommandDeliveryWayEnum.ONE_WAY,
      ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM,
      componentProps: {
        options: Object.keys(CommandDeliveryWayEnum).map((key) => ({
          label: CommandDeliveryWayNameEnum[key],
          value: CommandDeliveryWayEnum[key],
        })),
      },
    },
    {
      field: CommandFieldsEnum.TCP_COMMAND_VALUE,
      label: '命令',
      required: true,
      ifShow: ({ model }) =>
        deviceData.transportConfiguration.type === TransportTypeEnum.TCP &&
        model[CommandFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM,
      component: 'Input',
      rules: [{ validator: validateTCPCustomCommand }],
      componentProps: {
        placeholder: '请输入命令',
      },
    },
    {
      field: CommandFieldsEnum.COMAND_VALUE,
      label: '命令',
      component: 'JSONEditor',
      colProps: { span: 20 },
      changeEvent: 'update:value',
      valueField: 'value',
      required: true,
      rules: JSONEditorValidator(),
      ifShow: ({ model }) =>
        deviceData.transportConfiguration.type !== TransportTypeEnum.TCP &&
        model[CommandFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM,
      componentProps: {
        height: 250,
      },
    },
    {
      field: CommandFieldsEnum.SERVICE,
      label: '服务',
      component: 'ApiSelect',
      required: true,
      ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] !== CommandTypeEnum.CUSTOM,
      rules: [{ required: true, message: '请选择服务' }],
      componentProps: ({ formActionType }) => {
        const { setFieldsValue } = formActionType;
        return {
          api: getModelServices,
          params: {
            deviceProfileId: deviceProfileId.id,
          },
          valueField: 'identifier',
          labelField: 'functionName',
          getPopupContainer: () => document.body,
          placeholder: '请选择服务',
          onChange(
            value: string,
            options: ModelOfMatterParams & Record<'label' | 'value', string>
          ) {
            if (!value) return;
            setFieldsValue({
              [CommandFieldsEnum.CALL_TYPE]:
                options.callType === ServiceCallTypeEnum.ASYNC
                  ? CommandDeliveryWayEnum.ONE_WAY
                  : CommandDeliveryWayEnum.TWO_WAY,
              [CommandFieldsEnum.MODEL_INPUT]: null,
              [CommandFieldsEnum.SERVICE_OBJECT_MODEL]: Object.assign(options, {
                functionName: options.label,
                identifier: options.value,
              }),
            });
          },
        };
      },
    },
    {
      field: CommandFieldsEnum.SERVICE_OBJECT_MODEL,
      label: '服务物模型',
      component: 'Input',
      ifShow: false,
    },
    {
      field: CommandFieldsEnum.MODEL_INPUT,
      component: 'Input',
      label: '输入参数',
      changeEvent: 'update:value',
      valueField: 'value',
      ifShow: ({ model }) =>
        model[CommandFieldsEnum.SERVICE] &&
        model[CommandFieldsEnum.SERVICE_OBJECT_MODEL] &&
        model[CommandFieldsEnum.COMMAND_TYPE] !== CommandTypeEnum.CUSTOM,
      componentProps: {
        formProps: {
          wrapperCol: { span: 24 },
        } as FormProps,
      },
      slot: 'serviceCommand',
    },
  ];
};