Add GitHub workflow and S3 mini targets

This commit is contained in:
Djuri Baars 2024-03-16 22:59:11 +01:00
parent dbf7cc46d1
commit 082d61c84e
11 changed files with 262 additions and 25 deletions

View file

@ -0,0 +1,43 @@
name: "Install and build"
description: "Install and build"
runs:
using: "composite"
steps:
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: yarn
cache-dependency-path: '**/yarn.lock'
- uses: actions/cache@v3
with:
path: |
~/.cache/pip
~/.platformio/.cache
~/data/node_modules
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Get current date
id: dateAndTime
shell: bash
run: echo "dateAndTime=$(date +'%Y-%m-%d-%H:%M')" >> $GITHUB_OUTPUT
- name: Install PlatformIO Core
shell: bash
run: pip install --upgrade platformio
# - name: Run unit tests
# shell: bash
# run: mkdir -p junit-reports && pio test -e native_test_only --junit-output-path junit-reports/
# - name: Publish Test Report
# uses: mikepenz/action-junit-report@v4
# if: success() || failure() # always run even if the previous step fails
# with:
# report_paths: '**/junit-reports/*.xml'
# detailed_summary: true
- name: Build BTClock firmware
shell: bash
run: pio run
- name: Build BTClock filesystem
shell: bash
run: pio run --target buildfs

19
.github/workflows/pull_request.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: Pull Request Workflow
on:
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
checks: write
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: "Install and build"
uses: ./.github/actions/install-build

71
.github/workflows/tagging.yml vendored Normal file
View file

@ -0,0 +1,71 @@
name: BTClock CI
on:
push:
tags:
- '*'
jobs:
build:
strategy:
matrix:
epd_variant: [213epd, 29epd]
chip:
- name: lolin_s2_mini
version: esp32s2
# chips:
# - name: lolin_s3_mini
# version: esp32s3
runs-on: ubuntu-latest
permissions:
contents: write
checks: write
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: "Install and build"
uses: ./.github/actions/install-build
- name: Install esptools.py
run: pip install --upgrade esptool
- name: Create merged firmware binary
run: mkdir -p ${{ matrix.chip.name }}_${{ matrix.epd_variant }} && esptool.py --chip ${{ matrix.chips.version }} merge_bin -o ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${{ matrix.chip.name }}_${{ matrix.epd_variant }}.bin --flash_mode dio 0x0000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/bootloader.bin 0x8000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/partitions.bin 0xe000 ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin 0x10000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/firmware.bin 0x369000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/littlefs.bin
- name: Create checksum for merged binary
run: shasum -a 256 ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${{ matrix.chip.name }}_${{ matrix.epd_variant }}.bin | awk '{print $1}' > $${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${{ matrix.chip.name }}_${{ matrix.epd_variant }}.sha256
# - name: Write commit hash to file
# run: echo $GITHUB_SHA > ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/commit.txt
# - name: Write build date to file
# run: echo "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" > ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/date.txt
# - name: Copy all artifacts to output folder
# run: cp .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/*.bin ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin ${{ matrix.chip.name }}_${{ matrix.epd_variant }}
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: build-${{ matrix.chip.name }}-${{ matrix.epd_variant }}
path: |
${{ matrix.chip.name }}_${{ matrix.epd_variant }}/*.bin
${{ matrix.chip.name }}_${{ matrix.epd_variant }}/*.sha256
release:
runs-on: ubuntu-latest
permissions:
contents: write
checks: write
needs: build
- name: Download matrix outputs
uses: actions/download-artifact@v4
with:
name: build-*
- name: Create release
uses: ncipollo/release-action@v1
with:
artifacts: "*/*.bin,*/*.sha256"
allowUpdates: true
removeArtifacts: true
makeLatest: true

View file

@ -2,7 +2,7 @@
; ;
; Build options: build flags, source filter ; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags ; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages ; Library options: dependencies, extra library storages tl
; Advanced options: extra scripting ; Advanced options: extra scripting
; ;
; Please visit documentation for the other options and examples ; Please visit documentation for the other options and examples
@ -10,6 +10,7 @@
[platformio] [platformio]
data_dir = data/build data_dir = data/build
default_envs = lolin_s2_mini_213epd, lolin_s2_mini_29epd, lolin_s3_mini_213epd
[btclock_base] [btclock_base]
platform = espressif32 platform = espressif32
@ -30,16 +31,30 @@ lib_deps =
extends = btclock_base extends = btclock_base
board = lolin_s2_mini board = lolin_s2_mini
[env:lolin_s3_mini]
extends = btclock_base
board = lolin_s3_mini
[env:lolin_s2_mini_213epd] [env:lolin_s2_mini_213epd]
extends = env:lolin_s2_mini extends = env:lolin_s2_mini
board = lolin_s2_mini
build_flags = build_flags =
${btclock_base.build_flags} ${btclock_base.build_flags}
-D VERSION_EPD_2_13 -D VERSION_EPD_2_13
[env:lolin_s2_mini_29epd] [env:lolin_s2_mini_29epd]
extends = env:lolin_s2_mini extends = env:lolin_s2_mini
board = lolin_s2_mini build_flags =
${btclock_base.build_flags}
-D VERSION_EPD_2_9
[env:lolin_s3_mini_213epd]
extends = env:lolin_s3_mini
build_flags =
${btclock_base.build_flags}
-D VERSION_EPD_2_13
[env:lolin_s3_mini_29epd]
extends = env:lolin_s3_mini
build_flags = build_flags =
${btclock_base.build_flags} ${btclock_base.build_flags}
-D VERSION_EPD_2_9 -D VERSION_EPD_2_9

View file

@ -19,6 +19,24 @@ void setupTime()
void setupPreferences() void setupPreferences()
{ {
preferences.begin("btclock", false); preferences.begin("btclock", false);
if (!preferences.isKey(SETTING_ROW1_CONTENT))
{
preferences.putUInt(SETTING_ROW1_CONTENT, LINE_BLOCKHEIGHT);
}
if (!preferences.isKey(SETTING_ROW2_CONTENT))
{
preferences.putUInt(SETTING_ROW2_CONTENT, LINE_SATSPERUNIT);
}
if (!preferences.isKey(SETTING_ROW3_CONTENT))
{
preferences.putUInt(SETTING_ROW3_CONTENT, LINE_MEMPOOL_FEES);
}
if (!preferences.isKey(SETTING_CURRENCY))
{
preferences.putString(SETTING_CURRENCY, CURRENCY_USD);
}
} }
void setupWifi() void setupWifi()

View file

@ -6,6 +6,9 @@ const String mempoolPriceApiUrl = mempoolInstance + "/api/v1/prices";
const String mempoolBlockApiUrl = mempoolInstance + "/api/blocks/tip/height"; const String mempoolBlockApiUrl = mempoolInstance + "/api/blocks/tip/height";
const String mempoolFeeApiUrl = mempoolInstance + "/api/v1/fees/recommended"; const String mempoolFeeApiUrl = mempoolInstance + "/api/v1/fees/recommended";
uint lastPrice;
uint lastBlock;
uint getPrice() uint getPrice()
{ {
HTTPClient http; HTTPClient http;
@ -22,10 +25,10 @@ uint getPrice()
String payload = http.getString(); String payload = http.getString();
JsonDocument doc; JsonDocument doc;
deserializeJson(doc, payload); deserializeJson(doc, payload);
usdPrice = doc["USD"].as<uint>();
eurPrice = doc["EUR"].as<uint>();
return usdPrice; lastPrice = doc[preferences.getString(SETTING_CURRENCY)].as<uint>();
return lastPrice;
} }
else else
{ {
@ -36,7 +39,7 @@ uint getPrice()
return 0; return 0;
} }
String getBlock() uint getBlock()
{ {
HTTPClient http; HTTPClient http;
@ -49,9 +52,10 @@ String getBlock()
uint usdPrice, eurPrice; uint usdPrice, eurPrice;
if (httpCode == 200) if (httpCode == 200)
{ {
String payload = http.getString(); uint payload = http.getString().toInt();
return payload; lastBlock = payload;
return lastBlock;
} }
else else
{ {
@ -59,7 +63,7 @@ String getBlock()
} }
http.end(); http.end();
return ""; return 0;
} }
String getMempoolFees() String getMempoolFees()

View file

@ -8,5 +8,5 @@
#include "shared.hpp" #include "shared.hpp"
uint getPrice(); uint getPrice();
String getBlock(); uint getBlock();
String getMempoolFees(); String getMempoolFees();

View file

@ -89,7 +89,7 @@ void loop()
} }
} }
String block = getBlock(); String block = String(getBlock());
uint tryCount = 0; uint tryCount = 0;
while (block.equals("")) while (block.equals(""))

View file

@ -56,13 +56,28 @@
#define ICON_CHECK "Q" #define ICON_CHECK "Q"
#define ICON_WARNING "R" #define ICON_WARNING "R"
#define SETTING_ROW1_CONTENT "row1"
#define SETTING_ROW2_CONTENT "row2"
#define SETTING_ROW3_CONTENT "row3"
#define SETTING_CURRENCY "currency"
const int LINE_BLOCKHEIGHT = 0; const int LINE_BLOCKHEIGHT = 0;
const int LINE_HALVING_COUNTDOWN = 1; const int LINE_MEMPOOL_FEES = 1;
const int LINE_SATSPERDOLLAR = 2; const int LINE_MEMPOOL_FEES_MEDIAN = 2;
const int LINE_FIATPRICE = 3; const int LINE_HALVING_COUNTDOWN = 10;
const int LINE_MEMPOOL_FEES = 4; const int LINE_SATSPERUNIT = 20;
const int LINE_TIME = 5; const int LINE_FIATPRICE = 30;
const int LINE_DATE = 6; const int LINE_MARKETCAP = 40;
const int LINE_TIME = 99;
const int LINE_DATE = 100;
#define CURRENCY_USD "USD"
#define CURRENCY_EUR "EUR"
#define CURRENCY_GBP "GBP"
#define CURRENCY_CAD "CAD"
#define CURRENCY_CHF "CHF"
#define CURRENCY_AUD "AUD"
#define CURRENCY_JPY "JPY"
extern WiFiClientSecure client; extern WiFiClientSecure client;
extern GxEPD2_BW<EPD_CLASS, EPD_CLASS::HEIGHT> display; extern GxEPD2_BW<EPD_CLASS, EPD_CLASS::HEIGHT> display;

View file

@ -2,12 +2,20 @@
#include <LittleFS.h> #include <LittleFS.h>
AsyncWebServer server(80); AsyncWebServer server(80);
String uintSettings[] = {SETTING_ROW1_CONTENT, SETTING_ROW2_CONTENT, SETTING_ROW3_CONTENT};
void setupWebserver() { void setupWebserver()
if (!LittleFS.begin(true)) { {
if (!LittleFS.begin(true))
{
Serial.println(F("An Error has occurred while mounting LittleFS")); Serial.println(F("An Error has occurred while mounting LittleFS"));
} }
server.on("/api/settings", HTTP_GET, onApiSettingsGet);
AsyncCallbackJsonWebHandler *settingsPatchHandler =
new AsyncCallbackJsonWebHandler("/api/json/settings", onApiSettingsPatch);
server.addHandler(settingsPatchHandler);
server.serveStatic("/build", LittleFS, "/build"); server.serveStatic("/build", LittleFS, "/build");
server.on("/", HTTP_GET, onIndex); server.on("/", HTTP_GET, onIndex);
@ -20,17 +28,54 @@ void setupWebserver() {
server.begin(); server.begin();
} }
void onIndex(AsyncWebServerRequest *request) { void onApiSettingsGet(AsyncWebServerRequest *request)
{
JsonDocument root;
for (String setting : uintSettings)
{
root[setting] = preferences.getUInt(setting.c_str());
}
AsyncResponseStream *response =
request->beginResponseStream("application/json");
serializeJson(root, *response);
request->send(response);
}
void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
{
JsonObject settings = json.as<JsonObject>();
for (String setting : uintSettings)
{
if (settings.containsKey(setting))
{
preferences.putUInt(setting.c_str(), settings[setting].as<uint>());
Serial.printf("Setting %s to %d\r\n", setting.c_str(),
settings[setting].as<uint>());
}
}
request->send(200);
}
void onIndex(AsyncWebServerRequest *request)
{
request->send(LittleFS, "/index.html", String(), false); request->send(LittleFS, "/index.html", String(), false);
} }
void onNotFound(AsyncWebServerRequest *request) { void onNotFound(AsyncWebServerRequest *request)
{
if (request->method() == HTTP_OPTIONS || if (request->method() == HTTP_OPTIONS ||
request->hasHeader("Sec-Fetch-Mode")) { request->hasHeader("Sec-Fetch-Mode"))
{
// Serial.printf("NotFound, Return[%d]\n", 200); // Serial.printf("NotFound, Return[%d]\n", 200);
request->send(200); request->send(200);
} else { }
else
{
// Serial.printf("NotFound, Return[%d]\n", 404); // Serial.printf("NotFound, Return[%d]\n", 404);
request->send(404); request->send(404);
} }

View file

@ -2,8 +2,15 @@
// Keep order of includes because of conflicts // Keep order of includes because of conflicts
#include "ESPAsyncWebServer.h" #include "ESPAsyncWebServer.h"
#include "AsyncJson.h"
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <shared.hpp>
void setupWebserver(); void setupWebserver();
void onApiSettingsGet(AsyncWebServerRequest *request);
void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json);
void onIndex(AsyncWebServerRequest *request); void onIndex(AsyncWebServerRequest *request);
void onNotFound(AsyncWebServerRequest *request); void onNotFound(AsyncWebServerRequest *request);