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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
43 changes: 17 additions & 26 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
# Development

> Bitbot is somewhat cobbled together, but is fairly carefully commented and has been factored with ease of change in mind.

## ✔️ Tests
> [python unittests](/tests) with the default test framework

python3 -m unittest discover tests -v
[python unit tests](/tests) with the default test framework
`python3 -m unittest discover tests -v`

## ✉️ Env vars
> `BITBOT_TESTRUN` loads one chart and then exits

> `BITBOT_SHOWIMAGE` [opens the image in vscode](/run.py) after loading the chart

> `BITBOT_OUTPUT` may be set to `disk` to write to disk rather than the e-ink display

export BITBOT_TESTRUN=true BITBOT_OUTPUT=disk BITBOT_SHOWIMAGE=true
`BITBOT_TESTRUN` loads one chart and then exits
`BITBOT_SHOWIMAGE` [opens the image in vscode](/run.py) after loading the chart
`BITBOT_OUTPUT` may be set to `disk` to write to disk rather than the e-ink display
`export BITBOT_TESTRUN=true BITBOT_OUTPUT=disk BITBOT_SHOWIMAGE=true`

## 📻 Easy WiFi config
> [`comitup`](https://github.com/davesteele/comitup) is used for the ***disk image***, it creates a **config hotspot** on the Pi if it **cant connect** to any wifi itself.

> The config file is located at `/etc/comitup.conf`
[`comitup`](https://github.com/davesteele/comitup) is used for the ***disk image***, it creates a **config hotspot** on the Pi if it **cant connect** to any wifi itself.
The config file is located at `/etc/comitup.conf`
```sh
# show comitup info
sudo comitup -i
Expand All @@ -28,11 +22,9 @@ sudo comitup-cli
```

## 🌳Logging
> BitBot will log to `syslog`, `StdOut` and a rolling `debug.log` file, configured in [📁logging.ini](/logging.ini)

> Log level is **defaulted to `INFO`**, but there is some ***limited debug level logging*** if you wish to get more info.

> Cron jobs were configured to output to syslog. 😞
BitBot will log to the `config web-ui` `syslog`, `StdOut` and a rolling `debug.log` file, configured in [📁logging.ini](/logging.ini)
Log level is **defaulted to `INFO`**, but there is some ***limited debug level logging*** if you wish to get more info.
Cron jobs were configured to output to syslog. 😞
```sh
# roling file log
tail ~/bitbot/debug.log
Expand All @@ -41,23 +33,22 @@ tail -f /var/log/syslog | grep 'Bitbot:'
```

## 🎁 Packages
UML diagram of broad [package interactions](http://www.plantuml.com/plantuml/svg/3Oon3KCX30NxFqMo0EvJ_LN0M7mhO11-LjOFrUckkDkHDsBqwwt6FQh4xgy7MFuXslcNckA94YwRfq4CYUUWEgseDIgACa4Zgvt6JcT5A_CtD_6qZbstM3ty0m00)

- [Pimoroni](pimoroni.com) [`inky`](https://github.com/pimoroni/inky) does the **e-ink display**,
- [`CCXT`](https://github.com/ccxt/ccxt) talks to **crypto exchanges**
- [`MPL-Finance`](https://github.com/matplotlib/mpl-finance) **draws the graphs** (and could do with updating to [`mplfinance`](https://github.com/matplotlib/mplfinance))
- [`Pillow`](https://github.com/python-pillow/Pillow) draws **drawing overlay** text onto the graph

![Package Interactions](http://www.plantuml.com/plantuml/svg/3Oon3KCX30NxFqMo0EvJ_LN0M7mhO11-LjOFrUckkDkHDsBqwwt6FQh4xgy7MFuXslcNckA94YwRfq4CYUUWEgseDIgACa4Zgvt6JcT5A_CtD_6qZbstM3ty0m00)

## 🐳 Docker
> **Github actions** builds and tests and publishes a **container image** on each commit to `main` and `release`
### 🐳 Build
> building on `x86` is way faster than on the Pi
**Github actions** builds and tests and publishes a **container image** on each commit to `main` and `release`

🐳 Build on `x86` is way faster than on the Pi.
```sh
# remove the `--platform` args if building on a pi
docker buildx build --platform linux/arm/v6 . -t bitbot -f scripts/docker/dockerfile --progress string
```
### 🐳 Run
> **Priviledged access** is needed for `GPIO`, this looks to be fixable thru bind mounts
🐳 Run **Priviledged access** is needed for `GPIO`, this looks to be fixable thru bind mounts.
```sh
docker run --privileged --platform linux/arm/v6 bitbot
```
2 changes: 1 addition & 1 deletion docs/device_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
- A list of **supported crypto-exchanges** can be found [here](https://github.com/ccxt/ccxt/wiki/Exchange-Markets)
- Please see your selected exchange for the ***instruments that it supports***

### Bitbot uses [Style Files](../config/base.mplstyle) to control the chart layout.
### Bitbot uses [Style Files](../config/mpl_styles/base.mplstyle) to control the chart layout.
- If you're feeling experimental.. you can edit these! Examples of the ***styling*** options can be [found here](https://matplotlib.org/stable/tutorials/introductory/customizing.html#the-default-matplotlibrc-file)

### Inky Impression **Button** support
Expand Down
36 changes: 0 additions & 36 deletions docs/docker_installation.md

This file was deleted.

67 changes: 25 additions & 42 deletions docs/notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,38 @@ todo:
- moving averages
- indicators


> Build arm6 on x86
# Docker
Build arm6 on x86
```bash
docker run -e QEMU_CPU=arm1176 --privileged --rm -it --platform linux/arm/v6 balenalib/raspberry-pi:buster bash
docker run -e QEMU_CPU=arm1176 --privileged --rm -it --platform linux/arm/v6 balenalib/raspberry-pi:buster bash
# build container atrm6
docker buildx build --platform linux/arm/v6 . -t bitbot --progress string
# run it, have to specify which chip QEMU should emulate
docker run -e QEMU_CPU=arm1176 --privileged --rm -t --platform linux/arm/v6 navikey/raspbian-buster:latest bash

docker buildx build --platform linux/arm/v6 . -t bitbot -f scripts/docker/dockerfile --progress string
docker run -e QEMU_CPU=arm1176 --privileged --rm -it --platform linux/arm/v6 bitbot
```

# Hackery
```bash
# remove all containers
docker container rm $(docker container ls -q -a)
#' which cpus to use for the build
# --cpuset-cpus=0-3'
# wifi-connect docker pull balenablocks/wifi-connect:rpi
docker run --network=host -v /run/dbus/:/run/dbus/ balenablocks/wifi-connect:rpi

# error: failed to solve: failed to solve with frontend dockerfile.v0: failed to create LLB definition: rpc error: code = Unknown desc = error getting credentials - err: exit status 255, out: ``
= In ~/.docker/config.json `change credsStore to credStore`

# error exec "--env" "executable file not found in $PATH: unknown"
= badly ordered docker args, envs must come before image name
```

# Testing
```bash
# test run
docker run --rm --env BITBOT_TESTRUN=true --env BITBOT_OUTPUT=disk --env BITBOT_SHOWIMAGE=false bb

# run tests
docker run --rm \
--name bitbot_tests \
Expand All @@ -62,17 +67,24 @@ bb \
python3 -m unittest discover
```

> get linux os version
# PiOS
Get linux os version
```sh
cat /etc/os-release
```

> enable vnc raspiconfig
Enable vnc raspiconfig
```sh
sudo raspi-config nonint do_vnc 0
```

> setup my git
Check cpu arch
```sh
dpkg --print-architecture
```

# Git
Setup my git
```sh
# setup user
git config --global user.email ccbing@gmail.com
Expand All @@ -87,38 +99,9 @@ git config --global --unset user.password
git config --global alias.ci commit
git config --global alias.st status
```
> check cpu arch
```sh
dpkg --print-architecture
```


## fonts
> place in `~/.fonts` or `/usr/local/share/fonts` for system wide access
mkdir ~/.fonts && cp ~/bitbot/src/resources/04B_03__.TTF ~/.fonts/04B_03__.TTF

> manually rebuild the font cache with `fc-cache -f -v`

> list fonts with `fc-list`



# balena
```
# install gbalena cli
wget https://github.com/balena-io/balena-cli/releases/download/v13.3.0/balena-cli-v13.3.0-linux-x64-standalone.zip
unzip balena-cli-v13.3.0-linux-x64-standalone.zip
# balena cli
balena login
balena push gh_donbing/teste
# git
# add pud key to balena
balena key add Main ~/.ssh/id_rsa.pub
# list keys
balena keys
# push to balena
git remote add balena gh_donbing@git.balena-cloud.com:gh_donbing/teste.git
# push our main branch to balena master branch
git push balena main:master
```

# Fonts
- place in `~/.fonts` or `/usr/local/share/fonts` for system wide access
- `mkdir ~/.fonts && cp ~/bitbot/src/resources/04B_03__.TTF ~/.fonts/04B_03__.TTF`
- manually rebuild the font cache with `fc-cache -f -v`
- list fonts with `fc-list`
3 changes: 1 addition & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@
- [⚙️ Device **Setup**](docs/device_setup.md)
- [💾 **Config** Options](docs/config_options.md)
- [📒 Dev **Notes**](docs/development.md)
- [🐋 **Docker** Setup](docs/docker_installation.md)
- [📈 Current charting examples](/tests/images/)
- [📈 Chart examples](/tests/images/)
6 changes: 4 additions & 2 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ def refresh_display(sc, reason):
if config.photo_mode_enabled():
if reason != "scheduled":
app.display_photo()
else:
app.display_chart()
elif app.display_chart():
# 🪳 show image in vscode for debug
if config.shoud_show_image_in_vscode():
os.system("code last_display.png")
elif app.youtube_subs_enabled():
app.display_youtube_subs()


# ⌛ dont reschedule if testing
if not config.is_test_run():
Expand Down
8 changes: 7 additions & 1 deletion src/bitbot.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from PIL import Image, ImageDraw, ImageFont
from PIL import Image, ImageDraw
from os.path import exists
import io
from src.exchanges import crypto_exchanges, stock_exchanges
Expand All @@ -7,6 +7,7 @@
from src.drawing.chart_overlay import ChartOverlay
from src.display.picker import picker as display_picker
from src.configuration.network_utils import wait_for_internet_connection
from src.youtube_stats.subscriber_counter import YouTubeSubscriberCount


class Cartographer():
Expand Down Expand Up @@ -68,5 +69,10 @@ def display_photo(self):
if(exists(image_path)):
self.display.show(Image.open(image_path))

@info_log
def display_youtube_subs(self):
subscriber_display = YouTubeSubscriberCount(self.display.size(), self.display.title_font, self.config)
subscriber_display.play()

def __repr__(self):
return f'<BitBot output: {str(self.config.output_device_name())}>'
16 changes: 13 additions & 3 deletions src/configuration/bitbot_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,13 @@ def set_display(self, formData):
self.save()

# 🖼️ picture frame mode
def photo_mode_enabled(self):
return self.config['picture_frame_mode']["enabled"] == 'true'

def toggle_photo_mode(self, enabled_state, cycle_state):
self.config['picture_frame_mode']["enabled"] = enabled_state
self.config['picture_frame_mode']["cycle_pictures"] = cycle_state

def photo_mode_enabled(self):
return self.config['picture_frame_mode']["enabled"] == 'true'

def cycle_pictures_enabled(self):
return self.config['picture_frame_mode']["cycle"] == 'true'

Expand Down Expand Up @@ -188,3 +188,13 @@ def intro_background(self):
self.config_files.resource_folder,
self.config['first_run']['intro_background_image']
)

# 📺 youtube setup
def youtube_subs_enabled(self):
return self.config['youtube_subs']["enabled"] == 'true'

def youtube_channelid():
return "UCAotflAHrgfuhK9Rw-C_-Ug"

def youtube_key():
return "AIzaSyCFJ6-vHN9KgOE3a6mjdqBcG-pYlwcRGj4"
21 changes: 14 additions & 7 deletions src/configuration/bitbot_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@ def __init__(self, base_path):
self.config_ini = self.existing_file_path('config.ini')
self.logging_ini = self.existing_file_path('logging.ini')

self.base_style = self.existing_file_path('base.mplstyle')
self.default_style = self.existing_file_path('default.mplstyle')
self.volume_style = self.existing_file_path('volume.mplstyle')
self.small_screen_style = self.existing_file_path('small.mplstyle')
self.expanded_style = self.existing_file_path('default.expanded.mplstyle')
self.small_expanded_style = self.existing_file_path('small.expanded.mplstyle')

self.base_style = self.load_mpl_style('base.mplstyle')
self.default_style = self.load_mpl_style('default.mplstyle')
self.volume_style = self.load_mpl_style('volume.mplstyle')
self.small_screen_style = self.load_mpl_style('small.mplstyle')
self.expanded_style = self.load_mpl_style('default.expanded.mplstyle')
self.small_expanded_style = self.load_mpl_style('small.expanded.mplstyle')

def load_mpl_style(self, file_name):
file_path = pjoin(self.config_folder, 'mpl_styles', file_name)
if not exists(file_path):
self.file_not_found(file_path)
self.all_files[file_name] = file_path
return file_path

def existing_file_path(self, file_name):
file_path = pjoin(self.config_folder, file_name)
if not exists(file_path):
Expand Down
Loading