@iot9x.com/ipc-utils
Version:
九星云、九星小程序、九星配置工具所共用的库方法
268 lines (267 loc) • 15.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CJT188 = void 0;
const util_1 = require("./util");
const constant_1 = require("./constant");
const water_1 = require("./resolve/water");
const gas_1 = require("./resolve/gas");
const heat_1 = require("./resolve/heat");
class CJT188 {
constructor(params) {
/** 唤醒码 */
this.wakeUpCode = 'FE';
/**
* 唤醒长度
* @default 4
* @description 默认为4,则表示命令格式为:FE FE FE FE 68 ……
*/
this.wakeUpLength = 4;
/**
* 表地址,A0~A6
* @description 默认为广播地址,这里存储的是已经对齐并转小端之后的格式
* @default 'AAAAAAAAAAAAAA'
*/
this.address = 'AAAAAAAAAAAAAA';
/** 序列号 */
this.ser = 0;
this.optionValidate(params);
if (params === null || params === void 0 ? void 0 : params.wakeUpCode)
this.wakeUpCode = params.wakeUpCode;
if (params === null || params === void 0 ? void 0 : params.wakeUpLength)
this.wakeUpLength = params.wakeUpLength;
if (params === null || params === void 0 ? void 0 : params.address)
this.address = params.address.padStart(14, '0').match(/\w{2}/g).reverse().join('');
if (params === null || params === void 0 ? void 0 : params.ser)
this.ser = params.ser;
if (params === null || params === void 0 ? void 0 : params.meterType)
this.meterType = params.meterType;
}
/**
* 参数校验
* @param options 参数
* @param checkMeterType 是否校验仪表类型
*/
optionValidate(options, checkMeterType) {
if (options === null || options === void 0 ? void 0 : options.wakeUpCode) {
if (options.wakeUpCode.length % 2)
throw new Error('唤醒码长度不正确');
if (!/^\w+$/i.test(options.wakeUpCode))
throw new Error('唤醒码必须为十六进制字符串');
}
if (options === null || options === void 0 ? void 0 : options.wakeUpLength) {
if (options.wakeUpLength < 0)
throw new Error('唤醒长度不可小于0');
if (!Number.isInteger(options.wakeUpLength))
throw new Error('唤醒长度必须为整数');
}
if (options === null || options === void 0 ? void 0 : options.address) {
if (!/^\w+$/i.test(options.address))
throw new Error('表地址必须为十六进制字符串');
const address = options.address.padStart(14, '0');
if (address.length !== 14)
throw new Error('表地址长度不正确');
}
if (options === null || options === void 0 ? void 0 : options.ser) {
if (options.ser < 0 || options.ser > 0xff)
throw new Error('序列号范围不正确');
if (!Number.isInteger(options.ser))
throw new Error('序列号格式不正确');
}
if (checkMeterType) {
const meterType = (options === null || options === void 0 ? void 0 : options.meterType) || this.meterType;
if (!meterType)
throw new Error('请明确仪表类型');
}
}
//#region 读计量数据
/**
* 获取读计量数据命令
* @param options 生成参数
* @returns 读计量数据命令
*/
readMeteringDataCMD(options) {
this.optionValidate(options, true); // * 额外参数校验
const wakeUpHex = util_1.Util.getWakeUpHex((options === null || options === void 0 ? void 0 : options.wakeUpCode) || this.wakeUpCode, (options === null || options === void 0 ? void 0 : options.wakeUpLength) || this.wakeUpLength);
const meterTypeHex = ((options === null || options === void 0 ? void 0 : options.meterType) || this.meterType).toString(16).padStart(2, '0');
const addressHex = (options === null || options === void 0 ? void 0 : options.address) ? options.address.padStart(14, '0').match(/\w{2}/g).reverse().join('') : this.address;
const controlHex = constant_1.ControlCode.ReadData.toString(16).padStart(2, '0');
const dataLengthHex = '03';
const dataIdentifierHex = constant_1.DataIdentifier.ReadMeteringData.toString(16).padStart(4, '0');
const serHex = ((options === null || options === void 0 ? void 0 : options.ser) || this.ser).toString(16).padStart(2, '0');
const payloadHex = constant_1.FRAME_PREFIX + meterTypeHex + addressHex + controlHex + dataLengthHex + dataIdentifierHex + serHex;
const csHex = util_1.Util.getCS(payloadHex);
const cmdHex = wakeUpHex + payloadHex + csHex + constant_1.FRAME_SUFFIX;
this.ser = (this.ser + 1) % 256; // * 序列化+1
return util_1.Util.hexToUint8Array(cmdHex);
}
/**
* 获取读计量数据命令
* @param options 生成参数
* @returns 读计量数据命令
*/
static readMeteringDataCMD(options) {
return new CJT188(options).readMeteringDataCMD(options);
}
/**
* 读计量数据返回内容解析
* @param data 读计量数据从站返回数据
* @param options 额外参数
* @returns 读计量数据返回内容
*/
resolveReadMeteringDataRes(data, options) {
this.optionValidate(options, true); // * 额外参数校验
const { meterType, address, dataIdentifier, dataPayload } = util_1.Util.unpacking(data, (options === null || options === void 0 ? void 0 : options.wakeUpCode) || this.wakeUpCode, constant_1.ControlCode.ReadData);
if (dataIdentifier !== constant_1.DataIdentifier.ReadMeteringData)
throw new Error(`标识符应为0x${constant_1.DataIdentifier.ReadMeteringData.toString(16).toUpperCase().padStart(4, '0')},实为0x${dataIdentifier
.toString(16)
.toUpperCase()
.padStart(4, '0')}`);
if ((meterType & constant_1.CJT188MeterType.WaterMeter) === constant_1.CJT188MeterType.WaterMeter)
return water_1.WaterResolve.readMeteringData(dataPayload, address);
if ((meterType & constant_1.CJT188MeterType.GasMeter) === constant_1.CJT188MeterType.GasMeter)
return gas_1.GasResolve.readMeteringData(dataPayload, address);
if ((meterType & constant_1.CJT188MeterType.HeatMeter) === constant_1.CJT188MeterType.HeatMeter)
return heat_1.HeatResolve.readMeteringData(dataPayload, address);
throw new Error('暂不支持其他仪表数据解析');
}
/**
* 读计量数据返回内容解析
* @param data 读计量数据从站返回数据
* @param options 额外参数
* @returns 读计量数据返回内容
*/
static resolveReadMeteringDataRes(data, options) {
return new CJT188(options).resolveReadMeteringDataRes(data, options);
}
//#endregion
//#region 读地址
/**
* 获取读仪表地址命令
* @param options 生成参数
* @returns 读仪表地址命令
*/
readAddressCMD(options) {
this.optionValidate(options, true); // * 额外参数校验
const wakeUpHex = util_1.Util.getWakeUpHex((options === null || options === void 0 ? void 0 : options.wakeUpCode) || this.wakeUpCode, (options === null || options === void 0 ? void 0 : options.wakeUpLength) || this.wakeUpLength);
const meterTypeHex = ((options === null || options === void 0 ? void 0 : options.meterType) || this.meterType).toString(16).padStart(2, '0');
const addressHex = (options === null || options === void 0 ? void 0 : options.address) ? options.address.padStart(14, '0').match(/\w{2}/g).reverse().join('') : this.address;
const controlHex = constant_1.ControlCode.ReadAddress.toString(16).padStart(2, '0');
const dataLengthHex = '03';
const dataIdentifierHex = constant_1.DataIdentifier.ReadAddress.toString(16).padStart(4, '0');
const serHex = ((options === null || options === void 0 ? void 0 : options.ser) || this.ser).toString(16).padStart(2, '0');
const payloadHex = constant_1.FRAME_PREFIX + meterTypeHex + addressHex + controlHex + dataLengthHex + dataIdentifierHex + serHex;
const csHex = util_1.Util.getCS(payloadHex);
const cmdHex = wakeUpHex + payloadHex + csHex + constant_1.FRAME_SUFFIX;
this.ser = (this.ser + 1) % 256; // * 序列化+1
return util_1.Util.hexToUint8Array(cmdHex);
}
/**
* 获取读仪表地址命令
* @param options 生成参数
* @returns 读仪表地址命令
*/
static readAddressCMD(options) {
return new CJT188(options).readAddressCMD(options);
}
/**
* 读仪表地址返回内容解析
* @param data 读仪表地址从站返回数据
* @param options 额外参数
* @returns 读仪表地址返回内容
*/
resolveReadAddressRes(data, options) {
this.optionValidate(options, true); // * 额外参数校验
const { address, dataIdentifier } = util_1.Util.unpacking(data, (options === null || options === void 0 ? void 0 : options.wakeUpCode) || this.wakeUpCode, constant_1.ControlCode.ReadAddress);
if (dataIdentifier !== constant_1.DataIdentifier.ReadAddress)
throw new Error(`标识符应为0x${constant_1.DataIdentifier.ReadAddress.toString(16).toUpperCase().padStart(4, '0')},实为0x${dataIdentifier
.toString(16)
.toUpperCase()
.padStart(4, '0')}`);
return address;
}
/**
* 读仪表地址返回内容解析
* @param data 读仪表地址从站返回数据
* @param options 额外参数
* @returns 读仪表地址返回内容
*/
static resolveReadAddressRes(data, options) {
return new CJT188(options).resolveReadAddressRes(data, options);
}
//#endregion
//#region 读历史数据
/**
* 获取读历史数据命令
* @param options 生成参数
* @returns 读历史数据命令
*/
readHistoryDataCMD(month, options) {
this.optionValidate(options, true); // * 额外参数校验
const wakeUpHex = util_1.Util.getWakeUpHex((options === null || options === void 0 ? void 0 : options.wakeUpCode) || this.wakeUpCode, (options === null || options === void 0 ? void 0 : options.wakeUpLength) || this.wakeUpLength);
const meterTypeHex = ((options === null || options === void 0 ? void 0 : options.meterType) || this.meterType).toString(16).padStart(2, '0');
const addressHex = (options === null || options === void 0 ? void 0 : options.address) ? options.address.padStart(14, '0').match(/\w{2}/g).reverse().join('') : this.address;
const controlHex = constant_1.ControlCode.ReadData.toString(16).padStart(2, '0');
const dataLengthHex = '03';
const dataIdentifierHex = constant_1.DataIdentifier[`ReadHistoryData${month}`].toString(16).padStart(4, '0');
const serHex = ((options === null || options === void 0 ? void 0 : options.ser) || this.ser).toString(16).padStart(2, '0');
const payloadHex = constant_1.FRAME_PREFIX + meterTypeHex + addressHex + controlHex + dataLengthHex + dataIdentifierHex + serHex;
const csHex = util_1.Util.getCS(payloadHex);
const cmdHex = wakeUpHex + payloadHex + csHex + constant_1.FRAME_SUFFIX;
this.ser = (this.ser + 1) % 256; // * 序列化+1
return util_1.Util.hexToUint8Array(cmdHex);
}
/**
* 获取读历史数据命令
* @param options 生成参数
* @returns 读历史数据命令
*/
static readHistoryDataCMD(month, options) {
return new CJT188(options).readHistoryDataCMD(month, options);
}
//#endregion
//#region 写阀门控制
// TODO: 写入相关方法(写数据、写地址、写机电同步数据)
/**
* 获取开启阀门命令
* @param options 生成参数
* @returns 开启阀门命令
*/
writeOpenValveCMD(options) {
this.optionValidate(options, true); // * 额外参数校验
const wakeUpHex = util_1.Util.getWakeUpHex((options === null || options === void 0 ? void 0 : options.wakeUpCode) || this.wakeUpCode, (options === null || options === void 0 ? void 0 : options.wakeUpLength) || this.wakeUpLength);
const meterTypeHex = ((options === null || options === void 0 ? void 0 : options.meterType) || this.meterType).toString(16).padStart(2, '0');
const addressHex = (options === null || options === void 0 ? void 0 : options.address) ? options.address.padStart(14, '0').match(/\w{2}/g).reverse().join('') : this.address;
const controlHex = constant_1.ControlCode.WriteData.toString(16).padStart(2, '0');
const dataLengthHex = '04';
const dataIdentifierHex = constant_1.DataIdentifier.WriteValveControl.toString(16).padStart(4, '0');
const serHex = ((options === null || options === void 0 ? void 0 : options.ser) || this.ser).toString(16).padStart(2, '0');
const controlDataHex = '55';
const payloadHex = constant_1.FRAME_PREFIX + meterTypeHex + addressHex + controlHex + dataLengthHex + dataIdentifierHex + serHex + controlDataHex;
const csHex = util_1.Util.getCS(payloadHex);
const cmdHex = wakeUpHex + payloadHex + csHex + constant_1.FRAME_SUFFIX;
this.ser = (this.ser + 1) % 256; // * 序列化+1
return util_1.Util.hexToUint8Array(cmdHex);
}
/**
* 获取关闭阀门命令
* @param options 生成参数
* @returns 关闭阀门命令
*/
writeCloseValveCMD(options) {
this.optionValidate(options, true); // * 额外参数校验
const wakeUpHex = util_1.Util.getWakeUpHex((options === null || options === void 0 ? void 0 : options.wakeUpCode) || this.wakeUpCode, (options === null || options === void 0 ? void 0 : options.wakeUpLength) || this.wakeUpLength);
const meterTypeHex = ((options === null || options === void 0 ? void 0 : options.meterType) || this.meterType).toString(16).padStart(2, '0');
const addressHex = (options === null || options === void 0 ? void 0 : options.address) ? options.address.padStart(14, '0').match(/\w{2}/g).reverse().join('') : this.address;
const controlHex = constant_1.ControlCode.WriteData.toString(16).padStart(2, '0');
const dataLengthHex = '04';
const dataIdentifierHex = constant_1.DataIdentifier.WriteValveControl.toString(16).padStart(4, '0');
const serHex = ((options === null || options === void 0 ? void 0 : options.ser) || this.ser).toString(16).padStart(2, '0');
const controlDataHex = '99';
const payloadHex = constant_1.FRAME_PREFIX + meterTypeHex + addressHex + controlHex + dataLengthHex + dataIdentifierHex + serHex + controlDataHex;
const csHex = util_1.Util.getCS(payloadHex);
const cmdHex = wakeUpHex + payloadHex + csHex + constant_1.FRAME_SUFFIX;
this.ser = (this.ser + 1) % 256; // * 序列化+1
return util_1.Util.hexToUint8Array(cmdHex);
}
}
exports.CJT188 = CJT188;