You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何追踪Azure IoT Hub设备连接状态?连接韧性实现疑问

Azure IoT Hub设备连接韧性与状态检测问题解答

1. 错误及连接关闭事件监听器的正确性

你的监听器存在两处关键问题:

  • 事件绑定时机错误:你在调用iotHubClient.open()之后才绑定事件,可能错过初始连接阶段的事件触发;正确做法是在调用open()前完成所有事件绑定。
  • 事件名称误用:close不是Client对象的标准事件,应监听disconnect事件来捕获连接断开;另外,error事件会触发,但需注意未捕获的Promise rejection会导致进程意外退出,需额外处理。

2. 检查连接状态的内置方法

当前版本的azure-iot-device SDK已不再暴露client.connectionState或twin.connectionState这类同步属性。若要获取底层连接状态,可通过getTransport()获取MQTT传输实例,再访问其内部客户端的状态:

const mqttTransport = iotHubClient.getTransport();
// 底层MQTT客户端的connected属性,仅作参考,状态可能有延迟
const isConnected = mqttTransport.client?.connected;

但更可靠的方式是通过事件维护自定义的连接状态标记,因为连接状态是异步变化的,同步属性无法保证实时性。

3. 监听连接状态变化并维护标记

以下是修正后的代码,包含连接状态标记、正确的事件监听、重连逻辑及进程异常防护:

const fs = require('fs');
const { join } = require('path');
const { Mqtt } = require('azure-iot-device-mqtt');
const { Client } = require('azure-iot-device');

// 文件路径配置
const azPrivateKeyFilePath = join(__dirname, './rsa_private_key.key');
const azCertificateFilePath = join(__dirname, './rsa_cert.crt');
const offlineDataPath = join(__dirname, './offline_data.json');

// 设备配置
const device_id = 'xxx';
const deviceConnectionString = `xxx`;
const connOptions = {
    cert: fs.readFileSync(azCertificateFilePath, 'utf-8').toString(),
    key: fs.readFileSync(azPrivateKeyFilePath, 'utf-8').toString()
};

// 连接状态标记
let isConnected = false;
let iotHubClient = null;

// 保存离线数据到文件
function saveOfflineData(data) {
    let existingData = [];
    if (fs.existsSync(offlineDataPath)) {
        existingData = JSON.parse(fs.readFileSync(offlineDataPath, 'utf-8'));
    }
    existingData.push(data);
    fs.writeFileSync(offlineDataPath, JSON.stringify(existingData));
}

// 发送离线数据
async function sendOfflineData() {
    if (!fs.existsSync(offlineDataPath)) return;
    const dataList = JSON.parse(fs.readFileSync(offlineDataPath, 'utf-8'));
    for (const data of dataList) {
        try {
            await iotHubClient.sendEvent(data);
        } catch (err) {
            console.log('重发离线数据失败,停止重发:', err.message);
            // 将未发送的数据重新写入文件
            const remainingData = dataList.slice(dataList.indexOf(data));
            fs.writeFileSync(offlineDataPath, JSON.stringify(remainingData));
            return;
        }
    }
    // 全部发送成功,删除离线文件
    fs.unlinkSync(offlineDataPath);
}

// 建立IoT Hub连接
function establishIoTHubConnection() {
    iotHubClient = Client.fromConnectionString(deviceConnectionString, Mqtt);
    iotHubClient.setOptions(connOptions);

    // 绑定事件(必须在open前执行)
    iotHubClient.on('connect', () => {
        console.log(`Connected to IoT Hub - ${device_id}`);
        isConnected = true;
        // 重连成功后发送离线数据
        sendOfflineData();
    });

    iotHubClient.on('disconnect', () => {
        console.log('Disconnected from IoT Hub.');
        isConnected = false;
        // 尝试重连(添加指数退避逻辑更佳)
        setTimeout(establishIoTHubConnection, 5000);
    });

    iotHubClient.on('error', (err) => {
        console.log('IoT Hub error:', err.message);
        isConnected = false;
    });

    // 处理未捕获的Promise拒绝,避免进程退出
    process.on('unhandledRejection', (reason) => {
        console.log('Unhandled Rejection:', reason);
    });

    // 处理未捕获的异常,避免进程退出
    process.on('uncaughtException', (err) => {
        console.log('Uncaught Exception:', err.message);
        isConnected = false;
    });

    // 打开连接
    iotHubClient.open()
        .catch((err) => {
            console.log('Could not connect:', err.message);
            isConnected = false;
            // 初始连接失败,重试
            setTimeout(establishIoTHubConnection, 5000);
        });

    // 获取设备孪生
    iotHubClient.getTwin((err, twin) => {
        if (err) {
            console.log('Could not get device twin');
        } else {
            twin.on('properties.desired', (desiredState) => {
                const { config } = desiredState;
                if (config) {
                    console.log('UPDATING DEVICE CONFIG', JSON.stringify(config));
                }
            });
        }
    });
}

// 示例:发送数据前检查连接状态
function sendData(data) {
    if (isConnected) {
        iotHubClient.sendEvent(data)
            .catch((err) => {
                console.log('Send data failed, saving to offline:', err.message);
                saveOfflineData(data);
            });
    } else {
        console.log('Device offline, saving data to file');
        saveOfflineData(data);
    }
}

establishIoTHubConnection();

内容的提问来源于stack exchange,提问作者jlyh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 11:22:03