SamsTheNerd
SamsTheNerd

Reputation: 38

AWS iot with esp32 receives messages from some topics but not others?

I'm using this aws-iot library for esp32 and i'm having trouble receiving messages from a certain topic.

My Code:

if (device.connect(HOST_ADDRESS, const_cast<char*>(client_id.c_str())) == 0) {
    Serial.println("Connected To AWS");
    delay(1000);

    char getAcceptedTopic[60];
    strcpy(getAcceptedTopic, "Lamps/"); //these ones need to be strcpy to get it started
    strcat(getAcceptedTopic, const_cast<char*>(myLampCred.username.c_str()));
    strcat(getAcceptedTopic, "/rga");

    Serial.print("\ngetAcceptedTopic: ");
    Serial.print(getAcceptedTopic);


    char republishedShadowTopic[60];
    strcpy(republishedShadowTopic, "Lamp/");
    strcat(republishedShadowTopic, const_cast<char*>(myLampCred.username.c_str()));
    strcat(republishedShadowTopic, "/rs");



    if (0==device.subscribe(getAcceptedTopic, mySubCallBackHandler)) {
    //if (0==device.subscribe("Lamps/SamHang/rs", mySubCallBackHandler)) { //try just doing it with the string? 
    Serial.print("Subscribe Successful");
    } else {
    Serial.println("Subscribe Failed, Check The Thing Name and Certificates");
    while(1);
    } 

    if (0==device.subscribe("testchannel", mySubCallBackHandler)) {
    Serial.println("Subscribe Successful");
    } else {
    Serial.println("Subscribe Failed, Check The Thing Name and Certificates");
    while(1);
    } 
    //will need to add in effects/channel topic at some point, but since none of the effects code is set up yet anyways, theres no point in adding a topic now

    Serial.println(republishedShadowTopic);
    if (0 == device.subscribe(republishedShadowTopic, mySubCallBackHandler)){
        Serial.println("Subscribe Successful");
    } else {
        Serial.println("Subscribe Failed, Check The THing Name and Certificates");
        while(1);
    }

    delay(500);
    //send get request
    gettingShadow = true;
    std::string shadowGetTopic = "$aws/things/" + myLampCred.username + "Lamp/shadow/get";
    publishFunc(shadowGetTopic.c_str(), "");
} else {
    //could add error for this but unless the host address changes and EVERYTHING breaks or wifi isn't connected, then there shouldn't be a problem
    Serial.println("AWS connection failed, check the HOST address");
    while(1);
}

I have three topics that I am subscribed to, testchannel, Lamps/user/rga (in variable getAcceptedTopic), and Lamp/user/rs (in variable republishedShadowTopic).

In these topics user can change based on what device the code is uploaded to and the username is retrieved using myLampCred.username (which returns a std::string). So if myLampCred.username = actualUsername, then the getAccepted topic name that it should subscribe to is "Lamps/actualUsername/rga"

I am able to receive messages on my getAccepted topic and my testchannel topic always but don't receive messages on the republishedShadow topic. If i replace the republishedShadowTopic variable with "Lamp/actualUsername/rs" then it works and receives messages like it should. I would think that the issue is something with how I'm declaring/building the variable but I make the getAccepted topic variable in the same way and that one works fine?

I also sent messages of various lengths through each topic and each message got the same result relative to it's topic so I don't think it has to do with the content of the messages. I also checked the configuration file and I don't think that anything there would be restricting this? I am pretty sure that any issue is in the segment of code that I shared, since any message that is received is announced when it arrives.

My current theory is that there is a data type problem somewhere? but the device.subscribe() method is asking for a char* and as far as I know that is what I'm giving it (I am still not 100% on all of the char[] vs char* and const, I understand what each one is but not how to use them I suppose). I have tried various forms of chars and std::string conversions but none seem to work unless based on a string literal.

I'm very confused on this and any help would be greatly appreciated, Thanks! :D

Upvotes: 0

Views: 274

Answers (1)

chwala
chwala

Reputation: 199

The code that creates republishedShadowTopic looks fine. String created by this code should be the same as string literal "Lamp/actualUsername/rs", just look here.

I'm not an expert on Arduino, but as far as I know, string literals may be stored in read-only memory (in case of Arduino that would be flash memory, I guess).

Attempting to modify a string literal results is undefined behavior: they may be stored in read-only storage (such as .rodata) or combined with other string literals.

The reason why it works when you're using string literal could be its static storage duration.

String literals have static storage duration, and thus exist in memory for the life of the program.

On the other hand, your array has an automatic storage duration, which means it may be invalid after exiting current scope.

When you take a look here, you'll see that address of your string has been forwarded and stored right here.

After you exit scope inside this if statement:

if (device.connect(HOST_ADDRESS, const_cast<char*>(client_id.c_str())) == 0)

you can no longer rely on this pointer. I assume you will receive a message after you exit that if statement.

You can test my hypothesis very easily. Just make this array as static or global and check that it works. You should do the same with the first array, because you probably were lucky that it worked.

Upvotes: 1

Related Questions