连接到物联网核心 MQTT

Connecting to IoT Core MQTT

我正在尝试连接到 Google 的 MQTT 服务器,但出现错误 我创建了所有证书并注册了我的设备 (Adafruit huzzah32)

并且文档说您连接到 mqtt.googleapis.com:8883

我也是

WiFiClientSecure wifi;
MQTTClient client;
client.begin("mqtt.googleapis.com", 8883, wifi);

当我尝试连接时,我使用设备路径

const char* jwt = "{json web token}";
const char* device = "projects/{project-id}/locations/{cloud-region}/registries/{registry-id}/devices/{device-id}";

Serial.print("Connecting to mqtt");
while (!client.connect(device,"unused",jwt)) {
    Serial.print(".");
    delay(1000);
}

Serial.println();
Serial.println("Connected to mqtt");

但始终无法连接

我通过调用验证了 google 证书 openssl s_client -showcerts -connect mqtt.googleapis.com:8883 然后我输入了我制作的 RSA 私钥和证书密钥

wifi.setCACert(googleCertificate2);
wifi.setCertificate(myCertificate);
wifi.setPrivateKey(privateCert);

我做错了什么?

这是连接文档 https://cloud.google.com/iot/docs/how-tos/mqtt-bridge

更新

我做了一个快速的 java 示例,看看我是否可以连接他们用于连接的示例,我得到一个 MqttExceptionBad user name or password (4)

这是代码

private void doStuff(){
        String clientId = String.format("ssl://%s:%s", "mqtt.googleapis.com", 8883);
        String mqttClientId = String.format("projects/%s/locations/%s/registries/%s/devices/%s","{project_id}", "us-central1", "{register}", "{device}");
        MqttConnectOptions connectOptions = new MqttConnectOptions();
        connectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);

        Properties sslProps = new Properties();
        sslProps.setProperty("com.ibm.ssl.protocol", "TLSv1.2");
        connectOptions.setSSLProperties(sslProps);

        connectOptions.setUserName("unused");


        try{
            String jwt = createJwtRsa("{project-id}");
            connectOptions.setPassword(jwt.toCharArray());
            MqttClient client = new MqttClient(clientId, mqttClientId, new MemoryPersistence());

            while(!client.isConnected()){
                try{
                    client.connect(connectOptions);
                }catch (MqttException e) {
                    e.printStackTrace();
                }
            }
            Log.d("","");
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private String createJwtRsa(String projectId) throws Exception {
        DateTime now = new DateTime();
        JwtBuilder jwtBuilder =
                Jwts.builder().setIssuedAt(now.toDate()).setExpiration(now.plusDays(1000000).toDate()).setAudience(projectId);

        byte[] keyBytes = readBytes(getAssets().open("rsa_private_pkcs8"));
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");

        PrivateKey k = kf.generatePrivate(spec);

        return jwtBuilder.signWith(SignatureAlgorithm.RS256, k).compact();
    }

如您所见,我已将 IoT 服务帐户添加到 IAM

这是否意味着我使用 openssl 生成的密钥不正确?

此处 IAM roles are being explained ...the paragraph here 听起来与您描述的相似:

On the IAM page in Google Cloud Platform Console, verify that the role Cloud IoT Core Service Agent appears in the Members list for the relevant project service account. (Look for the project service account that ends in @gcp-sa-cloudiot.iam.gserviceaccount.com.)

If the Cloud IoT Core Service Agent role does not appear in the Members list, use gcloud to add the cloudiot.serviceAgent role to the relevant project service account. This role includes permission to publish to Pub/Sub topics.

如果尚未安装,所有这些 gcloud CLI 命令都需要 Cloud SDK,这些命令可用于列出和编辑配置(所有这些都可以通过控制台,以及)...它可能更容易,因为那里的所有示例也都使用它。

更新 ...

关于 JWT 刷新令牌,请参阅此 article or have some Q & A or the specification: JSON Web Token (JWT), JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants。 这是另一篇相关文章:https://medium.com/google-cloud/refreshing-json-web-tokens-jwts-for-google-cloud-iot-core-897318df3836

我的问题最终是我试图在我的 Json Web 令牌上设置一个非常长的到期日期(故意这样我就不必继续生成新的,因为我还没有找到一种方法来在 arduino 中执行此操作)并且看起来 google 的 mqtt 服务器一天内不接受任何内容,因此必须每天更新密钥。

另外,为了连接到 MQTT 服务器,我必须将 arduino 上 MqttClient 的缓冲区大小更改为 1024 字节的缓冲区大小。

MQTTClient client(1024);

少了我会得到一个错误,说缓冲区不够大。