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