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

Flutter Web通过MQTT连接Azure IoT Hub失败,请求排查原因

Flutter Web对接Azure IoT Hub MQTT连接失败排查

我正在开发Flutter Web应用,需要对接Azure IoT Hub读取数据并在组件中展示。下面是我实现的MQTT连接逻辑代码:

class MqttHandler with ChangeNotifier {
  final ValueNotifier<String> data = ValueNotifier<String>("");
  late MqttBrowserClient client;

  Future<Object> connect() async {
    client = MqttBrowserClient(
        'ws://iothub.azure-devices.net', '');
    client.port = 443;
    client.logging(on: true);
    client.onConnected = onConnected;
    client.onDisconnected = onDisconnected;
    client.onUnsubscribed = onUnsubscribed;
    client.onSubscribed = onSubscribed;
    client.onSubscribeFail = onSubscribeFail;
    client.pongCallback = pong;
    client.keepAlivePeriod = 60;
    client.logging(on: true);
    client.websocketProtocols = ['mqtts'];

    /// Set the correct MQTT protocol for mosquito
    client.setProtocolV311();
    
    final MqttConnectMessage connectMessage = MqttConnectMessage()
      .authenticateAs('iothub.azure-devices.net/DEVICE01', 'SharedAccessSignature')
      .withClientIdentifier('DEVICE01')
      .keepAliveFor(60)
      .startClean();

    client.connectionMessage = connectMessage;
    try {
      await client.connect();
    } catch (e) {
      print('Exception: $e');
      client.disconnect();
    }

    if (client.connectionStatus!.state == MqttConnectionState.connected) {
      print('MQTT_LOGS::Azure client connected');
    } else {
      print(
          'MQTT_LOGS::ERROR Azure client connection failed - disconnecting, status is ${client.connectionStatus}');
      client.disconnect();
      return -1;
    }

    print('MQTT_LOGS::Subscribing to the test/lol topic');
    const topic = 'devices/EZTRDEVICE01/messages/events/';
    client.subscribe(topic, MqttQos.atMostOnce);

    client.updates!.listen((List<MqttReceivedMessage<MqttMessage?>>? c) {
      final recMess = c![0].payload as MqttPublishMessage;
      final pt =
          MqttPublishPayload.bytesToStringAsString(recMess.payload.message);

      data.value = pt;
      notifyListeners();
      print(
          'MQTT_LOGS:: New data arrived: topic is <${c[0].topic}>, payload is $pt');
      print('');
    });

    return client;
  }

  void onConnected() {
    print('MQTT_LOGS:: Connected');
  }

  void onDisconnected() {
    print('MQTT_LOGS:: Disconnected');
  }

  void onSubscribed(String topic) {
    print('MQTT_LOGS:: Subscribed topic: $topic');
  }

  void onSubscribeFail(String topic) {
    print('MQTT_LOGS:: Failed to subscribe $topic');
  }

  void onUnsubscribed(String? topic) {
    print('MQTT_LOGS:: Unsubscribed topic: $topic');
  }

  void pong() {
    print('MQTT_LOGS:: Ping response client callback invoked');
  }

  void publishMessage(String message) {
    const pubTopic = 'test/sample';
    final builder = MqttClientPayloadBuilder();
    builder.addString(message);

    if (client.connectionStatus?.state == MqttConnectionState.connected) {
      client.publishMessage(pubTopic, MqttQos.atMostOnce, builder.payload!);
    }
  }
}

运行时出现以下错误日志:

-2024-02-02 17:42:43.068 -- SynchronousMqttBrowserConnectionHandler::internalConnect - pre sleep, state = Connection status is connecting with return code of noneSpecified and a disconnection origin of none
1-2024-02-02 17:42:48.121 -- SynchronousMqttBrowserConnectionHandler::internalConnect - post sleep, state = Connection status is connecting with return code of noneSpecified and a disconnection origin of none
1-2024-02-02 17:42:48.122 -- SynchronousMqttBrowserConnectionHandler::internalConnect failed
Exception: mqtt-client::NoConnectionException: The maximum allowed connection attempts ({3}) were exceeded. The broker is not responding to the connection request message (Missing Connection Acknowledgement?
1-2024-02-02 17:42:48.124 -- MqttConnectionHandlerBase::disconnect - entered
1-2024-02-02 17:42:48.124 -- MqttConnectionHandlerBase::_performConnectionDisconnect entered
1-2024-02-02 17:42:48.125 -- MqttConnectionKeepAlive::stop - stopping keep alive
MQTT_LOGS:: Disconnected
MQTT_LOGS::ERROR Azure client connection failed - disconnecting, status is Connection status is disconnected with return code of noneSpecified and a disconnection origin of solicited
MQTT_LOGS:: Disconnected

应用在Chrome中运行,使用了mqtt_browser_client.dart,已尝试将端口改为443,但问题依旧。请问可能的原因是什么?


可能的原因及修复方案
  • WebSocket地址与协议错误
    Azure IoT Hub的WebSocket MQTT连接必须使用加密的wss://协议,而非明文的ws://,且地址需要包含/websocket后缀,正确格式应为wss://{你的IoT Hub名称}.azure-devices.net/websocket。代码中使用ws://iothub.azure-devices.net会导致连接被服务端拒绝,无法获取ACK响应。

  • 认证参数格式错误
    authenticateAs的第一个参数应为纯设备ID(如DEVICE01),而非iothub.azure-devices.net/DEVICE01;第二个参数必须是完整的Shared Access Signature(SAS)令牌字符串(格式类似SharedAccessSignature sr=xxx&sig=xxx&se=xxx),不能用占位符'SharedAccessSignature'。无效的认证信息会导致IoT Hub静默拒绝连接。

  • WebSocket协议标识配置错误
    client.websocketProtocols应设置为['mqtt'],而非['mqtts']。mqtts是TCP加密连接的标识,WebSocket场景下服务端仅识别mqtt协议,错误配置会导致服务端无法解析连接请求。

  • 设备状态异常
    确保DEVICE01已在Azure IoT Hub中注册且状态为启用。未注册或被禁用的设备发起连接时,IoT Hub不会返回连接确认,直接导致连接超时失败。

  • 订阅主题设备ID不匹配
    虽然不是连接失败的直接原因,但代码中订阅的主题devices/EZTRDEVICE01/messages/events/里的设备ID与客户端标识DEVICE01不一致,后续即便连接成功也无法接收数据,建议统一为devices/DEVICE01/messages/events/。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 02:35:15