Skip to content

以下为基于京泉仪表 LXSY-15E 冷水表、采用 CJ188 冷水表协议 接入 ThinkLink 的标准对接文档。该方案以 KC22 作为采集器,通过 M-Bus 对接冷水表。由于该方案本质上是 CJ188 冷水表模板化适配,因此其他支持或可兼容 CJ/T 188 冷水表协议 的品牌水表,也可参考本模板进行适配。相关基础信息来自你提供的设备资料与 CJ188 协议文档

模型清单

可使用下列名称或 ID 在 ThinkLink 中搜索对应模型。

模型类型名称id_name平台模型 ID
TemplateCJ188 COOL WATER92529888803688453

1. 传感器简介

本次对接的传感器设备为 京泉仪表 LXSY-15E 冷水表,英文名 JQYB,业务代码为 23103,平台模板名称为 CJ188 COOL WATER。该设备属于冷水表,协议侧采用 CJ/T 188-2004 体系中的冷水表类别,表类型代码为 0x10


2. 产品特点

  1. 采用 CJ188 冷水表协议,协议标准清晰,便于标准化接入。
  2. 支持通过 M-Bus 接口接入采集器。
  3. 支持读取表计地址、读取水量数据、设置表地址,以及阀门开关控制。
  4. 平台侧已整理出对应的 EB 逻辑、物模型、参数模型与 RPC 模板,便于批量复制到其他同类冷水表项目。
  5. 该模板具备较好的通用性,适用于其他兼容 CJ188 冷水表协议 的品牌水表适配。

3. 适用范围

本方案适用于以下场景:

  • 住宅小区冷水表远程抄表
  • 园区/楼宇冷水计量
  • 存量 CJ188 冷水表无线化改造
  • 需要通过 ThinkLink 进行统一物模型解析、数据订阅与远程参数配置的项目

说明:
本方案以 LXSY-15E 为例,但本质上是 CJ188 冷水表通用模板。对于其他品牌,只要其协议帧格式、数据标识、地址编码方式与状态位定义兼容或接近 CJ188 冷水表模板,即可在此基础上进行适配。该结论是结合你提供的模板信息与协议结构做出的工程化归纳。


4. 采集器信息

4.1 硬件信息

采集器采用 KC22
已知硬件信息如下:

  • 设备型号:KC22
  • 接口:M-Bus
  • 供电方式:电池供电
  • 电池容量:10800mA时
  • 对外供电:M-Bus

4.2 接线信息

电源与通讯接口

  • KC22 采用电池供电。
  • KC22 通过 M-Bus 与冷水表通信,并向从站提供总线侧驱动/供电能力。
  • 根据协议文档,M-Bus 接口支持一主一从或一主多从,且从站连接方式为无极性。主站工作时需向总线提供电源。通讯方式为半双工。传输波特率适用范围为 300bps~9600bps,本项目模板实际使用 2400bps、8位数据位、1位停止位、偶校验

传感器接口

  • 传感器接口类型:M-Bus
  • KC22 对外供电方式:M-Bus 总线供电
  • 该方案中,LXSY-15E 冷水表通过 M-Bus 接入 KC22。

5. 数据采集

本方案中,通过 CJ188 协议读取冷水表数据,不是 Modbus。
因此此处应表述为:

本方案中,通过 CJ188 协议读取以下数据内容:

  • 表计地址
  • 当前流量
  • 总累计流量
  • 状态字
  • 阀门状态
  • 读数故障状态

依据协议文档,读表数据使用:

  • CTR = 0x01
  • DI = 0x901F

表计回复时:

  • CTR = 0x81
  • 数据区中包含当前流量、累计流量、时间保留字段、状态字等内容。

5.1 寄存器定义

CJ188 协议不是 Modbus 寄存器模型,因此这里更准确应理解为“数据标识定义”。

读数相关

  • 读表计数据:DI0 DI1 = 90 1F
  • 读表计地址:DI0 DI1 = 81 0A
  • 写表计地址:DI0 DI1 = A0 18
  • 操作阀门:DI0 DI1 = A0 17

读表计数据帧定义

请求帧:

  • 起始符:68h
  • 表类型 T:冷水表为 10h
  • 地址:A0-A6
  • 控制码:01h
  • 数据长度:03h
  • 数据标识:90 1F
  • 序号:SER
  • 校验:CS
  • 结束符:16h

应答帧:

  • 控制码:81h
  • 数据长度:16h
  • 数据标识:90 1F
  • 数据区包括:
    • 14-17:当前流量读数
    • 18:当前流量单位,m³,对应 2C
    • 19-22:总累计流量读数
    • 23:累计流量单位,m³,对应 2C
    • 24-30:时间保留字节
    • 31:状态字 S0
    • 32:状态字 S1

5.2 状态位定义

CJ188 状态字共 2 字节,其中常用为 S0
根据协议:

  • bit0-bit1:阀门状态
    • 00:开
    • 01:关
    • 11:异常
  • bit2:读数故障
    • 0:正常
    • 1:异常
  • 其余位:保留

6. EdgeBus 模型

6.1 EB 配置参数

从你提供的 EB 配置中提取如下:

  • SwVersion: 31
  • BaudRate: 2400
  • StopBits: 1
  • DataBits: 8
  • Checkbit: EVEN
  • Battery: true
  • ConfirmDuty: 60
  • BzType: 23103
  • BzVersion: 17

6.2 EB 代码

以下为你提供的 EB 代码原文:

typescript
import { Buffer } from "buffer";
import { buildOtaFile } from "@EBSDK/run";
import {
    ActionAfertExpr, CalcData,
    CrcMode,
    CvtRule,
    EBBuffer,
    ExprCondition,
    LoraUpEvent,
    QueryEvent, SetUpCovDataType,QuItemBase,
    QuItemModBus,QuItemCJ188, UserConfQueryItem, EventConfig, Utils
} from "@EBSDK/EBCompiler/all_variable";
import { EBModel } from "@EBSDK/EBCompiler/EBModel/EBModel";
import { EventInfoItem } from "@EBSDK/EBCompiler/plugins/EBHelper";
import type { UserConfUPItem } from "@EBSDK/EBCompiler/plugins/EBHelper";
import { CheckbitEnum, getOtaConfig, HwTypeEnum, UpgrdTypeEnum } from "@EBSDK/otaConfig";

let otaConfig = getOtaConfig({
    SwVersion:31,
    BaudRate: 2400,
    StopBits: 1,
    DataBits: 8,
    Checkbit: CheckbitEnum.EVEN,
    Battery: true,
    ConfirmDuty: 60,
    BzType: 23103, // required ,2 bytes
    BzVersion: 18 // required,1 bytes
})
const eventInfo:UserConfUPItem[]=[
    {
        name:"cj188-coolwater",port:22,version:"0x87",dataType:"0x03",upPeriodIndex:70,
        indexAddr:5,addrSize:7,
        quInfo:[
            {   protocol:"CJ188",code:"0x0103",periodIndex:70,
                indexAPP:150,indexCMD:2,copySize:7,preamble:10,
                cmd:"0x68 10 AA AA AA AA AA AA AA 01 03 90 1F 12 0C 16",
                ack:"0x68 10 01 00 00 05 08 00 00 81 16 90 1F 00   00 23 01 00 2C 00 00 00 00 2C 00 00 00 00 00 00 00 00 00 48 16",
                listVal:[
                    { start:"14", end:"23"}
                ]
            }
        ]
    }
]
const MODBUS_TT = (ebModel: EBModel) => {
    for (let i=0; i<eventInfo.length; i++){
        let event=new EventInfoItem(eventInfo[i]);
        event.upEventSetup()
        event.eventInstall()
    }
    return JSON.stringify(ebModel, null, 2)
}
buildOtaFile(import.meta.url, otaConfig, MODBUS_TT)

来源:

6.3 说明

当前 EB 逻辑说明:

  1. KC22 通过 M-Bus / CJ188 周期性发起水表数据读取。
  2. 查询报文核心为 读表数据命令,即 68 10 ... 01 03 90 1F ... 16
  3. EB 逻辑中对返回帧进行了关键校验:
    • 起始位 0x68
    • DI 校验 0x90 0x1F
    • 结束位 0x16
    • CRC 采用 SUM 方式
  4. 采到的应答帧中,EB 会将:
    • 地址段复制到 LoRaWAN 上行
    • 当前流量和累计流量数据段复制到 LoRaWAN 上行
    • 状态字复制到 LoRaWAN 上行
  5. LoRaWAN 上行端口为 22
  6. 该逻辑的核心目的是将 CJ188 原始表计应答帧 映射为 ThinkLink 可直接解析的标准上行数据格式。
  7. 参数索引中 periodIndex=70addrIndex=150,与后续参数物模型中的 app_70app_150 正好对应,说明采集周期和表地址都可通过平台参数/RPC下发方式动态配置。

7. 物模型

7.1 物模型基本信息

数据物模型

  • 名称:[CJ188-COOLWATER]
  • ID Name:cj188_coolwater_23103

参数物模型

  • 名称:[CJ188-COOLWATER-PARA]
  • ID Name:cj188_coolwater_para_23103

7.2 上行帧结构

上行端口:

  • port: 22

帧定义:

typescript
let frameInfo = {
        port:22,
        dataLen:-1,
        rssi:true,
        battery:4,
        tagList:[
            { index:0, tag:0x87 },
            { index:1, tag:0x03 }
        ]
    }

字段定义:

typescript
let appInfo = [
        { name:"addr", field_name:"addr", unit:"", index:5, type:"hexLE7" },
        { name:"instantflow", field_name:"instantflow", unit:"m³", index:12, type:"bcdLE4", coefficient:0.01,decimal:2 },
        { name:"totalflow", field_name:"totalflow", unit:"m³", index:17, type:"bcdLE4", coefficient:0.01,decimal:2 },
        { name:"status", field_name:"status", unit:"", index:22, type:"uint8" }
    ]

说明:

  • addr:表地址,7字节,低字节在前
  • instantflow:当前流量,BCD 小端 4 字节,系数 0.01
  • totalflow:累计流量,BCD 小端 4 字节,系数 0.01
  • status:状态字 S0,1 字节

7.3 物模型脚本

typescript
let frameInfo = {
    port: 22,
    dataLen: -1,
    rssi: true,
    battery: 4,
    tagList: [
        { index: 0, tag: 0x87 },
        { index: 1, tag: 0x03 }
    ]
}

let appInfo = [
    { name: "addr", field_name: "addr", unit: "", index: 5, type: "hexLE7" },
    { name: "instantflow", field_name: "instantflow", unit: "m³", index: 12, type: "bcdLE4", coefficient: 0.01, decimal: 2 },
    { name: "totalflow", field_name: "totalflow", unit: "m³", index: 17, type: "bcdLE4", coefficient: 0.01, decimal: 2 },
    { name: "status", field_name: "status", unit: "", index: 22, type: "uint8" }
]

let tdata = {}
let payParser = new PayloadParser({
    device: device,
    msg: msg,
    frameInfo: frameInfo,
    appInfo: appInfo,
})
tdata = payParser.telemetry()

return {
    telemetry_data: tdata,
    server_attrs: null,
    shared_attrs: null
}

8. 第三方平台数据订阅

8.1 MQTT Topic

/v32/{Organization Account}/tkl/up/telemetry/{eui}

8.2 上报示例数据

根据本模板的物模型字段,修正后的示例数据建议如下:

json
{
    "eui": "6353012af10a9331",
    "active_time": "2026-04-05T10:00:00.000Z",
    "thingModelId": "cj188_coolwater_23103",
    "thingModelIdName": "CJ188-COOLWATER",
    "telemetry_data": {
        "addr": "01000005080000",
        "snr": 13.5,
        "rssi": -51,
        "battery": 3.37,
        "instantflow": 123.45,
        "totalflow": 5657.00,
        "status": 1
    }
}

9. RPC

9.1 RPC 名称

配置参数 RPC

  • 名称:[CJ188 SET] para 23103
  • ID Name:cj188_coolwater_set_23103

读取参数 RPC

  • 名称:[CJ188 GET] para 23103
  • ID Name:cj188_coolwater_get_23103

9.2 参数定义

参数定义如下:

  • retries
    • 字段名:retries
    • 类型:uint8
  • pwron_delay
    • 字段名:pwron_delay
    • 单位:ms
    • 索引:38
    • 类型:uint16le
  • period
    • 字段名:period
    • 单位:m
    • 索引:70
    • 类型:uint32LE
  • addr
    • 字段名:addr
    • 索引:150
    • 类型:hexLE7

补充说明:

  • period 在设置 RPC 中会被转换为秒,即 params.period * 60
  • 在参数上报解析时,又会除以 60,还原为分钟显示
    这说明平台侧希望对外统一用“分钟”作为采样周期配置单位。

9.3 RPC 代码

配置参数 RPC

typescript
let classMode = (device && device.shared_attrs && device.shared_attrs.class_mode) || "ClassA";
const rpcName="cj188_coolwater_set_23103"
let paraDef= {
    app_34: {name: "retries", field_name: "retries", unit: "",  type: "uint8"},
    app_38: { name: "pwron_delay", field_name: "pwron_delay", unit: "ms", index: 38, type: "uint16le" },
    app_70: {name: "period", field_name: "period", unit: "m",  type: "uint32LE"},
    app_150: {name: "addr", field_name: "addr", unit: "", type: "hexLE7"},
}
logger.info("set paras")
let paraInput = {...params}
paraInput.retries=2
paraInput.pwron_delay=1000
paraInput.period=params.period*60
let frames=RPCHelper.buildFrame({
    paraDef:paraDef,
    params:paraInput});
let redoBuffer=RPCHelper.redo()
let dnBuffer=Buffer.alloc(frames.writeBuffer.length+frames.readBuffer.length);
frames.writeBuffer.copy(dnBuffer,0)
frames.readBuffer.copy(dnBuffer,frames.writeBuffer.length)
let msgQue=Utils.makeParaSetMSG({
    device:device,
    classMode:classMode,
    rpcName:rpcName,
    params:params,
    paraDownBuffer:dnBuffer,
    extraAppBuffer:redoBuffer
})
if (msgQue.length==0)  return null
return msgQue

读取参数 RPC

typescript
let paraDef= {
    app_34: {name: "retries", field_name: "retries", unit: "",  type: "uint8"},
    app_38: { name: "pwron_delay", field_name: "pwron_delay", unit: "ms", index: 38, type: "uint16le" },
    app_70: {name: "period", field_name: "period", unit: "m",  type: "uint32LE"},
    app_150: {name: "addr", field_name: "addr", unit: "", type: "hexLE7"},
}
let frames=RPCHelper.buildFrame({
    paraDef:paraDef,
    params:params});
let msg=RPCHelper.makeMSG({
    msgType:Utils.msgType.paras,
    device:device,
    dnBuffer:frames.readBuffer,
    sleepTime:0,
})
return [msg]

来源:


10. 模板选择

在 ThinkLink 平台中搜索模板:

  • CJ188 COOL WATER
  • cj188_coolwater_23103
  • cj188_coolwater_para_23103
  • cj188_coolwater_set_23103
  • cj188_coolwater_get_23103

或按业务类型查找:

  • 冷水表
  • CJ188 冷水表
  • 业务代码 23103

补充说明

  1. 本方案协议层是 CJ188,不是 Modbus,因此文档中“寄存器”应理解为 CJ188 数据标识与数据区定义
  2. 该模板非常适合做 CJ188 冷水表通用模板。在实际项目中,若其他品牌冷水表的:
    • 表类型仍为冷水表 0x10
    • 读数 DI 为 90 1F
    • 地址编码为 7 字节 BCD 小端
    • 状态字规则兼容
      则通常只需调整少量地址或厂商侧差异,即可沿用本模板。