Kutluhan Aktar
Published © CC BY

Telegram-Enabled Thermal Printer w/ Arduino Nano 33 IoT

Via Telegram, control thermal printers remotely to print out notes, shopping lists, URLs, payments, barcodes, and episode release dates.

ExpertFull instructions provided2 hours18,195
Telegram-Enabled Thermal Printer w/ Arduino Nano 33 IoT

Things used in this project

Hardware components

Arduino Nano 33 IoT
Arduino Nano 33 IoT
×1
DFRobot Tiny (Embedded) Thermal Printer - TTL Serial
×1
SparkFun MB102 Power Supply Module
×1
12V External Battery
×1
Mini Breadboard
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

Arduino IDE
Arduino IDE
Telegram Bot API
Visual Studio 2017
Microsoft Visual Studio 2017

Hand tools and fabrication machines

Hot glue gun (generic)
Hot glue gun (generic)

Story

Read more

Custom parts and enclosures

Telegram_Thermal_Printer_Bot.zip

note.h

list.h

url.h

payment.h

product.h

series.h

home.h

images.zip

Schematics

connections

Code

Telegram-Enabled-Thermal-Printer.ino

Arduino
         /////////////////////////////////////////////  
        //     Telegram-Enabled Thermal Printer    //
       //             w/ Nano 33 IoT              //
      //             ---------------             //
     //          (Arduino Nano 33 IoT)          //           
    //             by Kutluhan Aktar           // 
   //                                         //
  /////////////////////////////////////////////

//
// Via Telegram, control thermal printers to print notes, shopping lists, URLs, payments, product barcodes, and episode release dates.
//
// For more information:
// https://www.theamplituhedron.com/projects/Telegram-enabled-Thermal-Printer-with-Arduino-Nano-33-IoT
//
//
// Connections
// Arduino Nano 33 IoT :           
//                                Tiny (Embedded) Thermal Printer
// TX  --------------------------- RX
// RX  --------------------------- TX
// GND --------------------------- GND


// Include the required libraries.
#include <SPI.h>
#include <WiFiNINA.h>
#include "Adafruit_Thermal.h"


char ssid[] = "[_SSID_]";        // your network SSID (name)
char pass[] = "[_PASSWORD_]";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;                // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;

// Change the server before running the code.
char server[] = "www.theamplituhedron.com";

// Define the pathway of the results page of the Telegram webhook.
String application = "/Telegram_Thermal_Printer_Bot/results.php";

// Initialize the Ethernet client library.
WiFiSSLClient client;

// Hardware Serial
Adafruit_Thermal printer(&Serial1);     // Pass addr to printer constructor

// Include icons and pictures to be printed.
#include "note.h"
#include "list.h"
#include "url.h"
#include "payment.h"
#include "product.h"
#include "series.h"
#include "home.h"

void setup() {
  // NOTE: SOME PRINTERS NEED 19200 BAUD instead of 9600, check test page.
  Serial1.begin(9600);  // Initialize hardware serial
  printer.begin();      // Init printer (same regardless of serial type)

  // Check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) { Serial.println("Communication with WiFi module failed!"); while (true); }
  // Attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    // Wait 10 seconds for connection:
    delay(10000);
  }

  // Verify connection on the serial monitor.
  Serial.println("Connected to WiFi!");
  delay(1000);

  // Print the home page showing available commands and functions:
  // print_home("theamplituhedron.com");
}

void loop() {
  // Connect to the Telegram webhook's results page on TheAmplituhedron.
  if (client.connect(server, 443)){
    Serial.println("Connected to the results page!"); // If get a connection, report back via serial:
    // Make an HTTP request:
    client.println("GET " + application + " HTTP/1.1");
    client.println("Host: www.theamplituhedron.com");
    client.println("Connection: close");
    client.println();
  }else{
    Serial.println("Connection Error!");
  }

  delay(2000); // Wait 2 seconds after connection...
  
  // If there are incoming bytes available, get the response from the Telegram webhook's results page.
  String response = "";
  while (client.available()) { char c = client.read(); response += c; }
  if(response != "" && response.indexOf("%") > 0){
    // Split the response string by a pre-defined delimiter in a simple way. '%'(percentage) is defined as the delimiter in this project.
    int delimiter, delimiter_1, delimiter_2;
    delimiter = response.indexOf("%");
    delimiter_1 = response.indexOf("%", delimiter + 1);
    delimiter_2 = response.indexOf("%", delimiter_1 +1);
    // Glean information as substrings.
    String command = response.substring(delimiter + 1, delimiter_1);
    String content = response.substring(delimiter_1 + 1, delimiter_2);
    // Print the requested command with the given content:
    if(command == "_note") print_notes(content);
    if(command == "shopping") print_shopping_list(content);
    if(command == "url") print_URL(content);
    if(command == "payment") print_payments(content);
    if(command == "barcode"){ char converted[sizeof(content)]; content.toCharArray(converted, sizeof(converted)); print_product_barcode(converted); }
    if(command == "series") print_series(content);
    if(command == "home") print_home(content);
  }
  delay(3000); // Wait 3 seconds before connection...
}

void print_notes(String text){
  printer.printBitmap(80, 80, note_logo);
  printer.boldOn();
  printer.justify('R');
  printer.setSize('L');
  printer.println(F("Note\n"));
  printer.boldOff();
  printer.justify('L');
  printer.setSize('M');
  printer.println(text);
  printer.feed(5);
  printer.setDefault(); // Restore printer to defaults
}

void print_shopping_list(String text){
  printer.printBitmap(80, 80, list_logo);
  printer.boldOn();
  printer.justify('R');
  printer.setSize('L');
  printer.println(F("Shopping"));
  printer.println(F("List\n"));
  printer.boldOff();
  printer.justify('L');
  printer.setSize('S');
  printer.setLineHeight(50);
  printer.println(text);
  printer.setLineHeight();
  printer.feed(5);
  printer.setDefault(); // Restore printer to defaults
}

void print_URL(String text){
  printer.printBitmap(80, 80, url_logo);
  printer.boldOn();
  printer.justify('R');
  printer.setSize('L');
  printer.println(F("URL\n"));
  printer.boldOff();
  printer.justify('L');
  printer.setSize('S');
  printer.println(text);
  printer.feed(5);
  printer.setDefault(); // Restore printer to defaults
}

void print_payments(String text){
  printer.printBitmap(80, 80, payment_logo);
  printer.boldOn();
  printer.justify('R');
  printer.setSize('L');
  printer.println(F("Payment\n"));
  printer.boldOff();
  printer.justify('L');
  printer.setSize('M');
  printer.println(text);
  printer.feed(5);
  printer.setDefault(); // Restore printer to defaults
}

void print_product_barcode(const char *text){
  printer.printBitmap(80, 80, product_logo);
  printer.boldOn();
  printer.justify('R');
  printer.setSize('L');
  printer.println(F("Product\n"));
  printer.boldOff();
  printer.justify('L');
  // CODE 93: compressed version of CODE 39:
  printer.setBarcodeHeight(30);
  printer.printBarcode(text, CODE93);
  printer.feed(5);
  printer.setDefault(); // Restore printer to defaults
}

void print_series(String text){
  printer.printBitmap(80, 80, series_logo);
  printer.boldOn();
  printer.justify('R');
  printer.setSize('L');
  printer.println(F("New"));
  printer.println(F("Episode\n"));
  printer.boldOff();
  printer.justify('L');
  printer.setSize('M');
  printer.println(text);
  printer.feed(5);
  printer.setDefault(); // Restore printer to defaults
}

void print_home(String _server){
  printer.printBitmap(80, 80, home_logo);
  printer.printBitmap(80, 80, home_logo);
  printer.printBitmap(80, 80, home_logo);
  printer.boldOn();
  printer.justify('C');
  printer.setSize('L');
  printer.println(F("Telegram"));
  printer.println(F("Enabled"));
  printer.println(F("Thermal"));
  printer.println(F("Printer\n"));
  printer.justify('L');
  printer.setSize('M');
  printer.println(F("Available"));
  printer.println(F("Printer"));
  printer.println(F("Commands:\n"));
  printer.boldOff();
  printer.setSize('S');
  printer.setLineHeight(50);
  printer.println(F("1) Notes\n"));
  printer.printBitmap(80, 80, note_logo);
  printer.println(F("2) Shopping List\n"));
  printer.printBitmap(80, 80, list_logo);
  printer.println(F("3) URL\n"));
  printer.printBitmap(80, 80, url_logo);
  printer.println(F("4) Payments\n"));
  printer.printBitmap(80, 80, payment_logo);
  printer.println(F("5) Product Barcode\n"));
  printer.printBitmap(80, 80, product_logo);
  printer.println(F("6) Series\n"));
  printer.printBitmap(80, 80, series_logo);
  printer.println(F("7) Home\n"));
  printer.printBitmap(80, 80, home_logo);
  printer.justify('C');
  printer.println(F("Running On:"));
  printer.println(_server);
  printer.setSize('L');
  printer.inverseOn();
  printer.println(F("&&&&&"));
  printer.inverseOff();
  printer.feed(5);
  printer.setDefault(); // Restore printer to defaults
}

index.php (webhook)

PHP
<?php

// Define the themal_printer class and functions:
class thermal_printer {
	public $token, $web_path, $conn, $table;
	
	public function __init__($token, $web_path, $conn, $table){
		$this->token = $token;
		$this->web_path = $web_path.$token;
		$this->conn = $conn;
		$this->table = $table;
	}
	
	public function send_message($id, $string){
		$new_message = $this->web_path."/sendMessage?chat_id=".$id."&text=".urlencode($string);
		file_get_contents($new_message);
	}
	
	public function send_photo($id, $photo, $caption){
	    $new_photo = $this->web_path."/sendPhoto?chat_id=".$id."&photo=".$photo."&caption=".$caption;
	    file_get_contents($new_photo);
	}
	
	public function database_update($command, $content){
		$sql = "UPDATE `$this->table` SET `command`='$command', `content`='$content', `status`='ready' LIMIT 1";
		mysqli_query($this->conn, $sql);
	}
}

// Define database and server settings:
$server = "localhost";
$username = "<username>";
$password = "<password>";
$database_name = "telegramprinter";
$table_name = "entries";

$conn = mysqli_connect($server, $username, $password, $database_name);

$printer = new thermal_printer();
$printer->__init__("123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11", "https://api.telegram.org/bot", $conn, $table_name);

// Get updates from the Telegram Bot API.
$updates = json_decode(file_get_contents('php://input'), TRUE); 

// Get commands.
if($updates['update_id']){
	$chat_id =   $updates['message']['chat']['id'];
	$message = $updates['message']['text'];
    
	if($updates["message"]["photo"]){
		$printer->send_message($chat_id, "Thank you for sending me a photo but I cannot process it yet ");
	}else if($updates["message"]["video"]){
		$printer->send_message($chat_id, "Thank you for sending me a video but I cannot process it yet  ");
	}else if($updates["message"]["document"]){
		$printer->send_message($chat_id, "Thank you for sending me a file but I cannot process it yet  ");
	}else{
		if(strpos($message, "/print_notes") !== FALSE){
			$command = "_note";
			$content = explode(" ", $message, 2)[1];
			$printer->database_update($command, $content);
			$printer->send_message($chat_id, "Printed: ".$content);
		}
		if(strpos($message, "/print_shopping_list") !== FALSE){
			$command = "shopping";
			$content = explode(" ", $message, 2)[1];
			$printer->database_update($command, $content);
			$printer->send_message($chat_id, "Printed: ".$content);
		}
		if(strpos($message, "/print_url") !== FALSE){
			$command = "url";
			$content = explode(" ", $message, 2)[1];
			$printer->database_update($command, $content);
			$printer->send_message($chat_id, "Printed: ".$content);
		}
		if(strpos($message, "/print_payments") !== FALSE){
			$command = "payment";
			$content = explode(" ", $message, 2)[1];
			$printer->database_update($command, $content);
			$printer->send_message($chat_id, "Printed: ".$content);
		}
		if(strpos($message, "/print_product_barcode") !== FALSE){
			$command = "barcode";
			$content = explode(" ", $message, 2)[1];
			$printer->database_update($command, $content);
			$printer->send_message($chat_id, "Printed: ".$content);
		}
		if(strpos($message, "/print_series") !== FALSE){
			$command = "series";
			$content = explode(" ", $message, 2)[1];
			$printer->database_update($command, $content);
			$printer->send_message($chat_id, "Printed: ".$content);
		}
		
		switch($message){
		  case '/print_home':
		  $printer->database_update("home", "theamplituhedron.com");
		  $printer->send_message($chat_id, "Printed: OK");
		  break;	
		  case '/start':
		  $printer->send_message($chat_id, "Leave a blank space before entering the text you want to print with thermal printers for these commands:\n\n/print_notes text\n/print_shopping_list item1, item2...\n/print_url text\n/print_payments text\n/print_product_barcode text\n/print_series text\n\nEnter /help to view descriptions.");
		  break;			
		  case 'How r u?':
		  $printer->send_message($chat_id, "Thanks for asking.\nData processing is running just fine ");
		  break;
		  case '/cover':
		  $printer->send_photo($chat_id, "https://www.theamplituhedron.com/Telegram_Thermal_Printer_Bot/spiderman.jpg", 'Friendly Neighborhood Spider-Man');
	      break;
		  case '/arduino':
		  $printer->send_photo($chat_id, "https://www.theamplituhedron.com/Telegram_Thermal_Printer_Bot/arduino.jpg", 'Arduino Nano 33 IoT Schematics');
	      break;
		  case '/help':
		  $printer->send_message($chat_id, "Leave a blank space before entering the text you want to print with thermal printers for these commands:\n\n/print_notes text\n/print_shopping_list item1, item2...\n/print_url text\n/print_payments text\n/print_product_barcode text\n/print_series text\n\nDescriptions:\n\n/print_home - print all available functions\n/print_notes - send and print a note\n/print_shopping_list - create and print a shopping list\n/print_url - send and print URLs\n/print_payments - define and print payments\n/print_product_barcode - define and print product barcodes\n/print_series - enter and print a new episode date\n/cover - display the given cover picture\n/arduino - display Nano 33 IoT schematics\n/help - functions and instructions");
		  break;	  
	    }
	}
}

?>

results.php

PHP
<?php

// Define database and server settings:
$server = "localhost";
$username = "<username>";
$password = "<password>";
$database_name = "telegramprinter";
$table_name = "entries";

$conn = mysqli_connect($server, $username, $password, $database_name);

$sql = "SELECT * FROM `$table_name` LIMIT 1";
$result = mysqli_query($conn, $sql);
$check = mysqli_num_rows($result);
if($check < 1){
	echo 'No entry found!';
}else{
	if($row = mysqli_fetch_assoc($result)){
		if($row['status'] == "ready"){
			echo "%".$row['command']."%".$row['content']."%";
			$sql_update = "UPDATE `$table_name` SET `status`='printed' LIMIT 1";
			mysqli_query($conn, $sql_update);
		}else if($row['status'] == "printed"){
			echo "Already Printed! Waiting new commands...";
		}
	}
}

?>

Credits

Kutluhan Aktar

Kutluhan Aktar

81 projects • 306 followers
AI & Full-Stack Developer | @EdgeImpulse | @Particle | Maker | Independent Researcher

Comments