cotestatnt / AsyncTelegram2

Powerful, flexible and secure Arduino Telegram BOT library. Hardware independent, it can be used with any MCU capable of handling an SSL connection.
MIT License
85 stars 25 forks source link

sometime Bot answers twice #77

Closed konig87nikkinakki closed 2 years ago

konig87nikkinakki commented 2 years ago

Hi, this is not properly an issue: it's something wrong on sketch i think. i tried to modify lightbot.ino because i need a welcome message at startup, so this is sketch:


#define USE_CLIENTSSL false

#include <AsyncTelegram2.h>
// Timezone definition
#include <time.h>
#define MYTZ "CET-1CEST,M3.5.0,M10.5.0/3"

#ifdef ESP8266
#include <ESP8266WiFi.h>
BearSSL::WiFiClientSecure client;
BearSSL::Session session;
BearSSL::X509List certificate(telegram_cert);

#elif defined(ESP32)
#include <WiFi.h>
#include <WiFiClient.h>
#if USE_CLIENTSSL
#include <SSLClient.h>
#include "tg_certificate.h"
WiFiClient base_client;
SSLClient client(base_client, TAs, (size_t)TAs_NUM, A0, 1, SSLClient::SSL_ERROR);
#else
#include <WiFiClientSecure.h>
WiFiClientSecure client;
#endif
#endif

AsyncTelegram2 myBot(client);
const char* ssid = "my_ssid"; // SSID WiFi network
const char* pass = "my_wpakey"; // Password WiFi network
const char* token = "1989143778:AAGx67iAR_o54zyTYQIwYEMHZ73Cx1_zXXX"; // Telegram token

const uint8_t LED = LED_BUILTIN;

const int64_t destinatari[] = {755575XXX, 76154XXX2};
int totale_numero_di_destinatari = 0;
int contatore = 0;
TBMessage msg;
IPAddress ilmioip;

void setup() {
  // initialize the Serial
  Serial.begin(115200);
  Serial.println("\nStarting TelegramBot...");

  // set the pin connected to the LED to act as output pin
  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH); // turn off the led (inverted logic!)

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
  delay(500);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }

#ifdef ESP8266
  // Sync time with NTP, to check properly Telegram certificate
  configTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
  //Set certficate, session and some other base client properies
  client.setSession(&session);
  client.setTrustAnchors(&certificate);
  client.setBufferSizes(1024, 1024);
#elif defined(ESP32)
  // Sync time with NTP
  configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
#if USE_CLIENTSSL == false
  client.setCACert(telegram_cert);
#endif
#endif

  // Set the Telegram bot properies
  myBot.setUpdateTime(1000);
  myBot.setTelegramToken(token);

  // Check if all things are ok
  Serial.print("\nTest Telegram connection... ");
  myBot.begin() ? Serial.println("OK") : Serial.println("NOK");

  Serial.print("Bot name: @");
  Serial.println(myBot.getBotName());

  ilmioip = WiFi.localIP();
  totale_numero_di_destinatari = sizeof(destinatari) / sizeof(destinatari[0]);

  for (contatore; contatore < totale_numero_di_destinatari; contatore++)
  {
    myBot.sendTo(destinatari[contatore], "ESP32 è stato spento e riacceso. IP: " + (String)ilmioip[0] + "." + (String)ilmioip[1] + "." + (String)ilmioip[2] + "." + (String)ilmioip[3]) + "\n";
    delay(100);
  }
}

void loop() {
  // local variable to store telegram message data

  // if there is an incoming message...
  if (myBot.getNewMessage(msg)) {
    String msgText = msg.text;

    if (msgText.equals("/light_on")) {                 // if the received message is "LIGHT ON"...
      digitalWrite(LED, LOW);                          // turn on the LED (inverted logic!)
      myBot.sendMessage(msg, "Light is now ON");       // notify the sender
    }
    else if (msgText.equals("/light_off")) {           // if the received message is "LIGHT OFF"...
      digitalWrite(LED, HIGH);                          // turn off the led (inverted logic!)
      myBot.sendMessage(msg, "Light is now OFF");       // notify the sender
    }
    else {                                              // otherwise...
      // generate the message for the sender
      String reply;
      reply = "Welcome " ;
      reply += msg.sender.username;
      reply += ".\nTry /light_on or /light_off ";
      myBot.sendMessage(msg, reply);                    // and send it
    }
  }

}

As you can see, a FOR send to DESTINATARI the welcome message. it WORKS, both my phones receive welcome message but then when one of them send command /light_on or /light_off ESP32 answers him twice "Light is now ON" or "off".

i don't ask you to fix my problem, please just tell me if it's a library bug or if it's my sketch not good. before to code harder, i d like to fix these small issues, thank you so much!

cotestatnt commented 2 years ago

I'm sorry, but there was a small bug, I've just uploaded a fix and drafted a new release.

Aniway, why you set TBMessage msg; as global? It should be local, otherwise it keeps in memory your last message and in the next loop it will be processed again. You could clear the content of msg.text, but it's a non-sense, keep it local.

Regarding the welcome message, could be clearer in this way (C ++ 11 range-based for, and no use of global variables) Concatenating String as you have done it is not recommended because a lot of unnecessarily "temporary" copies are created.

For your needs, maybe is more convenient create a group and send message only once. Every member of groups will can then interact with bot directly from group chat.

If you are using ESP32, I would suggest also to update to latest versione of core 2.0.3 because they have done a very good work in this latest release.

  const int64_t destinatari[] = {755575XXX, 76154XXX2};
  ....
  ....

  for (int64_t destinatario : destinatari)
  {
    char welcomeMessage[100];
    snprintf (welcomeMessage, sizeof(welcomeMessage), 
              "ESP32 è stato spento e riacceso. IP: %d.%d.%d.%d\n",
              WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
    myBot.sendTo(destinatario, welcomeMessage);
    delay(100);
  }
konig87nikkinakki commented 2 years ago

Thank you for support, i use TBMessage msg as global because in other functions i use myBot.sendTo(msg.sender.id, "risposta") to answer only to the sender of message, and (i ve thought) if TBMessage is local, msg.sender.id in other function could be Null. i ll try to use it local and see what happens.

i dont want to create a Telegram Group because users dont need to contact each other, that s why I better like to do what i was trying to code.

where is the fix that you just uploaded? is it a library's new version?

ok i ll download 2.0.3 this afternoon :-D

cotestatnt commented 2 years ago

Some time it's needed in order to see new versions with Arduino Library manager.

If you need to do something with message inside a function, you can pass the reference to TBMessage

void doSomething (TBMessage &theMsg) {
  Serial.print("New message from ");
  Serial.println(theMsg.sender.id);
  Serial.println(theMsg.text);
}

void loop() {
  TBMessage msg;
  if (myBot.getNewMessage(msg)) {
    doSomething (msg);
  }
}