-1

I have an app which connects to io.adafruit MQTT and publishes to my feeds when new data is available, NO PROBLEM.

I am working with Arduino programing on an ESP8266-01.

I do this by setting up the connection into and publish info in my header? (space before void setup() like this:

#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");

I would like to make it so I can add the AIO_USERNAME and AIO_KEY when the app first starts up and the user enters their WiFi name and password.

I have set it up so the userName and Key are saved to eprom and read from there.

I have even redefined the AIO_USERNAME and AIO_KEY after they are retrieved from eprom.

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

fails to connect to my account at adafruit.

I have tried moving the info into

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

but that doesn't work and open another can of worms.

such as the last line gets an

expected primary-expression before '(' token

error

Does anyone have a suggestion as to how to update or replace the AIO_USERNAME and AIO_KEY so the stored data is used?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
user1114881
  • 731
  • 1
  • 12
  • 25

1 Answers1

0

I had an app that I used to connect to io.adafruit and use MQTT to gather and disseminate my sensor readings. I had it working great. When the app was first launched the user entered their wifi name and password and using WiFiManager they signed into their network and the info was stored for later use. I also added a time offset variable to be filled in and saved it to EEPROM.

As described in my original post I then wanted to add the Adafruit userName and IOKEY. However because I hard coded them I had placed the set up of these in the header and in order to have the user enter this information and save it to EEPROM I needed to move them. But where. I finally came up with the following solution. In the header I created these constants.

#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());

Then in the void loop(){ I put

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

then in the 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("\nSending 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.

This solved the problem of how to input the UserName and IOKey and write and read it from EEPROM for io.adafruit.com. I hope it helps anyone who may run up against a similar problem

user1114881
  • 731
  • 1
  • 12
  • 25