Skip to content


Repository files navigation

GitHub Actions Test Status Total lgtm alerts Language grade: Python Language grade: Javascript

Prepaid Mate

Tired of fishing cash out of your pockets? Regardless of whether you pronounce it [ˈpriːpɛɪ̯t ˈmaːtə] or [ˈpriːpɛɪ̯t meɪt], paying for drinks was never easier!

Put a fistful of dollars in the piggy bank and add the amount using any computer or smartphone to your account. Thirsty? Start scanning! Identify yourself with your personal RFID token (or barcode) and scan the barcode on the drink. Cheers!

Table of contents

Design Principles

  • either the environment Prepaid Mate is running in is trusted or you need transport layer encryption (e.g. SSL)
  • passwords are hashed, but not encrypted during transport (replay attacks are possible without SSL)
  • no sessions, if you press refresh/back/forward in your browser, you won't be logged in anymore

Required Hardware

  • some (embedded) computer running the software
  • USB HID barcode scanner
  • optional: USB HID RFID scanner
  • optional: speakers for audio feedback

Software Components

  • flask server application providing a simple sqlite-backed API for
    • creating/modifying/viewing accounts
    • adding/view money (transactions)
    • performing payments
  • scanner client listening to barcode/RFID events and triggering payments
  • simple, static web frontend (currently in development, at the moment German only)

Installation and configuration

Assuming you're running Debian (or Ubuntu) and want to use a virtualenv:

$ apt-get install python3 python3-virtualenv python3-pip virtualenv espeak

Create the virtualenv and activate it:

$ virtualenv -p python3 prepaid-mate-venv
$ source prepaid-mate-venv/bin/activate

Now install the Python dependencies via pip inside the virtualenv:

(prepaid-mate-venv) $ pip install -r requirements.txt

In order to install Prepaid Mate in editable (development) mode use:

(prepaid-mate-venv) $ pip install -e .

Create a config file named config. Use config.sample as a starting point.

Run it

Now start the development server:

(prepaid-mate-venv) $ flask run

Or start the development server in debug mode:

(prepaid-mate-venv) $ FLASK_DEBUG=1 flask run

Now head your browser to http://localhost:5000/static/index.html to start. Do not use the development server in a production environment. See below how to deploy Prepaid Mate.

In order to start the client:

(prepaid-mate-venv) $ scanner-client

Test it

Assuming you performed the steps above:

$ apt-get install umockdev

Activate your virtualenv one more time:

$ source prepaid-mate-venv/bin/activate

Now install the testing dependencies via pip inside the virtualenv:

(prepaid-mate-venv) $ pip install -r test-requirements.txt

Now run the test suite:

(prepaid-mate-venv) $ pytest -v

Deploy it

There is no need to clone Prepaid Mate manually. All of the above steps are not necessary for deployment.

Assuming you're running Debian (or Ubuntu) and want to use a virtualenv:

$ apt-get install python3 python3-virtualenv python3-pip virtualenv nginx espeak git

Now switch to the user that should run Prepaid Mate and create a directory for the venv and configs:

$ adduser prepaid-mate input # allow access to HID devices
$ adduser prepaid-mate audio # allow access to audio devices
$ su someuser
$ mkdir -p /your/desired/location/
$ cd /your/desired/location/

Create the virtualenv prod-venv (or name it as you like) and activate it:

$ virtualenv -p python3 prod-venv
$ source prod-venv/bin/activate

Now install gunicorn (WSGI server) and Prepaid Mate:

(prod-venv) $ pip install gunicorn
(prod-venv) $ pip install -e git+

Configurations for udev, gunicorn and nginx are located in prod-venv/src/prepaid-mate/deploy/. Adjust path, user and group as needed and copy these files to their corresponding location in your target filesystem.

Create a config file named config. Use prod-venv/src/prepaid-mate/config.sample as a starting point. You should turn the debug option off.

Now enable the nginx site, enable the gunicorn service and (re)start the services:

$ ln -s /etc/nginx/sites-available/prepaid_mate /etc/nginx/sites-enabled/prepaid_mate
$ systemctl enable gunicorn.service
$ systemctl enable scanner-client.service
$ systemctl restart nginx.service gunicorn.service scanner-client.service

Prepaid Mate should now respond at http://localhost/ and you can start scanning.

Update it

Switch to the user that runs Prepaid Mate and change into the directory created above:

$ su someuser
$ cd /your/installed/location/

Activate the virtualenv created above:

$ source prod-venv/bin/activate

Now update Prepaid Mate:

(prod-venv) $ pip install -e git+

Now restart the services:

$ systemctl restart scanner-client.service gunicorn.service

Prepaid Mate should now respond at http://localhost/ and you can start scanning.


I accidentally added a wrong amount of money to my account. How can I fix it?

Prepaid Mate works like a bank. Perform another transaction to cancel it out. You can add negative amounts of money (while your balance cannot become negative).

I forgot my password. How can I reset it?

Find the physical device the service is running on, you'll find the login credentials on it. Log in via SSH and run the reset password script with your username as argument:

$ prepaid-mate-reset-pw someuser

You will be asked to type a new password.

There is a new drink in the fridge. How can I add it to the database?

Log in via SSH, scan the drink's barcode and run the new drink script within 60 seconds:

$ prepaid-mate-new-drink

You will be asked if the preset barcode is correct. Then set name, price and volume. Please make sure the input data is correct. If you mess up, stop all Prepaid Mate services, make a database backup and edit the SQLite database manually (hint: sqlitebrowser). Now start the services again.

How can I add a custom sound as greeting?

Copy a 48 kHz 16 bit LE mono wav (<=480 KiB) named <RFID code>.wav into the prepaid-mate root directory, next to config and db.sqlite. Look up your RFID/barcode in the webinterface (log in -> click on your username -> modify account). If the file meets the requirements it will be played instead of the usual espeak "hi <user>". Make sure you have a unique recognizable sound bite.