2026年2月21日 星期六

ESP32 Telegram Channel POST

 ESP32 Telegram Channel POST

這段程式碼是一個基於 ESP32的 Telegram 機器人範例,功能非常單純: 它會接收使用者傳送的訊息,並原封不動地回傳(Echo)。



//*******************************************************************/
/*******************************************************************
*  An example of bot that echos back any messages received,
*  including ones from channels
*                                                                          
*  written by Brian Lough
*******************************************************************/
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

// Wifi network station credentials
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
// Telegram BOT Token (Get from Botfather)
#define BOT_TOKEN "77389402154:AAHbrWu9ovb1BKPQ2yWs1bNSjNxfCGCrEWU-o"

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

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

void handleNewMessages(int numNewMessages)
{
  for (int i = 0; i < numNewMessages; i++)
  {
    if (bot.messages[i].type == "channel_post")
    {
      bot.sendMessage(bot.messages[i].chat_id, bot.messages[i].chat_title + " " + bot.messages[i].text, "");
    }
    else
    {
      bot.sendMessage(bot.messages[i].chat_id, bot.messages[i].text, "");
    }
  }
}

void setup()
{
  Serial.begin(115200);
  Serial.println();

  // attempt to connect to Wifi network:
  Serial.print("Connecting to Wifi SSID ");
  Serial.print(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }
  Serial.print("\nWiFi connected. IP address: ");
  Serial.println(WiFi.localIP());

  Serial.print("Retrieving time: ");
  configTime(0, 0, "tock.stdtime.gov.tw"); // get UTC time via tock.stdtime.gov.tw
  time_t now = time(nullptr);
  while (now < 24 * 3600)
  {
    Serial.print(".");
    delay(100);
    now = time(nullptr);
  }
  Serial.println(now);
}

void loop()
{
  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();
  }
}


程式碼逐行詳解

1. 引用與基本定義

C++
#include <WiFi.h>              // 用於處理 ESP32 的 WiFi 連線
#include <WiFiClientSecure.h>  // 用於處理 HTTPS 加密連線(Telegram 要求 SSL/TLS)
#include <UniversalTelegramBot.h> // Telegram Bot 的核心 API 函式庫

2. 設定網路與機器人資訊

C++
#define WIFI_SSID "Wokwi-GUEST"      // WiFi 帳號(這裡使用 Wokwi 模擬器的預設值)
#define WIFI_PASSWORD ""             // WiFi 密碼
#define BOT_TOKEN "7738940254:..."   // 從 BotFather 取得的機器人唯一金鑰
const unsigned long BOT_MTBS = 1000; // 設定掃描新訊息的間隔時間(1000 毫秒 = 1 秒)

3. 實例化物件

C++
WiFiClientSecure secured_client;             // 建立加密的網路連線用戶端
UniversalTelegramBot bot(BOT_TOKEN, secured_client); // 建立機器人物件
unsigned long bot_lasttime;                  // 記錄上次檢查訊息的時間

4. 處理新訊息的函式 (handleNewMessages)

這是機器人的「大腦」,決定收到訊息後要做什麼。

C++
void handleNewMessages(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) { // 逐一處理收到的每一則訊息
    // 如果訊息來自「頻道 (Channel)」
    if (bot.messages[i].type == "channel_post") {
      // 回傳:頻道名稱 + 訊息內容
      bot.sendMessage(bot.messages[i].chat_id, bot.messages[i].chat_title + " " + bot.messages[i].text, "");
    } 
    // 如果是個人私訊或群組訊息
    else {
      // 回傳:原本的訊息內容
      bot.sendMessage(bot.messages[i].chat_id, bot.messages[i].text, "");
    }
  }
}

5. 初始化設定 (setup)

C++
void setup() {
  Serial.begin(115200); // 開啟序列號視窗,波特率 115200

  // 1. 連接 WiFi
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  // 加入 Telegram 的根憑證,確保 HTTPS 連線安全性
  secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT); 
  
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("\nWiFi connected.");

  // 2. 同步網路時間(Telegram API 需要正確的時間戳記才能運作)
  configTime(0, 0, "tock.stdtime.gov.tw"); 
  time_t now = time(nullptr);
  while (now < 24 * 3600) { // 等待時間同步完成
    delay(100);
    now = time(nullptr);
  }
  Serial.println(now);
}

6. 主要迴圈 (loop)

C++
void loop() {
  // 檢查是否到了該掃描訊息的時間 (每秒一次)
  if (millis() - bot_lasttime > BOT_MTBS) {
    // 向 Telegram 伺服器詢問是否有新訊息,並回報最後收到的 ID
    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(); // 更新檢查時間
  }
}

重要提醒

  1. 安全性:你在程式碼中直接寫出了 BOT_TOKEN。雖然這在測試時很方便,但如果上傳到 GitHub 等公開平台,別人就能控制你的機器人。請妥善保管此 Token

  2. 根憑證TELEGRAM_CERTIFICATE_ROOTUniversalTelegramBot 內建的憑證。如果 Telegram 更新了憑證而你的庫太舊,連線可能會失敗。

  3. Wokwi 模擬:這段程式碼可以直接在 Wokwi 平台上運行,因為它使用了模擬器專用的 WiFi SSID。

沒有留言:

張貼留言

ESP32 Telegram 指令選單(Bot Commands)

ESP32 Telegram 指令選單(Bot Commands)  /*******************************************************************  ***********************************...