Created
December 5, 2021 13:22
-
-
Save OzTamir/f7c103ff1b933d18a428d92df0e598f2 to your computer and use it in GitHub Desktop.
CuBus - Display the time until the bus gets to the stop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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