Package: zinemachine
The Zine MachineThe Zine Machine is a little box that spits short passages of text out of a receipt printer.It uses a python running on a Raspberry Pi Zero W to receive input from GPIO buttons and drive the receipt printer over bluetooth. When printing a zine, it loads.zinefiles from the filesystem and sends the commands to the printer over a serial connection, using the modulepython-escposSetuppip install zinemachineSeeRaspberry Pi Setupfor full instructions on how to set up and configure your Raspberry Pi for the Zine Machine.Usagepython -m zinemachine [command]Valid commands:print FILE: Print a single zine fileserve -c CATEGORY PIN: Run persistently, and print random zine inCATEGORYwhen button on GPIO pinPINis pressed. Provide multiple-cflags to register additional buttons. Categories are directories containing.zinefiles under$PWD/zines/(e.g.-c diy 18binds all zines under$PWD/zines/diyto pin 18)validate [FILE]: Run the.zinefile validator on theFILEor directory. Defaults to$PWD/zines/Use-hto list help and additional commands.python -m zinemachine -h
python -m zinemachine print -h
python -m zinemachine serve -h
python -m zinemachine validate -hAdding zinesCreate azines/directory and add a subdirectory for each category of zine. Using theservecommand,.zineand.txtfiles in a category are randomly printed when the button bound to that category is pressed.Files and directories starting with a period.are ignored.You can copy thesample zinesdirectory from the Github repo as a starting point..zine filesA zine file is a text file (UTF-8) containing an optional metadata header followed by the text of a zine.The header encodes metadata using colon:separated key-value pairs.It must begin with a line consisting of five dashes-----.Each key-value pair must be on a single line ended by a newline character\n.The header should be terminated with a line of five dashes-----. The first non-empty line that does not contain a colon is also considered the end of the header.The rest of the file contains the text of the zine.-----
Title: My first zine
Author: Elliot Hatch
Description: A receipt printer will print this!
URL: https://github.com/elliothatch/zine-machine/blob/master/test-zines/.test/first-zine.zine
Date Published: 2023-08-19
-----
<h1>Hello</h1>
Welcome to my zine.
...Header keys are case insensitive and must not contain a colon. All whitespace is stripped from keys. Leading and trailing whitespace is stripped from values.The zine machine recognizes these fields. More fields may be provided but may not be used by the zine machine.TitleAuthorDescriptionPublisherDate Published- ISO format. Recommended format: YYYY-MM-DDURLMarkup.zinefiles support rich markup for enhanced features. Markup resembles a limited set of HTML tags. Some tags can be nested in other tags.<h1>Header</h1>- Header, printed in double sized text.<u>Underlined</u>- Underline<u2>Underlined 2</u2>- Underline style 2<b>Bolded</b>- Bold. Does not have an effect with default configuration because the Zine Machine bolds all text for improved readability. Auto-bold can be disabled with a command line argument.<invert>Inverted</invert>- Invert (black background, white text)<img src="image.png">Caption</img>- Insert an image with optional caption. src path is relative to the.zinefile. You can group images with a zine by placing them all together in a directory.ValidationRunning the Zine Machine with thevalidatecommand will check all zines in its index for header errors, invalid markup, and unprintable characters and images.The default validation settings for printable characters and max image width are based on manually determined values for the generic receipt printer we used (LMP201). If your printer supports more fonts or prints images at a different pixel width, you can configure these settings with the printer profile (currently requires Python module usage).You can provide the--resizeflag with an optional maximum pixel width (--resize 200, default 576) to automatically downscale images that are too large for the printer. The original image will be saved with an.origextension. If the Zine Machine will print an error if it tries to print an image that is too wide.Raspberry Pi SetupWiring the buttonsYou can run the Zine Machine to use any GPIO pins for the print category buttons. It configures the buttons in PULL_UP mode using the Pi's internal pull-up resistors.The standard configuration is to use 4 buttons, wired to to the ground and GPIO pins opposite the micro USB power connector. This allows you to crimp all the wires into a standard 2x3 rectangular connector, sharing a common ground.Pin numbers:Blue: 16Yellow: 20Green: 19Pink: 26Connector diagram (g=ground, G=Green, .=unused, etc.):| |g P G| . . .
| |. Y B| . . .
\------------ (edge of board)Flash Raspberry Pi OSUse the Raspberry Pi imager to flash Raspberry Pi OS to the SD card.
After you select the OS image, click the gear in the bottom right to set some advanced options that will make it easier to work with the Pi.Set hostname
zinemachine.localEnable SSH
Use password authentication
Set username and passwordConfigure wireless LAN
Enter your WiFi SSID and password, and select your country code.Set locale settings
Set to your keyboard layout, or certain keypresses may be interpreted differently than you expect.Start up Raspberry PiInsert the SD card into the Raspberry Pi and apply power. It will take awhile to boot up, so wait 2-5 minutes. Since you configured the WiFi network and SSH during the flashing step, you should be able to see the raspberry pi show up in your router's device table.Open a terminal and connect to the Raspberry Pi with the following command, replacingIP_ADDRwith the address of your Pi:ssh pi@IP_ADDRAlternatively, plug a keyboard, mouse, and monitor into your Raspberry Pi and configure it directly from there.Update Package Repossudo apt-get update
sudo apt-get upgradeBind Bluetooth on BootBefore we can connect to the printer, we need to bind RFCOMM to the printer's bluetooth device. then we can use the device/dev/rfcomm0to establish a connection.Open a text editor to create the systemd service filesudo nano /etc/systemd/system/receipt-bluetooth.serviceCopy and paste thereceipt-bluetooth.servicecontents into the file.Modify the MAC address to match MAC address of your receipt printer (replace 02:3B:A9:4C:F0:AE with the MAC address listed by the printer, usually found by printing a test sheet)Enable the service on boot.--nowstarts it immediatelysudo systemctl enable --now receipt-bluetooth.serviceThis service does NOT connect to the printer, it only configures the bluetooth connection. The actual connection is made when the device is used inzine-machine.pyPython SetupUpgrade the Python package manager, pippip install --upgrade pipInstall the zinemachine Python package.pip install zinemachineAdd zines and testYou will need to add some Zines to the Raspberry Pi before you can start printing them. As a starting point, download thesample zinesfrom the Github repository.If you are connected to the Pi via SSH, download these to your local computer, then copy them to the Pi by opening a new terminal and entering the command, replacingIP_ADDRwith the IP address you used to SSH into the Pi:rsync -avzh ./zines/ pi@IP_ADDR:/home/pi/zine-machine/zines/The first argument of the command,./zines/should be the sample zine directory you downloaded eariler. The trailing/is important.After the download is complete, you can test the Zine Machine. It looks for zines in thezines/directory under the current working directory, so firstcdinto the parent directory abovezines/.cd /home/pi/zine-machineIf you've wired the buttons according to the standardPin configuration, you can run the Zine Machine with the following command:python -m zinemachine serve -c theory pink -c ecology yellow -c diy green -c queer-stuff blueAfter a few seconds, the receipt printer should output "Ready to print!", and you can push a button to print a random zine.If you didn't use the standard wiring configuration, you can use pin numbers instead of color names. The following command is equivilent to the previous one:python -m zinemachine serve -c theory 26 -c ecology 20 -c diy 19 -c queer-stuff 16PressCTRL-Cto stop the Zine Machine.NOTE: The Zine machine also comes configured with two button combinations. Hold all 4 buttons for 5 seconds to shutdown the Pi, or hold just the pink, yellow, and green buttons for 5 seconds to stop the Zine Machine program without shutting down.These commands are hardcoded via GPIO pin number, and will not work if you use custom GPIO pin.Enable start on bootOpen a text editor to create the systemd service filesudo nano /etc/systemd/system/zine-machine.serviceCopy and paste thezine-machine.servicecontents into the file.Modify theExecStartline if you need to change the categories or buttonsModify theWorkingDirectoryline if you need to change where the zines will be loaded from. The path should be the directory containing thezines/folder.Enable to start on boot.sudo systemctl enable zine-machine.serviceYou can now start the Zine Machine as a background daemon withsudo systemctl start zine-machineCheck the status of the zine machine service withsudo systemctl status zine-machineand view operational logs withsudo journalctl -u zine-machineThe Zine Machine will now automatically start when the Raspberry Pi turns on! Make sure the receipt printer is turned on BEFORE you power up the Raspberry Pi. If it loses connection with the printer at any point, you can reset the Zine Machine program by holding the PINK, YELLOW, and GREEN buttons for 5 seconds (assuming standard wiring).Module UsageThe Zine Machine can also be used as a python module, withimport zinemachinefor further customization. Refer tomain.pyfor basic usage.Input ManagerThe input manager allows you to bind a function to a combination of pressed or held buttons.UseaddButtonto register a new button that can be used in button combinations.UseaddChordto create an input binding that will execute a function when the appropriate buttons are pressed.WhenholdTimeis 0 (default) it creates a "pressRelease" command, which fires when all buttons in the chord are pressed, then released.WhenholdTimeis greater than 0, a "pressHold" command is created, which fires when the buttons in the chord are pressed and held for the given time, in seconds. Whenever a button is pressed or released, the hold timer is reset back to zero, so the command is only triggered after the exact chord has been held forholdTime.InputManager is also initialized with awaitTime(default 0.25 seconds), which adds a grace period where a button is still considered held down after it is released. This wait time is ONLY considered for "pressRelease" commands, so that even if you do not release all the buttons of a chord at the exact same time, it is still considered a press-release of the entire chord, instead of just the last button released. The wait timer resets whenever any button is released--even if each button in the chord is released one at a time, they are all considered part of the "pressRelease" chord as long as the time between each release is less thanwaitTime.DevelopmentSetupclone this repogit clone https://github.com/elliothatch/zine-machine.git

cd zine-machineUpgrade pippip install --upgrade pipCreate virtual environment (optional)python -m venv .You must source the virtual environment before installing or running the project.source bin/activateinstall the package in editable mode (--userdoes nothing in venv)python -m pip install -e . --userrunpython -m zinemachinetestpython -m unittest