Acces a variable in the library

Greetings,

I was trying to read and write from the firebase database with a wemos D1 mini because of that I dowloaded the FirebaseArduino library and the example code didn't work. After some research I found that the fingerprint of the website changes once in three month then I changed the fingerprint in the FirebaseHttpClient.h and it worked like a charm. The project that I am working on will be in a hard to reach place. I don't want to take the board once in three month only for uploading a code. So I decided to read the fingerprint from a website and then change the fingerprint in the code but there is a big problem. Figerprint is in the library and I don't know how to reach a variable in the library. My question is: How can I reach a variable in the library?

Header File:

#ifndef FIREBASE_HTTP_CLIENT_H
#define FIREBASE_HTTP_CLIENT_H

#include <string>

#include "Arduino.h"
#include "Stream.h"

struct HttpStatus {
  static const int TEMPORARY_REDIRECT = 307;
};

class FirebaseHttpClient {
 public:
  static FirebaseHttpClient* create();

  virtual void setReuseConnection(bool reuse) = 0;
  virtual void begin(const std::string& url) = 0;
  virtual void begin(const std::string& host, const std::string& path) = 0;

  virtual void end() = 0;

  virtual void addHeader(const std::string& name, const std::string& value) = 0;
  virtual void collectHeaders(const char* header_keys[],
                              const int header_key_count) = 0;
  virtual std::string header(const std::string& name) = 0;

  virtual int sendRequest(const std::string& method, const std::string& data) = 0;

  virtual std::string getString() = 0;

  virtual Stream* getStreamPtr() = 0;

  virtual std::string errorToString(int error_code) = 0;

  virtual bool connected() = 0;

 protected:
  static const uint16_t kFirebasePort = 443;
};

static const char kFirebaseFingerprint[] = //The variable that I want to change
      "6E:F3:55:47:6D:F1:0E:5B:2B:04:F2:F8:C0:8B:E8:05:65:0F:1A:C1"; // 2021-09 

#endif  // FIREBASE_HTTP_CLIENT_H

My code:

#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>

#define FIREBASE_HOST "example.firebaseio.com"
#define FIREBASE_AUTH "token_or_secret"
#define WIFI_SSID "SSID"
#define WIFI_PASSWORD "PASSWORD"

void setup() {
  Serial.begin(9600);
  //Reach internet to a website and read fingerprint 
  //change fingerprint in the library
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("connected: ");
  Serial.println(WiFi.localIP());
  
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

int n = 0;

void loop() {
  // set value
  Firebase.setFloat("number", 42.0);
  // handle error
  if (Firebase.failed()) {
      Serial.print("setting /number failed:");
      Serial.println(Firebase.error());  
      return;
  }
  delay(1000);
  
  // update value
  Firebase.setFloat("number", 43.0);
  // handle error
  if (Firebase.failed()) {
      Serial.print("setting /number failed:");
      Serial.println(Firebase.error());  
      return;
  }
  delay(1000);

  // get value 
  Serial.print("number: ");
  Serial.println(Firebase.getFloat("number"));
  delay(1000);

  // remove value
  Firebase.remove("number");
  delay(1000);

  // set string value
  Firebase.setString("message", "hello world");
  // handle error
  if (Firebase.failed()) {
      Serial.print("setting /message failed:");
      Serial.println(Firebase.error());  
      return;
  }
  delay(1000);
  
  // set bool value
  Firebase.setBool("truth", false);
  // handle error
  if (Firebase.failed()) {
      Serial.print("setting /truth failed:");
      Serial.println(Firebase.error());  
      return;
  }
  delay(1000);

  // append a new value to /logs
  String name = Firebase.pushInt("logs", n++);
  // handle error
  if (Firebase.failed()) {
      Serial.print("pushing /logs failed:");
      Serial.println(Firebase.error());  
      return;
  }
  Serial.print("pushed: /logs/");
  Serial.println(name);
  delay(1000);
}

static usually implies that the symbol is not accessible outside file scope.

and i don't see a public function to overwrite the Fingerprint. you could write one and add it to the library

change the declaration to:

char kFirebaseFingerprint[60] =
"6E:F3:55:47:6D:F1:0E:5B:2B:04:F2:F8:C0:8B:E8:05:65:0F:1A:C1"; // 2021-09 

Then, in your sketch, put:
extern char kFirebaseFingerprint[60];

Then you can write a different 59 character string into that buffer whenever you want. I assume you will need to do that before:
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);

Except, you'll note that the array is actually DEFINED as a free variable (not part of the class) in the header file, not just DECLARED. Since this file #include(d) in the .ino, the variable should be available there. This is really BAD coding practice and makes me wonder about the quality of the entire library.

EDIT:
But, since it's static, there will be two different arrays allocated. One in the library's .cpp and one in the main .ino. Looks sketchy to me.

Yikes!

If the #include file is use more than one place, you will get a doubly-defined variable. In that case, swap the two declarations. Put:
extern char kFirebaseFingerprint[60];
in the #include file and put this in your sketch:

char kFirebaseFingerprint[60] =
"6E:F3:55:47:6D:F1:0E:5B:2B:04:F2:F8:C0:8B:E8:05:65:0F:1A:C1"; // 2021-09 

Thanks for the answer,

I did the changes you said but the program gave me an error. Here is the error message:

Arduino: 1.8.14 Hourly Build 2020/12/04 05:33 (Windows 10), Board: "LOLIN(WEMOS) D1 R2 & mini, 80 MHz, Flash, Legacy (new can return nullptr), All SSL ciphers (most compatible), 4MB (FS:2MB OTA:~1019KB), v2 Lower Memory, Disabled, None, Only Sketch, 921600"

c:/users/burak_2022/appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-4-b40a506/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld.exe: libraries\firebase-arduino-master\FirebaseHttpClient_Esp8266.cpp.o: in function `FirebaseHttpClientEsp8266::setReuseConnection(bool)':

C:\Users\Burak_2022\Documents\Arduino\libraries\firebase-arduino-master\src/FirebaseHttpClient_Esp8266.cpp:44: undefined reference to `kFirebaseFingerprint'

collect2.exe: error: ld returned 1 exit status

exit status 1

Error compiling for board LOLIN(WEMOS) D1 R2 & mini.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

you need to post the changes, the complete code

Thanks for the answer,
My Code

#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>

#define FIREBASE_HOST "example.firebaseio.com"
#define FIREBASE_AUTH "token_or_secret"
#define WIFI_SSID "SSID"
#define WIFI_PASSWORD "PASSWORD"

void setup() {
  Serial.begin(9600);
  //Reach internet to a website and read fingerprint
  char kFirebaseFingerprint[60] =
    "6E:F3:55:47:6D:F1:0E:5B:2B:04:F2:F8:C0:8B:E8:05:65:0F:1A:C1"; // 2021-09
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("connected: ");
  Serial.println(WiFi.localIP());

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

int n = 0;

void loop() {
  // set value
  Firebase.setFloat("number", 42.0);
  // handle error
  if (Firebase.failed()) {
    Serial.print("setting /number failed:");
    Serial.println(Firebase.error());
    return;
  }
  delay(1000);

  // update value
  Firebase.setFloat("number", 43.0);
  // handle error
  if (Firebase.failed()) {
    Serial.print("setting /number failed:");
    Serial.println(Firebase.error());
    return;
  }
  delay(1000);

  // get value
  Serial.print("number: ");
  Serial.println(Firebase.getFloat("number"));
  delay(1000);

  // remove value
  Firebase.remove("number");
  delay(1000);

  // set string value
  Firebase.setString("message", "hello world");
  // handle error
  if (Firebase.failed()) {
    Serial.print("setting /message failed:");
    Serial.println(Firebase.error());
    return;
  }
  delay(1000);

  // set bool value
  Firebase.setBool("truth", false);
  // handle error
  if (Firebase.failed()) {
    Serial.print("setting /truth failed:");
    Serial.println(Firebase.error());
    return;
  }
  delay(1000);

  // append a new value to /logs
  String name = Firebase.pushInt("logs", n++);
  // handle error
  if (Firebase.failed()) {
    Serial.print("pushing /logs failed:");
    Serial.println(Firebase.error());
    return;
  }
  Serial.print("pushed: /logs/");
  Serial.println(name);
  delay(1000);
}

Header File

#ifndef FIREBASE_HTTP_CLIENT_H
#define FIREBASE_HTTP_CLIENT_H

#include <string>

#include "Arduino.h"
#include "Stream.h"

struct HttpStatus {
  static const int TEMPORARY_REDIRECT = 307;
};

class FirebaseHttpClient {
 public:
  static FirebaseHttpClient* create();

  virtual void setReuseConnection(bool reuse) = 0;
  virtual void begin(const std::string& url) = 0;
  virtual void begin(const std::string& host, const std::string& path) = 0;

  virtual void end() = 0;

  virtual void addHeader(const std::string& name, const std::string& value) = 0;
  virtual void collectHeaders(const char* header_keys[],
                              const int header_key_count) = 0;
  virtual std::string header(const std::string& name) = 0;

  virtual int sendRequest(const std::string& method, const std::string& data) = 0;

  virtual std::string getString() = 0;

  virtual Stream* getStreamPtr() = 0;

  virtual std::string errorToString(int error_code) = 0;

  virtual bool connected() = 0;

 protected:
  static const uint16_t kFirebasePort = 443;
};
extern char kFirebaseFingerprint[60];

#endif  // FIREBASE_HTTP_CLIENT_H

in the code you originally posted, it appears library defines the fingerprint array in the .h file allowing it to be modified by the user of the library. the drawback of this is that the fingerprint array gets duplicated in every file including the .h. no harm but wasteful.

in the code you posted in reply #8, the fingerprint array is defined inside setup() and is therefore not accessible outside that function.

the code should at least compile if the definition is moved outside of setup().

don't see any code for updating the fingerprint array

What board and IDE do you use that you can use std::string?

Change that to this:

char kFirebaseFingerprint[60] =
    "6E:F3:55:47:6D:F1:0E:5B:2B:04:F2:F8:C0:8B:E8:05:65:0F:1A:C1"; // 2021-09

void setup() {
  Serial.begin(9600);
  //Reach internet to a website and read fingerprint

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

Local variables (declared inside a function) can't be used outside the function. You need 'kFirebaseFingerprint' to be global.

Thanks for the asnwer,

Whoops. :sweat_smile:

Wemos D1 mini.

Arduino ide??

Is not the only IDE

But they all use pretty much the same tool chain.

Except for AVR-based ones, most "Arduino" boards have some form of support for the STL.

Is there a fonction which automatic update the fingerprint ?

I think it's the SHA-1 Fingerprint (20 bytes) in the server's certificate. Of course if you grab it and use it without checking the rest of the certificate, that's no better than "client.setInsecure();"

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.