[ { "id": "1407d4531e19a951", "type": "tab", "label": "透析中心环境温度数据转发", "disabled": false, "info": "从HomeAssistant获取温度传感器数据并发布到公司MQTT服务器" }, { "id": "97e254f4a87ddde9", "type": "mqtt in", "z": "1407d4531e19a951", "name": "订阅HA温度传感器", "topic": "homeassistant/sensor/+/state", "qos": "0", "datatype": "auto", "broker": "mqtt-ha-broker", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 150, "y": 100, "wires": [ [ "44d729e67618e4f2" ] ] }, { "id": "44d729e67618e4f2", "type": "function", "z": "1407d4531e19a951", "name": "处理温度数据", "func": "// 从全局变量获取共享配置\nconst nameSpace = global.get(\"nameSpace\") || \"Environment\";\nconst clientCode = global.get(\"clientCode\") || \"Data-It_XzOffice\";\nconst targetDeviceId = global.get(\"deviceId\") || \"sensor.miaomiaoc_cn_blt_3_11a1sbr5k5o01_t2_temperature_p_2_1\";\n\n// 从topic中提取当前设备ID\nconst topicParts = msg.topic.split('/');\nconst currentDeviceId = topicParts.length >= 3 ? topicParts[2] : \"\";\n\n// 只处理目标设备的消息\nif (currentDeviceId !== targetDeviceId) {\n node.log(\"忽略设备消息: \" + currentDeviceId + \" (目标设备: \" + targetDeviceId + \")\");\n return null;\n}\n\n// 生成唯一的消息ID\nconst messageId = \"temp_\" + Date.now() + \"_\" + Math.floor(Math.random() * 1000);\nconst timestamp = Date.now();\nconst deviceType = \"sensor\";\n\n// 解析温度值\nlet temperature = parseFloat(msg.payload);\nif (isNaN(temperature)) {\n node.warn(\"接收到无效的温度值: \" + msg.payload);\n return null;\n}\n\n// 按照胜透物联网通信协议格式化数据\nconst protocolMessage = {\n \"messageId\": messageId,\n \"timestamp\": timestamp,\n \"clientCode\": clientCode,\n \"deviceId\": targetDeviceId,\n \"deviceType\": deviceType,\n \"version\": \"1.0\",\n \"data\": {\n \"properties\": {\n \"temperature\": {\n \"value\": temperature,\n \"unit\": \"°C\",\n \"quality\": \"good\",\n \"timestamp\": timestamp\n }\n }\n }\n};\n\n// 设置输出消息\nmsg.payload = JSON.stringify(protocolMessage);\nmsg.topic = `${nameSpace}/sensor/${clientCode}/${targetDeviceId}/properties`;\nmsg.qos = 0;\n\nnode.log(\"温度数据已处理: \" + temperature + \"°C (设备: \" + targetDeviceId + \")\");\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 420, "y": 100, "wires": [ [ "573842ea77192dbb", "4c630c164e08dc2c" ] ] }, { "id": "573842ea77192dbb", "type": "mqtt out", "z": "1407d4531e19a951", "name": "发布到公司MQTT", "topic": "", "qos": "", "retain": "", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "mqtt-company-broker", "x": 990, "y": 80, "wires": [] }, { "id": "4c630c164e08dc2c", "type": "debug", "z": "1407d4531e19a951", "name": "调试输出", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 1040, "y": 360, "wires": [] }, { "id": "495c392574ee1bf4", "type": "inject", "z": "1407d4531e19a951", "name": "发布设备物模型", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "60", "crontab": "", "once": true, "onceDelay": "5", "topic": "shengtou/sensor/TH001_HA/model", "payload": "", "payloadType": "date", "x": 170, "y": 180, "wires": [ [ "3aea3ce2deb4ea99" ] ] }, { "id": "3aea3ce2deb4ea99", "type": "function", "z": "1407d4531e19a951", "name": "生成物模型数据", "func": "const messageId = \"mdl_\" + Date.now();\nconst timestamp = Date.now();\n// 从全局变量获取共享配置\nconst nameSpace = global.get(\"nameSpace\") || \"Environment\";\nconst clientCode = global.get(\"clientCode\") || \"Data-It_XzOffice\";\nconst deviceId = global.get(\"deviceId\") || \"sensor.miaomiaoc_cn_blt_3_11a1sbr5k5o01_t2_temperature_p_2_1\";\nconst deviceType = \"sensor\";\n\n// 按照胜透物联网通信协议生成物模型定义\nconst modelMessage = {\n \"messageId\": messageId,\n \"timestamp\": timestamp,\n \"clientCode\": clientCode,\n \"deviceId\": deviceId,\n \"deviceType\": deviceType,\n \"version\": \"1.0\",\n \"data\": {\n \"model\": {\n \"deviceInfo\": {\n \"manufacturer\": \"小米\",\n \"model\": \"MIAOMIAOC_CN_BLT_3_11A1SBR5K5O01_T2\",\n \"version\": \"1.0.0\",\n \"description\": \"米家温湿度传感器(通过HomeAssistant集成)\"\n },\n \"properties\": {\n \"temperature\": {\n \"dataType\": \"float\",\n \"unit\": \"°C\",\n \"range\": {\n \"min\": -40,\n \"max\": 85\n },\n \"precision\": 1,\n \"description\": \"环境温度\"\n }\n },\n \"events\": {\n \"startup\": {\n \"eventType\": \"info\",\n \"description\": \"设备启动事件\"\n }\n },\n \"alarms\": {\n \"TEMP_HIGH\": {\n \"alarmType\": \"threshold_exceeded\",\n \"description\": \"温度过高报警\",\n \"defaultThreshold\": 35.0\n },\n \"TEMP_LOW\": {\n \"alarmType\": \"threshold_exceeded\",\n \"description\": \"温度过低报警\",\n \"defaultThreshold\": 0.0\n }\n }\n }\n }\n};\n\n// 设置MQTT发布主题\nmsg.topic = `${nameSpace}/sensor/${clientCode}/${deviceId}/model`;\nmsg.payload = JSON.stringify(modelMessage);\nmsg.qos = 1;\n\nnode.log(\"设备物模型数据已生成,发布到主题: \" + msg.topic);\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 400, "y": 160, "wires": [ [ "573842ea77192dbb", "4c630c164e08dc2c" ] ] }, { "id": "70e1e283448c941e", "type": "inject", "z": "1407d4531e19a951", "name": "设备状态心跳", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "120", "crontab": "", "once": true, "onceDelay": "10", "topic": "shengtou/sensor/TH001_HA/status", "payload": "", "payloadType": "date", "x": 160, "y": 240, "wires": [ [ "ae74b6d386748045" ] ] }, { "id": "ae74b6d386748045", "type": "function", "z": "1407d4531e19a951", "name": "生成状态数据", "func": "const messageId = \"sts_\" + Date.now();\nconst timestamp = Date.now();\n// 从全局变量获取共享配置\nconst nameSpace = global.get(\"nameSpace\") || \"Environment\";\nconst clientCode = global.get(\"clientCode\") || \"Data-It_XzOffice\";\nconst deviceId = global.get(\"deviceId\") || \"sensor.miaomiaoc_cn_blt_3_11a1sbr5k5o01_t2_temperature_p_2_1\";\nconst deviceType = \"sensor\";\n\n// 计算设备运行时间(从第一次启动开始)\nif (!context.get(\"startTime\")) {\n context.set(\"startTime\", timestamp);\n}\nconst startTime = context.get(\"startTime\");\nconst uptime = timestamp - startTime;\n\n// 按照胜透物联网通信协议生成状态数据\nconst statusMessage = {\n \"messageId\": messageId,\n \"timestamp\": timestamp,\n \"clientCode\": clientCode,\n \"deviceId\": deviceId,\n \"deviceType\": deviceType,\n \"version\": \"1.0\",\n \"data\": {\n \"status\": {\n \"online\": true,\n \"lastHeartbeat\": timestamp,\n \"uptime\": uptime\n }\n }\n};\n\n// 设置MQTT发布主题\nmsg.topic = `${nameSpace}/sensor/${clientCode}/${deviceId}/status`;\nmsg.payload = JSON.stringify(statusMessage);\nmsg.qos = 0;\n\nnode.log(\"设备状态心跳已发送,发布到主题: \" + msg.topic);\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 400, "y": 240, "wires": [ [ "573842ea77192dbb", "4c630c164e08dc2c" ] ] }, { "id": "7f9acf10d0c6085d", "type": "inject", "z": "1407d4531e19a951", "name": "初始化全局配置", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": true, "onceDelay": "1", "topic": "", "payload": "", "payloadType": "date", "x": 150, "y": 40, "wires": [ [ "6f6b825dfc5e9512" ] ] }, { "id": "6f6b825dfc5e9512", "type": "function", "z": "1407d4531e19a951", "name": "设置全局配置", "func": "// 设置全局共享常量\nglobal.set(\"nameSpace\", \"Environment\");\nglobal.set(\"clientCode\", \"Data-It_XzOffice\");\nglobal.set(\"deviceId\", \"sensor.miaomiaoc_cn_blt_3_11a1sbr5k5o01_t2_temperature_p_2_1\");\n\nnode.log(\"全局配置已设置: nameSpace=\" + global.get(\"nameSpace\") + \", clientCode=\" + global.get(\"clientCode\") + \", deviceId=\" + global.get(\"deviceId\"));\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 360, "y": 40, "wires": [ [ "794c422d39898a7f" ] ] }, { "id": "794c422d39898a7f", "type": "function", "z": "1407d4531e19a951", "name": "更新MQTT订阅Topic", "func": "// 从全局变量生成HomeAssistant MQTT订阅Topic\nconst deviceId = global.get(\"deviceId\") || \"sensor.miaomiaoc_cn_blt_3_11a1sbr5k5o01_t2_temperature_p_2_1\";\nconst haTopic = `homeassistant/sensor/${deviceId}/state`;\n\n// 将Topic保存到全局变量供其他地方使用\nglobal.set(\"haSubscribeTopic\", haTopic);\n\nnode.log(\"HomeAssistant订阅Topic已更新: \" + haTopic);\nnode.log(\"注意:如需更改MQTT In节点的订阅Topic,请手动修改为: \" + haTopic);\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 590, "y": 40, "wires": [ [] ] }, { "id": "3bf854e9bd3e6937", "type": "inject", "z": "1407d4531e19a951", "name": "启动事件", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": true, "onceDelay": "15", "topic": "shengtou/sensor/TH001_HA/events", "payload": "", "payloadType": "date", "x": 160, "y": 340, "wires": [ [ "26f6196b2d6fba29" ] ] }, { "id": "26f6196b2d6fba29", "type": "function", "z": "1407d4531e19a951", "name": "生成启动事件", "func": "const messageId = \"evt_startup_\" + Date.now();\nconst timestamp = Date.now();\n// 从全局变量获取共享配置\nconst nameSpace = global.get(\"nameSpace\") || \"Environment\";\nconst clientCode = global.get(\"clientCode\") || \"Data-It_XzOffice\";\nconst deviceId = global.get(\"deviceId\") || \"sensor.miaomiaoc_cn_blt_3_11a1sbr5k5o01_t2_temperature_p_2_1\";\nconst deviceType = \"sensor\";\n\n// 按照胜透物联网通信协议生成事件数据\nconst eventMessage = {\n \"messageId\": messageId,\n \"timestamp\": timestamp,\n \"clientCode\": clientCode,\n \"deviceId\": deviceId,\n \"deviceType\": deviceType,\n \"version\": \"1.0\",\n \"data\": {\n \"events\": [\n {\n \"eventType\": \"startup\",\n \"eventLevel\": \"info\",\n \"eventCode\": \"EVT_001\",\n \"description\": \"HomeAssistant温度传感器代理设备启动完成\",\n \"timestamp\": timestamp\n }\n ]\n }\n};\n\n// 设置MQTT发布主题\nmsg.topic = `${nameSpace}/sensor/${clientCode}/${deviceId}/events`;\nmsg.payload = JSON.stringify(eventMessage);\nmsg.qos = 1;\n\nnode.log(\"设备启动事件已生成,发布到主题: \" + msg.topic);\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 380, "y": 320, "wires": [ [ "573842ea77192dbb", "4c630c164e08dc2c" ] ] }, { "id": "mqtt-ha-broker", "type": "mqtt-broker", "name": "HomeAssistant MQTT", "broker": "192.168.50.83", "port": "1883", "clientid": "", "autoConnect": true, "usetls": false, "protocolVersion": "4", "keepalive": "60", "cleansession": true, "autoUnsubscribe": true, "birthTopic": "", "birthQos": "0", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willPayload": "", "willMsg": {}, "sessionExpiry": "" }, { "id": "mqtt-company-broker", "type": "mqtt-broker", "name": "公司MQTT服务器", "broker": "mqtt-test.ihemodialysis.com", "port": "62183", "clientid": "", "usetls": false, "protocolVersion": "4", "keepalive": "60", "cleansession": true, "birthTopic": "", "birthQos": "0", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closePayload": "", "closeMsg": {}, "willTopic": "shengtou/sensor/TH001_HA/status", "willQos": "0", "willPayload": "{\"messageId\":\"sts_offline\",\"timestamp\":0,\"deviceId\":\"TH001_HA\",\"deviceType\":\"sensor\",\"version\":\"1.0\",\"data\":{\"status\":{\"online\":false,\"lastHeartbeat\":0,\"uptime\":0}}}", "willMsg": {}, "sessionExpiry": "" } ]