Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/build-and-push-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Create and publish Docker image

on:
push:
branches: ['main', 'release', 'project_structure']
branches: ['develop', 'release']

env:
REGISTRY: ghcr.io
Expand Down
46 changes: 28 additions & 18 deletions bitbot.dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,45 @@
FROM python:3.11-slim-bookworm
# Stage 1: Build stage
FROM python:3.11-slim-bookworm AS builder

# avoid bytecode baggage
# Avoid bytecode baggage
ENV PYTHONDONTWRITEBYTECODE=1

# install OS reqs
RUN apt-get update -y && \
apt-get install -y \
--no-install-recommends \
libopenblas-dev libopenjp2-7 libtiff6 libxcb1 libfreetype6-dev \
&& rm -rf /var/lib/apt/lists/*

# venv to keep python happy
# Create a virtual environment
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# update pip
# Update pip
RUN python3 -m pip install --upgrade pip --no-cache-dir

# download python reqs
# Copy and install Python dependencies
COPY requirements.txt .
RUN python3 -m pip download \
-r requirements.txt \
--extra-index-url https://www.piwheels.org/simple

# install python reqs
RUN python3 -m pip install -v \
--prefer-binary \
-r requirements.txt \
--extra-index-url https://www.piwheels.org/simple
--extra-index-url https://www.piwheels.org/simple \
--no-cache-dir

# app code
# Stage 2: Final stage
FROM python:3.11-slim-bookworm

# Avoid bytecode baggage
ENV PYTHONDONTWRITEBYTECODE=1

# Install only the necessary runtime dependencies
RUN apt-get update -y && \
apt-get install -y \
--no-install-recommends \
libopenblas-dev libopenjp2-7 libtiff6 libxcb1 libfreetype6-dev \
&& rm -rf /var/lib/apt/lists/*

# Copy the virtual environment from the builder stage
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# Copy only the necessary application code
WORKDIR /code
COPY . .

# Set the default command
CMD ["python", "run.py"]
2 changes: 1 addition & 1 deletion config/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ enabled = false

[tide_times]
enabled = false
location_id = 9414290
location_id = 0184

[comments]
up = moon,yolo,pump it,gentlemen
Expand Down
2 changes: 1 addition & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ UML diagram of broad [package interactions](http://www.plantuml.com/plantuml/svg
- [`Pillow`](https://github.com/python-pillow/Pillow) draws **drawing overlay** text onto the graph

## 🐳 Docker
**Github actions** builds and tests and publishes a **container image** on each commit to `main` and `release`
**Github actions** builds and tests and publishes a **container image** on each commit to `develop` and `release`

🐳 `x86` faster than the Pi.
```sh
Expand Down
134 changes: 0 additions & 134 deletions index.html

This file was deleted.

23 changes: 9 additions & 14 deletions src/bitbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from os.path import exists
import io

from matplotlib import font_manager
from src.drawing.market_charts.mpf_plotted_chart import MplFinanceChart
from src.exchanges import crypto_exchanges, stock_exchanges
from src.configuration.log_decorator import info_log
Expand All @@ -15,10 +14,6 @@


class BitBot():
def __init__(self, config, display):
self.config = config
self.display = display

def __init__(self, config, files):
self.config = config
self.files = files
Expand Down Expand Up @@ -58,9 +53,9 @@ def display_chart(self):

@info_log
def display_message(self, message):
img = Image.new("P", self.display.size())
img = Image.new("RGBA", self.display.size(), (255, 0, 0, 0))
draw = ImageDraw.Draw(img)
centered_text(draw, message, self.display.title_font, self.display.size(), border=True)
centered_text(draw, message, self.display.title_font, img.size, border=True, pos="centre")
self.display.show(img)
return img

Expand Down Expand Up @@ -89,13 +84,13 @@ def display_tide_times(self):
@info_log
def display_connection_error(self):
self.display_message("""
NO INTERNET CONNECTION
----------------------------
Please check your WIFI
----------------------------
To configure WiFi access,
connect to 'bitbot-<nnn>' WiFi AP
and follow the instructions""")
NO INTERNET CONNECTION
----------------------------
Please check your WIFI
----------------------------
To configure WiFi access,
connect to 'comitup-<nnn>' WiFi AP
and follow the instructions""")

def __repr__(self):
return f'<BitBot output: {str(self.config.output_device_name())}>'
3 changes: 2 additions & 1 deletion src/configuration/bitbot_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,10 @@ def tide_times_enabled(self):
def tide_location_id(self):
return self.config['tide_times']["location_id"]

# timed meaages
# timed messages
def today_has_special_message(self, datetime):
return self.special_message(datetime) != None

def special_message(self, datetime):
return self.config.get('special_messages', datetime.strftime("%YYYY-%MM-%DD"), fallback=None)

23 changes: 13 additions & 10 deletions src/drawing/image_utils/Align.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@


class Align:
def TopRight(display, message_size):
return (display.size[0] - message_size[0] - padding - 1, padding)
def TopRight(display_size, message_size):
return (display_size[0] - message_size[0] - padding - 1, padding)

def BottomRight(display, message_size):
return (display.size[0] - message_size[0], display.size[1] - message_size[1])
def BottomRight(display_size, message_size):
display_width_minus_text_width = display_size[0] - message_size[0]
display_height_minus_text_height = display_size[1] - message_size[1]

return (display_width_minus_text_width, display_height_minus_text_height)

def BottomLeft(display, message_size):
return (0, display.size[1] - message_size[1])
def BottomLeft(display_size, message_size):
return (0, display_size[1] - message_size[1])

def TopLeft(display, message_size):
def TopLeft(display_size, message_size):
return (0 + padding + 1, 0 + padding + 1)

def Centre(display, message_size):
message_y = (display.size[1][1] - message_size[1]) / 2
message_x = (display.size[1][0] - message_size[0]) / 2
def Centre(display_size, message_size):
message_y = (display_size[0] - message_size[0]) / 2
message_x = (display_size[1] - message_size[1]) / 2
return (message_y, message_x)

# 🏳️ select image area with the most white pixels
Expand Down
16 changes: 8 additions & 8 deletions src/drawing/image_utils/CenteredText.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ def centered_text(draw, text, font, container_size, pos='centre', border=False):

# 📏 where to position the message
if pos == 'centre':
message_x, message_y = Align.Centre(container_size, message_size)
message_y, message_x = Align.Centre(container_size, message_size)
elif pos == 'topright':
message_x, message_y = Align.TopRight(container_size, message_size)
message_y, message_x = Align.TopRight(container_size, message_size)
elif pos == 'topleft':
message_x, message_y = Align.TopLeft(container_size, message_size)
message_y, message_x = Align.TopLeft(container_size, message_size)

# 🖊️ draw the message at position
draw.multiline_text(
(message_x, message_y),
(message_y, message_x),
text,
fill='black',
font=font,
align="left")

# 📏 measure border box
if border:
x0, y0 = (message_x - padding, message_y - padding)
x1 = message_x + message_size[0] + padding
y1 = message_y + message_size[1] + padding
y0, x0 = (message_y - padding, message_x - padding)
y1 = message_y + message_size[0] + padding
x1 = message_x + message_size[1] + padding
# 🖊️ draw box at position
draw.rectangle([(x0, y0), (x1, y1)], outline='red')
draw.rectangle([(y0, x0), (y1, x1)], outline='red')
2 changes: 1 addition & 1 deletion src/drawing/image_utils/DrawText.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ def __init__(self, text, font, colour='black', align=None):
self.align = align

def draw_on(self, draw, pos=(0, 0)):
pos = self.align(draw.im, self.size) if self.align else pos
pos = self.align(draw.im.size, self.size) if self.align else pos
draw.text(pos, self.text, self.colour, self.font)
4 changes: 2 additions & 2 deletions src/drawing/image_utils/TextBlock.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .DrawText import DrawText


# texts is array of drawtext
class TextBlock:
def __init__(self, texts, align=None):
self.texts = texts
Expand All @@ -26,5 +26,5 @@ def draw_on(self, draw, pos=(0, 0)):

def draw_text_row(self, draw, x_pos, y_pos, row):
for text in row:
text.draw_on(draw, (x_pos, y_pos))
text.draw_on(draw, pos=(x_pos, y_pos))
x_pos += DrawText.width(text)
Loading