Потеряно соединение при попытке соединения с брокером aws iot mqtt - PullRequest
0 голосов
/ 11 сентября 2018

это мой код

try {
            if (AWSIotKeystoreHelper.isKeystorePresent(keystorePath, keystoreName)) {
                if (AWSIotKeystoreHelper.keystoreContainsAlias(certificateId, keystorePath,
                        keystoreName, keystorePassword)) {
                    Log.i(LOG_TAG, "Certificate " + certificateId
                            + " found in keystore - using for MQTT.");
                    // load keystore from file into memory to pass on connection
                    clientKeyStore = AWSIotKeystoreHelper.getIotKeystore(certificateId,
                            keystorePath, keystoreName, keystorePassword);
                    btnConnect.setEnabled(true);
                    mqttManager.setAutoReconnect(false);
                } else {
                    Log.i(LOG_TAG, "Key/cert " + certificateId + " not found in keystore.");
                }
            } else {
                Log.i(LOG_TAG, "Keystore " + keystorePath + "/" + keystoreName + " not found.");
            }
        } catch (Exception e) {
            Log.e(LOG_TAG, "An error occurred retrieving cert/key from keystore.", e);
        }

        if (clientKeyStore == null) {
            Log.i(LOG_TAG, "Cert/key was not found in keystore - creating new key and certificate.");

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // Create a new private key and certificate. This call
                        // creates both on the server and returns them to the
                        // device.
                        CreateKeysAndCertificateRequest createKeysAndCertificateRequest =
                                new CreateKeysAndCertificateRequest();
                        createKeysAndCertificateRequest.setSetAsActive(true);
                        final CreateKeysAndCertificateResult createKeysAndCertificateResult;
                        createKeysAndCertificateResult =
                                mIotAndroidClient.createKeysAndCertificate(createKeysAndCertificateRequest);
                        Log.i(LOG_TAG,
                                "Cert ID: " +
                                        createKeysAndCertificateResult.getCertificateId() +
                                        " created.");

                        // store in keystore for use in MQTT client
                        // saved as alias "default" so a new certificate isn't
                        // generated each run of this application
                        AWSIotKeystoreHelper.saveCertificateAndPrivateKey(certificateId,
                                createKeysAndCertificateResult.getCertificatePem(),
                                createKeysAndCertificateResult.getKeyPair().getPrivateKey(),
                                keystorePath, keystoreName, keystorePassword);


                        // load keystore from file into memory to pass on
                        // connection
                        clientKeyStore = AWSIotKeystoreHelper.getIotKeystore(certificateId,
                                keystorePath, keystoreName, keystorePassword);


                        // Attach a policy to the newly created certificate.
                        // This flow assumes the policy was already created in
                        // AWS IoT and we are now just attaching it to the
                        // certificate.
                        AttachPrincipalPolicyRequest policyAttachRequest =
                                new AttachPrincipalPolicyRequest();
                        policyAttachRequest.setPolicyName(AWS_IOT_POLICY_NAME);
                        policyAttachRequest.setPrincipal(createKeysAndCertificateResult
                                .getCertificateArn());
                        mIotAndroidClient.attachPrincipalPolicy(policyAttachRequest);

                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                btnConnect.setEnabled(true);
                            }
                        });
                    } catch (Exception e) {
                        Log.e(LOG_TAG,
                                "Exception occurred when generating new private key and certificate.",
                                e);
                    }
                }
            }).start();
        }
    }

    View.OnClickListener connectClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Log.d(LOG_TAG, "clientId = " + clientId);

            try {
                mqttManager.connect(clientKeyStore, new AWSIotMqttClientStatusCallback() {
                    @Override
                    public void onStatusChanged(final AWSIotMqttClientStatus status,
                            final Throwable throwable) {
                        Log.d(LOG_TAG, "Status = " + String.valueOf(status));

                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (status == AWSIotMqttClientStatus.Connecting) {
                                    tvStatus.setText("Connecting...");

                                } else if (status == AWSIotMqttClientStatus.Connected) {
                                    tvStatus.setText("Connected");

                                } else if (status == AWSIotMqttClientStatus.Reconnecting) {
                                    if (throwable != null) {
                                        Log.e(LOG_TAG, "Connection error.", throwable);
                                    }
                                    tvStatus.setText("Reconnecting");
                                } else if (status == AWSIotMqttClientStatus.ConnectionLost) {
                                    if (throwable != null) {
                                        Log.e(LOG_TAG, "Connection error.", throwable);
                                    }
                                    tvStatus.setText("Disconnected");
                                } else {
                                    tvStatus.setText("Disconnected");

                                }
                            }
                        });
                    }
                });
            } catch (final Exception e) {
                Log.e(LOG_TAG, "Connection error.", e);
                tvStatus.setText("Error! " + e.getMessage());
            }
        }
    };

Когда я пытаюсь подключиться к брокеру AWS IOT MQTT с помощью телефона Android, я получил сообщение об ошибке:

E / com.amazonaws.demo.androidpubsub.PubSubActivity: ошибка соединения. Потеряно соединение (32109) - java.io.EOFException в org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run (CommsReceiver.java:146) на java.lang.Thread.run (Thread.java:818) Вызвано: java.io.EOFException в java.io.DataInputStream.readByte (DataInputStream.java:77) в org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage (MqttInputStream.java:65) в org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run (CommsReceiver.java:107) at java.lang.Thread.run (Thread.java:818)

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Как уже говорилось, проблема почти наверняка связана с отсутствием соответствующей политики, но это еще более осложняется из-за плохой обработки ошибок в примере кода AWS. Приведенный выше код сначала ищет в хранилище ключей устройства сохраненный сертификат и, если он найден, пытается подключиться, используя его. Если он не может найти сертификат под ожидаемым именем хранилища ключей, он создает новый сертификат, сохраняет его в хранилище ключей и затем пытается присоединить к нему принципиальную политику. Если что-то пойдет не так при получении политики от AWS, у вас останется неправильно настроенная запись в хранилище ключей, и код, предоставленный AWS, никогда не сможет восстановиться после этого. Я потратил много часов, экспериментируя с политиками, но безуспешно, пока не проследил код и не понял, что не имеет значения, какую политику я указал - код игнорировал ее и использовал неправильно настроенную политику в хранилище ключей!

В блоке catch в приведенном выше коде добавьте следующее

AWSIotKeystoreHelper.deleteKeystoreAlias(certificateId,
                            keystorePath, keystoreName, keystorePassword);

Это гарантирует, что не будет неверно настроенного сертификата, который вас обманул.

Что касается начальной ошибки, возможно, проблема в названии и контексте указанной вами политики. Я создал политики в IAM, и они не были распознаны - вам действительно нужно создать политику IoT, как описано выше Roshan в контексте IoT Core Security, и указать имя, которое вы даете ему в примере кода PubSub.

0 голосов
/ 26 октября 2018

Вышеуказанное исключение может быть вызвано различными причинами, такими как потеря сетевого подключения, ограничения политики для подключения или подписки и т. Д. К сожалению, клиент Mqtt Paho не всегда отлично передает исключения подключения, и поэтому может быть трудно устранить причинупроблема как раз из этого исключения.Кажется, вы следите за этим примером приложения.Я смог заставить приложение работать с инструкциями README.Ниже приведены некоторые моменты, которые, как я подозреваю, могут вызвать эту проблему:

  1. Убедитесь, что следующая политика IAM прикреплена к роли без проверки подлинности, созданной в рамках создания пула удостоверений

    {"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Action": ["iot: AttachPrincipalPolicy", "iot: CreateKeysAndCertificate"], "Resource": ["*"]}]}

  2. Убедитесь, что к сертификату устройства прикреплена следующая политика IoT

    {"Version": "2012-10-17"," Statement ": [{" Effect ":" Allow "," Action ":" iot: Connect "," Resource ":" "}, {" Effect ":" Allow "," Action ":["iot: Publish", "iot: Subscribe", "iot: Receive"], "Resource": ""}]}

Надеюсь, это поможет!

...