marvinroger / async-mqtt-client

📶 An Arduino for ESP8266 asynchronous MQTT client implementation
MIT License
849 stars 268 forks source link

Arduino - Can't set credentials with String.c_string() #269

Closed fanzypantz closed 3 years ago

fanzypantz commented 3 years ago

I'm not the biggest c++ programmer, so I'm not sure what is going on here. I have some declared static variables in an .h file to be the base values if no new values is assigned in the wifi portal. I can't use the new values for some reason. Converting from String to char array, seems to mess up the credentials.

I'm printing them out and they're identical. Am I just converting the string wrong? If I just use the MQTT_USER and MQTT_PASSWORD directly it works, but would obviously not make it editable from the portal.

Code:

void setupMqtt() {
    IPAddress mqpptIpAddress = MQTT_HOST;
    uint16_t mqttPort = MQTT_PORT;
    String mqttUser = MQTT_USER;
    String mqttPassword = MQTT_PASSWORD;
    if (serverName != NULL) {
        createIP(serverName);        
    }
    if (port != NULL) {
        mqttPort = port.toInt();       
    }
    if (username != NULL) {
        mqttUser = username;       
    }
    if (password != NULL) {
        mqttPassword = password;       
    }

    mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));

    mqttClient.onConnect(onMqttConnect);
    mqttClient.onDisconnect(onMqttDisconnect);
    mqttClient.onSubscribe(onMqttSubscribe);
    mqttClient.onUnsubscribe(onMqttUnsubscribe);
    mqttClient.onPublish(onMqttPublish);
    mqttClient.onMessage(onMqttMessage);
    mqttClient.setServer(mqpptIpAddress, mqttPort);

    // // If your broker requires authentication (username and password), set them below
    Serial.print("[MQTT] IP address:");
    Serial.print(mqpptIpAddress.toString());
    Serial.println(":");
    Serial.print("[MQTT] Port:");
    Serial.print(mqttPort);
    Serial.println(":");
    Serial.print("[MQTT] Username:");
    Serial.print(mqttUser.c_str());    
    Serial.print(":");
    Serial.print(MQTT_USER);
    Serial.println(":");
    Serial.print("[MQTT] Password:");
    Serial.print(mqttPassword.c_str());
    Serial.print(":");
    Serial.print(MQTT_PASSWORD);
    Serial.println(":");

    mqttClient.setCredentials(mqttUser.c_str(), mqttPassword.c_str());
}
bertmelis commented 3 years ago

mqttUser and mqttPassword are variables that only live in the scope of the setupMqtt function. As soon as the function ends, the variables are gone. the print function copies the values of these variables but the mqtt library does not. the mqtt library works asynchronously and will only read the variables when the connection is made which is "in the near future after calling connect".

You can solve your issue by not using local variables: by using references or pointers to static/global/long lived variables.