Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large performance improvements and a couple of nice to have new features #96

Merged
merged 3 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
._DS_Store
src/__pycache__
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
This project adheres to [Semantic Versioning](http://semver.org/).

# v0.5.0
## (2023-06-29)

* Upgrade: Switch Python version and base OS: Python 3.11 on Alpine
* New feature: `showDepartureNumbers` option - Adds 1st / 2nd / 3rd prefix as per UK train departures
* New feature: `firstDepartureBold` option - toggle bold of first departure line as this is regional
* New feature: `targetFPS` option - configurable FPS regulator (zero to disable)
* Development UX: `fpsTime` option - Adjusts how frequently the Effecive FPS is displayed
* Development UX: `headless` option - Run using emulated serial port (Useful for optimisation checks)
* Development UX: Skip NRE attribution sleep in emulation mode
* Development UX: Simplify Dockerfile slightly in an attempt to be Balena-y
* Performance: Seconds now render every 0.1 second, rather than a hotspot (reduce CPU)
* Performance: All "in-loop" TTF font rendering is now cached (reduce CPU)
* Fix: screen1Platform/screen2Platform being required incorrectly on the env

# v0.4.0
## (2023-02-18)

Expand Down
39 changes: 19 additions & 20 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
FROM balenalib/raspberry-pi-debian-python:3.7-buster-run AS builder
FROM balenalib/raspberry-pi-alpine-python:3.11.2-3.15-build as builder

WORKDIR /usr/src/app

RUN mkdir -p /usr/src/debian-rootfs

RUN install_packages apt-rdepends

RUN apt-get update && \
apt-get download \
$(apt-rdepends tzdata python3 libopenjp2-7 libfreetype6-dev libjpeg-dev libtiff5 libxcb1 | grep -v "^ " | sed 's/debconf-2.0/debconf/g' | sed 's/^libc-dev$/libc6-dev/g' | sed 's/^libz-dev$/zlib1g-dev/g')

RUN for pkg in *.deb; \
do dpkg-deb -x $pkg /usr/src/debian-rootfs; \
done
# Shared libraries
RUN apk add freetype-dev libjpeg-turbo-dev

# Install the required python packages, and save the compiled result to an output folder
# This requires gcc/etc which is why we do it in the build image and save the result for the run image
COPY ./requirements.txt .
RUN pip install -t /usr/src/python-packages -r requirements.txt --no-cache-dir --extra-index-url=https://www.piwheels.org/simple

RUN pip install --target=/usr/src/python-packages -r requirements.txt --no-cache-dir --config-settings="pillow=--disable-zlib"

FROM busybox:stable
# Grab the "run" image for the device, which is much lighter weight
FROM balenalib/raspberry-pi-alpine-python:3.11.2-3.15-run


COPY --from=builder /usr/src/debian-rootfs ./
# Copy in the compiled packages
COPY --from=builder /usr/src/python-packages/ /usr/src/python-packages/

COPY VERSION ./
# Shared libraries
RUN apk add freetype-dev libjpeg-turbo-dev

# And the app
WORKDIR /usr/src/app
COPY src ./src
ENV PYTHONPATH=/usr/src/python-packages/
COPY VERSION .

# Tell python where to find these mysterious precompiled packages
ENV PYTHONPATH=/usr/src/python-packages

CMD ["python3", "src/main.py"]
# And off we go
CMD ["python3", "src/main.py"]
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.0
0.5.0
6 changes: 5 additions & 1 deletion balena.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,9 @@ data:
- screen1Platform:
- screen2Platform:
- individualStationDepartureTime: False
version: 0.4.0
- showDepartureNumbers: False
- firstDepartureBold: True
- targetFPS: 70
- fpsTime: 10
version: 0.5.0

6 changes: 5 additions & 1 deletion docs/04-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ These environment variables are specified using the [balenaCloud dashboard](http
| `screen1Platform` | `1` (sets the platform you want to have displayed on the first or single-screen display)
| `screen2Platform` | `2` (sets the platform you want to have displayed on the second display)
| `individualStationDepartureTime` | `False` (Displays the estimated or scheduled time of the service at each leg of a journey)

| `fpsTime` | `4` (adjusts how often the effective FPS is displayed)
| `headless` | `True` (outputs to noop serial device rather than serial port; useful for running on a development machine)
| `showDepartureNumbers` | `True` (adds 1st / 2nd / 3rd as per UK train departures)
| `firstDepartureBold` | `False` (makes the first departure use either the bold or normal font)
| `targetFPS` | `20` (Frame rate regulator FPS target; 0 disables the regulator, which will increase FPS on constrained CPU, but will run the CPU hot at 100%.)

If using two screens the following line needs to be added into /boot/config.txt which is achieved by using the 'Define DT overlays' option within the Device configuration screen on balenaCloud: `spi1-3cs`

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
luma.oled
timeloop
requests
xmltodict
xmltodict
24 changes: 18 additions & 6 deletions src/config.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import os
import re


def loadConfig():
data = {
"journey": {},
"api": {}
}

data["targetFPS"] = int(os.getenv("targetFPS") or 70)
data["refreshTime"] = int(os.getenv("refreshTime") or 180)
data["fpsTime"] = int(os.getenv("fpsTime") or 180)
data["screenRotation"] = int(os.getenv("screenRotation") or 2)
data["screenBlankHours"] = os.getenv("screenBlankHours") or ""
data["headless"] = False
if os.getenv("headless") == "True":
data["headless"] = True
data["dualScreen"] = False
if os.getenv("dualScreen") == "True":
data["dualScreen"] = True
data["firstDepartureBold"] = True
if os.getenv("firstDepartureBold") == "False":
data["firstDepartureBold"] = False
data["hoursPattern"] = re.compile("^((2[0-3]|[0-1]?[0-9])-(2[0-3]|[0-1]?[0-9]))$")

data["journey"]["departureStation"] = os.getenv("departureStation") or "PAD"
Expand All @@ -26,19 +35,22 @@ def loadConfig():
data["journey"]["individualStationDepartureTime"] = True

data["journey"]["outOfHoursName"] = os.getenv("outOfHoursName") or "London Paddington"
data["journey"]["stationAbbr"] = { "International": "Intl." }
data["journey"]["stationAbbr"] = {"International": "Intl."}
data["journey"]['timeOffset'] = os.getenv("timeOffset") or "0"
data["journey"]["screen1Platform"] = os.getenv("screen1Platform")
data["journey"]["screen2Platform"] = os.getenv("screen2Platform")
data["journey"]["screen1Platform"] = os.getenv("screen1Platform") or ""
data["journey"]["screen2Platform"] = os.getenv("screen2Platform") or ""

if data["journey"]["screen1Platform"].isnumeric() != True:
if data["journey"]["screen1Platform"].isnumeric() is not True:
data["journey"]["screen1Platform"] = ""

if data["journey"]["screen2Platform"].isnumeric() != True:
if data["journey"]["screen2Platform"].isnumeric() is not True:
data["journey"]["screen2Platform"] = ""

data["api"]["apiKey"] = os.getenv("apiKey") or None
data["api"]["operatingHours"] = os.getenv("operatingHours") or ""

data["showDepartureNumbers"] = False
if os.getenv("showDepartureNumbers") == "True":
data["showDepartureNumbers"] = True

return data

Loading