1. 传感器简介

KS31 是一款基于 LoRaWAN 通信的 AI 采集器 ,支持 4-20mA 、0-10V 两种模拟量接口,可用于对接支持上述接口的传统传感器或仪表,实现无线采集与平台接入。
设备内置 4 节 2700mAh 锂亚电池,总电量约 10800mAh,具备低功耗、远距离通信能力,适合智慧工业、智慧楼宇等场景。
2. 产品特点
- 原生 LoRaWAN 通信,无需额外采集设备
- 支持 4 路 AI 接口
- 支持 4-20mA / 0-10V 两种接口型号
- 电池供电,续航可达 6 年以上(15分钟上报周期条件下)
- 支持 COV 变化上报
- 支持通过 NS 下发参数进行远程配置
- 防护等级 IP65
- 支持 CN470 / EU433 / EU868 / AS923 / AU915 / US902 等区域标准
3. 适用范围
适用于下列模拟量传感器/设备的无线采集接入:
- 工业现场 4-20mA 变送器
- 0-10V 输出类传感器
- 楼宇自动化模拟量设备
- 智慧工业、智慧楼宇环境监测场景
- 需要将传统模拟量设备快速接入 LoRaWAN 平台的项目
4. 采集器信息
4.1 硬件信息
由于 KS31 本身即为 原生 LoRaWAN AI 采集器 ,因此本项目中 无需额外采集器 。
KS31 自带 LoRaWAN 通信能力与 AI 接口采集能力。
4.2 接线信息
电源与通讯接口
- 通信方式:LoRaWAN
- 入网方式:OTAA / ABP,Class A
- 天线接口:LoRa 天线接口
- 接线口:PG7 防水接头
- 供电方式:4 节 2700mAh ER14505 锂亚电池
- 接线数量:5 根(含 1 根 GND)
传感器接口
- 支持 4 路 AI 接口
- 接口类型:
-
- 4-20mA
- 0-10V
- 型号对应不同接口版本
5. 数据采集
本方案中,KS31 为原生 LoRaWAN 设备,不通过 Modbus 采集寄存器 。
设备采用 LoRaWAN 应用层协议直接上报采样值、电池电压及状态信息。
5.1 寄存器定义
本设备 无 Modbus 寄存器定义 。
可关注的 LoRaWAN 上行数据字段如下:
0-10V 接口数据格式
- 端口号:11
- 版本号:0x82
- 控制字:0x25
- 标识符:0x17
- 数据内容:
-
- 设备状态
- 通道1采样值
- 通道2采样值
- 通道3采样值
- 通道4采样值
- 电池电压
4-20mA 接口数据格式
- 端口号:11
- 版本号:0x82
- 控制字:0x25
- 标识符:0x18
- 数据内容:
-
- 设备状态
- 通道1采样值
- 通道2采样值
- 通道3采样值
- 通道4采样值
- 电池电压
5.2 状态位定义
- 设备状态字段:
-
0x00:正常0x01:通信故障
6. EdgeBus 模型
KS31 本身是 LoRaWAN 设备,因此不需要 EB 代码。
文档中仅给出说明即可。
6.1 EB 配置参数
不需要。
6.2 EB 代码
不需要。
6.3 说明
当前 EB 逻辑说明:
- KS31 为原生 LoRaWAN AI 采集器
- 设备直接完成模拟量采集与 LoRaWAN 上报
- 不需要通过 KC 系列采集器或 EdgeBus 做协议转换
- 平台侧主要完成物模型解析、参数读写与 RPC 配置即可
7. 物模型
7.1 物模型基本信息
数据物模型
- 名称:
MT-KS31 - id Name:
mt_ks31
参数物模型
- 名称:
MT KS31 PARA - id Name:
mt_ks31_para
7.2 上行帧结构
- 端口号为 11 ,并按固定长度
21字节解析,且type字段映射为:
-
"17" -> "4-20mA""18" -> "0-10V"
上行帧结构
- Port:11
- 数据长度:21 字节
- Tag:
-
- Byte0 =
0x82 - Byte1 =
0x25
- Byte0 =
- 解析字段:
-
- Byte2:type
- Byte3:fault
- Byte4~7:chan1(uint32LE)
- Byte8~11:chan2(uint32LE)
- Byte12~15:chan3(uint32LE)
- Byte16~19:chan4(uint32LE)
- Byte20:battery/vbat(uint8)
换算逻辑
- 若
type = 4-20mA,则powerVal = 10 - 否则
powerVal = 11 - 通道换算:
-
chanX = 原始值 * powerVal / 64000- 再结合
baseX和ratioX做修正
- 电池换算:
-
battery = (原始值 * 1.6 / 254) + 2.0
7.3 物模型脚本
if (!noticeAttrs.telemetry_data) return null
let port = msg?.userdata?.port || null;
if (port !== 11) return null
let frameInfo = {
port: 11, dataLen: 21, rssi: true,
tagList: [
{ index: 0, tag: 0x82 },
{ index: 1, tag: 0x25 }
]
}
let appInfo = [
{ name: "type", field_name: "type", unit: "", index: 2, type: "hexBE1", options: { "17": "4-20mA", "18": "0-10V" } },
{ name: "fault", field_name: "fault", unit: "", index: 3, type: "uint8" },
{ name: "chan1", field_name: "chan1", unit: "v", index: 4, type: "uint32LE" },
{ name: "chan2", field_name: "chan2", unit: "v", index: 8, type: "uint32LE" },
{ name: "chan3", field_name: "chan3", unit: "v", index: 12, type: "uint32LE" },
{ name: "chan4", field_name: "chan4", unit: "v", index: 16, type: "uint32LE" },
{ name: "vbat", field_name: "vbat", unit: "v", index: 20, type: "uint8", decimal: 2 }
]
let payParser = new PayloadParser({
device: device,
msg: msg,
frameInfo: frameInfo,
appInfo: appInfo,
})
let tdata = payParser.telemetry()
if (tdata == undefined) return null
let base1 = device?.server_attrs?.base1 ?? 0
let base2 = device?.server_attrs?.base2 ?? 0
let base3 = device?.server_attrs?.base3 ?? 0
let base4 = device?.server_attrs?.base4 ?? 0
let ratio1 = device?.server_attrs?.ratio1 ?? 1
let ratio2 = device?.server_attrs?.ratio2 ?? 1
let ratio3 = device?.server_attrs?.ratio3 ?? 1
let ratio4 = device?.server_attrs?.ratio4 ?? 1
let powerVal = 11
if (tdata.type === "4-20mA") { powerVal = 10 }
let chan1 = tdata.chan1 * powerVal / 64000
let chan2 = tdata.chan2 * powerVal / 64000
let chan3 = tdata.chan3 * powerVal / 64000
let chan4 = tdata.chan4 * powerVal / 64000
tdata.chan1 = Number(((chan1 - base1) * ratio1).toFixed(3))
tdata.chan2 = Number(((chan2 - base2) * ratio2).toFixed(3))
tdata.chan3 = Number(((chan3 - base3) * ratio3).toFixed(3))
tdata.chan4 = Number(((chan4 - base4) * ratio4).toFixed(3))
tdata.battery = Number(((tdata.battery * 1.6) / 254 + 2.0).toFixed(2))
return {
telemetry_data: tdata,
server_attrs: null,
shared_attrs: null
}
8. 第三方平台数据订阅
8.1 MQTT Topic
/v32/{Organization Account}/tkl/up/telemetry/{eui}
8.2 上报示例数据
以下示例根据 KS31 的物模型字段进行了对应调整:
{
"eui": "ks31_demo_eui",
"active_time": "2026-04-12T08:00:00.000Z",
"thingModelId": "mt_ks31_demo",
"thingModelIdName": "mt_ks31",
"telemetry_data": {
"type": "4-20mA",
"fault": 0,
"chan1": 12.345,
"chan2": 8.765,
"chan3": 15.120,
"chan4": 6.540,
"battery": 3.18
}
}
说明:
type:接口类型fault:设备状态chan1~chan4:4 路模拟量换算后的值battery:电池电压值
9. RPC
9.1 RPC 名称
根据提供资料,KS31 的 RPC 包括:
[MT KS31 SET] para
id Name:mt_ks31_set_para[MT KS31 SET] ratio
id Name:mt_ks31_set_ratio[MT KS31 GET] para
id Name:mt_ks31_get_para
9.2 参数定义
常规参数
pwron_delay:上电延时,单位 ms,对应地址 38period_up:上报周期,单位 s,对应地址 40cov_enable1~4:4 路通道 COV 使能位,对应地址 150 的 bit0~bit3measurePeriod:采样周期,单位 s,对应地址 152covChan1~4:4 路通道 COV 阈值,对应地址 154 / 158 / 162 / 166
ratio 修正参数
base1~base4ratio1~ratio4
用于平台侧对 4 路通道值做基准偏移与比例修正。
9.3 RPC 代码
配置参数 RPC
let classMode = (device && device.shared_attrs && device.shared_attrs.class_mode) || "ClassA";
const rpcName = "mt_ks31_set_para"
let paraDef = {
app_38: { name: "pwron_delay", field_name: "pwron_delay", unit: "ms", index: 38, type: "uint16le" },
app_40: { name: "period_up", field_name: "period_up", unit: "s", type: "uint32LE" },
app_150_1: { name: "cov_enable1", field_name: "cov_enable1", unit: "", type: "bitLE0-0" },
app_150_2: { name: "cov_enable2", field_name: "cov_enable2", unit: "", type: "bitLE1-1" },
app_150_3: { name: "cov_enable3", field_name: "cov_enable3", unit: "", type: "bitLE2-2" },
app_150_4: { name: "cov_enable4", field_name: "cov_enable4", unit: "", type: "bitLE3-3" },
app_152: { name: "measurePeriod", field_name: "measurePeriod", unit: "s", type: "uint16LE" },
app_154: { name: "covChan1", field_name: "covChan1", unit: "", type: "floatLE", coefficient: 0.00015625, decimal: 3 },
app_158: { name: "covChan2", field_name: "covChan2", unit: "", type: "floatLE", coefficient: 0.00015625, decimal: 3 },
app_162: { name: "covChan3", field_name: "covChan3", unit: "", type: "floatLE", coefficient: 0.00015625, decimal: 3 },
app_166: { name: "covChan4", field_name: "covChan4", unit: "", type: "floatLE", coefficient: 0.00015625, decimal: 3 }
};
let paraInput = { ...params }
if (params?.cov_enable1) { paraInput.cov_enable1 = 1 } else { paraInput.cov_enable1 = 0 }
if (params?.cov_enable2) { paraInput.cov_enable2 = 1 } else { paraInput.cov_enable2 = 0 }
if (params?.cov_enable3) { paraInput.cov_enable3 = 1 } else { paraInput.cov_enable3 = 0 }
if (params?.cov_enable4) { paraInput.cov_enable4 = 1 } else { paraInput.cov_enable4 = 0 }
let frames = RPCHelper.buildFrame({ paraDef: paraDef, params: paraInput });
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,
})
if (msgQue.length == 0) return null
return msgQue
配置 ratio 参数 RPC
logger.info("set ratio para");
return [{
sleepTimeMs: 0,
type: "modifyAttrs",
dnMsg: {
server_attrs: params
}
}]
读取参数 RPC
let paraDef = {
app_38: { name: "pwron_delay", field_name: "pwron_delay", unit: "ms", index: 38, type: "uint16le" },
app_40: { name: "period_up", field_name: "period_up", unit: "s", type: "uint32LE" },
app_150_1: { name: "cov_enable1", field_name: "cov_enable1", unit: "", type: "bitLE0-0" },
app_150_2: { name: "cov_enable2", field_name: "cov_enable2", unit: "", type: "bitLE1-1" },
app_150_3: { name: "cov_enable3", field_name: "cov_enable3", unit: "", type: "bitLE2-2" },
app_150_4: { name: "cov_enable4", field_name: "cov_enable4", unit: "", type: "bitLE3-3" },
app_152: { name: "measurePeriod", field_name: "measurePeriod", unit: "s", type: "uint16LE" },
app_154: { name: "covChan1", field_name: "covChan1", unit: "", type: "floatLE", coefficient: 0.00015625, decimal: 3 },
app_158: { name: "covChan2", field_name: "covChan2", unit: "", type: "floatLE", coefficient: 0.00015625, decimal: 3 },
app_162: { name: "covChan3", field_name: "covChan3", unit: "", type: "floatLE", coefficient: 0.00015625, decimal: 3 },
app_166: { name: "covChan4", field_name: "covChan4", unit: "", type: "floatLE", coefficient: 0.00015625, decimal: 3 }
}
let frames = RPCHelper.buildFrame({ paraDef: paraDef });
let msg = RPCHelper.makeMSG({
msgType: Utils.msgType.paras,
device: device,
dnBuffer: frames.readBuffer,
sleepTime: 0,
});
return [msg];
10. 模板选择
在 ThinkLink 平台中搜索模板:
KS31MT-KS31
或按业务类型查找:
- LoRaWAN 原生 AI 采集器
- 4-20mA 采集设备
- 0-10V 采集设备
- 模拟量采集类设备