The goal is to be able to print a receipt with a QR Code when ordering a drink. From the qr code you go to a website to rate that specific drink. The receipt is necesary because i want the user to be able to rate the drink on their phone after consuming it, that way they can enjoy the drink and do not have to worry about a qr code on the screen that needs so stay open until then.
Parts:
- Thermal Printer: https://www.magicpos.shop/unsere-topseller/bondrucker-epson-tm-t88vi-usb-/-ethernet-schwarz-80/58mm-thermo-bon-kassendrucker-c31ce94112-m338a-ede8024c25be43a999623e24f694c281 Amazon
How to setup the bill printer
- Connect the printer to your network. It will print out its ip adress and network information.
- You can access admin interface by going to its ip adress. Default Username and Password are
epson
andepson
. - If you have a wireless adapter for your printer you can configure WIFI.
- Either setup your Router to assign a static IP-Adress to the printer or setup a static IP-Adress on the printer.
- For best practice update the firmware.
Python Code example
Generate QR Code
The code saves the qr code to the codes directory. If a qr code with that id already exists it skipps the generation step.
import qrcode
import os
output_dir = os.path.join(os.path.dirname(__file__), 'codes')
qr_filename = f'qrcode_{drink_id}.png'
qr_path = os.path.join(output_dir, qr_filename)
if not os.path.exists(qr_path):
qr_data = f"https://url.example?id={drink_id}"
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(qr_data)
qr.make(fit=True)
qr_image = qr.make_image(fill='black', back_color='white')
qr_image.save(qr_path)
Talk to Bill Printer
This code checks if the required port of the printer is reachable and prints a title, the QR-Code and cuts the paper afterwards.
from escpos.printer import Network
import socket
printer_ip = "your-printer-ip"
def is_printer_reachable(ip, port=9100, timeout=1):
"""Check if the printer is reachable by attempting a socket connection."""
try:
with socket.create_connection((ip, port), timeout):
return True
except (OSError, socket.timeout):
return False
if is_printer_reachable(printer_ip):
try:
p = Network(printer_ip)
# Center text
p.set(align='center')
p.text(f"My Title\n")
# Center QR Code 1
p.set(align='center')
p.image(qr_path)
# Cut the paper
p.cut()
except socket.error as e:
print(f"Error connecting to printer: {e}")
else:
print(f"Printer at {printer_ip} is not reachable. Please check the network connection.")
Conclusion
Next I´ll need to write a webapp where a user can rate a drink. I am thinking of going overkill: I only want legitimate ratings from users that actually ordered a drink but i want to do it without user authentication and it should also work with Shotland offline and not connected to the Internet. (The Ratings page should be avalible over the internet.) I am thinking about implementing a Public and Private Key system: I generate a Public and Private Keypair on Shotland. For every Rating QR-Code I generate a Key signed by the private Key of shotland which will be passed on as a path parameter. On the Webapp Rating site I will validate the authenticity of the key with the public key from Shotland. To ensure that a key does not get used twice I will put it on a blocklist (on the Webapp) once a Rating is submitted. What do you think about that approach? Is it overkill? Could I do it more overkill? Write your thoughts in the comments!
If you want to learn more about Shotland checkout the Shotland Overview Page.
[…] Shotland Drink Rating Module […]