This commit is contained in:
parent
cf44c61759
commit
82b3e3a0e6
6 changed files with 31 additions and 27 deletions
|
@ -5,13 +5,12 @@ from bottle_log import LoggingPlugin
|
||||||
from bottle_websocket import websocket, GeventWebSocketServer
|
from bottle_websocket import websocket, GeventWebSocketServer
|
||||||
from geventwebsocket.websocket import WebSocket
|
from geventwebsocket.websocket import WebSocket
|
||||||
|
|
||||||
|
from buba.animations.dbf import DBFAnimation
|
||||||
from buba.animations.icalevents import IcalEvents
|
from buba.animations.icalevents import IcalEvents
|
||||||
|
from buba.animations.time import BubaTime
|
||||||
from buba.appconfig import AppConfig
|
from buba.appconfig import AppConfig
|
||||||
from buba.bubaanimator import BubaAnimator
|
from buba.bubaanimator import BubaAnimator
|
||||||
from buba.animations.time import BubaTime
|
|
||||||
from buba.bubacmd import BubaCmd
|
from buba.bubacmd import BubaCmd
|
||||||
|
|
||||||
from buba.animations.dbf import DBFAnimation
|
|
||||||
from buba.websocketcomm import WebSocketClients
|
from buba.websocketcomm import WebSocketClients
|
||||||
|
|
||||||
config = AppConfig()
|
config = AppConfig()
|
||||||
|
@ -25,7 +24,6 @@ if config.debug:
|
||||||
app.install(LoggingPlugin(app.config))
|
app.install(LoggingPlugin(app.config))
|
||||||
TEMPLATE_PATH.insert(0, config.templatepath)
|
TEMPLATE_PATH.insert(0, config.templatepath)
|
||||||
|
|
||||||
|
|
||||||
websocket_clients = WebSocketClients()
|
websocket_clients = WebSocketClients()
|
||||||
buba = BubaCmd(config.serial, websocket_clients.send)
|
buba = BubaCmd(config.serial, websocket_clients.send)
|
||||||
animator = BubaAnimator(buba)
|
animator = BubaAnimator(buba)
|
||||||
|
@ -33,7 +31,9 @@ animator = BubaAnimator(buba)
|
||||||
animator.add(BubaTime)
|
animator.add(BubaTime)
|
||||||
animator.add(DBFAnimation, ds100="AHST", station="Holstenstraße")
|
animator.add(DBFAnimation, ds100="AHST", station="Holstenstraße")
|
||||||
animator.add(DBFAnimation, ds100="AHS", station="Altona", count=9)
|
animator.add(DBFAnimation, ds100="AHS", station="Altona", count=9)
|
||||||
animator.add(IcalEvents, url="https://cloud.hamburg.ccc.de/remote.php/dav/public-calendars/QJAdExziSnNJEz5g?export", title="CCCHH Events")
|
animator.add(IcalEvents, url="https://cloud.hamburg.ccc.de/remote.php/dav/public-calendars/QJAdExziSnNJEz5g?export",
|
||||||
|
title="CCCHH Events")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/static/<filepath>")
|
@app.route("/static/<filepath>")
|
||||||
def server_static(filepath):
|
def server_static(filepath):
|
||||||
|
@ -45,6 +45,7 @@ def server_static(filepath):
|
||||||
def root():
|
def root():
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
@app.get('/ws', apply=[websocket])
|
@app.get('/ws', apply=[websocket])
|
||||||
def websocket_endpoint(ws: WebSocket):
|
def websocket_endpoint(ws: WebSocket):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -37,7 +37,7 @@ class DBFAnimation(BubaAnimation):
|
||||||
sleep(60)
|
sleep(60)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def countdown(dt:datetime):
|
def countdown(dt: datetime):
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
try:
|
try:
|
||||||
dep_time = datetime.datetime.strptime(dt, "%H:%M").time()
|
dep_time = datetime.datetime.strptime(dt, "%H:%M").time()
|
||||||
|
@ -64,8 +64,9 @@ class DBFAnimation(BubaAnimation):
|
||||||
|
|
||||||
# Recalculate the timedelta
|
# Recalculate the timedelta
|
||||||
return BubaAnimation.countdown(datetime.datetime.combine(dep_date, dep_time))
|
return BubaAnimation.countdown(datetime.datetime.combine(dep_date, dep_time))
|
||||||
# dep_td = datetime.datetime.combine(dep_date, dep_time) - now
|
|
||||||
# return round(dep_td.total_seconds() / 60)
|
# dep_td = datetime.datetime.combine(dep_date, dep_time) - now
|
||||||
|
# return round(dep_td.total_seconds() / 60)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def short_station(station: str) -> str:
|
def short_station(station: str) -> str:
|
||||||
|
@ -78,6 +79,8 @@ class DBFAnimation(BubaAnimation):
|
||||||
station = station[:-8]
|
station = station[:-8]
|
||||||
if station == "Hbf":
|
if station == "Hbf":
|
||||||
station = "Hauptbahnhof"
|
station = "Hauptbahnhof"
|
||||||
|
if station == "Wedel(Holst)":
|
||||||
|
station = "Wedel"
|
||||||
return station
|
return station
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -101,7 +104,7 @@ class DBFAnimation(BubaAnimation):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
all = self.trains[:self.count]
|
all = self.trains[:self.count]
|
||||||
all_len = int((len(all)+1)/3)
|
all_len = int((len(all) + 1) / 3)
|
||||||
|
|
||||||
if len(self.trains) == 0:
|
if len(self.trains) == 0:
|
||||||
sleep(5)
|
sleep(5)
|
||||||
|
@ -110,7 +113,7 @@ class DBFAnimation(BubaAnimation):
|
||||||
if all_len == 1:
|
if all_len == 1:
|
||||||
title = self.station
|
title = self.station
|
||||||
else:
|
else:
|
||||||
title = f"{self.station} ({page+1}/{all_len})"
|
title = f"{self.station} ({page + 1}/{all_len})"
|
||||||
self.buba.text(page=0, row=0, col_start=0, col_end=92, text=title, align=BubaCmd.ALIGN_LEFT)
|
self.buba.text(page=0, row=0, col_start=0, col_end=92, text=title, align=BubaCmd.ALIGN_LEFT)
|
||||||
for i, train in enumerate(trains):
|
for i, train in enumerate(trains):
|
||||||
if train['isCancelled']:
|
if train['isCancelled']:
|
||||||
|
@ -118,10 +121,12 @@ class DBFAnimation(BubaAnimation):
|
||||||
else:
|
else:
|
||||||
when = self.countdown(train['actualDeparture'])
|
when = self.countdown(train['actualDeparture'])
|
||||||
self.buba.text(page=0, row=i + 1, col_start=0, col_end=11, text=self.short_train(train['train']))
|
self.buba.text(page=0, row=i + 1, col_start=0, col_end=11, text=self.short_train(train['train']))
|
||||||
self.buba.text(page=0, row=i + 1, col_start=12, col_end=104, text=self.short_station(train['destination']))
|
self.buba.text(page=0, row=i + 1, col_start=12, col_end=104,
|
||||||
|
text=self.short_station(train['destination']))
|
||||||
self.buba.text(page=0, row=i + 1, col_start=105, col_end=119,
|
self.buba.text(page=0, row=i + 1, col_start=105, col_end=119,
|
||||||
text=when, align=BubaCmd.ALIGN_RIGHT)
|
text=when, align=BubaCmd.ALIGN_RIGHT)
|
||||||
self.buba.set_page(0)
|
self.buba.set_page(0)
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
self.buba.text(page=0, row=0, col_start=93, col_end=119, text=datetime.datetime.now().strftime("%H:%M"), align=BubaCmd.ALIGN_RIGHT)
|
self.buba.text(page=0, row=0, col_start=93, col_end=119, text=datetime.datetime.now().strftime("%H:%M"),
|
||||||
|
align=BubaCmd.ALIGN_RIGHT)
|
||||||
sleep(2)
|
sleep(2)
|
||||||
|
|
|
@ -23,7 +23,7 @@ class IcalEvents(BubaAnimation):
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
tz = timezone(os.getenv("TZ", "Europe/Berlin"))
|
tz = timezone(os.getenv("TZ", "Europe/Berlin"))
|
||||||
events = icalevents.icalevents.events(self.url, tzinfo=tz, sort=True, end=datetime.now(tz)+timedelta(days=14))
|
events = icalevents.icalevents.events(self.url, tzinfo=tz, sort=True, end=datetime.now(tz) + timedelta(days=14))
|
||||||
for event in events:
|
for event in events:
|
||||||
event.start = event.start.astimezone(tz)
|
event.start = event.start.astimezone(tz)
|
||||||
self.events = events
|
self.events = events
|
||||||
|
@ -33,7 +33,8 @@ class IcalEvents(BubaAnimation):
|
||||||
for (page, events) in enumerate(self.chunk(self.events, 3)):
|
for (page, events) in enumerate(self.chunk(self.events, 3)):
|
||||||
if len(self.events) > 3:
|
if len(self.events) > 3:
|
||||||
self.buba.text(page=0, row=0, col_start=0, col_end=119,
|
self.buba.text(page=0, row=0, col_start=0, col_end=119,
|
||||||
text=f"{self.title} ({page + 1}/{int((len(self.events)+2) / 3)})", align=BubaCmd.ALIGN_LEFT)
|
text=f"{self.title} ({page + 1}/{int((len(self.events) + 2) / 3)})",
|
||||||
|
align=BubaCmd.ALIGN_LEFT)
|
||||||
else:
|
else:
|
||||||
self.buba.text(page=0, row=0, col_start=0, col_end=119, text=self.title, align=BubaCmd.ALIGN_LEFT)
|
self.buba.text(page=0, row=0, col_start=0, col_end=119, text=self.title, align=BubaCmd.ALIGN_LEFT)
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
|
|
|
@ -17,5 +17,6 @@ class BubaTime(BubaAnimation):
|
||||||
self.buba.set_page(0)
|
self.buba.set_page(0)
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
self.buba.text(page=0, row=0, col_start=93, col_end=119, text=datetime.now().strftime("%H:%M"), align=BubaCmd.ALIGN_RIGHT)
|
self.buba.text(page=0, row=0, col_start=93, col_end=119, text=datetime.now().strftime("%H:%M"),
|
||||||
|
align=BubaCmd.ALIGN_RIGHT)
|
||||||
sleep(2)
|
sleep(2)
|
||||||
|
|
|
@ -31,7 +31,7 @@ class BubaAnimation:
|
||||||
return iter(lambda: tuple(islice(it, size)), ())
|
return iter(lambda: tuple(islice(it, size)), ())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def countdown(dt:datetime):
|
def countdown(dt: datetime):
|
||||||
"""
|
"""
|
||||||
Compute a human-readable time specification until the target event starts. The day starts at 04:00.
|
Compute a human-readable time specification until the target event starts. The day starts at 04:00.
|
||||||
:param dt: datetime timezone-aware datetime
|
:param dt: datetime timezone-aware datetime
|
||||||
|
@ -44,14 +44,13 @@ class BubaAnimation:
|
||||||
if now_delta < timedelta(seconds=0):
|
if now_delta < timedelta(seconds=0):
|
||||||
return "now"
|
return "now"
|
||||||
if now_delta < timedelta(minutes=30):
|
if now_delta < timedelta(minutes=30):
|
||||||
return f"{int(now_delta.seconds/60)}m"
|
return f"{int(now_delta.seconds / 60)}m"
|
||||||
if day_delta < timedelta(hours=24):
|
if day_delta < timedelta(hours=24):
|
||||||
return f"{int((now_delta.seconds+3599)/3600)}h"
|
return f"{int((now_delta.seconds + 3599) / 3600)}h"
|
||||||
if day_delta < timedelta(days=7):
|
if day_delta < timedelta(days=7):
|
||||||
return dt.strftime("%a") # weekday
|
return dt.strftime("%a") # weekday
|
||||||
return dt.strftime("%d.%m.")
|
return dt.strftime("%d.%m.")
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ellipsis(text, max=28):
|
def ellipsis(text, max=28):
|
||||||
"""
|
"""
|
||||||
|
@ -61,7 +60,7 @@ class BubaAnimation:
|
||||||
:return: shortened text
|
:return: shortened text
|
||||||
"""
|
"""
|
||||||
if len(text) > max:
|
if len(text) > max:
|
||||||
text = text[:max - 2] + "..." # we can get away with just 2, since the periods are very narrow
|
text = text[:max - 2] + "..." # we can get away with just 2, since the periods are very narrow
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ class BubaCmd:
|
||||||
ALIGN_LEFT = 0x00
|
ALIGN_LEFT = 0x00
|
||||||
ALIGN_RIGHT = 0x01
|
ALIGN_RIGHT = 0x01
|
||||||
ALIGN_CENTER = 0x02
|
ALIGN_CENTER = 0x02
|
||||||
ALIGN_SCROLL = 0x03 # apparently not supported
|
ALIGN_SCROLL = 0x03 # apparently not supported
|
||||||
|
|
||||||
def __init__(self, serial: str, send: Callable):
|
def __init__(self, serial: str, send: Callable):
|
||||||
self.log = logging.getLogger(__name__)
|
self.log = logging.getLogger(__name__)
|
||||||
|
@ -38,7 +38,7 @@ class BubaCmd:
|
||||||
:param align: alignment options, see MIS1TextDisplay.ALIGN_*
|
:param align: alignment options, see MIS1TextDisplay.ALIGN_*
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
text = text.encode("CP437", "replace").decode("CP437") # force text to be CP437 compliant
|
text = text.encode("CP437", "replace").decode("CP437") # force text to be CP437 compliant
|
||||||
if self.display is not None:
|
if self.display is not None:
|
||||||
self.display.simple_text(page, row, col, text, align)
|
self.display.simple_text(page, row, col, text, align)
|
||||||
self.send({
|
self.send({
|
||||||
|
@ -50,7 +50,6 @@ class BubaCmd:
|
||||||
'align': align,
|
'align': align,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def text(self, page, row, col_start, col_end, text, align=MIS1TextDisplay.ALIGN_LEFT):
|
def text(self, page, row, col_start, col_end, text, align=MIS1TextDisplay.ALIGN_LEFT):
|
||||||
"""
|
"""
|
||||||
Send text to the specified row, placing it between col_start and col_end.
|
Send text to the specified row, placing it between col_start and col_end.
|
||||||
|
@ -65,7 +64,7 @@ class BubaCmd:
|
||||||
:param align: alignment options, see MIS1TextDisplay.ALIGN_*
|
:param align: alignment options, see MIS1TextDisplay.ALIGN_*
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
text = text.encode("CP437", "replace").decode("CP437") # force text to be CP437 compliant
|
text = text.encode("CP437", "replace").decode("CP437") # force text to be CP437 compliant
|
||||||
if self.display is not None:
|
if self.display is not None:
|
||||||
self.display.text(page, row, col_start, col_end, text, align)
|
self.display.text(page, row, col_start, col_end, text, align)
|
||||||
self.send({
|
self.send({
|
||||||
|
@ -78,7 +77,6 @@ class BubaCmd:
|
||||||
'align': align,
|
'align': align,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def set_page(self, page):
|
def set_page(self, page):
|
||||||
"""
|
"""
|
||||||
Display the given page.
|
Display the given page.
|
||||||
|
@ -88,7 +86,6 @@ class BubaCmd:
|
||||||
"""
|
"""
|
||||||
return self.set_pages([(page, 255)])
|
return self.set_pages([(page, 255)])
|
||||||
|
|
||||||
|
|
||||||
def set_pages(self, pages):
|
def set_pages(self, pages):
|
||||||
"""
|
"""
|
||||||
Configure automatic paging.
|
Configure automatic paging.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue