Search code examples
arduinogoogle-cloud-platformmqttesp32google-cloud-iot

Connecting to IoT Core MQTT


I am trying to connect to Google's MQTT server but I am getting errors I created all the certificates and registered my device (Adafruit huzzah32)

and the documentation says you connect to mqtt.googleapis.com:8883

So I do

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

When I try to connect I use the device path

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");

but it never connects

I verified the google certificate by calling openssl s_client -showcerts -connect mqtt.googleapis.com:8883 and I put in my RSA Private key and certificate key that was made

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

What am I doing wrong?

Here is the connection documentation https://cloud.google.com/iot/docs/how-tos/mqtt-bridge

Update

I made a quick java example to see if I can connect going off the example they have for connecting and I get a MqttException saying Bad user name or password (4)

Here is the code for that

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();
    }

As you can see here I have the IoT service acount added to IAM enter image description here

Does that mean my keys that I generated with openssl are incorrect?


Solution

  • My problem ended up being that I was trying to set a really large expiration date on my Json Web Token (on purpose so I didnt have to keep generating new ones since I have not found a way to do that in arduino) and it looks like that google's mqtt server does not accept anything over a day so the keys will have to be updated daily.

    Also inorder to connect to the MQTT server I had to change the buffer size of the MqttClient on the arduino to have a buffer size of 1024 bytes.

    MQTTClient client(1024);
    

    anything less I would get an error saying buffer isnt big enough.