A low power device to display impactful messages daily. Upload a set of quotes to the device and see it change to display a new quote each day! Dynamically add new quotes by interfacing with a preloaded API
This project was written in python, using PIL for text display, waveshare epd libraries to interface with the screen and python flask with gunicorn to host the api, alowing remote easy upload of quotes to the device. This repository includes a bash script in order to setup the brunt of the scripts and file system scaffolding
The setup of this project is relatively easy and requires only a little technical knowledge (mainly for ssh and interfacing with the API), i have divided this instruction set into easy to digest sections
To assemble this device all you will need is:
- Raspberry pi Zero 2w
- GPIO Headers (Alternatively if you don't want to solder get a Pi zero 2w with these pre-installed)
- Micro usb power supply
- SD card (32GB is more than enough)
- Waveshare E ink display hat 2.13 in
- OPTIONAl Case (you can find some good cases that incorporate both the pi and the screen online, or 3D print your own)
To setup the PI OS:
- Download / Run Pi Imager.
- Select Raspberry Pi Model: Choose Raspberry Pi Zero 2 W.
- Select OS: Choose Raspbian 64 Bit Lite.
- Configure SSH Settings: Enable SSH and set your SSH key for accessing the Pi remotely.
- Etch the OS onto the SD Card: Write the OS to your SD card, then insert it into the Raspberry Pi and plug in the power.
- SSH into Raspberry Pi: Connect remotely. At this point, it may be beneficial to give the Pi a static IP address.
- Open Terminal and Run the Following Command:
sudo raspi-config
- Choose Interfacing Options.
- Select SPI.
- Choose Yes to enable the SPI interface.
- Reboot the pi using the following command:
sudo reboot
The OS does not come with git preinstalled so first run
sudo apt install gitThen clone:
git clone https://https://github.com/ioNclash/QuoteyOnce this is done, cd into the repository to continue with the next steps:
cd /path/to/quoteyThe startup script automatically runs a lot of privalleged commands, if you are worried about this, feel free to inspect the script before running. When you're happy run:
chmod +x setup.sh
sudo ./setup.shAfter this has been ran, you will have all the needed libraries and json files, the quote change script will be set to display at midnight and the API will be running
The API has 5 uses: / GET - Returns help on how to use the api /quote GET - Returns the daily quote as quote:{quotation:"str",source:"str",author:"str"} /quote POST - Adds a new quote, payload should have string fields quotation, source and author /quotes GET - Returns an array of quote objects /quotes POST - Replaces the contents of quote.json with the payload. payload should be in the format quotes: with an array of quote objects
You can integrate the API with any platform you see fit, or use curl or postman if you feel like avoiding the hastle Once you have populated the quotes json you can run
python3 quotey.pyTo display your first quote, or just wait till midnight for the cycle to start!
To use the API, i built a home assistant integration to show me the daily quote on my dashboard and add quotes through a series of input boxes

Configuration.yaml
# REST sensor to show current quote
sensor:
- platform: rest
name: Current Quote
unique_id: current_quote_sensor
resource: http://IP ADDR:5000/quote
method: GET
headers:
Content-Type: application/json
value_template: "{{ value_json.quote.quotation }}"
json_attributes_path: "$.quote"
json_attributes:
- quotation
- author
- source
scan_interval: 3600
# Input helpers for quote form
input_text:
quote_quotation:
name: Quote Text
max: 255
quote_author:
name: Quote Author
max: 100
quote_source:
name: Quote Source
max: 100
input_button:
submit_quote:
name: Submit Quote
icon: mdi:send
# REST command to post quote
rest_command:
add_quote:
url: "http://IP ADDR:5000/quote"
method: POST
headers:
Content-Type: application/json
payload: >
{
"quotation": "{{ quotation }}",
"author": "{{ author }}",
"source": "{{ source }}"
}Automation
alias: Submit Quote When Button Pressed
description: ""
trigger:
- platform: state
entity_id:
- input_button.submit_quote
condition: []
action:
- service: rest_command.add_quote
data:
quotation: "{{ states('input_text.quote_quotation') }}"
author: "{{ states('input_text.quote_author') }}"
source: "{{ states('input_text.quote_source') }}"
- service: input_text.set_value
target:
entity_id:
- input_text.quote_quotation
- input_text.quote_author
- input_text.quote_source
data:
value: ""
- service: homeassistant.update_entity
target:
entity_id: sensor.current_quote
mode: singleQuote of the day card
type: markdown
title: Quote of the Day
content: >
{{ state_attr('sensor.current_quote', 'quotation') }} — *{{
state_attr('sensor.current_quote', 'author') }}* ({{
state_attr('sensor.current_quote', 'source') }})
Add new Quote card
type: entities
title: Add New Quote
entities:
- entity: input_text.quote_quotation
name: Quotation
- entity: input_text.quote_author
name: Author
- entity: input_text.quote_source
name: Source
- type: button
name: Submit Quote
action_name: Submit
tap_action:
action: call-service
service: script.add_quote
data:
quotation: "{{ states('input_text.quote_quotation') }}"
author: "{{ states('input_text.quote_author') }}"
source: "{{ states('input_text.quote_source') }}"
icon: mdi:send
This project relies on a Waveshare EPD python module to interface with the E ink display