gx
chenyc
2025-12-10 1daaf55ceac01b00be25aecc7efb57cf47a34155
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// aliyun-iot.js
const axios = require('axios');
const IotDevice = require('aliyun-iot-device-sdk');
const logger = require('./logger');
const LRU = require('lru-cache');
const { getAliyunDeviceSecret } = require('./api');
 
// 缓存三元组:MAC → {productKey, deviceName, deviceSecret}
const tripleCache = new LRU({
  max: 1000,
  ttl: 1000 * 60 * 60 // 1小时
});
 
// 存储已创建的设备客户端
const deviceClients = new Map();
 
/**
 * 根据 MAC 获取阿里云 IoT 三元组
 * @param {string} mac
 * @returns {Promise<Object>} {productKey, deviceName, deviceSecret}
 */
async function getTripleByMac(mac) {
  const cached = tripleCache.get(mac);
  if (cached) {
    logger.info(`缓存命中三元组`, { deviceMac: mac, productKey: cached.productKey });
    return cached;
  }
 
  try {
    logger.info(`请求三元组`, { deviceMac: mac });
    const response= await getAliyunDeviceSecret('device/info/getAliyunDeviceSecret',mac)
    console.log(response.data);
 
    const { productKey, deviceName, deviceSecret } = response.data.data;
    if (!productKey || !deviceName || !deviceSecret) {
      throw new Error('三元组不完整');
    }
 
    const triple = { productKey, deviceName, deviceSecret };
    tripleCache.set(mac, triple);
    logger.info(`三元组获取成功`, { deviceMac: mac, productKey });
 
    return triple;
  } catch (error) {
    logger.error(`获取三元组失败`, { deviceMac: mac, error: error.message });
    throw error;
  }
}
 
/**
 * 获取或创建 IoT 设备客户端
 * @param {Object} triple
 * @returns {Object} MQTT 客户端
 */
function getClient(triple) {
  const { productKey, deviceName } = triple;
  const clientId = `${productKey}/${deviceName}`;
 
  if (deviceClients.has(clientId)) {
    return deviceClients.get(clientId);
  }
 
  const client = IotDevice.device({
    productKey,
    deviceName,
    deviceSecret: triple.deviceSecret,
    region: process.env.IOT_REGION || 'cn-shanghai'
  });
 
  client.on('connect', () => {
    logger.info(`IoT 设备连接成功`, { deviceId: clientId });
  });
 
  client.on('error', (err) => {
    logger.error(`IoT 设备连接错误`, { deviceId: clientId, error: err.message });
  });
 
  deviceClients.set(clientId, client);
  return client;
}
 
/**
 * 发布数据到阿里云 IoT
 * @param {Object} triple
 * @param {any} data
 */
function publishToIot(triple, data,logMeta) {
  console.log('publishToIot called with data:');
  console.log(data);
  const iotMode={
    A:(data.UF_Goal.Value/1000).toFixed(2), //脱水目标量  统一单位  
    B:(data.UF_Volume.Value/1000).toFixed(), //脱水量
    C:(data.UF_Rate.Value/1000).toFixed(), //脱水速率超滤率(除水速度)
    D:data.Eff_BloodFlow.Value.toString(), //血流量
    H:data.VenousPressure.Value.toString(), //静脉压
    o:data.ArterialPressure.Value.toString(), //动脉压
    J:data.TMP.Value.toString(), //跨膜压
    G:data.Conductivity.Value.toString(), //电导率
    L:data.Eff_DialysateFlow.Value.toString(), //透析液流量
    F:data.Eff_DialysateTemperature.Value.toString(), //透析液温度
    n:logMeta.deviceMac,
    IPAddress:logMeta.deviceIp
  }
  console.log('Mapped iotMode data:');
  logger.info(`${triple} 打包上报属性:`, iotMode);
  console.log(iotMode);
  const client = getClient(triple);
  const topic=`/sys/${triple.productKey}/${triple.deviceName}/thing/event/property/post`
  client.postProps(iotMode, (res) => {
    if (res.message==='success') {
        logger.info(`${triple} 上报属性成功:`, res);
      
    } else {
        logger.error(`${triple} 上报属性失败:`, res);
    }
  });
}
 
module.exports = {
  getTripleByMac,
  publishToIot
};