Skip to content

Instantly share code, notes, and snippets.

@OzTamir
Created December 5, 2021 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OzTamir/f7c103ff1b933d18a428d92df0e598f2 to your computer and use it in GitHub Desktop.
Save OzTamir/f7c103ff1b933d18a428d92df0e598f2 to your computer and use it in GitHub Desktop.
CuBus - Display the time until the bus gets to the stop
#!/usr/bin/python
# -*- coding:utf-8 -*-
import math
import logging
import time
import requests
from PIL import Image,ImageDraw,ImageFont
from waveshare_epd import epd2in13_V2
logging.basicConfig(level=logging.INFO)
STOP_ID = 'STOP_ID'
BUS_LINE_NAME = 'BUS_NAME'
API_ENDPOINT = 'http://<server_ip>/tts/{stop}/{bus}'.format(stop=STOP_ID, bus=BUS_LINE_NAME)
class PartialUpdateEPD(object):
def __init__(self, epd):
self.epd = epd
self.height = self.epd.height
self.width = self.epd.width
self.image = Image.new('1', (self.width, self.height), 255)
self.draw = ImageDraw.Draw(self.image)
self.epd.init(self.epd.FULL_UPDATE)
self.epd.displayPartBaseImage(self.epd.getbuffer(self.image))
epd.init(epd.PART_UPDATE)
def display(self, buffer):
self.epd.displayPartial(buffer)
def getbuffer(self, image):
return self.epd.getbuffer(image.rotate(180))
def fetch_next_bus():
logging.info("Fetching next bus...")
response = requests.get(API_ENDPOINT)
if response.status_code == 200:
return response.json()
else:
return None
def init_epd():
epd = epd2in13_V2.EPD()
logging.info("Initiating Screen...")
epd.init(epd.FULL_UPDATE)
epd.Clear(0xFF)
return PartialUpdateEPD(epd)
def display_tts(epd, tts_in_minutes):
font = ImageFont.truetype('Azeret.ttf', 120)
small_font = ImageFont.truetype('Alef.ttf', 15)
logging.info("Time to station: %d" % tts_in_minutes)
image = Image.new('1', (epd.height, epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(image)
if tts_in_minutes < 10:
draw.text((85, -20), u'%d' % tts_in_minutes, font = font, fill = 0)
else:
draw.text((50, -20), u'%d' % tts_in_minutes, font = font, fill = 0)
draw.text((25, 100), u'Minutes \'till the bus is here!', font = small_font, fill = 0)
epd.display(epd.getbuffer(image))
def display_no_buses(epd):
font = ImageFont.truetype('Alef.ttf', 50)
small_font = ImageFont.truetype('Alef.ttf', 15)
logging.info("Time to station: Unknown")
image = Image.new('1', (epd.height, epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(image)
draw.text((15, 0), u'No Buses\n soon', font = font, fill = 0)
epd.display(epd.getbuffer(image))
def display_now(epd):
font = ImageFont.truetype('Alef.ttf', 100)
small_font = ImageFont.truetype('Alef.ttf', 15)
logging.info("Time to station: NOW!")
image = Image.new('1', (epd.height, epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(image)
draw.text((0, -15), u'NOW', font = font, fill = 0)
draw.text((15, 100), u'Hopefully you\'ve left by now!', font = small_font, fill = 0)
epd.display(epd.getbuffer(image))
def display_error(epd):
font = ImageFont.truetype('Alef.ttf', 50)
logging.info("Time to station: Unknown")
image = Image.new('1', (epd.height, epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(image)
draw.text((15, 25), u'ERROR :(', font = font, fill = 0)
epd.display(epd.getbuffer(image))
def end_message(epd):
small_font = ImageFont.truetype('Alef.ttf', 17)
logging.info("Bye!")
image = Image.new('1', (epd.height, epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(image)
bmp = Image.open('bus.bmp')
image.paste(bmp, (75,0))
epd.display(epd.getbuffer(image))
draw.text((5, 100), u'CuBus - Watching Line %s' % BUS_LINE_NAME, font = small_font, fill = 0)
epd.display(epd.getbuffer(image))
def ms_to_minutes(ms):
return int(math.floor(ms / 60000))
def choose_nearest_bus(buses):
return min(buses, key=lambda bus: bus['tts'])
def update_screen(epd):
tts = fetch_next_bus()
if len(tts['results']) == 0:
display_no_buses(epd)
else:
nearest_bus = choose_nearest_bus(tts['results'])
tts_in_minutes = ms_to_minutes(nearest_bus['tts']) - 1
if tts_in_minutes > 1 and tts_in_minutes < 50:
display_tts(epd, tts_in_minutes)
else:
display_now(epd)
time.sleep(5)
def main():
logging.info('[STARTING] BusCube - Watching Line %s' % BUS_LINE_NAME)
epd = init_epd()
while True:
try:
update_screen(epd)
except KeyboardInterrupt:
end_message(epd)
break
except Exception as e:
logging.error(e)
display_error(epd)
time.sleep(60 * 10)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment