useGetModbusCommand.ts 5.29 KB
import { ExtensionDesc } from '/@/api/device/model/modelOfMatterModel';
import { genModbusCommand } from '/@/api/task';
import { GenModbusCommandType } from '/@/api/task/model';
import { ModbusCRCEnum, RegisterActionTypeEnum } from '/@/enums/objectModelEnum';
import { useMessage } from '/@/hooks/web/useMessage';

export const InsertString = (t: any, c: any, n: any) => {
  const r: string | number[] = [];

  for (let i = 0; i * 2 < t.length; i++) r.push(t.substr(i * 2, n));

  return r.join(c);
};

export const FillString = (t: any, c: any, n: any, b: any) => {
  if (t === '' || c.length !== 1 || n <= t.length) return t;

  const l = t.length;

  for (let i = 0; i < n - l; i++) {
    if (b === true) t = c + t;
    else t += c;
  }
  return t;
};

export const SingleToHex = (t: any) => {
  if (t === '') return '';

  t = parseFloat(t);

  if (isNaN(t) === true) return 'Error';

  if (t === 0) return '00000000';

  let s, e, m;

  if (t > 0) {
    s = 0;
  } else {
    s = 1;

    t = 0 - t;
  }
  m = t.toString(2);

  if (m >= 1) {
    if (m.indexOf('.') === -1) m = `${m}.0`;

    e = m.indexOf('.') - 1;
  } else {
    e = 1 - m.indexOf('1');
  }
  if (e >= 0) m = m.replace('.', '');
  else m = m.substring(m.indexOf('1'));

  if (m.length > 24) m = m.substr(0, 24);
  else m = FillString(m, '0', 24, false);

  m = m.substring(1);

  e = (e + 127).toString(2);

  e = FillString(e, '0', 8, true);

  let r = parseInt(s + e + m, 2).toString(16);

  r = FillString(r, '0', 8, true);

  return InsertString(r, ' ', 2).toUpperCase();
};

export const FormatHex = (t: any, n: any, ie: any) => {
  const r: string[] = [];

  let s = '';

  let c = 0;

  for (let i = 0; i < t.length; i++) {
    if (t.charAt(i) !== ' ') {
      s += t.charAt(i);

      c += 1;

      if (c === n) {
        r.push(s);

        s = '';

        c = 0;
      }
    }
    if (ie === false) {
      if (i === t.length - 1 && s !== '') r.push(s);
    }
  }
  return r.join('\n');
};

export const FormatHexBatch = (t: any, n: any, ie: any) => {
  const a = t.split('\n');

  const r: string[] = [];

  for (let i = 0; i < a.length; i++) r[i] = FormatHex(a[i], n, ie);

  return r.join('\n');
};

export const SingleToHexBatch = (t: any) => {
  const a = t.split('\n');

  const r: string[] = [];

  for (let i = 0; i < a.length; i++) r[i] = SingleToHex(a[i]);

  return r.join('\r\n');
};

const getArray = (values: any) => {
  const str = values.replace(/\s+/g, '');
  const array: any = [];

  for (let i = 0; i < str.length; i += 4) {
    const chunk = parseInt(str.substring(i, i + 4), 16);
    array.push(chunk);
  }
  return array;
};

const getFloatPart = (number: string | number) => {
  const isLessZero = Number(number) < 0;
  number = number.toString();
  const floatPartStartIndex = number.indexOf('.');
  const value = ~floatPartStartIndex
    ? `${isLessZero ? '-' : ''}0.${number.substring(floatPartStartIndex + 1)}`
    : '0';
  return Number(value);
};

const REGISTER_MAX_VALUE = Number(0xffff);

export function useGetModbusCommand() {
  const { createMessage } = useMessage();

  const getModbusCommand = async (
    value: number,
    extensionDesc: ExtensionDesc,
    deviceAddressCode: string
  ) => {
    const { registerAddress, actionType, zoomFactor } = extensionDesc as Required<ExtensionDesc>;

    const params: GenModbusCommandType = {
      crc: ModbusCRCEnum.CRC_16_LOWER,
      registerNumber: 1,
      deviceCode: deviceAddressCode,
      registerAddress,
      method: actionType,
      registerValues: [value],
    };

    if (actionType === RegisterActionTypeEnum.INT) {
      const newValue = Math.trunc(value) * zoomFactor + getFloatPart(value) * zoomFactor;

      if (newValue % 1 !== 0) {
        createMessage.warning(`属性下发类型必须是整数,缩放因子为${zoomFactor}`);
        return;
      }

      if (value * zoomFactor > REGISTER_MAX_VALUE) {
        createMessage.warning(`属性下发值不能超过${REGISTER_MAX_VALUE},缩放因子为${zoomFactor}`);
        return;
      }

      params.registerValues = [newValue];
    } else if (actionType === RegisterActionTypeEnum.DOUBLE) {
      const regex = /^-?\d+(\.\d{0,2})?$/;
      const values = Math.trunc(value) * zoomFactor + getFloatPart(value) * zoomFactor;

      if (!regex.test(values.toString())) {
        createMessage.warning(`属性下发值精确到两位小数,缩放因子为${zoomFactor}`);
        return;
      }

      const newValue = values === 0 ? [0, 0] : getArray(SingleToHex(values));
      params.registerValues = newValue;
      params.registerNumber = 2;
      params.method = '10';
    }

    return await genModbusCommand(params);
  };

  /**
   *
   * @param extensionDesc 物模型拓展描述符
   * @param deviceAddressCode 设备地址码
   */
  const validateCanGetCommand = (
    extensionDesc?: ExtensionDesc,
    deviceAddressCode?: string,
    createValidateMessage = true
  ) => {
    const result = { flag: true, message: '' };
    if (!extensionDesc) {
      result.flag = false;
      result.message = '当前物模型扩展描述没有填写';
    }

    if (!deviceAddressCode) {
      result.flag = false;
      result.message = '当前设备未绑定设备地址码';
    }

    if (result.message && createValidateMessage) createMessage.warning(result.message);

    return result;
  };

  return {
    getModbusCommand,
    validateCanGetCommand,
  };
}