shamblett / mqtt5_client

A server and browser based MQTT 5 client for dart
Other
49 stars 25 forks source link

AWS IOT Connection #71

Closed Zaherkorechi closed 9 months ago

Zaherkorechi commented 9 months ago

Hello there,

I am wondaring if there any example for using the lib with AWS IoT.

Thanks.

Zaherkorechi commented 9 months ago

I am trying to run this code, to read topic from AWS IOT

final MqttServerClient client = MqttServerClient(
      'a3h6qhd8wo8w5o-ats.iot.ca-central-1.amazonaws.com',
      'KorechiTestConnection');
      bool isConnected = false;

  TextEditingController idTextController = TextEditingController();

  _connect() async {
    ProgressDialog progressDialog = ProgressDialog(context,
        blur: 0,
        dialogTransitionType: DialogTransitionType.Shrink,
        dismissable: false,
        title: const Text("Connecting"),
        message: const Text("Please Wait, Connecting to AWS IoT MQTT Broker"));
    progressDialog.setLoadingWidget(const CircularProgressIndicator(
      valueColor: AlwaysStoppedAnimation(Colors.red),
    ));
    progressDialog.show();

    isConnected = await mqttConnect(idTextController.text.trim());
    progressDialog.dismiss();
  }

  _disconnect() {
    client.disconnect();
  }

  Future<bool> mqttConnect(String uniqueId) async {
    setStatus("Connecting to MQTT Broker");

    // After adding your certificates to the pubspec.yaml, you can use Security Context.
    //
    final List<int> rootCA =
        (await rootBundle.load('assets/certs/rootCA.pem')).buffer.asUint8List();
    final List<int> deviceCert =
        (await rootBundle.load('assets/certs/device_pem.crt'))
            .buffer
            .asUint8List();
    final List<int> privateKey =
        (await rootBundle.load('assets/certs/private_pem.key'))
            .buffer
            .asUint8List();

    SecurityContext context = SecurityContext.defaultContext;
    try {
      print("First file");
      context.setClientAuthoritiesBytes(rootCA);
      print("Third file");
      context.usePrivateKeyBytes(privateKey);
      print("Second file");
      context.useCertificateChainBytes(deviceCert);
    } catch (e) {
      print("Error $e");
      return false;
    }
    //
    client.securityContext = context;

    client.logging(on: true);
    client.keepAlivePeriod = 30;
    client.port = 8883;
    client.secure = true;
    client.onConnected = onConnected;
    client.onDisconnected = onDisconnected;
    client.pongCallback = pong;

    final MqttConnectMessage connMess = MqttConnectMessage()
        .withClientIdentifier("KorechiTestConnection")
        .startClean();
    client.connectionMessage = connMess;

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

    if (client.connectionStatus!.state == MqttConnectionState.connected) {
      print("Connected to AWS Successfully!");
    } else {
      print("Connected to AWS Error!");
      return false;
    }

    const topic = 'sdk/test/python';
    client.subscribe(topic, MqttQos.atLeastOnce);

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

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

    return true;
  }

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

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

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

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

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

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

It is seems it start connecting but I am getting this error:

I/flutter (17393): 2023-11-21 11:58:44.177336 -- MqttConnectionHandlerBase::connect - server a3h6qhd8wo8w5o-ats.iot.ca-central-1.amazonaws.com, port 8883
I/flutter (17393): 2023-11-21 11:58:44.180885 -- MqttSynchronousServerConnectionHandler::internalConnect entered
I/flutter (17393): 2023-11-21 11:58:44.181410 -- MqttSynchronousServerConnectionHandler::internalConnect - initiating connection try 0, auto reconnect in progress false
I/flutter (17393): 2023-11-21 11:58:44.181661 -- MqttSynchronousServerConnectionHandler::internalConnect - secure selected
I/flutter (17393): 2023-11-21 11:58:44.182743 -- MqttSynchronousServerConnectionHandler::internalConnect - calling connect
I/flutter (17393): 2023-11-21 11:58:44.183581 -- MqttServerSecureConnection::connect - entered
I/flutter (17393): 2023-11-21 11:58:44.454726 -- MqttServerSecureConnection::connect - securing socket
I/flutter (17393): 2023-11-21 11:58:44.455492 -- MqttServerSecureConnection::connect - start listening
I/flutter (17393): 2023-11-21 11:58:44.455880 -- MqttServerConnection::_startListening
I/flutter (17393): 2023-11-21 11:58:44.458305 -- MqttSynchronousServerConnectionHandler::internalConnect - connection complete
I/flutter (17393): 2023-11-21 11:58:44.458530 -- MqttSynchronousServerConnectionHandler::internalConnect sending connect message
I/flutter (17393): 2023-11-21 11:58:44.458988 -- MqttConnectionHandlerBase::sendMessage - sending message started >>> -> MQTTMessage of type MqttMessageType.connect
I/flutter (17393): MessageType = MqttMessageType.connect Duplicate = false Retain = false Qos = atMostOnce Size = 0
I/flutter (17393): ProtocolName = MQTT
I/flutter (17393): ProtocolVersion = 5
I/flutter (17393): ConnectFlags = CleanStart=true, WillFlag=false, WillQos=atMostOnce, WillRetain=false, PasswordFlag=false, UserNameFlag=false
I/flutter (17393): KeepAlive = 0
I/flutter (17393): Properties = No properties setWill topic = null
I/flutter (17393): User name = not set
I/flutter (17393): Password = not set
I/flutter (17393): 2023-11-21 11:58:44.484987 -- MqttConnectionHandlerBase::sendMessage - sending message ended >>>
I/flutter (17393): 2023-11-21 11:58:44.486030 -- MqttSynchronousServerConnectionHandler::internalConnect - pre sleep, state = Connection status is connecting with return code of notSet and a disconnection origin of none
I/flutter (17393): 2023-11-21 11:58:44.514640 -- MqttConnectionBase::_onDone - calling disconnected callback
I/flutter (17393): 2023-11-21 11:58:49.493702 -- MqttSynchronousServerConnectionHandler::internalConnect - post sleep, state = Connection status is connecting with return code of notSet and a disconnection origin of none
I/flutter (17393): 2023-11-21 11:58:49.494522 -- MqttSynchronousServerConnectionHandler::internalConnect - initiating connection try 1, auto reconnect in progress false
I/flutter (17393): 2023-11-21 11:58:49.494731 -- MqttSynchronousServerConnectionHandler::internalConnect - secure selected
I/flutter (17393): 2023-11-21 11:58:49.494909 -- MqttSynchronousServerConnectionHandler::internalConnect - calling connect
I/flutter (17393): 2023-11-21 11:58:49.495089 -- MqttServerSecureConnection::connect - entered
I/flutter (17393): 2023-11-21 11:58:49.633601 -- MqttServerSecureConnection::connect - securing socket
I/flutter (17393): 2023-11-21 11:58:49.633914 -- MqttServerSecureConnection::connect - start listening
I/flutter (17393): 2023-11-21 11:58:49.634051 -- MqttServerConnection::_startListening
I/flutter (17393): 2023-11-21 11:58:49.634288 -- MqttSynchronousServerConnectionHandler::internalConnect - connection complete
I/flutter (17393): 2023-11-21 11:58:49.634411 -- MqttSynchronousServerConnectionHandler::internalConnect sending connect message
I/flutter (17393): 2023-11-21 11:58:49.634509 -- MqttConnectionHandlerBase::sendMessage - sending message started >>> -> MQTTMessage of type MqttMessageType.connect
I/flutter (17393): MessageType = MqttMessageType.connect Duplicate = false Retain = false Qos = atMostOnce Size = 34
I/flutter (17393): ProtocolName = MQTT
I/flutter (17393): ProtocolVersion = 5
I/flutter (17393): ConnectFlags = CleanStart=true, WillFlag=false, WillQos=atMostOnce, WillRetain=false, PasswordFlag=false, UserNameFlag=false
I/flutter (17393): KeepAlive = 0
I/flutter (17393): Properties = No properties setWill topic = null
I/flutter (17393): User name = not set
I/flutter (17393): Password = not set
I/flutter (17393): 2023-11-21 11:58:49.635371 -- MqttConnectionHandlerBase::sendMessage - sending message ended >>>
I/flutter (17393): 2023-11-21 11:58:49.635643 -- MqttSynchronousServerConnectionHandler::internalConnect - pre sleep, state = Connection status is connecting with return code of notSet and a disconnection origin of none
I/flutter (17393): 2023-11-21 11:58:49.676156 -- MqttConnectionBase::_onDone - calling disconnected callback
I/flutter (17393): 2023-11-21 11:58:54.643511 -- MqttSynchronousServerConnectionHandler::internalConnect - post sleep, state = Connection status is connecting with return code of notSet and a disconnection origin of none
I/flutter (17393): 2023-11-21 11:58:54.644104 -- MqttSynchronousServerConnectionHandler::internalConnect - initiating connection try 2, auto reconnect in progress false
I/flutter (17393): 2023-11-21 11:58:54.644313 -- MqttSynchronousServerConnectionHandler::internalConnect - secure selected
I/flutter (17393): 2023-11-21 11:58:54.644526 -- MqttSynchronousServerConnectionHandler::internalConnect - calling connect
I/flutter (17393): 2023-11-21 11:58:54.644701 -- MqttServerSecureConnection::connect - entered
I/flutter (17393): 2023-11-21 11:58:54.712398 -- MqttServerSecureConnection::connect - securing socket
I/flutter (17393): 2023-11-21 11:58:54.712736 -- MqttServerSecureConnection::connect - start listening
I/flutter (17393): 2023-11-21 11:58:54.712894 -- MqttServerConnection::_startListening
I/flutter (17393): 2023-11-21 11:58:54.713180 -- MqttSynchronousServerConnectionHandler::internalConnect - connection complete
I/flutter (17393): 2023-11-21 11:58:54.713347 -- MqttSynchronousServerConnectionHandler::internalConnect sending connect message
I/flutter (17393): 2023-11-21 11:58:54.713486 -- MqttConnectionHandlerBase::sendMessage - sending message started >>> -> MQTTMessage of type MqttMessageType.connect
I/flutter (17393): MessageType = MqttMessageType.connect Duplicate = false Retain = false Qos = atMostOnce Size = 34
I/flutter (17393): ProtocolName = MQTT
I/flutter (17393): ProtocolVersion = 5
I/flutter (17393): ConnectFlags = CleanStart=true, WillFlag=false, WillQos=atMostOnce, WillRetain=false, PasswordFlag=false, UserNameFlag=false
I/flutter (17393): KeepAlive = 0
I/flutter (17393): Properties = No properties setWill topic = null
I/flutter (17393): User name = not set
I/flutter (17393): Password = not set
I/flutter (17393): 2023-11-21 11:58:54.714395 -- MqttConnectionHandlerBase::sendMessage - sending message ended >>>
I/flutter (17393): 2023-11-21 11:58:54.714693 -- MqttSynchronousServerConnectionHandler::internalConnect - pre sleep, state = Connection status is connecting with return code of notSet and a disconnection origin of none
I/flutter (17393): 2023-11-21 11:58:54.740386 -- MqttConnectionBase::_onDone - calling disconnected callback
I/flutter (17393): 2023-11-21 11:58:59.722459 -- MqttSynchronousServerConnectionHandler::internalConnect - post sleep, state = Connection status is connecting with return code of notSet and a disconnection origin of none
I/flutter (17393): 2023-11-21 11:58:59.724835 -- MqttSynchronousServerConnectionHandler::internalConnect failed
I/flutter (17393): 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?
I/flutter (17393): 2023-11-21 11:58:59.737259 -- MqttConnectionHandlerBase::disconnect
I/flutter (17393): 2023-11-21 11:58:59.738071 -- MqttConnectionHandlerBase::_performConnectionDisconnect entered
I/flutter (17393): MQTT_LOGS:: Disconnected
I/flutter (17393): Connected to AWS Error!

Do any one know what I miss here?

The broker is not responding to the connection request message (Missing Connection Acknowledgement?

Thanks

shamblett commented 9 months ago

There is an AWS example in the examples directory, other than that search through the closed issues, there have been many with AWS problems, most of them solved.

Zaherkorechi commented 9 months ago

I am sorry, @shamblett. I check all the example, I didn't find one for AWS IOT. Please, may you share the link with me. Thanks in advance

shamblett commented 9 months ago

Ah it may be in the mqtt_client package, please check there.

Zaherkorechi commented 9 months ago

I followed the example, but still getting the same issue.

I/flutter (30785): 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?

I am wondaring if there a way to get more info from the for this exception.

Also, I am wondaring if there is any things, I should do in AWS console to make the connection works.

FYI: for keys, I used the one which AWS console ask to download for creating the device and start the connection from the IoT device side.

Thanks for help in advance.

shamblett commented 9 months ago

Your only recourse is to examine your broker logs in AWS to see why its not con ecting, there are many ways this could fail as you may have seen in the closed issues.

Without a connection ack message the client has no reason code so cant shed any light on this.

Zaherkorechi commented 9 months ago

Thanks you @shamblett, for notes. I solved the issue by give the mobile client in AWS full permission. I think I have to give full permission for both of the client to do communication. This is are policy needed to make the connection.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "*"
    }
  ]
}
hacker1024 commented 7 months ago

This is what I've done to authenticate with IAM. It uses the official AWS Signature Version 4 package.

import 'package:aws_common/aws_common.dart';
import 'package:aws_signature_v4/aws_signature_v4.dart';
import 'package:mqtt5_client/mqtt5_server_client.dart';

void main(List<String> arguments) async {
  const host = "";
  const region = "";
  const clientIdentifier = "";

  final uri = await const AWSSigV4Signer().presign(
    AWSHttpRequest(
      method: AWSHttpMethod.get,
      uri: Uri(
        scheme: "wss",
        host: "$host.iot.$region.amazonaws.com",
        pathSegments: const ["mqtt"],
      ),
    ),
    credentialScope: AWSCredentialScope(
      region: region,
      service: AWSService.iotDataPlane,
    ),
    // The maximum expiry duration is 7 days.
    // https://docs.aws.amazon.com/IAM/latest/UserGuide/aws-signing-authentication-methods.html
    expiresIn: const Duration(days: 7),
  );

  final client =
      MqttServerClient.withPort(uri.toString(), clientIdentifier, 443);
  client.useWebSocket = true;
  await client.connect();

  print("Connected!");
}