带有 esp32 的 AWS iot 接收来自某些主题的消息而不是其他主题?

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

我正在使用 this aws-iot library for esp32,但我无法接收来自特定主题的消息。

我的代码:

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

我订阅了三个主题,testchannel、Lamps/user/rga(在变量 getAcceptedTopic 中)和 Lamp/user/rs(在变量 republishedShadowTopic 中)。

在这些主题中,用户可以根据代码上传到的设备进行更改,并使用 myLampCred.username(returns 和 std::string 检索用户名)。所以如果 myLampCred.username = actualUsername,那么它应该订阅的 getAccepted 主题名称是 "Lamps/actualUsername/rga"

我总是能够收到有关 getAccepted 主题和 testchannel 主题的消息,但收不到有关 republishedShadow 主题的消息。如果我用 "Lamp/actualUsername/rs" 替换 republishedShadowTopic 变量,那么它可以正常工作并接收应有的消息。我认为问题出在我如何 declaring/building 变量上,但我以相同的方式制作 getAccepted 主题变量并且那个工作正常?

我还通过每个主题发送了各种长度的消息,并且每条消息相对于它的主题都得到了相同的结果,所以我认为这与消息的内容无关。 我还检查了配置文件,我认为不会有任何限制吗? 我很确定任何问题都在我共享的代码段中,因为收到的任何消息都会在到达时宣布。

我目前的理论是某处存在数据类型问题?但是 device.subscribe() 方法要求一个 char*,据我所知,这就是我给它的(我仍然不是 100% 在所有 char[] vs char* 和 const 上,我了解每个 是什么 但不知道如何使用它们)。我尝试了各种形式的字符和 std::string 转换,但 none 似乎可以工作,除非基于字符串文字。

对此我很困惑,如有任何帮助,我们将不胜感激,谢谢! :D

创建 republishedShadowTopic 的代码看起来不错。这段代码创建的字符串应该和字符串字面量"Lamp/actualUsername/rs"一样,看看here.

我不是 Arduino 方面的专家,但据我所知,字符串文字可能存储在只读存储器中(如果是 Arduino,我猜是闪存)。

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.

它在您使用字符串文字时起作用的原因可能是它的静态存储持续时间。

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

另一方面,您的数组有一个自动存储期限,这意味着它可能在退出当前范围后无效。

当你看的时候here, you'll see that address of your string has been forwarded and stored right here.

退出此 if 语句内的作用域后:

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

你不能再依赖这个指针了。我假设您在退出该 if 语句后会收到一条消息。

你可以很容易地验证我的假设。只需将此数组设置为静态或全局数组并检查它是否有效。你应该对第一个数组做同样的事情,因为你可能很幸运它能工作。