Shotland Drink Rating Module

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:

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 and epson.
  • 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.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
Scroll to Top