UNPKG

@iot9x.com/ipc-utils

Version:

九星云、九星小程序、九星配置工具所共用的库方法

268 lines (267 loc) 15.2 kB
"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;