shamblett / mqtt_client

A server and browser based MQTT client for dart
Other
548 stars 176 forks source link

Connection to https url was not upgraded to websockets #466

Closed ranjan98 closed 1 year ago

ranjan98 commented 1 year ago

I have been trying to connect to AWS IoT Core but I am unable to fix this issue. Basically, I am using port 443 to connect to MQTT Client but it gives me error that the connection cannot be upgraded to websockets. I am using the latest mqtt_client (10.0.0), and I also tried with version 9. I have tried several solutions floating around on github and stack overflow but still stuck on the same issue.

I also tried to run the example (aws_iot_cognito.dart) and it shows the same error. (Connection to https://# was not upgraded to websockets

Please help!

Logs:

flutter: 1-2023-05-29 11:46:02.726613 -- MqttConnectionBase::_onError - calling disconnected callback
flutter: Exception Occurred:
flutter: Connection Failed with error: WebSocketException: Connection to 'https://<hidden>.iot.ca-central-1.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<hidden>%2F20230529%2Fca-central-1%2Fiotdevicegateway%2Faws4_request&X-Amz-Date=20230529T154602Z&X-Amz-SignedHeaders=host&X-Amz-Signature=<hidden>&X-Amz-Security-Token=<hidden>#' was not upgraded to websocket
flutter: Client Connection Status Check: Connection status is faulted with return code of noneSpecified and a disconnection origin of none
flutter: 1-2023-05-29 11:46:02.727653 -- MqttConnectionHandlerBase::disconnect - entered

Also, if I try to change the port to 8883, I get Connection terminated during handshake error:


flutter: 4-2023-05-29 12:13:43.776317 -- MqttConnectionBase::_onError - calling disconnected callback
flutter: Exception Occurred:
flutter: Connection Failed with error: HandshakeException: Connection terminated during handshake
flutter: Client Connection Status Check: Connection status is faulted with return code of noneSpecified and a disconnection origin of none
flutter: 4-2023-05-29 12:13:43.777628 -- MqttConnectionHandlerBase::disconnect - entered
flutter: 4-2023-05-29 12:13:43.777831 -- MqttConnectionHandlerBase::_performConnectionDisconnect entered
flutter: 4-2023-05-29 12:13:43.778048 -- MqttConnectionKeepAlive::stop - stopping keep alive
flutter: Disconnected

After some time, I also get the following error:


flutter: 4-2023-05-29 12:14:20.194065 -- MqttConnectionBase::_onError - calling disconnected callback
flutter: Exception Occurred:
flutter: Connection Failed with error: SocketException: Operation timed out (OS Error: Operation timed out, errno = 60), address = a153dwfz99hvwi-ats.iot.ca-central-1.amazonaws.com, port = 64098
flutter: Client Connection Status Check: Connection status is disconnected with return code of noneSpecified and a disconnection origin of solicited
flutter: Disconnected

If I change it to any other port, it just shows WS URL is wss:// and gets disconnected after that:

flutter: 5-2023-05-29 12:15:32.690591 -- MqttClient::connect - Connection timeout period is 5000 milliseconds
flutter: 5-2023-05-29 12:15:32.691883 -- MqttClient::connect - keep alive is enabled with a value of 300 seconds
flutter: 5-2023-05-29 12:15:32.692099 -- MqttConnectionKeepAlive:: Initialised with a keep alive value of 300 seconds
flutter: 5-2023-05-29 12:15:32.692275 -- MqttConnectionKeepAlive:: Disconnect on no ping response is disabled
flutter: 5-2023-05-29 12:15:32.692411 -- MqttConnectionHandlerBase::connect - server wss://<hidden>.iot.ca-central-1.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<hidden>%2F20230529%2Fca-central-1%2Fiotdevicegateway%2Faws4_request&X-Amz-Date=20230529T154602Z&X-Amz-SignedHeaders=host&X-Amz-Signature=<hidden>&X-Amz-Security-Token=<hidden>
flutter: 5-2023-05-29 12:15:32.692544 -- SynchronousMqttServerConnectionHandler::internalConnect entered
flutter: 5-2023-05-29 12:15:32.692645 -- SynchronousMqttServerConnectionHandler::internalConnect - initiating connection try 0, auto reconnect in progress false
flutter: 5-2023-05-29 12:15:32.692734 -- SynchronousMqttServerConnectionHandler::internalConnect - websocket selected
flutter: 5-2023-05-29 12:15:32.692839 -- SynchronousMqttServerConnectionHandler::internalConnect - calling connect
flutter: 5-2023-05-29 12:15:32.692921 -- MqttWsConnection::connect - entered
flutter: 5-2023-05-29 12:15:32.693365 -- MqttWsConnection::connect - WS URL is wss://<hidden>.iot.ca-central-1.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<hidden>%2F20230529%2Fca-central-1%2Fiotdevicegateway%2Faws4_request&X-Amz-Date=20230529T154602Z&X-Amz-SignedHeaders=host&X-Amz-Signature=<hidden>&X-Amz-Security-Token=<hidden>

Reloaded 1 of 2494 libraries in 416ms (compile: 82 ms, reload: 194 ms, reassemble: 122 ms).
flutter: 5-2023-05-29 12:16:48.352749 -- MqttConnectionBase::_onError - calling disconnected callback
flutter: Exception Occurred:
flutter: Connection Failed with error: SocketException: Operation timed out (OS Error: Operation timed out, errno = 60), address = a153dwfz99hvwi-ats.iot.ca-central-1.amazonaws.com, port = 64323
flutter: Client Connection Status Check: Connection status is faulted with return code of noneSpecified and a disconnection origin of none
flutter: 5-2023-05-29 12:16:48.353984 -- MqttConnectionHandlerBase::disconnect - entered
flutter: 5-2023-05-29 12:16:48.354175 -- MqttConnectionHandlerBase::_performConnectionDisconnect entered
flutter: 5-2023-05-29 12:16:48.354486 -- MqttConnectionKeepAlive::stop - stopping keep alive
flutter: Disconnected
flutter: 5-2023-05-29 12:18:04.590564 -- MqttConnectionKeepAlive::pingRequired
flutter: 5-2023-05-29 12:18:04.591032 -- MqttConnectionKeepAlive::pingRequired - NOT sending ping - not connected
flutter: 5-2023-05-29 12:18:04.591228 -- MqttConnectionKeepAlive::pingRequired - restarting ping timer

flutter doctor:

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.10.2, on macOS 13.3 22E252 darwin-arm64, locale en-CA)
[!] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    ! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.1)
[✓] VS Code (version 1.77.0)
[✓] VS Code (version 1.77.0)
[✓] Connected device (4 available)
[✓] Network resources

! Doctor found issues in 1 category.

Here is the code:

import 'dart:developer' as developer;
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:celebright_flutter/constants/constants.dart';
import 'package:flutter/material.dart';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
import 'mqtt_request.dart';

class CustomMqtt extends StatefulWidget {
  const CustomMqtt({super.key});

  @override
  State<CustomMqtt> createState() => _CustomMqttState();
}

class _CustomMqttState extends State<CustomMqtt> {
  static const host = '<hidden>-ats.iot.ca-central-1.amazonaws.com';
  static const region = 'ca-central-1';

  var accessKey = ""; // fetched from Amplify Auth Cognito
  var secretKey = ""; // fetched from Amplify Auth Cognito
  var sessionToken = ""; // fetched from Amplify Auth Cognito
  var identityId = ""; // fetched from Amplify Auth Cognito
  late MqttServerClient client;

  void mqttConnect(
    String endpoint,
    String clientId,
    String awsAccessKeyId,
    String awsSecretKey,
  ) async {

    client = MqttServerClient(endpoint, clientId);
    client.logging(on: true);
    client.autoReconnect = true;
    client.port = 80;
    client.useWebSocket = true;
    client.keepAlivePeriod = 300;
    client.connectTimeoutPeriod = 10;
    client.setProtocolV311();
    client.onDisconnected = onDisconnected;
    client.onConnected = onConnected;
    client.onSubscribed = onSubscribed;
    client.onSubscribeFail = onSubscribeFail;
    // client.useAlternateWebSocketImplementation = false;
    client.websocketProtocols = MqttClientConstants.protocolsSingleDefault;

    client.onUnsubscribed = onUnsubscribed;
    // client.onAutoReconnect = onAutoReconnect;

    final connectMessage = MqttConnectMessage()
        // .withClientIdentifier(clientId)
        .startClean()
        .withWillQos(MqttQos.atMostOnce);

    client.connectionMessage = connectMessage;

    try {
      await client.connect();
      print(client.connectionMessage);
    } on Exception catch (e) {
      print("Exception Occurred: ");
      print("Connection Failed with error: $e");
      print("Client Connection Status Check: ${client.connectionStatus}");
      client.disconnect();
    }
  }

// connection succeeded
  void onConnected() {
    print('Connected');
  }

// unconnected
  void onDisconnected() {
    print('Disconnected');
  }

// subscribe to topic succeeded
  void onSubscribed(String topic) {
    print('Subscribed topic: $topic');
  }

// subscribe to topic failed
  void onSubscribeFail(String topic) {
    print('Failed to subscribe $topic');
  }

// unsubscribe succeeded
  void onUnsubscribed(String? topic) {
    print('Unsubscribed topic: $topic');
  }

  @override
  void initState() {
    super.initState();
    // getAWSCredentials(); 
  }

  @override
  Widget build(BuildContext context) {
    // getAWSCredentials();
    print(sessionToken);

    var endpoint = createEndpoint(
        region,
        host, 
        accessKey,
        secretKey,
        sessionToken);
    mqttConnect(endpoint, identityId, accessKey, secretKey);
    return Scaffold(
      appBar: AppBar(title: const Text('Custom MQTT')),
      body: const Center(
        child: Text(
          'Custom MQTT Testing',
          style: TextStyle(color: defaultWhite),
        ),
      ),
    );
  }
}
shamblett commented 1 year ago

I'm sure I've seen this before but I'm no AWS expert, as far as I know the aws cognito example works, unless of course AWS has changed something in the meantime.

I see you are using 'client.websocketProtocols = MqttClientConstants.protocolsSingleDefault;', you could try this with an empty list i.e. client.websocketProtocols = [];' just to rule it out.

Other than that search the closed issues for AWS related problems or maybe the AWS logs on your broker may hold more information.

ranjan98 commented 1 year ago

I tried with the client.websocketProtocols = []; but still nothing. Not sure if this is AWS specific, as I ran the mqtt_server_client_websocket_secure.dart and it works fine on port 8081, but gives the exact same error (Connection was not upgraded to websockets) when I try with port 443. Not sure why it is not able to upgrade the https to wss.

I also tried with the AWS IoT Cognito example, still having same issue on 443.

shamblett commented 1 year ago

OK so what do your AWS logs say?

ranjan98 commented 1 year ago

I am not an expert in AWS but I tried looking into the Logs under AWSIotLogsV2, I don't see anything happening when I send the request.

shamblett commented 1 year ago

Not sure if I can help further, maybe ask on an AWS list or any users from the closed issues that have got this working maybe.

ranjan98 commented 1 year ago

I checked all the previous issues closed, and magically this one works: https://github.com/shamblett/mqtt_client/issues/246#issuecomment-792312522

Thanks :)