@iot9x.com/ipc-utils
Version:
九星云、九星小程序、九星配置工具所共用的库方法
628 lines (627 loc) • 32.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModbusRTU = void 0;
const constant_1 = require("./constant");
const util_1 = require("./util");
const validator_1 = require("./validator");
class ModbusRTU {
/**
* 实例化ModbusRTU类
* @param params 初始化参数
*/
constructor(params) {
/** CRC 顺序 */
this.crcOrder = constant_1.CRCOrder.LH;
/** 16位整型编码(有符号+无符号) */
this.i16Encode = constant_1.I16Encode.AB;
/** 32位整型编码(有符号+无符号) */
this.i32Encode = constant_1.I32Encode.ABCD;
/** 32位浮点型编码(FLOAT) */
this.f32Encode = constant_1.F32Encode.ABCD;
/** 64位整型编码(有符号+无符号) */
this.i64Encode = constant_1.I64Encode.ABCDEFGH;
/** 64位浮点型编码(Double) */
this.f64Encode = constant_1.F64Encode.ABCDEFGH;
const slaveIdValidateError = validator_1.Validator.slaveId(params.slaveId);
if (slaveIdValidateError)
throw new Error(slaveIdValidateError);
this.slaveId = params.slaveId;
if (params.crcOrder)
this.crcOrder = params.crcOrder;
if (params.i16)
this.i16Encode = params.i16;
if (params.i32)
this.i32Encode = params.i32;
if (params.f32)
this.f32Encode = params.f32;
if (params.i64)
this.i64Encode = params.i64;
if (params.f64)
this.f64Encode = params.f64;
}
//#region 读取相关指令生成
/**
* 读线圈寄存器——01功能码
* @param startAddress 起始地址
* @param count 线圈数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
readCoilCMD(startAddress, count, options) {
return this.getReadCMD('01', startAddress, Math.ceil(count / 8), options);
}
/**
* 读离散输入寄存器——02功能码
* @param startAddress 起始地址
* @param count 离散输入寄存器数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
readDiscreteInputCMD(startAddress, count, options) {
return this.getReadCMD('02', startAddress, Math.ceil(count / 8), options);
}
/**
* 读保持寄存器——03功能码
* @param startAddress 起始地址
* @param count 保持寄存器数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
readHoldCMD(startAddress, count, options) {
return this.getReadCMD('03', startAddress, count, options);
}
/**
* 根据数据类型读保持寄存器——03功能码
* @param startAddress 起始地址
* @param dataType 想要读取的数据类型
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
readHoldCMDByDataType(startAddress, dataType, options) {
if (dataType === constant_1.ModbusDataType.Coil)
throw new Error('不支持读取线圈类型数据');
const count = util_1.Util.getRegisterCountByDataType(dataType);
if (!count || count === 0)
throw new Error('数据类型格式不正确');
return this.getReadCMD('03', startAddress, count, options);
}
/**
* 根据数据类型列表读保持寄存器——03功能码
* @param startAddress 起始地址
* @param dataTypeList 想要读取的数据类型列表(按顺序排列哦)
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
readHoldCMDByDataTypeList(startAddress, dataTypeList, options) {
let sumCount = 0;
for (const dataType of dataTypeList) {
if (dataType === constant_1.ModbusDataType.Coil)
throw new Error('不支持读取线圈类型数据');
const count = util_1.Util.getRegisterCountByDataType(dataType);
if (!count || count === 0)
throw new Error('数据类型列表中有格式不正确的数据类型');
sumCount += count;
}
return this.getReadCMD('03', startAddress, sumCount, options);
}
/**
* 读输入寄存器——04功能码
* @param startAddress 起始地址
* @param count 输入寄存器数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
readInputCMD(startAddress, count, options) {
return this.getReadCMD('04', startAddress, count, options);
}
/**
* 根据数据类型读输入寄存器——04功能码
* @param startAddress 起始地址
* @param dataType 想要读取的数据类型
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
readInputCMDByDataType(startAddress, dataType, options) {
if (dataType === constant_1.ModbusDataType.Coil)
throw new Error('不支持读取线圈类型数据');
const count = util_1.Util.getRegisterCountByDataType(dataType);
if (!count || count === 0)
throw new Error('数据类型格式不正确');
return this.getReadCMD('04', startAddress, count, options);
}
/**
* 根据数据类型列表读输入寄存器——04功能码
* @param startAddress 起始地址
* @param dataTypeList 想要读取的数据类型列表(按顺序排列哦)
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
readInputCMDByDataTypeList(startAddress, dataTypeList, options) {
let sumCount = 0;
for (const dataType of dataTypeList) {
if (dataType === constant_1.ModbusDataType.Coil)
throw new Error('不支持读取线圈类型数据');
const count = util_1.Util.getRegisterCountByDataType(dataType);
if (!count || count === 0)
throw new Error('数据类型列表中有格式不正确的数据类型');
sumCount += count;
}
return this.getReadCMD('04', startAddress, sumCount, options);
}
/**
* 读取指令统一实现
* @param codeHex 功能码
* @param startAddress 起始地址
* @param count 寄存器数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
getReadCMD(codeHex, startAddress, count, options) {
const startAddressValidateError = validator_1.Validator.startAddress(startAddress);
if (startAddressValidateError)
throw new Error(startAddressValidateError);
const countValidateError = validator_1.Validator.registerCount(count);
if (countValidateError)
throw new Error(countValidateError);
const slaveId = (options === null || options === void 0 ? void 0 : options.slaveId) || this.slaveId;
const slaveIdValidateError = validator_1.Validator.slaveId(slaveId);
if (slaveIdValidateError)
throw new Error(slaveIdValidateError);
const slaveIdHex = slaveId.toString(16).padStart(2, '0');
const startAddressHex = startAddress.toString(16).padStart(4, '0');
const lengthHex = count.toString(16).padStart(4, '0');
const cmdHex = slaveIdHex + codeHex + startAddressHex + lengthHex;
const crcHex = util_1.Util.getCRC(cmdHex, (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
let result = (options === null || options === void 0 ? void 0 : options.lowerCase) ? (cmdHex + crcHex).toLowerCase() : (cmdHex + crcHex).toUpperCase();
if (options === null || options === void 0 ? void 0 : options.separator)
result = util_1.Util.hexSeparator(result, options.separator);
return result;
}
/**
* 读线圈寄存器——01功能码
* @param slaveId 从机地址
* @param startAddress 起始地址
* @param count 线圈数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
static readCoilCMD(slaveId, startAddress, count, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.readCoilCMD(startAddress, count, options);
}
/**
* 读离散输入寄存器——02功能码
* @param slaveId 从机地址
* @param startAddress 起始地址
* @param count 离散输入寄存器数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
static readDiscreteInputCMD(slaveId, startAddress, count, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.readDiscreteInputCMD(startAddress, count, options);
}
/**
* 读保持寄存器——03功能码
* @param slaveId 从机地址
* @param startAddress 起始地址
* @param count 保持寄存器数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
static readHoldCMD(slaveId, startAddress, count, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.readHoldCMD(startAddress, count, options);
}
/**
* 根据数据类型读保持寄存器——03功能码
* @param slaveId 从机地址
* @param startAddress 起始地址
* @param dataType 想要读取的数据类型
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
static readHoldCMDByDataType(slaveId, startAddress, dataType, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.readHoldCMDByDataType(startAddress, dataType, options);
}
/**
* 根据数据类型列表读保持寄存器——03功能码
* @param slaveId 从机地址
* @param startAddress 起始地址
* @param dataTypeList 想要读取的数据类型列表(按顺序排列哦)
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
static readHoldCMDByDataTypeList(slaveId, startAddress, dataTypeList, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.readHoldCMDByDataTypeList(startAddress, dataTypeList, options);
}
/**
* 读输入寄存器——04功能码
* @param slaveId 从机地址
* @param startAddress 起始地址
* @param count 输入寄存器数量
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
static readInputCMD(slaveId, startAddress, count, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.readInputCMD(startAddress, count, options);
}
/**
* 根据数据类型读输入寄存器——04功能码
* @param slaveId 从机地址
* @param startAddress 起始地址
* @param dataType 想要读取的数据类型
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
static readInputCMDByDataType(slaveId, startAddress, dataType, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.readInputCMDByDataType(startAddress, dataType, options);
}
/**
* 根据数据类型列表读输入寄存器——04功能码
* @param slaveId 从机地址
* @param startAddress 起始地址
* @param dataTypeList 想要读取的数据类型列表(按顺序排列哦)
* @param options 生成指令额外参数
* @returns 读取命令——十六进制字符串
*/
static readInputCMDByDataTypeList(slaveId, startAddress, dataTypeList, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.readInputCMDByDataTypeList(startAddress, dataTypeList, options);
}
//#endregion
//#region 读取返回解析
/**
* 解析01功能码返回内容
* @description 未考虑从机地址校验
* @param resHex 发送读取线圈指令(01功能码)后modbus从机返回内容,十六进制字符串
* @param options 解析额外参数
* @returns 解析结果
*/
resolveCoilRes(resHex, options) {
this.resCheck('01', resHex, options);
const result = [];
// * 读取payload并解析
const payload = resHex.slice(6, -4);
for (const byte of payload.match(/\w{2}/g)) {
for (const coilValue of parseInt(byte, 16).toString(2).padStart(8, '0').split('').reverse()) {
result.push(parseInt(coilValue));
}
}
return result;
}
/**
* 解析02功能码返回内容
* @description 未考虑从机地址校验
* @param resHex 发送读取输入寄存器指令(02功能码)后modbus从机返回内容,十六进制字符串
* @param options 解析额外参数
* @returns 解析结果
*/
resolveDiscreteInputRes(resHex, options) {
this.resCheck('02', resHex, options);
const result = [];
// * 读取payload并解析
const payload = resHex.slice(6, -4);
for (const byte of payload.match(/\w{2}/g)) {
for (const coilValue of parseInt(byte, 16).toString(2).padStart(8, '0').split('').reverse()) {
result.push(parseInt(coilValue));
}
}
return result;
}
/**
* 解析03功能码返回内容
* @description 未考虑从机地址校验
* @param resHex 发送读取保持寄存器指令(03功能码)后modbus从机返回内容,十六进制字符串
* @param options 解析额外参数
* @returns 寄存器原始值,十六进制字符串
*/
resolveHoldResRaw(resHex, options) {
this.resCheck('03', resHex, options);
return resHex.slice(6, -4);
}
resolveHoldResByDataType(resHex, dataType, options) {
this.resCheck('03', resHex, options);
const payload = resHex.slice(6, -4);
return util_1.Util.getValueByDataType(payload, dataType, (options === null || options === void 0 ? void 0 : options.i16) || this.i16Encode, (options === null || options === void 0 ? void 0 : options.i32) || this.i32Encode, (options === null || options === void 0 ? void 0 : options.f32) || this.f32Encode, (options === null || options === void 0 ? void 0 : options.i64) || this.i64Encode, (options === null || options === void 0 ? void 0 : options.f64) || this.f64Encode);
}
/**
* Modbus读取返回内容合法性校验
* @param codeHex 功能码十六进制字符串
* @param resHex 读取返回内容
* @param options 额外参数
*/
resCheck(codeHex, resHex, options) {
if (!resHex || !resHex.length)
throw new Error('要解析的内容不可为空');
resHex = resHex.match(/\w/g).join(''); // 去除可能有的分隔符。
if (resHex.length < 8)
throw new Error('返回内容长度不足'); // 十六进制的返回值最少也要8个字符,小于8个字符肯定不合理
// * CRC 值校验
const crcHex = util_1.Util.getCRC(resHex.slice(0, -4), (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
if (crcHex.toUpperCase() !== resHex.slice(-4).toUpperCase())
throw new Error('CRC校验失败');
// * 错误码校验
const resError = util_1.Util.checkResCode(codeHex, resHex.slice(2, 4), resHex.slice(4, 6));
if (resError)
throw new Error(resError);
}
//#endregion
//#region 写入(控制)相关指令生成
/**
* 写单个线圈——05功能码
* @param startAddress 线圈寄存器地址
* @param value 线圈值
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
writeCoilCMD(startAddress, value, options) {
const startAddressValidateError = validator_1.Validator.startAddress(startAddress);
if (startAddressValidateError)
throw new Error(startAddressValidateError);
const valueHex = value ? 'FF00' : '0000';
const slaveIdHex = ((options === null || options === void 0 ? void 0 : options.slaveId) || this.slaveId).toString(16).padStart(2, '0');
const startAddressHex = startAddress.toString(16).padStart(4, '0');
const cmdHex = slaveIdHex + '05' + startAddressHex + valueHex;
const crcHex = util_1.Util.getCRC(cmdHex, (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
let result = (options === null || options === void 0 ? void 0 : options.lowerCase) ? (cmdHex + crcHex).toLowerCase() : (cmdHex + crcHex).toUpperCase();
if (options === null || options === void 0 ? void 0 : options.separator)
result = util_1.Util.hexSeparator(result, options.separator);
return result;
}
/**
* 写入单个线圈寄存器——05功能码
* @param slaveId 从机地址
* @param startAddress 线圈寄存器地址
* @param value 线圈值
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
static writeCoilCMD(slaveId, startAddress, value, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.writeCoilCMD(startAddress, value, options);
}
/**
* 写多个线圈——0F功能码
* @param startAddress 线圈寄存器起始地址
* @param valueList 线圈值列表(按顺序哦)
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
writeMultiCoilCMD(startAddress, valueList, options) {
const startAddressValidateError = validator_1.Validator.startAddress(startAddress);
if (startAddressValidateError)
throw new Error(startAddressValidateError);
const coilCountHex = valueList.length.toString(16).toUpperCase().padStart(4, '0');
const byteCountHex = Math.ceil(valueList.length / 8)
.toString(16)
.toUpperCase()
.padStart(2, '0');
const valueHexList = [];
for (let i = 0; i < valueList.length; i += 8) {
const valueHex = parseInt(valueList
.slice(i, i + 8)
.reverse()
.join(''), 2)
.toString(16)
.toUpperCase()
.padStart(2, '0');
valueHexList.push(valueHex);
}
const valueHex = valueHexList.join('');
const slaveIdHex = ((options === null || options === void 0 ? void 0 : options.slaveId) || this.slaveId).toString(16).padStart(2, '0');
const startAddressHex = startAddress.toString(16).padStart(4, '0');
const cmdHex = slaveIdHex + '0F' + startAddressHex + coilCountHex + byteCountHex + valueHex;
const crcHex = util_1.Util.getCRC(cmdHex, (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
let result = (options === null || options === void 0 ? void 0 : options.lowerCase) ? (cmdHex + crcHex).toLowerCase() : (cmdHex + crcHex).toUpperCase();
if (options === null || options === void 0 ? void 0 : options.separator)
result = util_1.Util.hexSeparator(result, options.separator);
return result;
}
/**
* 写多个线圈——0F功能码
* @param slaveId 从机地址
* @param startAddress 线圈寄存器起始地址
* @param valueList 线圈值列表(按顺序哦)
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
static writeMultiCoilCMD(slaveId, startAddress, valueList, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.writeMultiCoilCMD(startAddress, valueList, options);
}
/**
* 写单个保持寄存器——06功能码
* @param startAddress 保持寄存器的地址
* @param valueHex 保持寄存器的值,十六进制字符串格式
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
writeHoldCMD(startAddress, valueHex, options) {
const startAddressValidateError = validator_1.Validator.startAddress(startAddress);
if (startAddressValidateError)
throw new Error(startAddressValidateError);
valueHex = valueHex.match(/\w/g).join(''); // * 去除十六进制字符串中可能有的分隔符
if (valueHex.length !== 4)
throw new Error('寄存器内容长度必须为4个字符');
const slaveIdHex = ((options === null || options === void 0 ? void 0 : options.slaveId) || this.slaveId).toString(16).padStart(2, '0');
const startAddressHex = startAddress.toString(16).padStart(4, '0');
const cmdHex = slaveIdHex + '06' + startAddressHex + valueHex;
const crcHex = util_1.Util.getCRC(cmdHex, (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
let result = (options === null || options === void 0 ? void 0 : options.lowerCase) ? (cmdHex + crcHex).toLowerCase() : (cmdHex + crcHex).toUpperCase();
if (options === null || options === void 0 ? void 0 : options.separator)
result = util_1.Util.hexSeparator(result, options.separator);
return result;
}
/**
* 写单个保持寄存器——06功能码
* @param slaveId 从机地址
* @param startAddress 保持寄存器的地址
* @param valueHex 保持寄存器的值,十六进制字符串格式
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
static writeHoldCMD(slaveId, startAddress, valueHex, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.writeHoldCMD(startAddress, valueHex, options);
}
/**
* 根据数据类型写单个保持寄存器——06功能码
* @param startAddress 保持寄存器的地址
* @param data 数据值
* @param dataType 数据类型
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
writeHoldByDataTypeCMD(startAddress, data, dataType, options) {
const startAddressValidateError = validator_1.Validator.startAddress(startAddress);
if (startAddressValidateError)
throw new Error(startAddressValidateError);
if (dataType !== constant_1.ModbusDataType.I16 && dataType !== constant_1.ModbusDataType.U16 && dataType !== constant_1.ModbusDataType.S2)
throw new Error('数据类型仅支持Int16、UInt16和两字节字符串');
const valueHex = util_1.Util.dataEncode(data, dataType, (options === null || options === void 0 ? void 0 : options.i16) || this.i16Encode, (options === null || options === void 0 ? void 0 : options.i32) || this.i32Encode, (options === null || options === void 0 ? void 0 : options.f32) || this.f32Encode, (options === null || options === void 0 ? void 0 : options.i64) || this.i64Encode, (options === null || options === void 0 ? void 0 : options.f64) || this.f64Encode);
const slaveIdHex = ((options === null || options === void 0 ? void 0 : options.slaveId) || this.slaveId).toString(16).padStart(2, '0');
const startAddressHex = startAddress.toString(16).padStart(4, '0');
const cmdHex = slaveIdHex + '06' + startAddressHex + valueHex;
const crcHex = util_1.Util.getCRC(cmdHex, (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
let result = (options === null || options === void 0 ? void 0 : options.lowerCase) ? (cmdHex + crcHex).toLowerCase() : (cmdHex + crcHex).toUpperCase();
if (options === null || options === void 0 ? void 0 : options.separator)
result = util_1.Util.hexSeparator(result, options.separator);
return result;
}
/**
* 根据数据类型写单个保持寄存器——06功能码
* @param slaveId 从机地址
* @param startAddress 保持寄存器的地址
* @param data 数据值
* @param dataType 数据类型
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
static writeHoldByDataTypeCMD(slaveId, startAddress, data, dataType, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.writeHoldByDataTypeCMD(startAddress, data, dataType, options);
}
/**
* 写多个保持寄存器——10功能码
* @param startAddress 保持寄存器起始地址
* @param valueHex 保持寄存器的值,十六进制字符串格式
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
writeMultiHoldCMD(startAddress, valueHex, options) {
const startAddressValidateError = validator_1.Validator.startAddress(startAddress);
if (startAddressValidateError)
throw new Error(startAddressValidateError);
valueHex = valueHex.match(/\w/g).join(''); // * 去除十六进制字符串中可能有的分隔符
if (valueHex.length % 4)
throw new Error('寄存器内容长度不合法');
const slaveIdHex = ((options === null || options === void 0 ? void 0 : options.slaveId) || this.slaveId).toString(16).padStart(2, '0');
const startAddressHex = startAddress.toString(16).padStart(4, '0');
const registerCountHex = (valueHex.length / 4).toString(16).padStart(4, '0');
const byteCountHex = (valueHex.length / 2).toString(16).padStart(2, '0');
const cmdHex = slaveIdHex + '10' + startAddressHex + registerCountHex + byteCountHex + valueHex;
const crcHex = util_1.Util.getCRC(cmdHex, (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
let result = (options === null || options === void 0 ? void 0 : options.lowerCase) ? (cmdHex + crcHex).toLowerCase() : (cmdHex + crcHex).toUpperCase();
if (options === null || options === void 0 ? void 0 : options.separator)
result = util_1.Util.hexSeparator(result, options.separator);
return result;
}
/**
* 写多个保持寄存器——10功能码
* @param slaveId 从机地址
* @param startAddress 保持寄存器起始地址
* @param valueHex 保持寄存器的值,十六进制字符串格式
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
static writeMultiHoldCMD(slaveId, startAddress, valueHex, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.writeMultiHoldCMD(startAddress, valueHex, options);
}
/**
* 根据数据类型写多个保持寄存器——10功能码
* @param startAddress 保持寄存器起始地址
* @param data 数据值
* @param dataType 数据类型
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
writeMultiHoldByDataTypeCMD(startAddress, data, dataType, options) {
const startAddressValidateError = validator_1.Validator.startAddress(startAddress);
if (startAddressValidateError)
throw new Error(startAddressValidateError);
if (dataType === constant_1.ModbusDataType.Coil)
throw new Error('不支持写入线圈类型数据');
const registerCount = util_1.Util.getRegisterCountByDataType(dataType);
const valueHex = util_1.Util.dataEncode(data, dataType, (options === null || options === void 0 ? void 0 : options.i16) || this.i16Encode, (options === null || options === void 0 ? void 0 : options.i32) || this.i32Encode, (options === null || options === void 0 ? void 0 : options.f32) || this.f32Encode, (options === null || options === void 0 ? void 0 : options.i64) || this.i64Encode, (options === null || options === void 0 ? void 0 : options.f64) || this.f64Encode);
const slaveIdHex = ((options === null || options === void 0 ? void 0 : options.slaveId) || this.slaveId).toString(16).padStart(2, '0');
const startAddressHex = startAddress.toString(16).padStart(4, '0');
const registerCountHex = registerCount.toString(16).padStart(4, '0');
const byteCountHex = (registerCount * 2).toString(16).padStart(2, '0');
const cmdHex = slaveIdHex + '10' + startAddressHex + registerCountHex + byteCountHex + valueHex;
const crcHex = util_1.Util.getCRC(cmdHex, (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
let result = (options === null || options === void 0 ? void 0 : options.lowerCase) ? (cmdHex + crcHex).toLowerCase() : (cmdHex + crcHex).toUpperCase();
if (options === null || options === void 0 ? void 0 : options.separator)
result = util_1.Util.hexSeparator(result, options.separator);
return result;
}
/**
* 根据数据类型写多个保持寄存器——10功能码
* @param startAddress 保持寄存器起始地址
* @param data 数据值
* @param dataType 数据类型
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
static writeMultiHoldByDataTypeCMD(slaveId, startAddress, data, dataType, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.writeMultiHoldByDataTypeCMD(startAddress, data, dataType, options);
}
/**
* 根据数据列表写多个保持寄存器——10功能码
* @param startAddress 保持寄存器起始地址
* @param dataList 要写入的数据和类型元组的列表
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
writeMultiHoldByDataTypeListCMD(startAddress, dataList, options) {
const startAddressValidateError = validator_1.Validator.startAddress(startAddress);
if (startAddressValidateError)
throw new Error(startAddressValidateError);
let registerCount = 0;
let valueHex = '';
for (const [data, dataType] of dataList) {
if (dataType === constant_1.ModbusDataType.Coil)
throw new Error('不支持写入线圈类型数据');
registerCount += util_1.Util.getRegisterCountByDataType(dataType);
valueHex += util_1.Util.dataEncode(data, dataType, (options === null || options === void 0 ? void 0 : options.i16) || this.i16Encode, (options === null || options === void 0 ? void 0 : options.i32) || this.i32Encode, (options === null || options === void 0 ? void 0 : options.f32) || this.f32Encode, (options === null || options === void 0 ? void 0 : options.i64) || this.i64Encode, (options === null || options === void 0 ? void 0 : options.f64) || this.f64Encode);
}
const slaveIdHex = ((options === null || options === void 0 ? void 0 : options.slaveId) || this.slaveId).toString(16).padStart(2, '0');
const startAddressHex = startAddress.toString(16).padStart(4, '0');
const registerCountHex = registerCount.toString(16).padStart(4, '0');
const byteCountHex = (registerCount * 2).toString(16).padStart(2, '0');
const cmdHex = slaveIdHex + '10' + startAddressHex + registerCountHex + byteCountHex + valueHex;
const crcHex = util_1.Util.getCRC(cmdHex, (options === null || options === void 0 ? void 0 : options.crcOrder) || this.crcOrder);
let result = (options === null || options === void 0 ? void 0 : options.lowerCase) ? (cmdHex + crcHex).toLowerCase() : (cmdHex + crcHex).toUpperCase();
if (options === null || options === void 0 ? void 0 : options.separator)
result = util_1.Util.hexSeparator(result, options.separator);
return result;
}
/**
* 根据数据列表写多个保持寄存器——10功能码
* @param startAddress 保持寄存器起始地址
* @param dataList 要写入的数据和类型元组的列表
* @param options 生成指令额外参数
* @returns 写入命令——十六进制字符串
*/
static writeMultiHoldByDataTypeListCMD(slaveId, startAddress, dataList, options) {
const rtu = new ModbusRTU({ slaveId });
return rtu.writeMultiHoldByDataTypeListCMD(startAddress, dataList, options);
}
}
exports.ModbusRTU = ModbusRTU;