@iot9x.com/ipc-utils
Version:
九星云、九星小程序、九星配置工具所共用的库方法
902 lines (901 loc) • 47.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AD02_BLE = void 0;
const protocol_1 = require("../../protocol");
const constant_1 = require("./constant");
const util_1 = require("./util");
/** JX-AD02 BLE蓝牙协议 */
class AD02_BLE {
//#region 硬件版本
/**
* 读取硬件版本指令
* @returns 可直接下发的蓝牙通信指令
*/
static readHardwareVersionCMD() {
const lengthHex = util_1.Util.getLengthHex();
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.ReadHardwareVersion);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.ReadHardwareVersion, sumCheckHex);
}
/**
* 解析硬件版本
* @param data 读取硬件版本蓝牙返回数据帧
* @returns 硬件版本(ASCII字符串)
*/
static resolveHardwareVersion(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.ReadHardwareVersion); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是硬件版本的ASCII编码
return util_1.Util.hexStrToASCII(util_1.Util.uint8ArrayToHexStr(payload));
}
//#endregion
//#region 软件版本
/**
* 读取软件版本指令
* @returns 可直接下发的蓝牙通信指令
*/
static readSoftwareVersionCMD() {
const lengthHex = util_1.Util.getLengthHex();
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.ReadSoftwareVersion);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.ReadSoftwareVersion, sumCheckHex);
}
/**
* 解析软件版本
* @param data 读取硬件版本蓝牙返回数据帧
* @returns 软件版本(ASCII字符串)
*/
static resolveSoftwareVersion(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.ReadSoftwareVersion); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是软件版本的ASCII编码
return util_1.Util.hexStrToASCII(util_1.Util.uint8ArrayToHexStr(payload));
}
//#endregion
//#region 协议版本
/**
* 读取协议版本指令
* @returns 可直接下发的蓝牙通信指令
*/
static readProtocolVersionCMD() {
const lengthHex = util_1.Util.getLengthHex();
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.ReadProtocolVersion);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.ReadProtocolVersion, sumCheckHex);
}
/**
* 解析协议版本
* @param data 读取协议版本蓝牙返回数据帧
* @returns 协议版本(ASCII字符串)
*/
static resolveProtocolVersion(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.ReadProtocolVersion); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是软件版本的ASCII编码
return util_1.Util.hexStrToASCII(util_1.Util.uint8ArrayToHexStr(payload));
}
//#endregion
//#region 密码校验
/**
* 获取密码校验指令
* @param password 密码(ASCII字符)
* @returns 可直接下发的蓝牙通信指令
*/
static passwordCheckCMD(password) {
if (password.length !== 4)
throw new Error('密码长度不正确');
const payloadHex = util_1.Util.asciiToHexStr(password);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.PasswordCheck, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.PasswordCheck, sumCheckHex, payloadHex);
}
/**
* 密码验证蓝牙返回内容解析
* @param data 密码验证蓝牙返回数据帧
* @returns 密码验证结果
*/
static resolvePasswordCheck(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.PasswordCheck); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是密码校验结果的ASCII编码
const result = util_1.Util.hexStrToASCII(util_1.Util.uint8ArrayToHexStr(payload));
if (result === 'OK')
return true;
if (result === 'Er')
return false;
throw new Error('未知验证结果:' + result);
}
//#endregion
//#region 密码设置
/**
* 获取设置密码指令
* @param password 密码(ASCII字符)
* @returns 可直接下发的蓝牙通信指令
*/
static setPasswordCMD(password) {
if (password.length !== 4)
throw new Error('密码长度不正确');
const payloadHex = util_1.Util.asciiToHexStr(password);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.PasswordSet, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.PasswordSet, sumCheckHex, payloadHex);
}
/**
* 设置密码蓝牙返回内容解析
* @param data 设置密码蓝牙返回数据帧
* @returns 密码设置结果
*/
static resolveSetPassword(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.PasswordSet); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是密码设置结果的ASCII编码
const result = util_1.Util.hexStrToASCII(util_1.Util.uint8ArrayToHexStr(payload));
if (result === 'OK')
return true;
if (result === 'Er')
return false;
throw new Error('未知设置结果:' + result);
}
//#endregion
//#region 输入(AI)相关
/**
* 获取模拟量输入(AI)类型(量程)指令
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @returns 可直接下发的蓝牙通信指令
*/
static readAITypeCMD(channel) {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataType(parseInt(`2${channel}00`, 16), protocol_1.ModbusDataType.U16);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取模拟量输入(AI)类型(量程)蓝牙返回内容解析
* @param data 读取AI类型(量程)蓝牙返回数据帧
* @returns AI量程类型,0——电压(0-10V);1——电流(0-24mA)
*/
static resolveAIType(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AI量程的 Modbus PDU 格式数据
return protocol_1.ModbusPDU.resolveHoldResByDataType(util_1.Util.uint8ArrayToHexStr(payload), protocol_1.ModbusDataType.U16);
}
/**
* 获取写入AI量程/类型指令
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @param type AI量程类型,0——电压(0-10V);1——电流(0-24mA)
* @returns 可直接下发的蓝牙通信指令
*/
static writeAITypeCMD(channel, type) {
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(parseInt(`2${channel}00`, 16), [[type, protocol_1.ModbusDataType.U16]]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 设置AI量程返回内容解析
* @param data 设置AI量程蓝牙返回数据帧
* @param channel AI通道。0——AI1;1——AI2
* @returns 写入结果
*/
static resolveWriteAITypeRes(data, channel) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是设置AI量程返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === parseInt(`2${channel}00`, 16) && count === 1;
}
/**
* 获取模拟量输入测量值指令
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @returns 可直接下发的蓝牙通信指令
*/
static readAICMD(channel) {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataType(parseInt(`F1${channel}5`, 16), protocol_1.ModbusDataType.U16);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取模拟量输入测量值蓝牙返回内容解析
* @param data 读取AI测量值蓝牙返回数据帧
* @returns AI测量值,电压0~10000,电流0~24000
*/
static resolveAI(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AI测量值的 Modbus PDU 格式数据
return protocol_1.ModbusPDU.resolveHoldResByDataType(util_1.Util.uint8ArrayToHexStr(payload), protocol_1.ModbusDataType.U16);
}
/**
* 获取模拟量输入运算后的值指令
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @returns 可直接下发的蓝牙通信指令
*/
static readUserAICMD(channel) {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataType(parseInt(`F1${channel}6`, 16), protocol_1.ModbusDataType.FLOAT);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取模拟量输入运算值蓝牙返回内容解析
* @param data 读取AI运算值蓝牙返回数据帧
* @returns AI运算值,浮点数
*/
static resolveUserAI(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AI运算值的 Modbus PDU 格式数据
return protocol_1.ModbusPDU.resolveHoldResByDataType(util_1.Util.uint8ArrayToHexStr(payload), protocol_1.ModbusDataType.FLOAT);
}
/**
* 获取模拟量输入(AI)用户自定义运算指令
* @description 由于双层四则运算的运算符和运算值在寄存器排列上连续,所以这里一次读取。
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @returns 可直接下发的蓝牙通信指令
*/
static readAICalculate(channel) {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataTypeList(parseInt(`2${channel}10`, 16), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.I16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.I16,
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取模拟量输入(AI)用户自定义运算返回内容解析
* @param data 读取模拟量输入运算蓝牙返回数据帧
* @returns 模拟量双层四则运算内容
*/
static resolveAICalculate(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是双层四则运算的 Modbus PDU 格式数据
const [operator1, value1, operator2, value2] = protocol_1.ModbusPDU.resolveHoldResByDataTypeList(util_1.Util.uint8ArrayToHexStr(payload), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.I16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.I16,
]);
return { operator1, value1, operator2, value2 };
}
/**
* 获取写入用户自定义运算公式配置指令
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @param formula 运算公式内容
* @returns 可直接下发的蓝牙通信指令
*/
static writeAICalculateCMD(channel, formula) {
if (!Number.isInteger(formula.value1) || !Number.isInteger(formula.value2))
throw new Error('运算数必须为整数');
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(parseInt(`2${channel}10`, 16), [
[formula.operator1, protocol_1.ModbusDataType.U16],
[formula.value1, protocol_1.ModbusDataType.I16],
[formula.operator2, protocol_1.ModbusDataType.U16],
[formula.value2, protocol_1.ModbusDataType.I16],
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 设置AI运算公式返回内容解析
* @param data 设置AI运算公式蓝牙返回数据帧
* @param channel AI通道。0——AI1;1——AI2
* @returns 写入结果
*/
static resolveWriteAICalculateRes(data, channel) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是写入AI运算公式返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === parseInt(`2${channel}10`, 16) && count === 4;
}
/**
* 获取AI校准配置指令
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @param type 通道类型,2——电压;3——电流
* @returns 可直接下发的蓝牙通信指令
*/
static readAICalibrateCMD(channel, type) {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataTypeList(parseInt(`2${channel}${type}0`, 16), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取AI校准配置返回内容解析
* @param data 读取AI校准配置蓝牙返回数据帧
* @returns 4个校准点数据的元组类型
*/
static resolveAICalibrate(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AI校验配置的 Modbus PDU 格式数据
return protocol_1.ModbusPDU.resolveHoldResByDataTypeList(util_1.Util.uint8ArrayToHexStr(payload), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
]);
}
/**
* 设置AI校准指令
* @deprecated 请使用下面的V2版方法
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @param type 通道类型,2——电压;3——电流
* @param valueList 校准值列表
* @returns 可直接下发的蓝牙通信指令
*/
static calibrateAICMD(channel, type, valueList) {
for (const value of valueList) {
if (!Number.isInteger(value))
throw new Error('校准值必须为整数');
}
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(parseInt(`2${channel}${type}0`, 16), valueList.map((value) => [value, protocol_1.ModbusDataType.U16]));
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* AI校准返回内容解析
* @deprecated 请使用下面的V2版方法
* @param data AI校准蓝牙返回数据帧
* @param channel AI通道。0——AI1;1——AI2
* @param type 通道类型,2——电压;3——电流
* @returns 校准结果
*/
static resolveCalibrateAIRes(data, channel, type) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AI校准返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === parseInt(`2${channel}${type}0`, 16) && count === 4;
}
/**
* 设置AI校准指令—V2版
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @param type 通道类型,2——电压;3——电流
* @param point 校准点
* @param value 校准值
* @returns 可直接下发的蓝牙通信指令
*/
static calibrateAICMD_V2(channel, type, point, value) {
if (!Number.isInteger(value))
throw new Error('校准值必须为整数');
const payloadHex = protocol_1.ModbusPDU.writeHoldByDataTypeCMD(parseInt(`2${channel}${type}${point - 1}`, 16), value, protocol_1.ModbusDataType.U16);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* AI校准返回内容解析—V2版
* @param data 下发AI校准指令蓝牙返回数据帧
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @param type 通道类型,2——电压;3——电流
* @param point 校准点
* @param value 校准值
* @returns AI校准结果
*/
static resolveCalibrateAIRes_V2(data, channel, type, point, value) {
if (!Number.isInteger(value))
throw new Error('校准值必须为整数');
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是下发AI校准指令返回结果的 Modbus PDU 格式数据
try {
return protocol_1.ModbusPDU.resolveWriteHoldByDataTypeRes(util_1.Util.uint8ArrayToHexStr(payload), parseInt(`2${channel}${type}${point - 1}`, 16), value, protocol_1.ModbusDataType.U16);
}
catch (error) {
if (error.message === '未知错误码FF')
throw new Error('无权限'); // 支持自定义无权限错误
throw error;
}
}
/**
* 读取AI自动上报配置指令
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @returns 可直接下发的蓝牙通信指令
*/
static readAIUploadCMD(channel) {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataTypeList(parseInt(`2${channel}40`, 16), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.I16,
protocol_1.ModbusDataType.I16,
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取AI上报配置返回内容解析
* @param data 获取AI上报配置蓝牙返回数据帧
* @returns AI上报配置
*/
static resolveAIUpload(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AI上报的 Modbus PDU 格式数据
const [typeValue, minChangeValue, timerValue, minZoneValue, maxZoneValue] = protocol_1.ModbusPDU.resolveHoldResByDataTypeList(util_1.Util.uint8ArrayToHexStr(payload), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.I16,
protocol_1.ModbusDataType.I16,
]);
const typeList = [];
if ((typeValue & constant_1.AD02_AIUploadType.Change) === constant_1.AD02_AIUploadType.Change)
typeList.push(constant_1.AD02_AIUploadType.Change);
if ((typeValue & constant_1.AD02_AIUploadType.Timer) === constant_1.AD02_AIUploadType.Timer)
typeList.push(constant_1.AD02_AIUploadType.Timer);
if ((typeValue & constant_1.AD02_AIUploadType.LessZone) === constant_1.AD02_AIUploadType.LessZone)
typeList.push(constant_1.AD02_AIUploadType.LessZone);
if ((typeValue & constant_1.AD02_AIUploadType.InZone) === constant_1.AD02_AIUploadType.InZone)
typeList.push(constant_1.AD02_AIUploadType.InZone);
if ((typeValue & constant_1.AD02_AIUploadType.MoreZone) === constant_1.AD02_AIUploadType.MoreZone)
typeList.push(constant_1.AD02_AIUploadType.MoreZone);
return { typeList, minChangeValue, timerValue, minZoneValue, maxZoneValue };
}
/**
* 获取设置AI上报配置指令
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @param typeList 上报类型列表
* @param minChangeValue 变化最小值,UInt16格式
* @param timerValue 定时时间,单位:秒,UInt16格式
* @param minZoneValue 区间下限值,Int16格式
* @param maxZoneValue 区间上限值,Int16格式
* @returns 可直接下发的蓝牙通信指令
*/
static setAIUploadCMD(channel, typeList, minChangeValue, timerValue, minZoneValue, maxZoneValue) {
if (!Number.isInteger(minChangeValue) || minChangeValue < 0)
throw new Error('变化最小值格式不正确');
if (!Number.isInteger(timerValue) || timerValue < 0)
throw new Error('定时时间格式不正确');
if (!Number.isInteger(minZoneValue))
throw new Error('区间下限值格式不正确');
if (!Number.isInteger(maxZoneValue))
throw new Error('区间上限值格式不正确');
const typeValue = typeList.reduce((a, b) => a + b, 0);
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(parseInt(`2${channel}40`, 16), [
[typeValue, protocol_1.ModbusDataType.U16],
[minChangeValue, protocol_1.ModbusDataType.U16],
[timerValue, protocol_1.ModbusDataType.U16],
[minZoneValue, protocol_1.ModbusDataType.I16],
[maxZoneValue, protocol_1.ModbusDataType.I16],
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 配置AI上报返回内容解析
* @param data 配置AI上报蓝牙返回数据帧
* @param channel 模拟量输入通道。0——AI1;1——AI2
* @returns 上报配置设置结果
*/
static resolveAIUploadRes(data, channel) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AI校准返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === parseInt(`2${channel}40`, 16) && count === 5;
}
//#endregion
//#region 输出(AO)相关
/**
* 获取模拟量输出(AO)的值指令
* @description 由于两个AO输出的值寄存器排列连续,所以这里**一次读取两个值**。
* @returns 可直接下发的蓝牙通信指令
*/
static readAOCMD() {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataTypeList(0, [protocol_1.ModbusDataType.U16, protocol_1.ModbusDataType.U16]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取模拟量输出(AO)的值返回内容解析
* @param data 读取AO数据蓝牙返回数据帧
* @returns AO值,元组格式,单位为毫伏
*/
static resolveAO(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AO值的 Modbus PDU 格式数据
return protocol_1.ModbusPDU.resolveHoldResByDataTypeList(util_1.Util.uint8ArrayToHexStr(payload), [protocol_1.ModbusDataType.U16, protocol_1.ModbusDataType.U16]);
}
/**
* 获取控制模拟量输出(AO)的指令
* @description 由于两个AO输出的值寄存器排列连续,所以这里**一次写入两个值**。
* @param ao1 AO1的控制值,单位:**毫伏**,合法范围为:`0-10000`
* @param ao2 AO2的控制值,单位:**毫伏**,合法范围为:`0-10000`
* @returns 可直接下发的蓝牙通信指令
*/
static writeAOCMD(ao1, ao2) {
if (ao1 < 0 || ao1 > 10000)
throw new Error('AO1超范围');
if (ao2 < 0 || ao2 > 10000)
throw new Error('AO2超范围');
if (!Number.isInteger(ao1))
throw new Error('AO1非正整数');
if (!Number.isInteger(ao2))
throw new Error('AO2非正整数');
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(0, [
[ao1, protocol_1.ModbusDataType.U16],
[ao2, protocol_1.ModbusDataType.U16],
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 写入控制AO值返回内容解析
* @param data 写入控制AO值蓝牙返回数据帧
* @returns 写入控制结果
*/
static resolveWriteAORes(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是写入AO值返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === 0 && count === 2;
}
/**
* 读取AO上电初始值指令
* @param channel 模拟量输出通道。0——AO1;1——AO2
* @returns 可直接下发的蓝牙通信指令
*/
static readAOInitCMD(channel) {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataTypeList(parseInt(`3${channel}01`, 16), [protocol_1.ModbusDataType.U16]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 读取AO上电初始值返回内容解析
* @param data 读取AO上电初始值蓝牙返回数据帧
* @returns AO上电初始值,单位:毫伏,UInt16格式
*/
static resolveAOInit(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AO上电初始值的 Modbus PDU 格式数据
return protocol_1.ModbusPDU.resolveHoldResByDataType(util_1.Util.uint8ArrayToHexStr(payload), protocol_1.ModbusDataType.U16);
}
/**
* 获取设置AO上电初始值指令
* @param channel AO通道。0——AO1;1——AO2
* @param initValue 上电初始值,单位:毫伏,范围:0-10000
* @returns 可直接下发的蓝牙通信指令
*/
static writeAOInitCMD(channel, initValue) {
if (initValue < 0 || initValue > 10000)
throw new Error('AO初始值超范围');
if (!Number.isInteger(initValue))
throw new Error('AO初始值非正整数');
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(parseInt(`3${channel}01`, 16), [[initValue, protocol_1.ModbusDataType.U16]]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 设置AO上电初始值返回内容解析
* @param data 写入AO上电初始值值蓝牙返回数据帧
* @param channel AO通道。0——AO1;1——AO2
* @returns 写入控制结果
*/
static resolveWriteAOInitRes(data, channel) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是写入AO上电初始值返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === parseInt(`3${channel}01`, 16) && count === 1;
}
/**
* 读取AO周期输出配置指令
* @param channel 模拟量输出通道。0——AO1;1——AO2
* @returns 可直接下发的蓝牙通信指令
*/
static readAOOutputCMD(channel) {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataTypeList(parseInt(`3${channel}10`, 16), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16, // 第7段持续时间
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取AO周期输出配置返回内容解析
* @param data 读取AO周期输出配置蓝牙返回数据帧
* @returns AO周期输出配置
*/
static resolveAOOutput(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是AO周期输出配置的 Modbus PDU 格式数据
const [period, voltage1, delay1, voltage2, delay2, voltage3, delay3, voltage4, delay4, voltage5, delay5, voltage6, delay6, voltage7, delay7] = protocol_1.ModbusPDU.resolveHoldResByDataTypeList(util_1.Util.uint8ArrayToHexStr(payload), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16, // 第7段持续时间
]);
return {
period,
voltage1,
delay1,
voltage2,
delay2,
voltage3,
delay3,
voltage4,
delay4,
voltage5,
delay5,
voltage6,
delay6,
voltage7,
delay7,
};
}
/**
* 生成AO周期输出配置下发指令
* @param channel 模拟量输出通道。0——AO1;1——AO2
* @param output AO周期输出配置
* @returns 可直接下发的蓝牙通信指令
*/
static writeAOOutputCMD(channel, output) {
if (!Number.isInteger(output.period))
throw new Error('周期数量必须为整数');
if (output.period < 0 || output.period > 7)
throw new Error('周期数量超范围');
if (!Number.isInteger(output.delay1) ||
output.delay1 < 0 ||
!Number.isInteger(output.delay2) ||
output.delay2 < 0 ||
!Number.isInteger(output.delay3) ||
output.delay3 < 0 ||
!Number.isInteger(output.delay4) ||
output.delay4 < 0 ||
!Number.isInteger(output.delay5) ||
output.delay5 < 0 ||
!Number.isInteger(output.delay6) ||
output.delay6 < 0 ||
!Number.isInteger(output.delay7) ||
output.delay7 < 0)
throw new Error('延迟时间必须为非负整数');
if (!Number.isInteger(output.voltage1) ||
output.voltage1 < 0 ||
!Number.isInteger(output.voltage2) ||
output.voltage2 < 0 ||
!Number.isInteger(output.voltage3) ||
output.voltage3 < 0 ||
!Number.isInteger(output.voltage4) ||
output.voltage4 < 0 ||
!Number.isInteger(output.voltage5) ||
output.voltage5 < 0 ||
!Number.isInteger(output.voltage6) ||
output.voltage6 < 0 ||
!Number.isInteger(output.voltage7) ||
output.voltage7 < 0)
throw new Error('输出电压必须为非负整数');
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(parseInt(`3${channel}10`, 16), [
[output.period, protocol_1.ModbusDataType.U16],
[output.voltage1, protocol_1.ModbusDataType.U16],
[output.delay1, protocol_1.ModbusDataType.U16],
[output.voltage2, protocol_1.ModbusDataType.U16],
[output.delay2, protocol_1.ModbusDataType.U16],
[output.voltage3, protocol_1.ModbusDataType.U16],
[output.delay3, protocol_1.ModbusDataType.U16],
[output.voltage4, protocol_1.ModbusDataType.U16],
[output.delay4, protocol_1.ModbusDataType.U16],
[output.voltage5, protocol_1.ModbusDataType.U16],
[output.delay5, protocol_1.ModbusDataType.U16],
[output.voltage6, protocol_1.ModbusDataType.U16],
[output.delay6, protocol_1.ModbusDataType.U16],
[output.voltage7, protocol_1.ModbusDataType.U16],
[output.delay7, protocol_1.ModbusDataType.U16],
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 设置AO周期输出配置返回内容解析
* @param data 写入AO周期输出配置蓝牙返回数据帧
* @param channel AO通道。0——AO1;1——AO2
* @returns 写入控制结果
*/
static resolveWriteAOOutputRes(data, channel) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是写入AO周期输出配置返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === parseInt(`3${channel}10`, 16) && count === 15;
}
//#endregion
//#region 通信配置
/**
* 读取串口参数配置指令
* @returns 可直接下发的蓝牙通信指令
*/
static readUartConfigCMD() {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataTypeList(0x1000, [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16, // 停止位
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取串口参数配置返回内容解析
* @param data 读取串口参数蓝牙返回数据帧
* @returns 串口参数配置
*/
static resolveUartConfig(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是串口参数配置的 Modbus PDU 格式数据
const [baudrate, databits, parity, stopbits] = protocol_1.ModbusPDU.resolveHoldResByDataTypeList(util_1.Util.uint8ArrayToHexStr(payload), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16, // 停止位
]);
return { baudrate, databits, parity, stopbits };
}
/**
* 生成串口参数配置下发指令
* @param config 串口参数配置
* @returns 可直接下发的蓝牙通信指令
*/
static writeUartConfigCMD(config) {
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(0x1000, [
[config.baudrate, protocol_1.ModbusDataType.U16],
[config.databits, protocol_1.ModbusDataType.U16],
[config.parity, protocol_1.ModbusDataType.U16],
[config.stopbits, protocol_1.ModbusDataType.U16],
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 配置串口参数返回内容解析
* @param data 配置串口参数蓝牙返回数据帧
* @returns 串口参数配置结果
*/
static resolveWriteUartConfigRes(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是配置串口参数返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === 0x1000 && count === 4;
}
/**
* 读取Modbus配置指令
* @returns 可直接下发的蓝牙通信指令
*/
static readModbusConfigCMD() {
const payloadHex = protocol_1.ModbusPDU.readHoldCMDByDataTypeList(0x1020, [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16, // 分帧时间,单位:毫秒
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 获取Modbus参数配置返回内容解析
* @param data 读取Modbus参数蓝牙返回数据帧
* @returns Modbus参数配置
*/
static resolveModbusConfig(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是Modbus参数配置的 Modbus PDU 格式数据
const [slaveId, timeout] = protocol_1.ModbusPDU.resolveHoldResByDataTypeList(util_1.Util.uint8ArrayToHexStr(payload), [
protocol_1.ModbusDataType.U16,
protocol_1.ModbusDataType.U16, // 分帧时间,单位:毫秒
]);
return { slaveId, timeout };
}
/**
* 生成Modbus参数配置下发指令
* @param config Modbus参数
* @returns 可直接下发的蓝牙通信指令
*/
static writeModbusConfigCMD(config) {
if (!Number.isInteger(config.slaveId))
throw new Error('从机地址非整数');
if (config.slaveId < 1 || config.slaveId > 255)
throw new Error('从机地址超范围');
if (!Number.isInteger(config.timeout) || config.timeout < 0)
throw new Error('分帧时间不是非负整数');
const payloadHex = protocol_1.ModbusPDU.writeMultiHoldByDataTypeListCMD(0x1020, [
[config.slaveId, protocol_1.ModbusDataType.U16],
[config.timeout, protocol_1.ModbusDataType.U16],
]);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 配置Modbus参数返回内容解析
* @param data 配置Modbus参数蓝牙返回数据帧
* @returns Modbus参数配置结果
*/
static resolveWriteModbusConfigRes(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是配置Modbus参数返回结果的 Modbus PDU 格式数据
const [address, count] = protocol_1.ModbusPDU.resolveWriteMultiHoldRes(util_1.Util.uint8ArrayToHexStr(payload));
return address === 0x1020 && count === 2;
}
//#endregion
//#region 操作命令
/**
* 获取重启指令
* @returns 可直接下发的蓝牙通信指令
*/
static rebootCMD() {
const payloadHex = protocol_1.ModbusPDU.writeHoldByDataTypeCMD(0xffff, constant_1.OperateCMD.Reboot, protocol_1.ModbusDataType.U16);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 下发重启指令返回内容解析
* @param data 下发重启指令蓝牙返回数据帧
* @returns 重启结果
*/
static resolveRebootRes(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是下发重启指令返回结果的 Modbus PDU 格式数据
try {
return protocol_1.ModbusPDU.resolveWriteHoldByDataTypeRes(util_1.Util.uint8ArrayToHexStr(payload), 0xffff, constant_1.OperateCMD.Reboot, protocol_1.ModbusDataType.U16);
}
catch (error) {
if (error.message === '未知错误码FF')
throw new Error('无权限'); // 支持自定义无权限错误
throw error;
}
}
/**
* 获取恢复出厂设置并重启指令
* @returns 可直接下发的蓝牙通信指令
*/
static recoveryCMD() {
const payloadHex = protocol_1.ModbusPDU.writeHoldByDataTypeCMD(0xffff, constant_1.OperateCMD.Recovery, protocol_1.ModbusDataType.U16);
const lengthHex = util_1.Util.getLengthHex(payloadHex);
const sumCheckHex = util_1.Util.getSumCheckHex(lengthHex, constant_1.BLE_CMD.Modbus, payloadHex);
return util_1.Util.getBLE_CMD(lengthHex, constant_1.BLE_CMD.Modbus, sumCheckHex, payloadHex);
}
/**
* 下发恢复出厂设置指令返回内容解析
* @param data 下发恢复出厂设置指令蓝牙返回数据帧
* @returns 恢复出厂设置结果
*/
static resolveRecoveryRes(data) {
util_1.Util.formatCheck(data, constant_1.BLE_CMD.Modbus); // * 蓝牙数据帧格式校验
const payload = util_1.Util.getPayload(data); // * 获取数据域内容,此部分就是下发恢复出厂设置指令返回结果的 Modbus PDU 格式数据
try {
return protocol_1.ModbusPDU.resolveWriteHoldByDataTypeRes(util_1.Util.uint8ArrayToHexStr(payload), 0xffff, constant_1.OperateCMD.Recovery, protocol_1.ModbusDataType.U16);
}
catch (error) {
if (error.message === '未知错误码FF')
throw new Error('无权限'); // 支持自定义无权限错误
throw error;
}
}
}
exports.AD02_BLE = AD02_BLE;