// aliyun-iot.js
|
const IotDevice = require('aliyun-iot-device-sdk');
|
const logger = require('./logger');
|
|
// 固定设备信息
|
const PRODUCT_KEY = 'k08fz9HAzxl';
|
const DEVICE_SECRET = '06f039246b5affc83b567baa8bb5b937';
|
|
// 存储设备实例(长连接复用)
|
const devices = new Map();
|
|
/**
|
* 获取或创建设备实例(长连接)
|
* @param {string} deviceId
|
* @return {Object|null} 设备实例 或 null(创建失败)
|
*/
|
function getOrCreateDevice(deviceId) {
|
if (!deviceId || typeof deviceId !== 'string') {
|
logger.error('无效的 deviceId', { deviceId });
|
return null;
|
}
|
|
const existingDevice = devices.get(deviceId);
|
if (existingDevice) {
|
return existingDevice;
|
}
|
|
try {
|
const device = IotDevice.device({
|
productKey: PRODUCT_KEY,
|
deviceName: deviceId,
|
deviceSecret: DEVICE_SECRET,
|
host: `${PRODUCT_KEY}.iot-as-mqtt.cn-shanghai.aliyuncs.com`,
|
port: 1883,
|
keepalive: 60,
|
clean: true,
|
reconnectPeriod: 5000 // 自动重连间隔
|
});
|
|
device.on('connect', () => {
|
logger.info(`✅ 设备 ${deviceId} 已连接到阿里云 IoT`);
|
});
|
|
device.on('reconnect', () => {
|
logger.warn(`🔁 设备 ${deviceId} 正在重连...`);
|
});
|
|
device.on('error', (err) => {
|
logger.error(`❌ 设备 ${deviceId} 发生错误`, {
|
错误: err.message,
|
堆栈: err.stack
|
});
|
});
|
|
device.on('offline', () => {
|
logger.warn(`⚠️ 设备 ${deviceId} 已离线`);
|
});
|
|
// 缓存实例
|
devices.set(deviceId, device);
|
|
return device;
|
|
} catch (err) {
|
logger.error('创建设备实例失败', {
|
错误: err.message,
|
堆栈: err.stack,
|
deviceId
|
});
|
return null;
|
}
|
}
|
|
/**
|
* 发送数据到阿里云 IoT(高频上报,长连接)
|
* @param {string} deviceId
|
* @param {Object} data
|
*/
|
function sendDataToAliyun(deviceId, data) {
|
// 参数校验
|
if (!deviceId || typeof deviceId !== 'string' || !data || typeof data !== 'object') {
|
logger.error('sendDataToAliyun 参数错误', { deviceId, data: typeof data });
|
return;
|
}
|
|
let device;
|
try {
|
device = getOrCreateDevice(deviceId);
|
if (!device) {
|
logger.error('无法创建设备实例', { deviceId });
|
return;
|
}
|
|
// 如果未连接,不阻塞,直接返回(可选:记录日志)
|
if (!device.connected) {
|
logger.warn(`设备 ${deviceId} 当前未连接,跳过发送`);
|
return;
|
}
|
|
// 发送数据
|
device.postProps(data, (res) => {
|
console.log('Aliyun IoT postProps 回调:', res);
|
if (res?.message === 'success') {
|
// 成功:无需日志(太频繁),可注释
|
logger.debug(`📡 数据已发送`, { deviceId });
|
} else {
|
const errorMsg = res?.message || '未知错误';
|
logger.error(`❌ 发送失败`, { deviceId, 错误: errorMsg, data });
|
}
|
});
|
|
} catch (err) {
|
logger.error('sendDataToAliyun 执行异常', {
|
错误: err.message,
|
堆栈: err.stack,
|
deviceId,
|
data
|
});
|
}
|
}
|
|
/**
|
* 关闭所有设备连接(用于进程退出)
|
*/
|
function closeAllConnections() {
|
devices.forEach((device, id) => {
|
try {
|
device.end();
|
logger.info(`已关闭设备连接: ${id}`);
|
} catch (err) {
|
logger.error(`关闭设备 ${id} 失败`, { 错误: err.message });
|
}
|
});
|
devices.clear();
|
}
|
|
// 优雅退出
|
process.on('SIGINT', closeAllConnections);
|
process.on('SIGTERM', closeAllConnections);
|
|
module.exports = {
|
sendDataToAliyun,
|
closeAllConnections // 可选导出,用于主程序调用
|
};
|