Telegram credentials hard code working but soft code not!

Trying to add code on esp32 to SimpleServer example sketch to enable text input Telegram credentials over web browser instead of hard coding on to the sketch. Using Preferences.h library saving credentials to retentive flash.

The code works fine with hard coded Chat_ID and BOTtoken credentials (uncommented line 45 & 46, #define ........, as well as commented line 199, 213, 251, 255). It does not work with (commented line 45 & 46, //#define ........, as well as uncommented line 199, 213, 251, 255) soft credential text inputs on the web page over acquired IP address on the browser after connecting to local network. http://IPADDRESS. It shows on serial monitor that it has successfully acquired credentials. Not too conversant with Arduino coding and need help. Perhaps something to do with type of variable I have tried to use (String) because the credentials show up on the serial monitor without quotes "". Here is the code:

//
// A simple server implementation showing how to:
//  * serve static messages
//  * read GET and POST parameters
//  * handle missing pages / 404s
//

#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebSrv.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <SimpleTimer.h>
#include <Preferences.h>
////#include <AsyncElegantOTA.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Arduino.h>
Preferences preferences;
AsyncWebServer server(80);
String CHAT_ID = "";
String BOTtoken = "";
String CHATID;
String TOKEN;
String chat_id;
#define BOTtoken "YOUR_TOKEN"
#define CHAT_ID "YOUR_CHATID"

unsigned long lastTime = 0;  
unsigned long timerDelay = 10;

const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

const char* PARAM_INPUT_1 = "CHATID";
const char* PARAM_INPUT_2 = "TOKEN";
const char* PARAM_MESSAGE = "message";

////#define BOTtoken "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
////#define CHAT_ID "XXXXXXXXX"

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .ds-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>Telegram Bot Credentials</h2>
  <p>
    <form action="/get">
    Telegram chat_Id: <input type="text" name="CHATID">
    <input type="submit" value="Submit">
    </form><br>
    <form action="/get">
    Telegram HTTP API Token: <input type="text" name="TOKEN">
    <input type="submit" value="Submit">
    </form><br>
      
    <br><i class="" style=" color:#0796f5;"></i></br>
    <br><span class="ds-labels">Telegram chat_Id: </span> 
    <span id="chatid">%CHATID%</span>
    <br> <span class="ds-labels">Telegram HTTP API Token: </span> 
    <span id="token">%TOKEN%</span>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("chatid").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/chatid", true);
  xhttp.send();
}, 10000) ;
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("token").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/token", true);
  xhttp.send();
}, 10000) ;
</script>
</html>)rawliteral";

// Replaces placeholder with DS18B20 values
String processor(const String & var){
  Serial.println(var);
    if(var == "CHATID"){
    return CHAT_ID;
    return String();
    }
    if(var == "TOKEN"){
    return BOTtoken;
    return String();
    }
  }

const unsigned long BOT_MTBS = 1000; // mean time between scan messages

unsigned long bot_lasttime; // last time messages' scan has been done
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOTtoken, secured_client);

void handleNewMessages(int numNewMessages)
{
  Serial.print("handleNewMessages ");
  Serial.println(numNewMessages);
  
  String answer;
  for (int i = 0; i < numNewMessages; i++)
  {
    telegramMessage &msg = bot.messages[i];
    Serial.println("Received " + msg.text);
    if (msg.text == "/help")
      answer = "So you need _help_, uh? me too! use /start or /status";
    else if (msg.text == "/start")
      answer = "Welcome my new friend! You are the first *" + msg.from_name + "* I've ever met";
    else if (msg.text == "/status")
      answer = "All is good here, thanks for asking!";
    else
      answer = "Say what?";

    bot.sendMessage(msg.chat_id, answer, "Markdown");
}
}

void bot_setup()
{
  const String commands = F("["
                            "{\"command\":\"help\",  \"description\":\"Get bot usage help\"},"
                            "{\"command\":\"start\", \"description\":\"Message sent when you open a chat with a bot\"},"
                            "{\"command\":\"status\",\"description\":\"Answer device current status\"}" // no comma on last command
                            "]");
  bot.setMyCommands(commands);
  //bot.sendMessage("25235518", "Hola amigo!", "Markdown");
}


void setup() {

    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.printf("WiFi Failed!\n");
        return;
    }

    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());

    secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org

    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
    });

    server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage1;
    String inputMessage2;
    String inputParam1;
    String inputParam2;
    // GET input1 value on <ESP_IP>/get?input1=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1)) {
      inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
      inputParam1 = PARAM_INPUT_1;
      CHATID = (inputMessage1); ////.c_str());
      ////CHAT_ID = String(CHATID);
      Serial.print("CHAT_ID=");
      Serial.println(CHAT_ID);
      preferences.begin("wifiCredentials",false);
      preferences.putString("CHAT_ID",CHAT_ID);
      Serial.print("Successfully put Chat_ID = ");
      Serial.println(CHAT_ID);
      preferences.end();    
    }
    // GET input2 value on <ESP_IP>/get?input2=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_2)) {
      inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
      inputParam2 = PARAM_INPUT_2;
      TOKEN = (inputMessage2); ////.c_str());
      ////BOTtoken = String(TOKEN);
      Serial.print("BOTtoken=");
      Serial.println(BOTtoken);
      preferences.begin("wifiCredentials",false);
      preferences.putString("BOTtoken",BOTtoken);
      Serial.print("Successfully put BOTtoken = ");
      Serial.println(BOTtoken);
      preferences.end();    
    }
    else {
      inputMessage1 = "No chat_id";
      inputMessage2 = "No Token";
      inputParam1 = "none";
      inputParam2 = "none";
    }
    Serial.println(inputMessage1);
    request->send(200, "text/html", "HTTP GET request sent to your ESP on input field (" 
                                     + inputParam1 + ") with value: " + inputMessage1 +
                                     "<br><a href=\"/\">Return to Home Page</a>");
    Serial.println(inputMessage2);
    request->send(200, "text/html", "HTTP GET request sent to your ESP on input field (" 
                                     + inputParam2 + ") with value: " + inputMessage2 +
                                     "<br><a href=\"/\">Return to Home Page</a>");                                
    });
    server.onNotFound(notFound);
  
    server.on("/CHATID", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", CHATID.c_str());
    });
    server.on("/TOKEN", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", TOKEN.c_str());
  });
  // Start server
    ////AsyncElegantOTA.begin(&server);
    server.begin();
    delay(100);

    preferences.begin("wifiCredentials",true);
      ////CHAT_ID = preferences.getString("CHAT_ID",CHAT_ID); ////.c_str();
      Serial.print("Retrieved CHAT_ID = ");
      Serial.println(CHAT_ID);
      
      ////BOTtoken = preferences.getString("BOTtoken",BOTtoken); ////.c_str();
      Serial.print("Retrieved BOTtoken = ");
      Serial.println(BOTtoken);
      preferences.end();       
      delay(2000);


    uint32_t chipId = 0;
    // Checks for new messages every 1 second.
    int botRequestDelay = 1000;
    unsigned long lastTimeBotRan;

  ////bot_setup();
}


void loop() {
  ////wm.process();
      Serial.print("CHAT_ID = ");
      Serial.println(CHAT_ID);
      Serial.print("BOTtoken = ");
      Serial.println(BOTtoken);
      delay(10000);


  if (millis() - bot_lasttime > BOT_MTBS)
  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages)
    {
      Serial.println("got response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    bot_lasttime = millis();
  }
}

as a quick guessing instead of

UniversalTelegramBot bot(BOTtoken, secured_client);

try

UniversalTelegramBot bot(BOTtoken.c_str(), secured_client);

UniversalTelegramBot bot(BOTtoken.c_str()

never worked with a TelegramBot
but quite often such functions expect c_strings as parameter

best regards Stefan

@StefanL38 ,

No it did not work. Perhaps there is some other reason.

It shows on the serial monitor, the saved value as this with correct credentials:

CHAT_ID = xxxxxxxxx
BOTtoken = xxxxxxxxxx: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Not sure why is it not using the values for the Telegram Bot chat?

Here is a code-version that prints "#" before and after your string
and you should do this printing at each place in your code where something with your botoken and chatID is done

If you print them in each place you can really see what the code does

there are some oddities on your code

here you are defining a variable and a macro

String CHAT_ID = "";
String BOTtoken = ""; // which one shall be valid?
String CHATID;
String TOKEN;
String chat_id;
#define BOTtoken "YOUR_TOKEN" // which one shall be valid?
#define CHAT_ID "YOUR_CHATID"

and here you are defining again

////#define BOTtoken "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
////#define CHAT_ID "XXXXXXXXX"

put all variable and define lines close together
to keep the overview what you define where and what is commented and what is active
why do you use return two times???

  if (var == "CHATID") {
    return CHAT_ID;
    return String();
  }
  if (var == "TOKEN") {
    return BOTtoken;
    return String();
  }
}

in your defition you are returning one single value

String processor(const String & var) {

this should be enough

  if (var == "CHATID") {
    return CHAT_ID;
  }
  if (var == "TOKEN") {
    return BOTtoken;
  }
}

//
// A simple server implementation showing how to:
//  * serve static messages
//  * read GET and POST parameters
//  * handle missing pages / 404s
//

#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebSrv.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <SimpleTimer.h>
#include <Preferences.h>
////#include <AsyncElegantOTA.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Arduino.h>
Preferences preferences;
AsyncWebServer server(80);
String CHAT_ID = "";
String BOTtoken = "";
String CHATID;
String TOKEN;
String chat_id;
#define BOTtoken "YOUR_TOKEN"
#define CHAT_ID "YOUR_CHATID"

unsigned long lastTime = 0;
unsigned long timerDelay = 10;

const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

const char* PARAM_INPUT_1 = "CHATID";
const char* PARAM_INPUT_2 = "TOKEN";
const char* PARAM_MESSAGE = "message";

////#define BOTtoken "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
////#define CHAT_ID "XXXXXXXXX"

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .ds-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>Telegram Bot Credentials</h2>
  <p>
    <form action="/get">
    Telegram chat_Id: <input type="text" name="CHATID">
    <input type="submit" value="Submit">
    </form><br>
    <form action="/get">
    Telegram HTTP API Token: <input type="text" name="TOKEN">
    <input type="submit" value="Submit">
    </form><br>
      
    <br><i class="" style=" color:#0796f5;"></i></br>
    <br><span class="ds-labels">Telegram chat_Id: </span> 
    <span id="chatid">%CHATID%</span>
    <br> <span class="ds-labels">Telegram HTTP API Token: </span> 
    <span id="token">%TOKEN%</span>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("chatid").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/chatid", true);
  xhttp.send();
}, 10000) ;
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("token").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/token", true);
  xhttp.send();
}, 10000) ;
</script>
</html>)rawliteral";

// Replaces placeholder with DS18B20 values
String processor(const String & var) {
  Serial.println(var);
  if (var == "CHATID") {
    return CHAT_ID;
    return String();
  }
  if (var == "TOKEN") {
    Serial.print("TOKEN=#");
    Serial.print(BOTtoken);
    Serial.print("#");
    return BOTtoken;
    return String(); // why are here two returns??
  }
}

const unsigned long BOT_MTBS = 1000; // mean time between scan messages

// why are these lines outside any functio???

unsigned long bot_lasttime; // last time messages' scan has been done
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOTtoken, secured_client);

void handleNewMessages(int numNewMessages)
{
  Serial.print("handleNewMessages ");
  Serial.println(numNewMessages);

  String answer;
  for (int i = 0; i < numNewMessages; i++)
  {
    telegramMessage &msg = bot.messages[i];
    Serial.println("Received " + msg.text);
    if (msg.text == "/help")
      answer = "So you need _help_, uh? me too! use /start or /status";
    else if (msg.text == "/start")
      answer = "Welcome my new friend! You are the first *" + msg.from_name + "* I've ever met";
    else if (msg.text == "/status")
      answer = "All is good here, thanks for asking!";
    else
      answer = "Say what?";

    bot.sendMessage(msg.chat_id, answer, "Markdown");
  }
}

void bot_setup()
{
  const String commands = F("["
                            "{\"command\":\"help\",  \"description\":\"Get bot usage help\"},"
                            "{\"command\":\"start\", \"description\":\"Message sent when you open a chat with a bot\"},"
                            "{\"command\":\"status\",\"description\":\"Answer device current status\"}" // no comma on last command
                            "]");
  bot.setMyCommands(commands);
  //bot.sendMessage("25235518", "Hola amigo!", "Markdown");
}


void setup() {

  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.printf("WiFi Failed!\n");
    return;
  }

  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org

  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html, processor);
  });

  server.on("/get", HTTP_GET, [] (AsyncWebServerRequest * request) {
    String inputMessage1;
    String inputMessage2;
    String inputParam1;
    String inputParam2;
    // GET input1 value on <ESP_IP>/get?input1=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1)) {
      inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
      inputParam1 = PARAM_INPUT_1;
      CHATID = (inputMessage1); ////.c_str());
      ////CHAT_ID = String(CHATID);
      Serial.print("CHAT_ID=");
      Serial.println(CHAT_ID);
      preferences.begin("wifiCredentials", false);
      preferences.putString("CHAT_ID", CHAT_ID);
      Serial.print("Successfully put Chat_ID = ");
      Serial.println(CHAT_ID);
      preferences.end();
    }
    // GET input2 value on <ESP_IP>/get?input2=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_2)) {
      inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
      inputParam2 = PARAM_INPUT_2;
      TOKEN = (inputMessage2); ////.c_str());
      ////BOTtoken = String(TOKEN);
      Serial.print("else if BOTtoken=#");
      Serial.print(BOTtoken);
      Serial.println("#");
      preferences.begin("wifiCredentials", false);
      preferences.putString("BOTtoken", BOTtoken);
      preferences.end();
    }
    else {
      inputMessage1 = "No chat_id";
      inputMessage2 = "No Token";
      inputParam1 = "none";
      inputParam2 = "none";
    }
    Serial.println(inputMessage1);
    request->send(200, "text/html", "HTTP GET request sent to your ESP on input field ("
                  + inputParam1 + ") with value: " + inputMessage1 +
                  "<br><a href=\"/\">Return to Home Page</a>");
    Serial.println(inputMessage2);
    request->send(200, "text/html", "HTTP GET request sent to your ESP on input field ("
                  + inputParam2 + ") with value: " + inputMessage2 +
                  "<br><a href=\"/\">Return to Home Page</a>");
  });
  server.onNotFound(notFound);

  server.on("/CHATID", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/plain", CHATID.c_str());
  });
  server.on("/TOKEN", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/plain", TOKEN.c_str());
  });
  // Start server
  ////AsyncElegantOTA.begin(&server);
  server.begin();
  delay(100);

  preferences.begin("wifiCredentials", true);
  ////CHAT_ID = preferences.getString("CHAT_ID",CHAT_ID); ////.c_str();
  Serial.print("Retrieved CHAT_ID = ");
  Serial.println(CHAT_ID);

  BOTtoken = preferences.getString("BOTtoken",BOTtoken); ////.c_str();
  Serial.print("Retrieved BOTtoken = #");
  Serial.print(BOTtoken);
  Serial.print("#");
  preferences.end();
  delay(2000);


  uint32_t chipId = 0;
  // Checks for new messages every 1 second.
  int botRequestDelay = 1000;
  unsigned long lastTimeBotRan;

  ////bot_setup();
}


void loop() {
  ////wm.process();
  Serial.print("CHAT_ID = ");
  Serial.println(CHAT_ID);
  Serial.print("BOTtoken = ");
  Serial.println(BOTtoken);
  delay(10000);


  if (millis() - bot_lasttime > BOT_MTBS)
  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages)
    {
      Serial.println("got response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    bot_lasttime = millis();
  }
}

best regards Stefan

@StefanL38 . Thank you for your insight and appreciate your suggestions.

I think we are missing the target goal.

As I mentioned on my earlier post that it works perfectly fine when I hard code CHAT_ID and BOTtoken like this:

#define BOTtoken "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
#define CHAT_ID "XXXXXXXXX"

XXXX replaced with correct credentials not disclosed here. This works fine, TelegramBot sends messages perfectly.

But our main aim is not to use hard coding i.e we want to comment it out. Instead want to insert CHAT_ID and BOTtoken (TelegramBot credentials) over the browser and save it on non-volatile memory by using Preferences.h library so that the end user of the device can get notifications on their own TelegramBot App.

My wild guess is this:

Since we are using Preferences.h library it might be fetching a key value pair for example
"BOTtoken": "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
from which we need to extract the content of the key i.e. we need to extract the content BOTtoken from the string "BOTtoken" so that it becomes
BOTtoken = "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" (BOTtoken without quotes)
and then the program will be able to execute it within the code:

UniversalTelegramBot bot(BOTtoken, secured_client);

I may be wrong but perhaps someone can assist on how to extract the content variable BOTtoken from the key "BOTtoken" so I can try it out.

Your last post was very short. If I would use such short answers the answer would be

use a constant string as the default value
Do debug printing to see what value you get.

End of posting.

Do you really know what do do?
I'm pretty sure you don't!

These short sentences are hard tpo understand.
You should write in more detail.

post a new code-version in a new posting. Where everything is commented out that shall be commented out and everything that shall be used is active.

This should be straight forward using preferences.getString
and to see what is extracted simply add code like this

  Serial.print("variable-NAME#");
  Serial.print(variable);
  Serial.println("#");

The leading "#" and the trailing "#" will make visible what is exactly inside the variable

I highly recommend that you use different names for the preferences-identifier and for the variable
Using the same name for different things in all other cases than here the preferences-identifier causes a compiler-error for thousands of reasons

Using the exact same name is a big source of easy to overlook bugs
So use something like

BOTtoken = preferences.getString("BOTtoken_PrefID","Assign_a_Real_Token");

.
.
if you lookup pages that show how to use preferences you can see

getString(const char* key, const String defaultValue)

there is const
if the preferences ID is not found the default-value of const String defaultValue will be used.

The default-value should be a constant
If you use a variable

myVariable1 = preferences.getString("ID1",myVar2;

If you haven't assigned the value for myVar2 some rubbish will be assigned to myVariable1
.
.
coding

BOTtoken = preferences.getString("BOTtoken_PrefID","Assign_a_Real_Token");

will assign the text "Assign_a_Real_Token" as text which will show in your website that there is no valid token yet.

best regards Stefan

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