本文档用于说明当前透析机 TCP 通讯服务中,**从设备报文中提取设备序列号**、**获取阿里云设备三元组**、**建立阿里云物联网连接**、**上报设备属性数据** 的完整流程。
目标是让其他开发人员在新的透析机联机项目中,按同样的业务规则实现一致的阿里云上报能力。
适用于以下类型的系统:
当前项目中与阿里云上报链路直接相关的模块如下:
index.jsStrholp.jsnapi.jsaliyun.jsonaliyun-iot-device-sdk系统需要支持以下业务能力:
n。productKeydeviceNamedeviceSecretIP:Port,对应代码中的 connectionId。postProps 方法,将设备实时属性上传到阿里云。文件:aliyun.json
当前配置示例:
{
"enabled": true,
"autoRegister": true
}
enabledbooleantrue:执行三元组获取、阿里云连接和属性上报false:跳过阿里云相关逻辑autoRegister
booleanisAutoRegister=1阿里云链路运行还依赖:
aliyun-iot-device-sdk 已安装透析机通过 TCP 发送 ASCII 数据流。
在当前实现中,完整报文需满足:
K1\r\n系统通过缓冲区持续接收数据,并从中提取完整报文。
完整报文解析由 Strholp.js 中的 strToObj(str, ipAddress) 完成。
其中设备序列号字段规则如下:
n: str.substring(192, 200)
即:
n192 到 200 位deviceName报文解析后至少要得到以下数据:
n:设备序列号suedtime:接收时间deviceType:设备类型IPAddress:连接来源标识sequenceDiagram
participant Device as 透析机
participant TCP as TCP服务
participant Parser as 协议解析器
participant API as 三元组接口
participant Aliyun as 阿里云物联网平台
Device->>TCP: 发送原始报文
TCP->>TCP: 按 K1 ~ \r\n 提取完整消息
TCP->>Parser: 解析报文
Parser-->>TCP: 返回 masData(含 n)
TCP->>TCP: 保存 info.iotDeviceNo = masData.n
TCP->>API: 请求三元组(deviceName=n)
API-->>TCP: 返回 productKey/deviceName/deviceSecret
TCP->>Aliyun: 使用三元组建立设备连接
TCP->>Aliyun: postProps(masData)
Aliyun-->>TCP: 返回上报结果
在 index.js 的 handleDevice(socket) 中:
remoteAddress::ffff: 前缀const connectionId = `${remoteAddress}:${socket.remotePort}`;
deviceInfoipAddressconnectedAtMslastAckstatus = 'pending'lastSignal = 'K'iotDevice = nulliotDeviceNo = ''lastAliyunRegisterAttempt = 0lastAliyunRegisterError = ''为后续“握手、解析、三元组获取、阿里云注册、属性上报”准备上下文。
chunk在 socket.on('data') 中:
chunk 转换为 ASCII 字符串bufferK1\r\nconst message = buffer.substring(startIdx, endIdx).trim();
K1 和 \r\n 时,才认为是一条完整数据message:完整报文字符串connectionId:连接标识在 handleData(connectionId, message) 中:
const masData = toModel(message, connectionId);
info.iotDeviceNo = masData.n;
info.masData = masData;
masData:完整解析对象masData.n:设备序列号info.iotDeviceNo:写入当前设备上下文info.masData:保存最近一帧数据lastAck若当前设备状态不是 valid,则执行:
info.status = 'valid'stopRetryMechanism(connectionId)startKeepAlive(connectionId, info.lastSignal)说明设备已经从“连接成功但未确认有效数据”状态,切换为“已具备正式上报条件”状态。
aliyunConfig.enabled === truemasData.nconst tupleResult = await this.registerAliyunDevice(connectionId);
在 registerAliyunDevice(connectionId) 中:
info.iotDeviceNoconst { data } = await getDeviceSYZ(info.iotDeviceNo);
getDeviceSYZ(deviceNo) 内部调用:getAliyunDeviceSecret('device/info/getAliyunDeviceSecret', deviceNo)
api.js 中发起 HTTP POST 请求:https://things.icoldchain.cn/device/info/getAliyunDeviceSecretPOSTapplication/x-www-form-urlencodedisAutoRegister=1
deviceName={设备序列号}
接口应返回如下信息:
productKeydeviceNamedeviceSecretn 必须作为接口中的 deviceName为避免频繁请求三元组接口,系统增加了重试冷却逻辑:
const ALIYUN_REGISTER_RETRY_MS = 60000;
当上一次三元组请求失败后,在 60 秒内重复请求会直接返回:
code = ALIYUN_TUPLE_RETRY_COOLDOWNreason = 上次失败原因 或 三元组重试冷却中其他项目接入时应保留该能力:
iotDevice使用阿里云 SDK 创建连接:
info.iotDevice = aliyunIot.device({
ProductKey: model.productKey,
DeviceName: model.deviceName,
DeviceSecret: model.deviceSecret
});
并监听两个事件:
connecterroriotDevice 实例iotDevice,后续上报不得重复创建info.iotDevice 已创建info.masData 不为空const propsResult = await this.postPropsToAliyun(connectionId);
info.iotDevice.postProps(info.masData, callback)
当前实现中,直接将完整解析对象 masData 作为属性对象上报。
masData 包含:
nsuedtimedeviceTypeIPAddresscode = ALIYUN_PROPS_OKreason = 成功code = ALIYUN_PROPS_FAILreason = 阿里云返回的失败信息或未知错误iotDevice 和 masData 均存在建议至少包含以下状态:
pendingvalidofflineerror建议按以下逻辑控制:
masData.n 为空或非法productKey、deviceName、deviceSecretlastAliyunRegisterErroriotDevice.on('error')postProps 返回非 successStrholp.jsstrToObj(str, ipAddress)nindex.jshandleData(connectionId, message)index.jsgetDeviceSYZ(deviceNo)文件:api.js
getAliyunDeviceSecret(url, deviceName)index.jsregisterAliyunDevice(connectionId)index.jspostPropsToAliyun(connectionId)其他透析机联机项目要复用此能力,至少必须实现:
deviceNameproductKey/deviceName/deviceSecret以下内容可以根据新透析机协议进行调整:
建议其他开发按以下顺序落地:
若其他透析机联机项目完成以下能力,则视为满足本需求:
postProps 上报属性https://things.icoldchain.cn/device/info/getAliyunDeviceSecretPOSTContent-Type: application/x-www-form-urlencodedisAutoRegister=1
deviceName={设备序列号}
const { data } = await getAliyunDeviceSecret(
'device/info/getAliyunDeviceSecret',
deviceNo
);
info.iotDevice = aliyunIot.device({
ProductKey: model.productKey,
DeviceName: model.deviceName,
DeviceSecret: model.deviceSecret
});
info.iotDevice.postProps(info.masData, (res) => {
if (res?.message === 'success') {
// 上报成功
} else {
// 上报失败
}
});
当前项目中的阿里云链路,本质上是一个标准的“设备数据驱动注册与上报流程”:
nn 为 deviceName 获取三元组postProps 上报其他透析机联机项目只要满足“**能解析出设备唯一编号**”这一前提,就可以照此模式复用整条阿里云上报链路。