// 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} {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 };