【问题标题】:How do I add Client Username and Key to MQTT Adafruit app如何将客户端用户名和密钥添加到 MQTT Adafruit 应用程序
【发布时间】:2022-11-12 08:57:12
【问题描述】:

我有一个连接到 io.adafruit MQTT 并在有新数据可用时发布到我的提要的应用程序,没问题。

我正在使用 ESP8266-01 上的 Arduino 编程。

我通过设置连接并在我的标题中发布信息来做到这一点? ( void setup() 之前的空格,如下所示:

#define AIO_SERVER      "io.adafruit.com"
#define AIO_SERVERPORT  1883                
#define AIO_USERNAME    "xxxxxxxx"
#define AIO_KEY         "xxxxxxxxxxxxxxxxxxxxxxx"

WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/temperature");
Adafruit_MQTT_Publish level = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/level");
Adafruit_MQTT_Publish level2 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/level2");
Adafruit_MQTT_Publish battery = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/battery");
Adafruit_MQTT_Publish date = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/date");
Adafruit_MQTT_Publish trip = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/trip");
Adafruit_MQTT_Publish video1 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/video");

我想这样做,以便在应用程序首次启动并且用户输入他们的 WiFi 名称和密码时添加 AIO_USERNAME 和 AIO_KEY。

我已将其设置为将用户名和密钥保存到 eprom 并从那里读取。

我什至在从 eprom 检索到 AIO_USERNAME 和 AIO_KEY 后重新定义了它们。

void setup(){

  WiFiManagerParameter customAPIKey("authorizationKey", "Authorization Code",authorizationKey, 32);
  WiFiManagerParameter customAPIKey2("apiKey", "Time Zone #", apiKey, 3);
  WiFiManagerParameter customAPIKey3("userNameKey", "User Name",userNameKey, 29);

  wifiManager.addParameter(&customAPIKey);
  wifiManager.addParameter(&customAPIKey2);
  wifiManager.addParameter(&customAPIKey3);

  strcpy(authorizationKey, customAPIKey.getValue());
  strcpy(apiKey, customAPIKey2.getValue());
  strcpy(userNameKey, customAPIKey3.getValue());

//write to eeprom

  EEPROM.begin(512);  //Initialize EEPROM
 
  EEPROM.write(addr, 'A');    //Write character A
  addr++;                      //Increment address
  EEPROM.write(addr, 'B');    //Write character A
  addr++;                      //Increment address
  EEPROM.write(addr, 'C');    //Write character A
  addr++;                      //Increment address
  EEPROM.write(addr, 'D');    //Write character A
   
  //Write string to eeprom
  String uuu = authorizationKey;
  Serial.print("uuu");
  Serial.print(uuu);
  String www = apiKey;//Homenetwork + uuu;
  Serial.print("www");
  Serial.print(www);
  String yyy = userNameKey;
  String vvv = String(www)+String(yyy)+String(",");
  Serial.print("vvv");
  Serial.print(vvv);
  for(int i=0;i<uuu.length();i++) //loop upto string lenght www.length() returns length of string
  {
    EEPROM.write(0x0F+i,uuu[i]); //Write one by one with starting address of 0x0F
  }
  for(int i=0;i<vvv.length();i++) //loop upto string lenght www.length() returns length of string
  {
    EEPROM.write(0x0+i,vvv[i]); //Write one by one with starting address of 0x0F
  }
  
  EEPROM.commit();    //Store data to EEPROM

//this is where I retrieve the info from the eeprom

void loop {

EEPROM.begin(512);
    Serial.println(""); //Goto next line, as ESP sends some garbage when you reset it  
  Serial.print(char(EEPROM.read(addr)));    //Read from address 0x00
  addr++;                      //Increment address
  Serial.print(char(EEPROM.read(addr)));    //Read from address 0x01
  addr++;                      //Increment address
  Serial.println(char(EEPROM.read(addr)));    //Read from address 0x02
addr++;                      //Increment address
  Serial.println(char(EEPROM.read(addr)));    //Read from address 0x03
  //addr++;                      //Increment address
  //Serial.println(char(EEPROM.read(addr)));    //Read from address 0x04
  //Read string from eeprom
  String www;   
  //Here we dont know how many bytes to read it is better practice to use some terminating character
  //Lets do it manually www.circuits4you.com  total length is 20 characters
  for(int i=0;i<32;i++) 
  {
    www = www + char(EEPROM.read(0x0F+i)); //Read one by one with starting address of 0x0F    
  }  
  String zzz;
  String uuu;
  for(int i=0;i<3;i++)
  {uuu =  uuu + char(EEPROM.read(0x0+i));
  } 
  
  String yyy = userNameKey;
  String vvv;
  for(int i=3;i<29;i++)
  {vvv =  vvv + char(EEPROM.read(0x0+i));
  } 
   www.toCharArray(auth,33);
   #define AIO_KEY auth
   Serial.println("KEY");
   Serial.print(AIO_KEY);
   Serial.println("this");
   Serial.print(www);  //Print the text on serial monitor
   Serial.println("that");
   Serial.print(uuu);
   Serial.println("those");
   Serial.print(vvv);
   int firstCommaIndex = vvv.indexOf(',');
    String wstemp = vvv.substring(0, firstCommaIndex);
    Serial.println("some");
    Serial.print(wstemp);
  
  
    int len = firstCommaIndex;
    wstemp.toCharArray(user,len+1);
    #define AIO_USERNAME user
    
    Serial.println("userr");
    Serial.print(AIO_USERNAME);
 //when I print out the AIO_USERNAME and AIO_KEY I get the correct data but the app

无法连接到我在 adafruit 的帐户。

我试过将信息移入

    void MQTT_connect() {
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/temperature");
Adafruit_MQTT_Publish level = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/level");
Adafruit_MQTT_Publish level2 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/level2");
Adafruit_MQTT_Publish battery = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/battery");
Adafruit_MQTT_Publish date = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/date");
Adafruit_MQTT_Publish trip = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/trip");
Adafruit_MQTT_Publish video1 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/video");
    }

但这不起作用并打开另一罐蠕虫。

比如最后一行得到一个

expected primary-expression before '(' token

错误

有没有人建议如何更新或替换 AIO_USERNAME 和 AIO_KEY 以便使用存储的数据?

【问题讨论】:

  • 我已回滚您的编辑。如果您想发布自己问题的解决方案,请使用回答.

标签: arduino mqtt arduino-esp8266 adafruit eeprom


【解决方案1】:

我有一个应用程序,用于连接到 io.adafruit 并使用 MQTT 收集和传播我的传感器读数。我让它工作得很好。当应用程序首次启动时,用户输入他们的 wifi 名称和密码,并使用 WiFiManager 登录到他们的网络,并将信息存储起来供以后使用。我还添加了一个要填写的时间偏移变量并将其保存到 EEPROM。
如我原来的帖子中所述,然后我想添加 Adafruit 用户名和 IOKEY。然而,因为我对它们进行了硬编码,所以我将这些设置放在了标题中,为了让用户输入这些信息并将其保存到 EEPROM,我需要移动它们。但是哪里。我终于想出了以下解决方案。 在标题中,我创建了这些常量。

#define AIO_SERVER      "io.adafruit.com"
#define AIO_SERVERPORT  1883                
char apiKey[32]="";
char authorizationKey[32]="";
char userNameKey[32]="";
char auth[32]="";
String TEMP = "";
char userbattery[]= "";
char userr[29]= "";
In the void setup(){ I have this
//this adds the spots for the clientName and Key to the WiFiManager access point.

  WiFiManagerParameter customAPIKey("authorizationKey", "Authorization Code",authorizationKey, 32);
  WiFiManagerParameter customAPIKey2("apiKey", "Time Zone #", apiKey, 3);
  WiFiManagerParameter customAPIKey3("userNameKey", "User Name",userNameKey, 29);

  wifiManager.addParameter(&customAPIKey);
  wifiManager.addParameter(&customAPIKey2);
  wifiManager.addParameter(&customAPIKey3);

  strcpy(authorizationKey, customAPIKey.getValue());
  strcpy(apiKey, customAPIKey2.getValue());
  strcpy(userNameKey, customAPIKey3.getValue());

然后在 void loop(){ 我把

WiFiManager wifiManager;
if (WiFi.status() == WL_DISCONNECTED) {
wifiManager.autoConnect("FloWT3");
delay(60000);}
//here I make sure I am connected to the internet.
else if (WiFi.status() == WL_CONNECTED) {        Serial.println("Connected");
delay(2000);

WiFiClient client;
EEPROM.begin(512);
//I added this because when the app started up after the original write to EEPROM it would write over the first characters   of each saved string so I checked to see. If it was the first time I allowed it to write to EEPROM otherwise I didn't.
String rrr = apiKey;
if (rrr.length() == 0){
Serial.print ("empty");
}
else {
Serial.print ("Not Empty");
//Here I created strings from the strcpy earlier and made sure they were saved the way I wanted.
String uuu = authorizationKey;
Serial.print("uuu");
Serial.print(uuu);
String www = apiKey;//Homenetwork + uuu;
Serial.print("www");
Serial.print(www);
String yyy = userNameKey;
//because the time offset and userName were not lengths that I could know I added a comma to each so I could split them later on.
String fff = String(www)+String(",");
String vvv = String(yyy)+String(",");
Serial.print("vvv");
Serial.print(vvv);
//Then I write the strings to EEPROM
for(int i=0;i<uuu.length();i++) //loop upto string lenght    www.length() returns length of string
{
EEPROM.write(0x06+i,uuu[i]); //Write one by one with starting address of 0x0F
}
for(int i=0;i<fff.length();i++) //loop upto string lenght www.length() returns length of string
{
EEPROM.write(0x50+i,fff[i]); //Write one by one with starting   address of 0x0F
}
for(int i=0;i<vvv.length();i++) //loop upto string lenght    www.length() returns length of string
{
EEPROM.write(0x90+i,vvv[i]); //Write one by one with starting  address of 0x0F
}

EEPROM.commit(); 
}

delay (1000);
//after a short delay I read the strings from EEPROM that had been saved.  The delay is for the first time the app is use and the EEPROM is written and then read
String wwww;   
for(int i=0;i<32;i++) 
{
wwww = wwww + char(EEPROM.read(0x06+i)); //Read one by one with starting address of 0x0F    
}  
String zzz;
String uuuu;
for(int i=0;i<32;i++)
{uuuu =  uuuu + char(EEPROM.read(0x50+i));
} 
String yyyy = userNameKey;
String vvvv;
for(int i=0;i<32;i++)
{vvvv =  vvvv + char(EEPROM.read(0x90+i));
} 
// convert the IOKEY to a char.
wwww.toCharArray(auth,33);//**
//check to see I got the strings from EEPROM the way I wanted them.
Serial.println("this");
Serial.print(wwww);  //this is the IOKEY
Serial.println("that");
Serial.print(uuuu);//this is the offset value
Serial.println("those");
Serial.print(vvvv);//this is the UserName
//Then using the commas I split off the strings I need from the full one saved to EEPROM.
int firstCommaIndex = uuuu.indexOf(',');
String dateOffset = uuuu.substring(0, firstCommaIndex);
Serial.println("most");
Serial.print(dateOffset);
int firstCommaIndexa = vvvv.indexOf(',');
String wstemp = vvvv.substring(0, firstCommaIndexa);
TEMP = wstemp;
int len = firstCommaIndexa;
//here I changed the UserName string to a char.
wstemp.toCharArray(userr,len+1);
Serial.println("some");
Serial.print(wstemp);
Serial.print(userr);
#define AIO_USERNAMES userr //This is used in the MQTT Client mqtt definition.**
Serial.println("userr");
Serial.print(AIO_USERNAMES);

然后在 MQTT_connect() {

 //these are the values of my sensors
float level1 = (floatFromPC);
float levela = (floatFromPC5);
uint32_t z=floatFromPC;
uint32_t p=4;
uint32_t y=(floatFromPC2-320);
if (y>500) {
y = 80;
}
float temperature1 = (floatFromPC3);
double temp2 = temperature1;
uint32_t x=temperature1;
uint32_t w=floatFromPC4;
int str_len = currentDate.length();
char v [str_len+1];
currentDate.toCharArray(v,str_len+1);

WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAMES, auth);//**AIO_USERNAMES and auth


//This is what is usually in the MQTT_connect() { 
int8_t ret;

if (mqtt.connected()) {
return;
}

Serial.print("Connecting to MQTT... ");

 uint8_t retries = 3;
 while ((ret = mqtt.connect()) != 0) { // connect will return 0    for connected
 Serial.println(mqtt.connectErrorString(ret));
 Serial.println("Retrying MQTT connection in 5 seconds...");
 mqtt.disconnect();
 delay(5000);  // wait 5 seconds
 retries--;
 if (retries == 0) {
 // basically die and wait for WDT to reset me
 while (1);
 }
 }
 Serial.println("MQTT Connected!");
 Serial.println("publishing to /get");

 //Here I create a string combining UserName with the feed.
 String UserString =String(TEMP) +    String("/feeds/battery,aaa");
 int firstCommaIndexb = UserString.indexOf(",");
 String batterySt = UserString.substring(0,firstCommaIndexb);
 int leng = firstCommaIndexb;

 Serial.println("leng");
 Serial.print(leng);
 batterySt.toCharArray(userbattery,leng+1);/create a char
 Serial.println("battery");
 Serial.print(batterySt);
 Serial.print(userbattery);
 #define BATTERY  userbattery 
 Serial.println("userb");
 Serial.print(BATTERY);//this is then used in the publish definition***
 Adafruit_MQTT_Publish battery =     Adafruit_MQTT_Publish(&mqtt,BATTERY);//***
 //and then this is the publish statement
 Serial.print(F("
Sending battery val "));
 Serial.print(y);
 Serial.print("...");
 if (! battery.publish(y)) {
 Serial.println(F("Failed"));
 } else {
 Serial.println(F("OK!"));
 }
 delay(500);



    //For some reason when I created the publish definitions in a similar
fashion and the did the publish statements the value would be publish one
after the other in the last stated publish feed.  So even though there was
a different definition for video, temperature, battery they would all be
written to the battery keeping only the last value.


 

    //To avoid this I used the same variable to create each 

definition except the feed name and fired each off before creating the

next. There is an example of the above.

这解决了如何输入UserName和IOKey并写入的问题 并从 io.adafruit.com 的 EEPROM 中读取。我希望它可以帮助任何可能遇到类似问题的人

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多