我正在使用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(返回std :: string)检索用户名的方式进行更改。因此,如果myLampCred.username = ActualUsername,则应订阅的getAccepted主题名称为“ Lamps / actualUsername / rga”
我能够始终在我的getAccepted主题和testchannel主题上接收消息,但不会在republishedShadow主题上接收消息。如果我将republishedShadowTopic变量替换为“ Lamp / actualUsername / rs”,则它将正常工作并收到应有的消息。我认为问题与我如何声明/构建变量有关,但是我以相同的方式使getAccepted主题变量正常运行吗?
我还通过每个主题发送了各种长度的消息,并且每个消息相对于其主题都得到相同的结果,因此我认为这与消息的内容无关。我还检查了配置文件,但我认为没有任何限制吗?我很确定任何问题都在我共享的代码段中,因为收到的任何消息都会在到达时宣布。
我目前的理论是某处存在数据类型问题?但是device.subscribe()方法正在请求一个char *,据我所知,这就是我给的(我对所有char []与char *和const的了解仍然不是100% what每个都是,但我想不是如何使用它们)。我尝试了各种形式的chars和std :: string转换,但是除非基于字符串文字,否则似乎没有任何效果。
我对此很困惑,任何帮助将不胜感激,谢谢! :D
创建republishedShadowTopic
的代码看起来不错。此代码创建的字符串应与字符串文字"Lamp/actualUsername/rs"
相同,只看here。
我不是Arduino方面的专家,但据我所知,字符串文字可能存储在只读存储器中(我想如果是Arduino,它将是闪存)。
尝试修改字符串文字结果是未定义的行为:它们可能存储在只读存储器(例如.rodata)中,或者与其他字符串文字结合。
使用字符串文字时它起作用的原因可能是它的静态存储持续时间。
字符串文字具有静态存储持续时间,因此在程序生命周期内存在内存中。
另一方面,您的数组具有自动存储期限,这意味着退出当前范围后,它可能无效。
[查看here时,您会看到字符串的地址已经转发并存储了right here。
在此if语句内退出范围后:
if (device.connect(HOST_ADDRESS, const_cast<char*>(client_id.c_str())) == 0)
您不能再依赖此指针。我假设您退出该if语句后会收到一条消息。
您可以很容易地检验我的假设。只需将此数组设置为静态或全局数组,然后检查其是否有效。您应该对第一个数组执行相同的操作,因为您可能很幸运它起作用了。