Telegrambot


huella, bellagente, saluti, baci abbracci e buona domenica.
qualche tempo fa avevo letto di uno che usava telegram per comandare il suo arduino, figo, e lo volevo fare anch'io, mi son fatto dare due link e ci ho provato.
devo dire che si tratta di una libreria fatta bene, che prevede tanti bei casi, ma se devo dire di esserne stato soddisfatto direi una bugia, e grossa.
macchinosa, e usa troppo gli oggetti stringa, appena ho cominciato divertirmi la mia povera nodemcu si incatastava, povera piccola. quindi mi sono messo di buzzo buono, e ho stroncato l'intera libreria, sostituita con due/tre funzioni in santo c, senza stringhe di liquerizia o altri santi da chiamare.
vi metto qui il programma che funzia, funzia abbastanza bene.

code: [select]

// la quarta zucca e' bianca

//una semplice interfaccia ai bot di telegram


// librerie
#include <esp8266wifi.h>
#include <wificlientsecure.h>
wificlientsecure client;


// dati connessione wifi
char ssid[] = "xxx";         // ssid
char password[] = "yyy";     // psk

// token del bot
#define token "11111:aaaaaaaaa"

// variabili di appoggio
char testo[101];      // il messaggio in ricezione, lungo al massimo 100 caratteri
int lentesto;
unsigned long int ultimo;   // il numero dell'ultimo messaggio ricevuto
unsigned long int appoggio; // il numero del messaggio in ricezione
unsigned long int mittente; // il numero del mittente ultimo messaggio

int passo = 10000;               //tempo tra una richiesta e la successiva
unsigned long int ultimotempo;   //ultima ricezione tentata


void setup() {

  serial.begin(9600);

  // su il wifi
  serial.print(f("connessione al wifi: "));
  serial.println(ssid);
  wifi.begin(ssid, password);

  while (wifi.status() != wl_connected) {
    serial.print(".");
    delay(500);
  }
  serial.print(f("connesso. ip: "));

  ipaddress ip = wifi.localip();
  serial.println(ip);

}



void loop() {
  // ogni passo millisecondi
  if (millis() - ultimotempo >  passo)  {
    ricevidalbot(); // lancio la ricezione
    // controllo che sia arrivato un nuovo messaggio

    if (appoggio > ultimo) {
      // aggiorno l'ultimo messaggio ricevuto
      ultimo = appoggio;
      // stampo la stringa ricevuta
      serial.print(f("updateid: "));
      serial.println (appoggio);
      serial.print(f("mittente: "));
      serial.println(mittente);
      serial.print(f("testo: "));
      serial.println(testo);
      // ringrazio per avermi scritto
      trasmettialbot(mittente, "grazie per avermi scritto");

    }
    else {
      serial.print(f("nulla di nuovo, ultimo update ricevuto: "));
      serial.println(ultimo);
    }
  }
}




void ricevidalbot(void)  {

  // connessione con telegram
  ultimotempo = millis(); // aggiorno il timer
  ipaddress server(149, 154, 167, 198);
  if (client.connect(server, 443)) {
    serial.println(f(".... connesso al server"));
    unsigned long ora;
    client.print(f("get /bot"));
    client.print (token);
    client.print (f("/getupdates?offset="));
    client.print (ultimo + 1);
    client.println (f("&limit=1"));
    // resetto la variabile di appoggio che mi serve per conteggiare il valore di ultimo update ricevuto
    appoggio = 0;
    // resetto la variabile di ultimo mittente
    mittente = 0;
    // svuoto il campo testo
    testo[0] = '\0'; // basta il primo carattere, le stringhe sono terminate dallo \0
    // il contatore di lunghezza del testo
    lentesto = 0;

    ora = millis();
    while (millis() - ora < 1000) {
      if (client.available()) {

        // passo alla funzione di trattamento il carattere ricevuto
        if (!tratta(client.read())) {
          break;
          // la tratta restituisce 0 quando è il momento di troncare
        };
      }
    }
  }
}


void trasmettialbot(unsigned long int mittente, char messaggio[]) {
  //trasmette al bot il messaggio
  // connessione con telegram
  ipaddress server(149, 154, 167, 198);
  if (client.connect(server, 443)) {
    serial.println(f(".... connesso al server"));

    client.print(f("get /bot"));
    client.print (token);
    client.print (f("/sendmessage?chat_id="));
    client.print (mittente);
    client.print (f("&text="));
    client.print (messaggio);
    client.println();
  }
}


int tratta(char c) {

  // tratta carattere per caratttere il testo messaggio ricevuto da telegram
  // riconosce le coppie di parentesi graffe
  // riconosce alcuni campi
  // restituisce 0 per fermare

  static int livello = 0; // il livello di rientro delle parentesi graffe
  static int trovato = 0; // quale nome di oggetto è stato trovato

# define numoggetti  4
  static char * oggetti[numoggetti] = {"none", "\"update_id\":", "chat\":\"id\":", "\"text\":\""};
  // questo somiglia un array di stringhe
  // realmente e' un array di puntatori stringa
  // il primo elemento è messo ciccare, per evitare trovato=0, che si confonde con trovato nulla
  static int corrente[numoggetti];
  // un array di posizioni correnti nell'array di stringhe

  // serial.println(c);
  if (c == '{') {
    livello++;
    return livello;
  }
  if (c == '}') {
    livello--;
    // trovato=0;
    return livello;
  }

  // ok, siamo nel corpo del messaggio
  //devo riconoscere se stiamo leggendo il nome di un oggetto conosciuto
  if (trovato) {
    // abbiamo trovato un nome di oggetto (: compreso)
    // adesso fino alla virgola o alla virgoletta
    // se si tratta di una virgola
    if (c == ',') {
      trovato = 0;
      // fine del valore
      return 1;

    }
    // o di una virgoletta
    if (c == '\"') {
      trovato = 0;
      // fine del valore
      return 1;
    }
  }
  // ok non è una virgola ne una virgoletta

  // campi numerici
  if (trovato == 1)
  { // updateid, che vale come ultimo messaggio

    appoggio = appoggio * 10 + c - '0';
    // traduco in intero

  }
  if (trovato == 2)
  { // mittente

    mittente = mittente * 10 + c - '0';
    // traduco in intero

  }
  // campi alfabetici, che per ora è solo text, corpo del messaggio
  if (trovato == 3)
    // siamo nel testo
    if (lentesto <= 100) {
      testo[lentesto] = c;
      lentesto++;
      testo[lentesto] = '\0'; // termina qui

    }
    else {
      trovato = 0;
      // tronco la lettura, per non sbordare, siamo oltre 100 byte
    }

  else {
    // non abbiamo ancora trovato il nome di un oggetto
    // vado avanti cercarlo

    (int = 0; < numoggetti; i++) {
      //per ogni oggetto

      if (c != oggetti[i][corrente[i]]) {
        // non corrisponde
        corrente[i] = 0;
      }
      else {
        // corrisponde
        corrente[i]++;
        //avanza un passo
        if (oggetti[i][corrente[i]] == '\0') {
          // oggetto finito
          // caso trovato
          corrente[i] = 0; //torno indietro
          trovato = i;
        }
      }
    }
  }
  return 1; // ok in lettura
}


c'è poco da commentare, credo, il programma è ben commentato di suo. limiti:
riceve un solo messaggio per volta, il più vecchio nella catasta di ricezione di telegram, ma tanto lo da subito per ricevuto e quindi la prossima volta ne riceve un'altro
accetta solo massimo 100 caratteri, dovrei dire primi 100, non si lamenta se ne arrivano di più, li scarta.
rispetto alle librerie più conosciute usa unsigned long per gli utenti e per messaggi, come dice papà telegram. interessante che la lavorazione del testo viene fatta mano mano che arriva, carattere per carattere, questo evita di dover usare stringhe di liquerizia e non richiede nemmeno grandi buffer di testo
provate e fatemi sapere


Arduino Forum > International > Italiano > Software (Moderator: leo72) > Telegrambot


arduino

Comments

Popular posts from this blog

Error compiling for board Arduino/Genuino Uno.

Installation database is corrupt

esp8266 (nodemcu 0.9) client.write très lent ???