/*
Name: keyboards.ino
Created: 05/03/2022
Author: Tolentino Cotesta <[email protected]>
Description: a more complex example that do:
1) if a "/inline_keyboard" text message is received, show the inline custom keyboard,
if a "/reply_keyboard" text message is received, show the reply custom keyboard,
otherwise reply the sender with "Try /reply_keyboard or /inline_keyboard" message
2) if "LIGHT ON" inline keyboard button is pressed turn on the LED and show a message
3) if "LIGHT OFF" inline keyboard button is pressed, turn off the LED and show a message
4) if "GitHub" inline keyboard button is pressed,
open a browser window with URL "https://github.com/cotestatnt/AsyncTelegram"
*/
#include <AsyncTelegram2.h>
#include <ESP32Servo.h>
// Timezone definition
#include <time.h>
#define MYTZ "CET-1CEST,M3.5.0,M10.5.0/3"
/*
Set true if you want use external library for SSL connection
For example https://github.com/OPEnSLab-OSU/SSLClient/ is very efficient BearSSL library and
you can use AsyncTelegram2 even with other MCUs or transport layer (ex. Ethernet or GPRS)
*/
#define USE_CLIENTSSL false
#ifdef ESP8266
#include <ESP8266WiFi.h>
WiFiClientSecure client;
Session session;
X509List certificate(telegram_cert);
#elif defined(ESP32)
#include <WiFi.h>
#include <WiFiClient.h>
#if USE_CLIENTSSL
#include <SSLClient.h> // https://github.com/OPEnSLab-OSU/SSLClient/
#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 = "Wokwi-GUEST"; // SSID WiFi network
const char* pass = ""; // Password WiFi network
const char* token = "6337364832:AAESU6OBIlAb0S_FaIY9UJTb3YxaBrM1yeg"; // Telegram token
// Check the userid with the help of bot @JsonDumpBot or @getidsbot (work also with groups)
// https://t.me/JsonDumpBot or https://t.me/getidsbot
int64_t userid = 123456789;
ReplyKeyboard myReplyKbd; // reply keyboard object helper
InlineKeyboard myInlineKbd, Inline, Inline2, Inline3, Inline4; // inline keyboard object helper
bool isKeyboardActive; // store if the reply keyboard is shown
#define OPEN_CALLBACK "doorOpen" // callback data sent when "LIGHT ON" button is pressed
#define CLOSE_CALLBACK "doorClose" // callback data sent when "LIGHT OFF" button is pressed
const uint8_t LED = 7;
Servo myServo;
const int servoPin = 9;
bool isBooking = false;
String bookingID;
String receiverPhoneNum;
String receiverPackageSize;
bool packageSizeSelected = false;
void moveServo(int angle) {
myServo.write(angle);
}
float calculatePrice(String packageSize) {
if (packageSize.equalsIgnoreCase("package_Small")) {
return 0.25;
} else if (packageSize.equalsIgnoreCase("package_Medium")) {
return 0.50;
} else if (packageSize.equalsIgnoreCase("package_Large")) {
return 0.75;
}
return 0.0; // default price if package size is not recognized
}
void setup() {
// pinMode(LED_BUILTIN, OUTPUT);
// pinMode(LED, OUTPUT);
// initialize the Serial
Serial.begin(115200);
// connects to the access point
WiFi.begin(ssid, pass);
delay(500);
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(500);
}
myServo.attach(servoPin);
#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 properties
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());
Inline.addButton("📦 Sender", "sender", KeyboardButtonQuery);
Inline.addButton("📫 Receiver", "receiver", KeyboardButtonQuery);
Inline2.addButton("👉 Book Now", "book_now", KeyboardButtonQuery);
Inline3.addButton("📦 Small $0.25", "package_Small", KeyboardButtonQuery);
Inline3.addButton("📦 Medium $0.50", "package_Medium", KeyboardButtonQuery);
Inline3.addButton("📦 Large $0.75", "package_Large", KeyboardButtonQuery);
Inline4.addButton("✅ Confirm", "confirm", KeyboardButtonQuery);
Inline4.addButton("✏️ Edit", "edit", KeyboardButtonQuery);
Inline4.addButton("❌ Cancel", "cancel", KeyboardButtonQuery);
// Add sample inline keyboard
myInlineKbd.addButton("🚪 OPEN", OPEN_CALLBACK, KeyboardButtonQuery);
myInlineKbd.addButton("🚪 CLOSE", CLOSE_CALLBACK, KeyboardButtonQuery);
myInlineKbd.addRow();
myInlineKbd.addButton("GitHub", "https://github.com/cotestatnt/AsyncTelegram2/", KeyboardButtonURL);
char welcome_msg[128];
snprintf(welcome_msg, 128, "BOT @%s online\n/help all commands avalaible.", myBot.getBotName());
// Send a message to specific user who has started your bot
myBot.sendTo(userid, welcome_msg);
//move servo to close position
moveServo(0);
}
void loop() {
// In the meantime LED_BUILTIN will blink with a fixed frequency
// to evaluate async and non-blocking working of library
static uint32_t ledTime = millis();
if (millis() - ledTime > 200) {
ledTime = millis();
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
// if there is an incoming message...
// local variable to store telegram message data
TBMessage msg;
if (myBot.getNewMessage(msg)) {
// check what kind of message I received
MessageType msgType = msg.messageType;
String msgText = msg.text;
String callbackData; // Move the declaration here
switch (msgType) {
case MessageText:
// received a text message
Serial.print("\nText message received: ");
Serial.println(msgText);
if (msgText.equalsIgnoreCase("/start")) {
myBot.sendMessage(msg, "Are you a sender or a receiver? Please select an option:", Inline);
}
else if (isBooking && msg.chatId == atoll(bookingID.c_str())) {
receiverPhoneNum = msg.text;
myBot.sendMessage(msg, "Thank you! Your receiver's phone number is: " + receiverPhoneNum);
myBot.sendMessage(msg, "Please select your package size", Inline3); // Added semicolon here
}
// the user write anything else and the reply keyboard is not active --> show a hint message
else {
myBot.sendMessage(msg, "Try /start");
}
break;
case MessageQuery:
// received a callback query message
msgText = msg.callbackQueryData;
Serial.print("\nCallback query message received: ");
Serial.println(msg.callbackQueryData);
callbackData = msg.callbackQueryData;
if (msgText.equalsIgnoreCase("sender")) {
myBot.sendMessage(msg, "SmartBox offers convenient, secure, and reliable package drop-off and pick-up with our digital locker. Our digital lockers simplify the shipping and receiving experience through the use of QR codes to ensure efficiency for customers with no-fail delivery.", Inline2);
myBot.endQuery(msg, "");
}
else if (msgText.equalsIgnoreCase("receiver")) {
myBot.sendMessage(msg, "This is receiver");
myBot.endQuery(msg, "");
}
else if (msgText.equalsIgnoreCase("book_now")) {
myBot.sendMessage(msg, "Please enter Receiver's Phone Number: ");
isBooking = true;
bookingID = msg.chatId;
myBot.endQuery(msg, "");
}
else if (callbackData.equalsIgnoreCase("package_Small") ||
callbackData.equalsIgnoreCase("package_Medium") ||
callbackData.equalsIgnoreCase("package_Large")) {
String sizeMessage;
if (callbackData.equalsIgnoreCase("package_Small")) {
sizeMessage = "You selected Small package size.";
} else if (callbackData.equalsIgnoreCase("package_Medium")) {
sizeMessage = "You selected Medium package size.";
} else if (callbackData.equalsIgnoreCase("package_Large")) {
sizeMessage = "You selected Large package size.";
}
myBot.sendMessage(msg, sizeMessage);
// End the query
myBot.endQuery(msg, "");
}
else if (msgText.equalsIgnoreCase(CLOSE_CALLBACK)) {
moveServo(0);
// Send a message acknowledging the action
myBot.sendMessage(msg, "Locker Closed");
// Terminate the callback
myBot.endQuery(msg, "Servo turn 0");
}
else if (msgText.equalsIgnoreCase(OPEN_CALLBACK)) {
moveServo(90); // Example: move to 90 degrees
// Send a message acknowledging the action
myBot.sendMessage(msg, "Locker Opened");
// Terminate the callback
myBot.endQuery(msg, "Servo turn 90");
}
break;
default:
break;
}
}
if (packageSizeSelected) {
// Calculate the price based on the selected package size
float price = calculatePrice(receiverPackageSize);
String confirmation = "<b>Please confirm the following details:</b>\n"
"Phone Number: <b>" + receiverPhoneNum + "</b>\n"
"Package Size: <b>" + receiverPackageSize + "</b>\n"
"Price: <b>$" + String(price, 2) + "</b>\n\n"
"Please click <b>Confirm</b> to confirm your package drop-off or <b>Cancel</b> to cancel the operation.";
myBot.sendMessage(msg, confirmation.c_str(), Inline4);
// Reset the flag to allow for processing the next package size selection
packageSizeSelected = false;
}
}