Compare commits

..

2 commits

Author SHA1 Message Date
Djuri Baars
981aea4981 Merge branch 'main' into feature/btc22 2024-09-28 00:05:55 +02:00
Djuri Baars
6dc3a2c3c8 Add integration with SR mining pool for Bitcoin Amsterdam '24 2024-09-25 17:27:39 +02:00
41 changed files with 265 additions and 1114 deletions

View file

@ -1,190 +0,0 @@
name: "BTClock CI"
on:
push:
tags:
- "*"
workflow_dispatch:
jobs:
build:
runs-on: docker
container:
image: ghcr.io/catthehacker/ubuntu:js-22.04
permissions:
contents: write
checks: write
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: yarn
cache-dependency-path: "**/yarn.lock"
- uses: actions/cache@v4
with:
path: |
~/.cache/pip
~/.platformio/.cache
~/data/node_modules
.pio
data/node_modules
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v5
with:
python-version: "3.9"
cache: "pip"
- 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: Build BTClock firmware
shell: bash
run: pio run
- name: Build BTClock filesystem
shell: bash
run: pio run --target buildfs
- name: Copy bootloader to output folder
run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin .pio
- name: Upload artifacts
uses: https://code.forgejo.org/forgejo/upload-artifact@v4
with:
include-hidden-files: true
retention-days: 1
name: prepared-outputs
path: .pio/**/*.bin
merge:
runs-on: docker
container:
image: ghcr.io/catthehacker/ubuntu:js-22.04
permissions:
contents: write
checks: write
needs: build
continue-on-error: true
strategy:
matrix:
chip:
- name: lolin_s3_mini
version: esp32s3
- name: btclock_rev_b
version: esp32s3
- name: btclock_v8
version: esp32s3
epd_variant: [213epd, 29epd]
exclude:
- chip: { name: btclock_rev_b, version: esp32s3 }
epd_variant: 29epd
- chip: { name: btclock_v8, version: esp32s3 }
epd_variant: 29epd
steps:
- uses: https://code.forgejo.org/forgejo/download-artifact@v4
with:
name: prepared-outputs
path: .pio
- name: Install esptools.py
run: pip install --upgrade esptool
- name: Create merged firmware binary
shell: bash
run: |
mkdir -p ${{ matrix.chip.name }}_${{ matrix.epd_variant }}
if [ "${{ matrix.chip.name }}" == "btclock_v8" ]; then
esptool.py --chip ${{ matrix.chip.version }} merge_bin \
-o ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${{ matrix.chip.name }}_${{ matrix.epd_variant }}.bin \
--flash_mode dio \
--flash_freq 80m \
--flash_size 16MB \
0x0000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/bootloader.bin \
0x8000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/partitions.bin \
0xe000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/ota_data_initial.bin \
0x10000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/firmware.bin \
0xDF0000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/littlefs_16MB.bin
elif [ "${{ matrix.chip.name }}" == "btclock_rev_b" ]; then
esptool.py --chip ${{ matrix.chip.version }} merge_bin \
-o ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${{ matrix.chip.name }}_${{ matrix.epd_variant }}.bin \
--flash_mode dio \
--flash_freq 80m \
--flash_size 8MB \
0x0000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/bootloader.bin \
0x8000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/partitions.bin \
0xe000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/ota_data_initial.bin \
0x10000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/firmware.bin \
0x6F0000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/littlefs_8MB.bin;
else
esptool.py --chip ${{ matrix.chip.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 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/ota_data_initial.bin \
0x10000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/firmware.bin \
0x380000 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/littlefs_4MB.bin
# Adjust the offset for littlefs or other files as needed for the original case
fi
- name: Create checksum for firmware
shell: bash
run: shasum -a 256 .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/firmware.bin | awk '{print $1}' > ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${{ matrix.chip.name }}_${{ matrix.epd_variant }}_firmware.bin.sha256
- name: Create checksum for merged binary
shell: bash
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 }}.bin.sha256
- name: Create checksum for littlefs partition
shell: bash
run: |
fs_file=$(find .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }} -name "littlefs*.bin")
echo $fs_file
fs_name=$(basename "$fs_file")
shasum -a 256 "$fs_file" | awk '{print $1}' > "${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${fs_name}.sha256"
cat "${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${fs_name}.sha256"
- name: Copy all artifacts to output folder
run: cp .pio/build/${{ matrix.chip.name }}_${{ matrix.epd_variant }}/*.bin .pio/boot_app0.bin ${{ matrix.chip.name }}_${{ matrix.epd_variant }}
- name: Create OTA binary file
run: mv ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/firmware.bin ${{ matrix.chip.name }}_${{ matrix.epd_variant }}/${{ matrix.chip.name }}_${{ matrix.epd_variant }}_firmware.bin
- name: Upload artifacts
uses: https://code.forgejo.org/forgejo/upload-artifact@v4
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: docker
permissions:
contents: write
checks: write
needs: merge
steps:
- name: Download matrix outputs
uses: https://code.forgejo.org/forgejo/download-artifact@v4
with:
pattern: build-*
merge-multiple: false
path: temp
- name: Copy files
run: |
mkdir -p release
find temp -type f \( -name "*.bin" -o -name "*.sha256" \) -exec cp -f {} release/ \;
- name: Create release
uses: https://code.forgejo.org/actions/forgejo-release@v2.4.0
with:
url: "https://git.btclock.dev"
repo: "${{ github.repository }}"
direction: upload
tag: "${{ github.ref_name }}"
sha: "${{ github.sha }}"
release-dir: release
token: ${{ secrets.TOKEN }}
override: ${{ github.ref_type != 'tag' && github.ref_name != 'main' }}
prerelease: ${{ github.ref_type != 'tag' && github.ref_name != 'main' }}
release-notes-assistant: false

1
.gitignore vendored
View file

@ -11,4 +11,3 @@ data/node_modules
node_modules node_modules
.DS_Store .DS_Store
*.bin *.bin
ci/cache

2
.gitmodules vendored
View file

@ -1,3 +1,3 @@
[submodule "data"] [submodule "data"]
path = data path = data
url = https://git.btclock.dev/btclock/webui.git url = https://github.com/btclock/webui.git

View file

@ -1,8 +1,6 @@
# BTClock v3 # BTClock v3
[![Latest release](https://git.btclock.dev/btclock/btclock_v3/badges/release.svg)](https://git.btclock.dev/btclock/btclock_v3/releases/latest) [![BTClock CI](https://github.com/btclock/btclock_v3/actions/workflows/tagging.yml/badge.svg)](https://github.com/btclock/btclock_v3/actions/workflows/tagging.yml)
[![BTClock CI](https://git.btclock.dev/btclock/btclock_v3/badges/workflows/push.yaml/badge.svg)](https://git.btclock.dev/btclock/btclock_v3/actions?workflow=push.yaml&actor=0&status=0)
Software for the BTClock project. Software for the BTClock project.

View file

@ -1,15 +0,0 @@
# Use the official Python 3.9 image as the base
FROM python:3.9-slim
# Set the working directory
WORKDIR /workspace
RUN apt-get update && apt-get install -y git
# Install PlatformIO
RUN pip install platformio
WORKDIR /usr/src
CMD ["platformio", "run"]

2
data

@ -1 +1 @@
Subproject commit 85b9b17506f89696b89ab6f6e6ed231b7a8f6e91 Subproject commit 95aa9d67d17dde32dab3216810e7b4e4086feb03

View file

@ -4,6 +4,6 @@ dependencies:
source: source:
type: idf type: idf
version: 4.4.7 version: 4.4.7
manifest_hash: cd2f3ee15e776d949eb4ea4eddc8f39b30c2a7905050850eed01ab4928143cff manifest_hash: 841ba2a95f4b32d39636bf4fdf07c48a2052f71c9728a5b7f263083a3b430a4f
target: esp32s3 target: esp32s3
version: 1.0.0 version: 1.0.0

View file

@ -9,7 +9,7 @@ std::array<std::string, NUM_SCREENS> parseBitaxeHashRate(std::string text)
// Calculate the position where the digits should start // Calculate the position where the digits should start
// Account for the position of the "mdi:pickaxe" and the "GH/S" label // Account for the position of the "mdi:pickaxe" and the "GH/S" label
std::size_t startIndex = NUM_SCREENS - 1 - textLength; std::size_t startIndex = NUM_SCREENS - textLength;
// Insert the "mdi:pickaxe" icon just before the digits // Insert the "mdi:pickaxe" icon just before the digits
if (startIndex > 0) if (startIndex > 0)
@ -23,8 +23,10 @@ std::array<std::string, NUM_SCREENS> parseBitaxeHashRate(std::string text)
ret[startIndex + i] = text.substr(i, 1); ret[startIndex + i] = text.substr(i, 1);
} }
ret[NUM_SCREENS - 1] = "GH/S"; char lastChar = text[textLength - 1];
ret[0] = "mdi:bitaxe";
ret[NUM_SCREENS - 1] = std::string(1, lastChar) + "H/S";
ret[0] = "BIT/AXE";
return ret; return ret;
} }
@ -37,7 +39,7 @@ std::array<std::string, NUM_SCREENS> parseBitaxeBestDiff(std::string text)
if (text.length() < NUM_SCREENS) if (text.length() < NUM_SCREENS)
{ {
text.insert(text.begin(), NUM_SCREENS - text.length(), ' '); text.insert(text.begin(), NUM_SCREENS - text.length(), ' ');
ret[0] = "mdi:bitaxe"; ret[0] = "BIT/AXE";
ret[1] = "mdi:rocket"; ret[1] = "mdi:rocket";
firstIndex = 2; firstIndex = 2;
} }

View file

@ -67,72 +67,33 @@ char getCurrencyChar(const std::string& input)
return CURRENCY_USD; // Assuming USD is the default for unknown inputs return CURRENCY_USD; // Assuming USD is the default for unknown inputs
} }
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currencySymbol, bool useSuffixFormat, bool mowMode, bool shareDot) std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currencySymbol, bool useSuffixFormat)
{ {
std::array<std::string, NUM_SCREENS> ret; std::array<std::string, NUM_SCREENS> ret;
std::string priceString; std::string priceString;
if (std::to_string(price).length() >= NUM_SCREENS || useSuffixFormat) if (std::to_string(price).length() >= NUM_SCREENS || useSuffixFormat)
{ {
int numScreens = shareDot || mowMode ? NUM_SCREENS - 1 : NUM_SCREENS - 2; priceString = getCurrencySymbol(currencySymbol) + formatNumberWithSuffix(price, NUM_SCREENS - 2);
priceString = getCurrencySymbol(currencySymbol) + formatNumberWithSuffix(price, numScreens, mowMode);
} }
else else
{ {
priceString = getCurrencySymbol(currencySymbol) + std::to_string(price); priceString = getCurrencySymbol(currencySymbol) + std::to_string(price);
} }
std::uint32_t firstIndex = 0; std::uint32_t firstIndex = 0;
if ((shareDot && priceString.length() <= (NUM_SCREENS)) || priceString.length() < (NUM_SCREENS)) if (priceString.length() < (NUM_SCREENS))
{ {
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' '); priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
if (mowMode)
{
ret[0] = "MOW/UNITS";
}
else
{
ret[0] = "BTC/" + getCurrencyCode(currencySymbol); ret[0] = "BTC/" + getCurrencyCode(currencySymbol);
}
firstIndex = 1; firstIndex = 1;
} }
size_t dotPosition = priceString.find('.');
if (shareDot && dotPosition != std::string::npos && dotPosition > 0)
{
std::vector<std::string> tempArray;
if (dotPosition != std::string::npos && dotPosition > 0)
{
for (size_t i = 0; i < priceString.length(); ++i)
{
if (i == dotPosition - 1)
{
tempArray.push_back(std::string(1, priceString[i]) + ".");
++i; // Skip the dot in the next iteration
}
else
{
tempArray.push_back(std::string(1, priceString[i]));
}
}
// Copy from tempArray to ret
for (std::uint32_t i = firstIndex; i < NUM_SCREENS && i - firstIndex < tempArray.size(); ++i)
{
ret[i] = tempArray[i - firstIndex];
}
}
}
else
{
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++) for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
{ {
ret[i] = std::string(1, priceString[i]); ret[i] = priceString[i];
} }
}
return ret; return ret;
} }
@ -145,27 +106,10 @@ std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price,ch
std::uint8_t insertSatSymbol = NUM_SCREENS - priceString.length() - 1; std::uint8_t insertSatSymbol = NUM_SCREENS - priceString.length() - 1;
if (priceString.length() < (NUM_SCREENS)) if (priceString.length() < (NUM_SCREENS))
{
// Check if price is greater than 1 billion
if (price >= 100000000)
{
double satsPerCurrency = (1.0 / static_cast<double>(price)) * 1e8; // Calculate satoshis
std::ostringstream oss;
oss << std::fixed << std::setprecision(3) << satsPerCurrency; // Format with 3 decimal places
priceString = oss.str();
}
else
{
priceString = std::to_string(static_cast<int>(round(1.0 / static_cast<double>(price) * 1e8))); // Default formatting
}
// Pad the string with spaces if necessary
if (priceString.length() < NUM_SCREENS)
{ {
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' '); priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
}
if (currencySymbol != CURRENCY_USD || price >= 100000000) // no time anymore when earlier than 1 if (currencySymbol != CURRENCY_USD)
ret[0] = "SATS/" + getCurrencyCode(currencySymbol); ret[0] = "SATS/" + getCurrencyCode(currencySymbol);
else else
ret[0] = "MSCW/TIME"; ret[0] = "MSCW/TIME";
@ -348,9 +292,9 @@ emscripten::val parseBlockHeightArray(std::uint32_t blockHeight)
return arrayToStringArray(parseBlockHeight(blockHeight)); return arrayToStringArray(parseBlockHeight(blockHeight));
} }
emscripten::val parsePriceDataArray(std::uint32_t price, const std::string &currencySymbol, bool useSuffixFormat = false, bool mowMode = false, bool shareDot = false) emscripten::val parsePriceDataArray(std::uint32_t price, const std::string &currencySymbol, bool useSuffixFormat = false)
{ {
return arrayToStringArray(parsePriceData(price, currencySymbol[0], useSuffixFormat, mowMode, shareDot)); return arrayToStringArray(parsePriceData(price, currencySymbol[0], useSuffixFormat));
} }
emscripten::val parseHalvingCountdownArray(std::uint32_t blockHeight, bool asBlocks) emscripten::val parseHalvingCountdownArray(std::uint32_t blockHeight, bool asBlocks)

View file

@ -2,7 +2,6 @@
#include <string> #include <string>
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <vector>
#include "utils.hpp" #include "utils.hpp"
@ -20,7 +19,7 @@ const std::string CURRENCY_CODE_JPY = "JPY";
const std::string CURRENCY_CODE_AUD = "AUD"; const std::string CURRENCY_CODE_AUD = "AUD";
const std::string CURRENCY_CODE_CAD = "CAD"; const std::string CURRENCY_CODE_CAD = "CAD";
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currency, bool useSuffixFormat = false, bool mowMode = false, bool shareDot = false); std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currency, bool useSuffixFormat = false);
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol); std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol);
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight); std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight);
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks); std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks);

View file

@ -29,11 +29,6 @@ double getSupplyAtBlock(std::uint32_t blockNr)
} }
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters) std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters)
{
return formatNumberWithSuffix(num, numCharacters, false);
}
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters, bool mowMode)
{ {
static char result[20]; // Adjust size as needed static char result[20]; // Adjust size as needed
const long long quadrillion = 1000000000000000LL; const long long quadrillion = 1000000000000000LL;
@ -61,53 +56,30 @@ std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters, bool mo
numDouble /= billion; numDouble /= billion;
suffix = 'B'; suffix = 'B';
} }
else if (num >= million || numDigits > 6 || (mowMode && num >= thousand)) else if (num >= million || numDigits > 6)
{ {
numDouble /= million; numDouble /= million;
suffix = 'M'; suffix = 'M';
} }
else if (!mowMode && (num >= thousand || numDigits > 3)) else if (num >= thousand || numDigits > 3)
{ {
numDouble /= thousand; numDouble /= thousand;
suffix = 'K'; suffix = 'K';
} }
else if (!mowMode) else
{ {
snprintf(result, sizeof(result), "%llu", (unsigned long long)num); snprintf(result, sizeof(result), "%llu", (unsigned long long)num);
// sprintf(result, "%llu", (unsigned long long)num);
return result; return result;
} }
else // mowMode is true and num < 1000
{
numDouble /= million;
suffix = 'M';
}
// Add suffix // Add suffix
int len; int len = snprintf(result, sizeof(result), "%.0f%c", numDouble, suffix);
// Mow Mode always uses string truncation to avoid rounding // If there's room, add decimal places
std::string mowAsString = std::to_string(numDouble);
if (mowMode) {
// Default to one decimal place
len = snprintf(result, sizeof(result), "%s%c", mowAsString.substr(0, mowAsString.find(".") + 2).c_str(), suffix);
}
else
{
len = snprintf(result, sizeof(result), "%.0f%c", numDouble, suffix);
}
// If there's room, add more decimal places
if (len < numCharacters) if (len < numCharacters)
{ {
int restLen = mowMode ? numCharacters - len : numCharacters - len - 1; snprintf(result, sizeof(result), "%.*f%c", numCharacters - len - 1, numDouble, suffix);
if (mowMode) {
snprintf(result, sizeof(result), "%s%c", mowAsString.substr(0, mowAsString.find(".") + 2 + restLen).c_str(), suffix);
}
else
{
snprintf(result, sizeof(result), "%.*f%c", restLen, numDouble, suffix);
}
} }
return result; return result;

View file

@ -11,5 +11,4 @@ int modulo(int x,int N);
double getSupplyAtBlock(std::uint32_t blockNr); double getSupplyAtBlock(std::uint32_t blockNr);
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters = 4); std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters = 4);
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters, bool mowMode);
int64_t getAmountInSatoshis(std::string bolt11); int64_t getAmountInSatoshis(std::string bolt11);

View file

@ -1,20 +0,0 @@
identifier: BTClock
maintainers:
- npub1k5f85zx0xdskyayqpfpc0zq6n7vwqjuuxugkayk72fgynp34cs3qfcvqg2
relays:
- wss://relay.noderunners.network/
- wss://nostr.sathoarder.com/
- wss://offchain.pub/
- wss://nostr3.daedaluslabs.io/
- wss://nostr4.daedaluslabs.io/
- wss://nostr.dbtc.link/
- wss://purplepag.es/
- wss://nos.lol/
- wss://nostr1.daedaluslabs.io/
- wss://nostr.noderunners.network/
- wss://nostr.lnbitcoin.cz/
- wss://relay.primal.net/
- wss://relay.damus.io
- wss://nostr-relay.derekross.me/
- wss://nostr2.azzamo.net/
- wss://nostr2.daedaluslabs.io/

View file

@ -1,7 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000, nvs, data, nvs, 36K, 20K,
otadata, data, ota, 0xe000, 0x2000, otadata, data, ota, 56K, 8K,
app0, app, ota_0, 0x10000, 0x1b8000, app0, app, ota_0, 64K, 1700K,
app1, app, ota_1, , 0x1b8000, app1, app, ota_1, , 1700K,
spiffs, data, spiffs, , 0x66C00, spiffs, data, spiffs, , 400K,
coredump, data, coredump,, 0x10000, coredump, data, coredump,, 64K,

1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 36K 0x5000 20K
3 otadata data ota 0xe000 56K 0x2000 8K
4 app0 app ota_0 0x10000 64K 0x1b8000 1700K
5 app1 app ota_1 0x1b8000 1700K
6 spiffs data spiffs 0x66C00 400K
7 coredump data coredump 0x10000 64K

View file

@ -1,7 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000, nvs, data, nvs, 36K, 20K,
otadata, data, ota, 0xe000, 0x2000, otadata, data, ota, 56K, 8K,
app0, app, ota_0, 0x10000, 0x6F0000, app0, app, ota_0, 64K, 4096K,
app1, app, ota_1, , 0x6F0000, app1, app, ota_1, , 4096K,
spiffs, data, spiffs, , 0x200000, spiffs, data, spiffs, , 400K,
coredump, data, coredump,, 0x10000, coredump, data, coredump,, 64K,

1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 36K 0x5000 20K
3 otadata data ota 0xe000 56K 0x2000 8K
4 app0 app ota_0 0x10000 64K 0x6F0000 4096K
5 app1 app ota_1 0x6F0000 4096K
6 spiffs data spiffs 0x200000 400K
7 coredump data coredump 0x10000 64K

View file

@ -1,7 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000, nvs, data, nvs, 36K, 20K,
otadata, data, ota, 0xe000, 0x2000, otadata, data, ota, 56K, 8K,
app0, app, ota_0, 0x10000, 0x370000, app0, app, ota_0, 64K, 1700K,
app1, app, ota_1, , 0x370000, app1, app, ota_1, , 1700K,
spiffs, data, spiffs, , 0xCD000, spiffs, data, spiffs, , 400K,
coredump, data, coredump,, 0x10000, coredump, data, coredump,, 64K,

1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 36K 0x5000 20K
3 otadata data ota 0xe000 56K 0x2000 8K
4 app0 app ota_0 0x10000 64K 0x370000 1700K
5 app1 app ota_1 0x370000 1700K
6 spiffs data spiffs 0xCD000 400K
7 coredump data coredump 0x10000 64K

View file

@ -15,14 +15,12 @@ default_envs = lolin_s3_mini_213epd, lolin_s3_mini_29epd, btclock_rev_b_213epd,
[btclock_base] [btclock_base]
platform = espressif32 @ ^6.9.0 platform = espressif32 @ ^6.8.1
framework = arduino, espidf framework = arduino, espidf
monitor_speed = 115200 monitor_speed = 115200
monitor_filters = esp32_exception_decoder, colorize monitor_filters = esp32_exception_decoder, colorize
board_build.filesystem = littlefs board_build.filesystem = littlefs
extra_scripts = pre:scripts/pre_script.py, post:scripts/extra_script.py extra_scripts = post:scripts/extra_script.py
board_build.embed_files =
x509_crt_bundle
build_flags = build_flags =
!python scripts/git_rev.py !python scripts/git_rev.py
-DLAST_BUILD_TIME=$UNIX_TIME -DLAST_BUILD_TIME=$UNIX_TIME
@ -34,11 +32,12 @@ build_unflags =
-fno-exceptions -fno-exceptions
lib_deps = lib_deps =
https://github.com/joltwallet/esp_littlefs.git https://github.com/joltwallet/esp_littlefs.git
bblanchon/ArduinoJson@^7.2.1 bblanchon/ArduinoJson@^7.1.0
mathieucarbou/ESPAsyncWebServer @ 3.3.23 mathieucarbou/ESPAsyncWebServer @ 3.3.1
robtillaart/MCP23017@^0.8.0 adafruit/Adafruit BusIO@^1.16.1
adafruit/Adafruit MCP23017 Arduino Library@^2.3.2
adafruit/Adafruit NeoPixel@^1.12.3 adafruit/Adafruit NeoPixel@^1.12.3
https://github.com/dsbaars/universal_pin#feature/mcp23017_rt https://github.com/dsbaars/universal_pin
https://github.com/dsbaars/GxEPD2#universal_pin https://github.com/dsbaars/GxEPD2#universal_pin
https://github.com/tzapu/WiFiManager.git#v2.0.17 https://github.com/tzapu/WiFiManager.git#v2.0.17
rblb/Nostrduino@1.2.8 rblb/Nostrduino@1.2.8
@ -64,7 +63,7 @@ build_unflags =
[env:btclock_rev_b] [env:btclock_rev_b]
extends = btclock_base extends = btclock_base
board = btclock_rev_b board = btclock_rev_b
board_build.partitions = partition_8mb.csv board_build.partitions = partition.csv
build_flags = build_flags =
${btclock_base.build_flags} ${btclock_base.build_flags}
-D MCP_INT_PIN=8 -D MCP_INT_PIN=8

View file

@ -1 +0,0 @@
platformio

View file

@ -5,9 +5,6 @@ from shutil import copyfileobj, rmtree
from pathlib import Path from pathlib import Path
import subprocess import subprocess
revision = ( revision = (
subprocess.check_output(["git", "rev-parse", "HEAD"]) subprocess.check_output(["git", "rev-parse", "HEAD"])
.strip() .strip()
@ -46,15 +43,5 @@ def before_buildfs(source, target, env):
output_directory = 'data/build_gz' output_directory = 'data/build_gz'
process_directory(input_directory, output_directory) process_directory(input_directory, output_directory)
flash_size = env.BoardConfig().get("upload.flash_size", "4MB")
fs_image_name = f"littlefs_{flash_size}"
env.Replace(ESP32_FS_IMAGE_NAME=fs_image_name)
env.Replace(ESP8266_FS_IMAGE_NAME=fs_image_name)
os.environ["PUBLIC_BASE_URL"] = "" os.environ["PUBLIC_BASE_URL"] = ""
fs_name = env.get("ESP32_FS_IMAGE_NAME", "littlefs.bin") env.AddPreAction("$BUILD_DIR/littlefs.bin", before_buildfs)
# Or alternatively:
# fs_name = env.get("FSTOOLNAME", "littlefs.bin")
# Use the variable in the pre-action
env.AddPreAction(f"$BUILD_DIR/{fs_name}.bin", before_buildfs)

View file

@ -1,7 +0,0 @@
Import("env")
flash_size = env.BoardConfig().get("upload.flash_size", "4MB")
fs_image_name = f"littlefs_{flash_size}"
env.Replace(ESP32_FS_IMAGE_NAME=fs_image_name)
env.Replace(ESP8266_FS_IMAGE_NAME=fs_image_name)

View file

@ -1015,267 +1015,11 @@ const unsigned char epd_icons_flash [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0
}; };
// 'bitaxe_logo', 122x250px
const unsigned char epd_icons_bitaxe_logo [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xcf, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0x83, 0xff, 0xff, 0xf7, 0xf0, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xf1, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xcf, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x07, 0xf9, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x07, 0xf8, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0xff, 0xff, 0x8f, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0x8f, 0xf7, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x11, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x9f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xfb, 0xf0, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xf7, 0xf8, 0x3f, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xf1, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0x83, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xef, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xff, 0xff, 0x83, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x1f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfe, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfc, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf8, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf0, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf0, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf8, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfc, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfe, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xbf, 0xff, 0x01, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x7f, 0xc1, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xfc, 0x03, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfc, 0x03, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xe0, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x81, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfc, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xfd, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0xfb, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xf3, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0xe7, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0x8f, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0x82, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 8032) // Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 8032)
const int epd_icons_allArray_LEN = 5; const int epd_icons_allArray_LEN = 4;
const unsigned char* epd_icons_allArray[epd_icons_allArray_LEN] = { const unsigned char* epd_icons_allArray[epd_icons_allArray_LEN] = {
epd_icons_pickaxe, epd_icons_pickaxe,
epd_icons_rocket_launch, epd_icons_rocket_launch,
epd_icons_lightning, epd_icons_lightning,
epd_icons_flash, epd_icons_flash
epd_icons_bitaxe_logo
}; };

View file

@ -17,14 +17,18 @@ std::string getBitaxeBestDiff()
void taskBitaxeFetch(void *pvParameters) void taskBitaxeFetch(void *pvParameters)
{ {
WiFiClientSecure client;
client.setCACert(srpool_ca);
for (;;) for (;;)
{ {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
HTTPClient http; HTTPClient http;
http.setUserAgent(USER_AGENT); http.setUserAgent(USER_AGENT);
String bitaxeApiUrl = "http://" + preferences.getString("bitaxeHostname", DEFAULT_BITAXE_HOSTNAME) + "/api/system/info"; String bitaxeApiUrl = preferences.getString("bitaxeHostname", DEFAULT_BITAXE_HOSTNAME);
http.begin(bitaxeApiUrl.c_str()); http.begin(client, bitaxeApiUrl.c_str());
int httpCode = http.GET(); int httpCode = http.GET();
@ -33,8 +37,8 @@ void taskBitaxeFetch(void *pvParameters)
String payload = http.getString(); String payload = http.getString();
JsonDocument doc; JsonDocument doc;
deserializeJson(doc, payload); deserializeJson(doc, payload);
bitaxeHashrate = std::to_string(static_cast<int>(std::round(doc["hashRate"].as<float>()))); bitaxeHashrate = doc["hashrate1m"].as<std::string>();
bitaxeBestDiff = doc["bestDiff"].as<std::string>(); bitaxeBestDiff = formatNumberWithSuffix(doc["bestever"].as<uint64_t>());
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BITAXE_HASHRATE || getCurrentScreen() == SCREEN_BITAXE_BESTDIFF)) if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BITAXE_HASHRATE || getCurrentScreen() == SCREEN_BITAXE_BESTDIFF))
{ {

View file

@ -2,7 +2,7 @@
char *wsServer; char *wsServer;
esp_websocket_client_handle_t blockNotifyClient = NULL; esp_websocket_client_handle_t blockNotifyClient = NULL;
uint currentBlockHeight = 873400; uint currentBlockHeight = 860000;
uint blockMedianFee = 1; uint blockMedianFee = 1;
bool blockNotifyInit = false; bool blockNotifyInit = false;
unsigned long int lastBlockUpdate; unsigned long int lastBlockUpdate;
@ -302,7 +302,7 @@ int getBlockFetch()
WiFiClientSecure client; WiFiClientSecure client;
if (preferences.getBool("mempoolSecure", DEFAULT_MEMPOOL_SECURE)) { if (preferences.getBool("mempoolSecure", DEFAULT_MEMPOOL_SECURE)) {
client.setCACertBundle(rootca_crt_bundle_start); client.setCACert(mempoolWsCert);
} }
String mempoolInstance = String mempoolInstance =

View file

@ -5,15 +5,15 @@ const TickType_t debounceDelay = pdMS_TO_TICKS(50);
TickType_t lastDebounceTime = 0; TickType_t lastDebounceTime = 0;
#ifdef IS_BTCLOCK_V8 #ifdef IS_BTCLOCK_V8
#define BTN_1 256 #define BTN_1 0
#define BTN_2 512 #define BTN_2 1
#define BTN_3 1024 #define BTN_3 2
#define BTN_4 2048 #define BTN_4 3
#else #else
#define BTN_1 2048 #define BTN_1 3
#define BTN_2 1024 #define BTN_2 2
#define BTN_3 512 #define BTN_3 1
#define BTN_4 256 #define BTN_4 0
#endif #endif
void buttonTask(void *parameter) { void buttonTask(void *parameter) {
@ -22,12 +22,11 @@ void buttonTask(void *parameter) {
std::lock_guard<std::mutex> lock(mcpMutex); std::lock_guard<std::mutex> lock(mcpMutex);
TickType_t currentTime = xTaskGetTickCount(); TickType_t currentTime = xTaskGetTickCount();
if ((currentTime - lastDebounceTime) >= debounceDelay) { if ((currentTime - lastDebounceTime) >= debounceDelay) {
lastDebounceTime = currentTime; lastDebounceTime = currentTime;
if (!digitalRead(MCP_INT_PIN)) { if (!digitalRead(MCP_INT_PIN)) {
uint pin = mcp1.getInterruptFlagRegister(); uint pin = mcp1.getLastInterruptPin();
switch (pin) { switch (pin) {
case BTN_1: case BTN_1:
@ -44,12 +43,12 @@ void buttonTask(void *parameter) {
break; break;
} }
} }
mcp1.getInterruptCaptureRegister(); mcp1.clearInterrupts();
} else { } else {
} }
// Very ugly, but for some reason this is necessary // Very ugly, but for some reason this is necessary
while (!digitalRead(MCP_INT_PIN)) { while (!digitalRead(MCP_INT_PIN)) {
mcp1.getInterruptCaptureRegister(); mcp1.clearInterrupts();
} }
} }
} }

View file

@ -2,12 +2,10 @@
#define MAX_ATTEMPTS_WIFI_CONNECTION 20 #define MAX_ATTEMPTS_WIFI_CONNECTION 20
// zlib_turbo zt;
Preferences preferences; Preferences preferences;
MCP23017 mcp1(0x20); Adafruit_MCP23X17 mcp1;
#ifdef IS_BTCLOCK_V8 #ifdef IS_BTCLOCK_V8
MCP23017 mcp2(0x21); Adafruit_MCP23X17 mcp2;
#endif #endif
#ifdef HAS_FRONTLIGHT #ifdef HAS_FRONTLIGHT
@ -37,7 +35,7 @@ void setup()
} }
{ {
std::lock_guard<std::mutex> lockMcp(mcpMutex); std::lock_guard<std::mutex> lockMcp(mcpMutex);
if (mcp1.read1(3) == LOW) if (mcp1.digitalRead(3) == LOW)
{ {
preferences.putBool("wifiConfigured", false); preferences.putBool("wifiConfigured", false);
preferences.remove("txPower"); preferences.remove("txPower");
@ -48,7 +46,7 @@ void setup()
} }
{ {
if (mcp1.read1(0) == LOW) if (mcp1.digitalRead(0) == LOW)
{ {
// Then loop forever to prevent anything else from writing to the screen // Then loop forever to prevent anything else from writing to the screen
while (true) while (true)
@ -56,7 +54,7 @@ void setup()
delay(1000); delay(1000);
} }
} }
else if (mcp1.read1(1) == LOW) else if (mcp1.digitalRead(1) == LOW)
{ {
preferences.clear(); preferences.clear();
queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS); queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
@ -68,7 +66,6 @@ void setup()
} }
setupWifi(); setupWifi();
// loadIcons();
setupWebserver(); setupWebserver();
@ -109,7 +106,6 @@ void setup()
#endif #endif
forceFullRefresh(); forceFullRefresh();
} }
void setupWifi() void setupWifi()
@ -136,7 +132,7 @@ void setupWifi()
bool buttonPress = false; bool buttonPress = false;
{ {
std::lock_guard<std::mutex> lockMcp(mcpMutex); std::lock_guard<std::mutex> lockMcp(mcpMutex);
buttonPress = (mcp1.read1(2) == LOW); buttonPress = (mcp1.digitalRead(2) == LOW);
} }
{ {
@ -149,7 +145,7 @@ void setupWifi()
WiFi.setHostname(softAP_SSID.c_str()); WiFi.setHostname(softAP_SSID.c_str());
String softAP_password = replaceAmbiguousChars( String softAP_password = replaceAmbiguousChars(
base64::encode(String(mac[2], 16) + String(mac[4], 16) + base64::encode(String(mac[2], 16) + String(mac[4], 16) +
String(mac[5], 16) + String(mac[1], 16) + String(mac[3], 16)) String(mac[5], 16) + String(mac[1], 16))
.substring(2, 10)); .substring(2, 10));
wm.setConfigPortalTimeout(preferences.getUInt("wpTimeout", DEFAULT_WP_TIMEOUT)); wm.setConfigPortalTimeout(preferences.getUInt("wpTimeout", DEFAULT_WP_TIMEOUT));
@ -159,10 +155,10 @@ void setupWifi()
wm.setAPCallback([&](WiFiManager *wifiManager) wm.setAPCallback([&](WiFiManager *wifiManager)
{ {
Serial.printf("Entered config mode:ip=%s, ssid='%s', pass='%s'\n", // Serial.printf("Entered config mode:ip=%s, ssid='%s', pass='%s'\n",
WiFi.softAPIP().toString().c_str(), // WiFi.softAPIP().toString().c_str(),
wifiManager->getConfigPortalSSID().c_str(), // wifiManager->getConfigPortalSSID().c_str(),
softAP_password.c_str()); // softAP_password.c_str());
// delay(6000); // delay(6000);
setFgColor(GxEPD_BLACK); setFgColor(GxEPD_BLACK);
setBgColor(GxEPD_WHITE); setBgColor(GxEPD_WHITE);
@ -288,10 +284,6 @@ void setupPreferences()
preferences.putBool("flDisable", isWhiteVersion() ? false : true); preferences.putBool("flDisable", isWhiteVersion() ? false : true);
} }
if (!preferences.isKey("gitReleaseUrl")) {
preferences.putString("gitReleaseUrl", DEFAULT_GIT_RELEASE_URL);
}
if (!preferences.isKey("fgColor")) { if (!preferences.isKey("fgColor")) {
preferences.putUInt("fgColor", isWhiteVersion() ? GxEPD_BLACK : GxEPD_WHITE); preferences.putUInt("fgColor", isWhiteVersion() ? GxEPD_BLACK : GxEPD_WHITE);
preferences.putUInt("bgColor", isWhiteVersion() ? GxEPD_WHITE : GxEPD_BLACK); preferences.putUInt("bgColor", isWhiteVersion() ? GxEPD_WHITE : GxEPD_BLACK);
@ -511,7 +503,7 @@ void setupHardware()
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000); Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
if (!mcp1.begin()) if (!mcp1.begin_I2C(0x20))
{ {
Serial.println(F("Error MCP23017 1")); Serial.println(F("Error MCP23017 1"));
@ -521,20 +513,17 @@ void setupHardware()
else else
{ {
pinMode(MCP_INT_PIN, INPUT_PULLUP); pinMode(MCP_INT_PIN, INPUT_PULLUP);
// mcp1.setupInterrupts(false, false, LOW); mcp1.setupInterrupts(false, false, LOW);
mcp1.enableControlRegister(MCP23x17_IOCR_ODR);
mcp1.mirrorInterrupts(true);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
mcp1.pinMode1(i, INPUT_PULLUP); mcp1.pinMode(i, INPUT_PULLUP);
mcp1.enableInterrupt(i, LOW); mcp1.setupInterruptPin(i, LOW);
} }
#ifndef IS_BTCLOCK_V8 #ifndef IS_BTCLOCK_V8
for (int i = 8; i <= 14; i++) for (int i = 8; i <= 14; i++)
{ {
mcp1.pinMode1(i, OUTPUT); mcp1.pinMode(i, OUTPUT);
} }
#endif #endif
} }
@ -545,7 +534,7 @@ void setupHardware()
#endif #endif
#ifdef IS_BTCLOCK_V8 #ifdef IS_BTCLOCK_V8
if (!mcp2.begin()) if (!mcp2.begin_I2C(0x21))
{ {
Serial.println(F("Error MCP23017 2")); Serial.println(F("Error MCP23017 2"));
@ -798,31 +787,3 @@ const char* getFirmwareFilename() {
return ""; return "";
} }
} }
const char* getWebUiFilename() {
if (HW_REV == "REV_B_EPD_2_13") {
return "littlefs_8MB.bin";
} else if (HW_REV == "REV_A_EPD_2_13") {
return "littlefs_4MB.bin";
} else if (HW_REV == "REV_A_EPD_2_9") {
return "littlefs_4MB.bin";
} else {
return "littlefs_4MB.bin";
}
}
// void loadIcons() {
// size_t ocean_logo_size = 886;
// int iUncompSize = zt.gzip_info((uint8_t *)epd_compress_bitaxe, ocean_logo_size);
// Serial.printf("uncompressed size = %d\n", iUncompSize);
// uint8_t *pUncompressed;
// pUncompressed = (uint8_t *)malloc(iUncompSize+4);
// int rc = zt.gunzip((uint8_t *)epd_compress_bitaxe, ocean_logo_size, pUncompressed);
// if (rc == ZT_SUCCESS) {
// Serial.println("Decode success");
// }
// }

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <MCP23017.h> #include <Adafruit_MCP23X17.h>
#include <Arduino.h> #include <Arduino.h>
#include <Preferences.h> #include <Preferences.h>
#include <WiFiClientSecure.h> #include <WiFiClientSecure.h>
@ -84,5 +84,3 @@ void addScreenMapping(int value, const char* name);
int findScreenIndexByValue(int value); int findScreenIndexByValue(int value);
String replaceAmbiguousChars(String input); String replaceAmbiguousChars(String input);
const char* getFirmwareFilename(); const char* getFirmwareFilename();
const char* getWebUiFilename();
// void loadIcons();

View file

@ -18,9 +18,6 @@
#define DEFAULT_DISABLE_FL false #define DEFAULT_DISABLE_FL false
#define DEFAULT_OWN_DATA_SOURCE true #define DEFAULT_OWN_DATA_SOURCE true
#define DEFAULT_STAGING_SOURCE false #define DEFAULT_STAGING_SOURCE false
#define DEFAULT_MOW_MODE false
#define DEFAULT_SUFFIX_SHARE_DOT false
#define DEFAULT_V2_SOURCE_CURRENCY CURRENCY_USD #define DEFAULT_V2_SOURCE_CURRENCY CURRENCY_USD
@ -45,8 +42,6 @@
#define DEFAULT_FL_EFFECT_DELAY 15 #define DEFAULT_FL_EFFECT_DELAY 15
#define DEFAULT_LUX_LIGHT_TOGGLE 128 #define DEFAULT_LUX_LIGHT_TOGGLE 128
#define DEFAULT_FL_OFF_WHEN_DARK true
#define DEFAULT_FL_ALWAYS_ON false #define DEFAULT_FL_ALWAYS_ON false
#define DEFAULT_FL_FLASH_ON_UPDATE false #define DEFAULT_FL_FLASH_ON_UPDATE false
@ -60,14 +55,9 @@
#define DEFAULT_ZAP_NOTIFY_ENABLED false #define DEFAULT_ZAP_NOTIFY_ENABLED false
#define DEFAULT_ZAP_NOTIFY_PUBKEY "b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422" #define DEFAULT_ZAP_NOTIFY_PUBKEY "b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422"
#define DEFAULT_LED_FLASH_ON_ZAP true
#define DEFAULT_FL_FLASH_ON_ZAP true
#define DEFAULT_HTTP_AUTH_ENABLED false #define DEFAULT_HTTP_AUTH_ENABLED false
#define DEFAULT_HTTP_AUTH_USERNAME "btclock" #define DEFAULT_HTTP_AUTH_USERNAME "btclock"
#define DEFAULT_HTTP_AUTH_PASSWORD "satoshi" #define DEFAULT_HTTP_AUTH_PASSWORD "satoshi"
#define DEFAULT_ACTIVE_CURRENCIES "USD,EUR,JPY" #define DEFAULT_ACTIVE_CURRENCIES "USD,EUR,JPY"
#define DEFAULT_GIT_RELEASE_URL "https://git.btclock.dev/api/v1/repos/btclock/btclock_v3/releases/latest"
#define DEFAULT_VERTICAL_DESC true

View file

@ -191,7 +191,7 @@ void setupDisplays()
} }
// Hold lower button to enable "storage mode" (prevents burn-in of ePaper displays) // Hold lower button to enable "storage mode" (prevents burn-in of ePaper displays)
if (mcp1.read1(0) == LOW) if (mcp1.digitalRead(0) == LOW)
{ {
setFgColor(GxEPD_BLACK); setFgColor(GxEPD_BLACK);
setBgColor(GxEPD_WHITE); setBgColor(GxEPD_WHITE);
@ -283,10 +283,7 @@ void prepareDisplayUpdateTask(void *pvParameters)
} }
else else
{ {
if (epdContent[epdIndex].length() == 2) { if (epdContent[epdIndex].length() > 1 && epdContent[epdIndex].indexOf(".") == -1)
showChars(epdIndex, epdContent[epdIndex], updatePartial, &FONT_BIG);
}
else if (epdContent[epdIndex].length() > 1 && epdContent[epdIndex].indexOf(".") == -1)
{ {
if (epdContent[epdIndex].equals("STS")) if (epdContent[epdIndex].equals("STS"))
{ {
@ -373,11 +370,7 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
void splitText(const uint dispNum, const String &top, const String &bottom, void splitText(const uint dispNum, const String &top, const String &bottom,
bool partial) bool partial)
{ {
if(preferences.getBool("verticalDesc", DEFAULT_VERTICAL_DESC) && dispNum == 0) {
displays[dispNum].setRotation(1);
} else {
displays[dispNum].setRotation(2); displays[dispNum].setRotation(2);
}
displays[dispNum].setFont(&FONT_SMALL); displays[dispNum].setFont(&FONT_SMALL);
displays[dispNum].setTextColor(getFgColor()); displays[dispNum].setTextColor(getFgColor());
@ -414,32 +407,6 @@ void splitText(const uint dispNum, const String &top, const String &bottom,
displays[dispNum].print(bottom); displays[dispNum].print(bottom);
} }
// void showChars(const uint dispNum, const String &chars, bool partial,
// const GFXfont *font)
// {
// displays[dispNum].setRotation(2);
// displays[dispNum].setFont(font);
// displays[dispNum].setTextColor(getFgColor());
// int16_t tbx, tby;
// uint16_t tbw, tbh;
// displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh);
// // center the bounding box by transposition of the origin:
// uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
// uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
// displays[dispNum].fillScreen(getBgColor());
// displays[dispNum].setCursor(x, y);
// displays[dispNum].print(chars);
// // displays[dispNum].setCursor(10, 3);
// // displays[dispNum].setFont(&FONT_SMALL);
// // displays[dispNum].setTextColor(getFgColor());
// // displays[dispNum].println("Y = " + y);
// }
void showDigit(const uint dispNum, char chr, bool partial, void showDigit(const uint dispNum, char chr, bool partial,
const GFXfont *font) const GFXfont *font)
{ {
@ -499,18 +466,6 @@ void showDigit(const uint dispNum, char chr, bool partial,
// displays[dispNum].println("Y = " + y); // displays[dispNum].println("Y = " + y);
} }
int16_t calculateDescent(const GFXfont *font) {
int16_t maxDescent = 0;
for (uint16_t i = font->first; i <= font->last; i++) {
GFXglyph *glyph = &font->glyph[i - font->first];
int16_t descent = glyph->yOffset;
if (descent > maxDescent) {
maxDescent = descent;
}
}
return maxDescent;
}
void showChars(const uint dispNum, const String &chars, bool partial, void showChars(const uint dispNum, const String &chars, bool partial,
const GFXfont *font) const GFXfont *font)
{ {
@ -520,35 +475,12 @@ void showChars(const uint dispNum, const String &chars, bool partial,
int16_t tbx, tby; int16_t tbx, tby;
uint16_t tbw, tbh; uint16_t tbw, tbh;
displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh); displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh);
int16_t descent = calculateDescent(font);
// center the bounding box by transposition of the origin: // center the bounding box by transposition of the origin:
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx; uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby; uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
displays[dispNum].fillScreen(getBgColor()); displays[dispNum].fillScreen(getBgColor());
// displays[dispNum].setCursor(x, y);
// displays[dispNum].print(chars);
for (int i = 0; i < chars.length(); i++) {
char c = chars[i];
if (c == '.' || c == ',') {
// For the dot, calculate its specific descent
GFXglyph *dotGlyph = &font->glyph[c -font->first];
int16_t dotDescent = dotGlyph->yOffset;
// Draw the dot with adjusted y-position
displays[dispNum].setCursor(x, y + dotDescent + dotGlyph->height + 8);
displays[dispNum].print(c);
} else {
// For other characters, use the original y-position
displays[dispNum].setCursor(x, y); displays[dispNum].setCursor(x, y);
displays[dispNum].print(c); displays[dispNum].print(chars);
}
// Move x-position for the next character
x += font->glyph[c - font->first].xAdvance;
}
} }
int getBgColor() { return bgColor; } int getBgColor() { return bgColor; }
@ -607,26 +539,15 @@ void renderIcon(const uint dispNum, const String &text, bool partial)
if (text.endsWith("rocket")) { if (text.endsWith("rocket")) {
iconIndex = 1; iconIndex = 1;
} }
else if (text.endsWith("lnbolt")) {
if (text.endsWith("lnbolt")) {
iconIndex = 3; iconIndex = 3;
} }
else if (text.endsWith("bitaxe")) {
iconIndex = 4;
}
displays[dispNum].drawInvertedBitmap(0,0, epd_icons_allArray[iconIndex], 122, 250, getFgColor()); displays[dispNum].drawInvertedBitmap(0,0, epd_icons_allArray[iconIndex], 122, 250, getFgColor());
// displays[dispNum].drawInvertedBitmap(0,0, getOceanIcon(), 122, 250, getFgColor());
} }
void renderQr(const uint dispNum, const String &text, bool partial) void renderQr(const uint dispNum, const String &text, bool partial)
{ {
#ifdef USE_QR #ifdef USE_QR

View file

@ -4,7 +4,6 @@
#include <Fonts/FreeSansBold9pt7b.h> #include <Fonts/FreeSansBold9pt7b.h>
#include <GxEPD2_BW.h> #include <GxEPD2_BW.h>
#include <mcp23x17_pin.hpp> #include <mcp23x17_pin.hpp>
#include <mutex> #include <mutex>
#include <native_pin.hpp> #include <native_pin.hpp>

View file

@ -285,7 +285,7 @@ void ledTask(void *parameter)
#ifdef HAS_FRONTLIGHT #ifdef HAS_FRONTLIGHT
bool frontlightWasOn = false; bool frontlightWasOn = false;
if (preferences.getBool("flFlashOnZap", DEFAULT_FL_FLASH_ON_ZAP)) if (preferences.getBool("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE))
{ {
if (frontlightOn) if (frontlightOn)
{ {
@ -307,7 +307,7 @@ void ledTask(void *parameter)
// blinkDelayTwoColor(250, 3, pixels.Color(142, 48, 235), // blinkDelayTwoColor(250, 3, pixels.Color(142, 48, 235),
// pixels.Color(169, 21, 255)); // pixels.Color(169, 21, 255));
#ifdef HAS_FRONTLIGHT #ifdef HAS_FRONTLIGHT
if (preferences.getBool("flFlashOnZap", DEFAULT_FL_FLASH_ON_ZAP)) if (preferences.getBool("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE))
{ {
vTaskDelay(pdMS_TO_TICKS(10)); vTaskDelay(pdMS_TO_TICKS(10));
if (frontlightWasOn) if (frontlightWasOn)

View file

@ -4,20 +4,16 @@ std::vector<nostr::NostrPool *> pools;
nostr::Transport *transport; nostr::Transport *transport;
TaskHandle_t nostrTaskHandle = NULL; TaskHandle_t nostrTaskHandle = NULL;
boolean nostrIsConnected = false; boolean nostrIsConnected = false;
boolean nostrIsSubscribed = false;
boolean nostrIsSubscribing = true;
String subIdZap;
void setupNostrNotify(bool asDatasource, bool zapNotify) void setupNostrNotify(bool asDatasource, bool zapNotify)
{ {
nostr::esp32::ESP32Platform::initNostr(false); nostr::esp32::ESP32Platform::initNostr(false);
// time_t now; time_t now;
// time(&now); time(&now);
// struct tm *utcTimeInfo; struct tm *utcTimeInfo;
// utcTimeInfo = gmtime(&now); utcTimeInfo = gmtime(&now);
// time_t utcNow = mktime(utcTimeInfo); time_t utcNow = mktime(utcTimeInfo);
// time_t timestamp60MinutesAgo = utcNow - 3600; time_t timestamp60MinutesAgo = utcNow - 3600;
try try
{ {
@ -31,7 +27,20 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
if (zapNotify) if (zapNotify)
{ {
subscribeZaps(pool, relay, 60); String subIdZap = pool->subscribeMany(
{relay},
{
{
{"kinds", {"9735"}},
{"limit", {"1"}},
{"since", {String(timestamp60MinutesAgo)}},
{"#p", {preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY)}},
},
},
handleNostrZapCallback,
onNostrSubscriptionClosed,
onNostrSubscriptionEose);
Serial.println("[ Nostr ] Subscribing to Zap Notifications");
} }
if (asDatasource) if (asDatasource)
@ -41,7 +50,7 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
{// First filter {// First filter
{ {
{"kinds", {"1"}}, {"kinds", {"1"}},
{"since", {String(getMinutesAgo(60))}}, {"since", {String(timestamp60MinutesAgo)}},
{"authors", {pubKey}}, {"authors", {pubKey}},
}}, }},
handleNostrEventCallback, handleNostrEventCallback,
@ -63,12 +72,11 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
sstatus="CONNECTED"; sstatus="CONNECTED";
}else if(status==nostr::ConnectionStatus::DISCONNECTED){ }else if(status==nostr::ConnectionStatus::DISCONNECTED){
nostrIsConnected = false; nostrIsConnected = false;
nostrIsSubscribed = false;
sstatus="DISCONNECTED"; sstatus="DISCONNECTED";
}else if(status==nostr::ConnectionStatus::ERROR){ }else if(status==nostr::ConnectionStatus::ERROR){
sstatus = "ERROR"; sstatus = "ERROR";
} }
Serial.println("[ Nostr ] Connection status changed: " + sstatus); //Serial.println("[ Nostr ] Connection status changed: " + sstatus);
}); });
} }
} }
@ -80,10 +88,8 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
void nostrTask(void *pvParameters) void nostrTask(void *pvParameters)
{ {
if(preferences.getBool("useNostr", DEFAULT_USE_NOSTR)) {
int blockFetch = getBlockFetch(); int blockFetch = getBlockFetch();
processNewBlock(blockFetch); processNewBlock(blockFetch);
}
while (1) while (1)
{ {
@ -92,10 +98,6 @@ void nostrTask(void *pvParameters)
// Run internal loop: refresh relays, complete pending connections, send // Run internal loop: refresh relays, complete pending connections, send
// pending messages // pending messages
pool->loop(); pool->loop();
if (!nostrIsSubscribed && !nostrIsSubscribing) {
Serial.println(F("Not subscribed"));
subscribeZaps(pool, preferences.getString("nostrRelay"), 1);
}
} }
vTaskDelay(pdMS_TO_TICKS(100)); vTaskDelay(pdMS_TO_TICKS(100));
} }
@ -123,8 +125,6 @@ void onNostrSubscriptionEose(const String &subId)
// This is the callback that will be called when the subscription is // This is the callback that will be called when the subscription is
// EOSE // EOSE
Serial.println("[ Nostr ] Subscription EOSE: " + subId); Serial.println("[ Nostr ] Subscription EOSE: " + subId);
nostrIsSubscribing = false;
nostrIsSubscribed = true;
} }
void handleNostrEventCallback(const String &subId, nostr::SignedNostrEvent *event) void handleNostrEventCallback(const String &subId, nostr::SignedNostrEvent *event)
@ -183,34 +183,6 @@ void handleNostrEventCallback(const String &subId, nostr::SignedNostrEvent *even
} }
} }
time_t getMinutesAgo(int min) {
time_t now;
time(&now);
return now - (min * 60);
}
void subscribeZaps(nostr::NostrPool *pool, const String &relay, int minutesAgo) {
if (subIdZap) {
pool->closeSubscription(subIdZap);
}
nostrIsSubscribing = true;
subIdZap = pool->subscribeMany(
{relay},
{
{
{"kinds", {"9735"}},
{"limit", {"1"}},
{"since", {String(getMinutesAgo(minutesAgo))}},
{"#p", {preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY)}},
},
},
handleNostrZapCallback,
onNostrSubscriptionClosed,
onNostrSubscriptionEose);
Serial.println("[ Nostr ] Subscribing to Zap Notifications since " + String(getMinutesAgo(minutesAgo)));
}
void handleNostrZapCallback(const String &subId, nostr::SignedNostrEvent *event) { void handleNostrZapCallback(const String &subId, nostr::SignedNostrEvent *event) {
// Received events callback, we can access the event content with // Received events callback, we can access the event content with
// event->getContent() Here you should handle the event, for this // event->getContent() Here you should handle the event, for this
@ -252,10 +224,7 @@ void handleNostrZapCallback(const String &subId, nostr::SignedNostrEvent *event)
setEpdContent(textEpdContent); setEpdContent(textEpdContent);
vTaskDelay(pdMS_TO_TICKS(315 * NUM_SCREENS) + pdMS_TO_TICKS(250)); vTaskDelay(pdMS_TO_TICKS(315 * NUM_SCREENS) + pdMS_TO_TICKS(250));
if (preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP))
{
queueLedEffect(LED_EFFECT_NOSTR_ZAP); queueLedEffect(LED_EFFECT_NOSTR_ZAP);
}
if (timerPeriod > 0) if (timerPeriod > 0)
{ {
esp_timer_start_periodic(screenRotateTimer, esp_timer_start_periodic(screenRotateTimer,

View file

@ -25,6 +25,3 @@ void handleNostrZapCallback(const String &subId, nostr::SignedNostrEvent *event)
void onNostrSubscriptionClosed(const String &subId, const String &reason); void onNostrSubscriptionClosed(const String &subId, const String &reason);
void onNostrSubscriptionEose(const String &subId); void onNostrSubscriptionEose(const String &subId);
time_t getMinutesAgo(int min);
void subscribeZaps(nostr::NostrPool *pool, const String &relay, int minutesAgo);

View file

@ -106,12 +106,9 @@ void handleOTATask(void *parameter)
ReleaseInfo getLatestRelease(const String &fileToDownload) ReleaseInfo getLatestRelease(const String &fileToDownload)
{ {
String releaseUrl = preferences.getString("gitReleaseUrl"); String releaseUrl = "https://api.github.com/repos/btclock/btclock_v3/releases/latest";
WiFiClientSecure client; WiFiClientSecure client;
// client.setCACert(isrg_root_x1cert); client.setCACert(github_root_ca);
client.setCACertBundle(rootca_crt_bundle_start);
HTTPClient http; HTTPClient http;
http.begin(client, releaseUrl); http.begin(client, releaseUrl);
http.setUserAgent(USER_AGENT); http.setUserAgent(USER_AGENT);
@ -156,7 +153,7 @@ ReleaseInfo getLatestRelease(const String &fileToDownload)
int downloadUpdateHandler(char updateType) int downloadUpdateHandler(char updateType)
{ {
WiFiClientSecure client; WiFiClientSecure client;
client.setCACertBundle(rootca_crt_bundle_start); client.setCACert(github_root_ca);
HTTPClient http; HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
@ -171,13 +168,14 @@ int downloadUpdateHandler(char updateType)
break; break;
case UPDATE_WEBUI: case UPDATE_WEBUI:
{ {
latestRelease = getLatestRelease(getWebUiFilename()); latestRelease = getLatestRelease("littlefs.bin");
// updateWebUi(latestRelease.fileUrl, U_SPIFFS); // updateWebUi(latestRelease.fileUrl, U_SPIFFS);
// return 0; // return 0;
} }
break; break;
} }
// First, download the expected SHA256 // First, download the expected SHA256
String expectedSHA256 = downloadSHA256(latestRelease.checksumUrl); String expectedSHA256 = downloadSHA256(latestRelease.checksumUrl);
if (expectedSHA256.isEmpty()) if (expectedSHA256.isEmpty())
@ -305,7 +303,7 @@ int downloadUpdateHandler(char updateType)
void updateWebUi(String latestRelease, int command) void updateWebUi(String latestRelease, int command)
{ {
WiFiClientSecure client; WiFiClientSecure client;
client.setCACertBundle(rootca_crt_bundle_start); client.setCACert(github_root_ca);
HTTPClient http; HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
http.begin(client, latestRelease); http.begin(client, latestRelease);
@ -423,7 +421,7 @@ String downloadSHA256(const String &sha256Url)
} }
WiFiClientSecure client; WiFiClientSecure client;
client.setCACertBundle(rootca_crt_bundle_start); client.setCACert(github_root_ca);
HTTPClient http; HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
http.begin(client, sha256Url); http.begin(client, sha256Url);

View file

@ -5,10 +5,44 @@ const char *wsOwnServerV2 = "wss://ws-staging.btclock.dev/api/v2/ws";
const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin"; const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin";
const char* coincapWsCert = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)EOF";
// WebsocketsClient client; // WebsocketsClient client;
esp_websocket_client_handle_t clientPrice = NULL; esp_websocket_client_handle_t clientPrice = NULL;
esp_websocket_client_config_t config; esp_websocket_client_config_t config;
uint currentPrice = 90000; uint currentPrice = 50000;
unsigned long int lastPriceUpdate; unsigned long int lastPriceUpdate;
bool priceNotifyInit = false; bool priceNotifyInit = false;
std::map<char, std::uint64_t> currencyMap; std::map<char, std::uint64_t> currencyMap;
@ -26,8 +60,7 @@ void setupPriceNotify()
{ {
config = {.uri = wsServerPrice, config = {.uri = wsServerPrice,
.user_agent = USER_AGENT}; .user_agent = USER_AGENT};
config.cert_pem = isrg_root_x1cert; config.cert_pem = coincapWsCert;
config.task_stack = (6*1024); config.task_stack = (6*1024);
} }
@ -126,11 +159,11 @@ void processNewPrice(uint newPrice, char currency)
{ {
// const unsigned long oldPrice = currentPrice; // const unsigned long oldPrice = currentPrice;
currencyMap[currency] = newPrice; currencyMap[currency] = newPrice;
if (currency == CURRENCY_USD && ( lastUpdateMap[currency] == 0 || // if (lastUpdateMap[currency] == 0 ||
(currentTime - lastUpdateMap[currency]) > 120)) // (currentTime - lastUpdateMap[currency]) > 120)
{ // {
preferences.putUInt("lastPrice", currentPrice); // preferences.putUInt("lastPrice", currentPrice);
} // }
lastUpdateMap[currency] = currentTime; lastUpdateMap[currency] = currentTime;
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) { // if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER ||

View file

@ -41,10 +41,7 @@ void workerTask(void *pvParameters) {
uint price = getPrice(currency); uint price = getPrice(currency);
if (getCurrentScreen() == SCREEN_BTC_TICKER) { if (getCurrentScreen() == SCREEN_BTC_TICKER) {
taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE), taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE));
preferences.getBool("mowMode", DEFAULT_MOW_MODE),
preferences.getBool("suffixShareDot", DEFAULT_SUFFIX_SHARE_DOT)
);
} else if (getCurrentScreen() == SCREEN_SATS_PER_CURRENCY) { } else if (getCurrentScreen() == SCREEN_SATS_PER_CURRENCY) {
taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL)); taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
} else { } else {

View file

@ -1,79 +1,77 @@
#include "shared.hpp" #include "shared.hpp"
// const char *github_root_ca = const char *srpool_ca = \
// "-----BEGIN CERTIFICATE-----\n" "-----BEGIN CERTIFICATE-----\n" \
// "MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL\n" "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" \
// "MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl\n" "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" \
// "eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT\n" "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n" \
// "JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx\n" "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n" \
// "MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\n" "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n" \
// "Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg\n" "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n" \
// "VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm\n" "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n" \
// "aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo\n" "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n" \
// "I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng\n" "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n" \
// "o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G\n" "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n" \
// "A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD\n" "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n" \
// "VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB\n" "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n" \
// "zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW\n" "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n" \
// "RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=\n" "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n" \
// "-----END CERTIFICATE-----\n" "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n" \
// "-----BEGIN CERTIFICATE-----\n" "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n" \
// "MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n" "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n" \
// "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n" \
// "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n" "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n" \
// "MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n" "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n" \
// "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n" \
// "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n" "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n" \
// "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n" "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n" \
// "2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n" "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n" \
// "1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n" "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n" \
// "q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n" "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n" \
// "tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n" "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n" \
// "vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n" "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n" \
// "BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n" "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" \
// "5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n" "-----END CERTIFICATE-----\n";
// "1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n"
// "NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n"
// "Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n"
// "8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n"
// "pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n"
// "MrY=\n"
// "-----END CERTIFICATE-----\n";
const char* isrg_root_x1cert = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)EOF";
const char *github_root_ca =
"-----BEGIN CERTIFICATE-----\n"
"MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL\n"
"MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl\n"
"eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT\n"
"JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx\n"
"MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\n"
"Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg\n"
"VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm\n"
"aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo\n"
"I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng\n"
"o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G\n"
"A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD\n"
"VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB\n"
"zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW\n"
"RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
"MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n"
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n"
"2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n"
"1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n"
"q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n"
"tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n"
"vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n"
"BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n"
"5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n"
"1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n"
"NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n"
"Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n"
"8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n"
"pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n"
"MrY=\n"
"-----END CERTIFICATE-----\n";
#ifdef TEST_SCREENS #ifdef TEST_SCREENS
uint8_t input_buffer[3 * input_buffer_pixels]; // up to depth 24 uint8_t input_buffer[3 * input_buffer_pixels]; // up to depth 24
@ -144,11 +142,3 @@ String calculateSHA256(WiFiClient *stream, size_t contentLength) {
return result; return result;
} }
// uint8_t* getOceanIcon() {
// zlib_turbo zt;
// int iUncompSize = zt.gzip_info((uint8_t *)ocean_logo_comp, ocean_logo_size);
// uint8_t *pUncompressed;
// pUncompressed = (uint8_t *)malloc(iUncompSize+4);
// zt.gunzip((uint8_t *)ocean_logo_comp, ocean_logo_size, pUncompressed);
// }

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "MCP23017.h" #include <Adafruit_MCP23X17.h>
// #include <zlib_turbo.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <WiFiClientSecure.h> #include <WiFiClientSecure.h>
#include <Preferences.h> #include <Preferences.h>
@ -10,7 +9,6 @@
#include <GxEPD2.h> #include <GxEPD2.h>
#include <GxEPD2_BW.h> #include <GxEPD2_BW.h>
#include <mbedtls/md.h> #include <mbedtls/md.h>
#include "esp_crt_bundle.h"
#include <Update.h> #include <Update.h>
#include <mutex> #include <mutex>
@ -18,9 +16,9 @@
#include "defaults.hpp" #include "defaults.hpp"
extern MCP23017 mcp1; extern Adafruit_MCP23X17 mcp1;
#ifdef IS_BTCLOCK_V8 #ifdef IS_BTCLOCK_V8
extern MCP23017 mcp2; extern Adafruit_MCP23X17 mcp2;
#endif #endif
extern Preferences preferences; extern Preferences preferences;
extern std::mutex mcpMutex; extern std::mutex mcpMutex;
@ -70,16 +68,8 @@ const PROGMEM int screens[SCREEN_COUNT] = {
const int usPerSecond = 1000000; const int usPerSecond = 1000000;
const int usPerMinute = 60 * usPerSecond; const int usPerMinute = 60 * usPerSecond;
// extern const char *github_root_ca; extern const char *github_root_ca;
extern const char *isrg_root_x1cert; extern const char *srpool_ca;
extern const uint8_t rootca_crt_bundle_start[] asm("_binary_x509_crt_bundle_start");
// extern const uint8_t ocean_logo_comp[] asm("_binary_ocean_gz_start");
// extern const uint8_t ocean_logo_comp_end[] asm("_binary_ocean_gz_end");
// uint8_t* getOceanIcon();
// const size_t ocean_logo_size = ocean_logo_comp_end - ocean_logo_comp;
const PROGMEM char UPDATE_FIRMWARE = U_FLASH; const PROGMEM char UPDATE_FIRMWARE = U_FLASH;
const PROGMEM char UPDATE_WEBUI = U_SPIFFS; const PROGMEM char UPDATE_WEBUI = U_SPIFFS;

View file

@ -510,7 +510,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
settings["timePerScreen"].as<uint>() * 60); settings["timePerScreen"].as<uint>() * 60);
} }
String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname", "nostrZapPubkey", "httpAuthUser", "httpAuthPass", "gitReleaseUrl"}; String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname", "nostrZapPubkey", "httpAuthUser", "httpAuthPass"};
for (String setting : strSettings) for (String setting : strSettings)
{ {
@ -546,10 +546,8 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
"mdnsEnabled", "otaEnabled", "stealFocus", "mdnsEnabled", "otaEnabled", "stealFocus",
"mcapBigChar", "useSatsSymbol", "useBlkCountdown", "mcapBigChar", "useSatsSymbol", "useBlkCountdown",
"suffixPrice", "disableLeds", "ownDataSource", "suffixPrice", "disableLeds", "ownDataSource",
"mowMode", "suffixShareDot", "flOffWhenDark",
"flAlwaysOn", "flDisable", "flFlashOnUpd", "flAlwaysOn", "flDisable", "flFlashOnUpd",
"mempoolSecure", "useNostr", "bitaxeEnabled", "mempoolSecure", "useNostr", "bitaxeEnabled",
"verticalDesc",
"nostrZapNotify", "stagingSource", "httpAuthEnabled"}; "nostrZapNotify", "stagingSource", "httpAuthEnabled"};
for (String setting : boolSettings) for (String setting : boolSettings)
@ -689,10 +687,6 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
root["useBlkCountdown"] = preferences.getBool("useBlkCountdown", DEFAULT_USE_BLOCK_COUNTDOWN); root["useBlkCountdown"] = preferences.getBool("useBlkCountdown", DEFAULT_USE_BLOCK_COUNTDOWN);
root["suffixPrice"] = preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE); root["suffixPrice"] = preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE);
root["disableLeds"] = preferences.getBool("disableLeds", DEFAULT_DISABLE_LEDS); root["disableLeds"] = preferences.getBool("disableLeds", DEFAULT_DISABLE_LEDS);
root["mowMode"] = preferences.getBool("mowMode", DEFAULT_MOW_MODE);
root["verticalDesc"] = preferences.getBool("verticalDesc", DEFAULT_VERTICAL_DESC);
root["suffixShareDot"] = preferences.getBool("suffixShareDot", DEFAULT_SUFFIX_SHARE_DOT);
root["hostnamePrefix"] = preferences.getString("hostnamePrefix", DEFAULT_HOSTNAME_PREFIX); root["hostnamePrefix"] = preferences.getString("hostnamePrefix", DEFAULT_HOSTNAME_PREFIX);
root["hostname"] = getMyHostname(); root["hostname"] = getMyHostname();
@ -707,9 +701,6 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
root["nostrZapNotify"] = preferences.getBool("nostrZapNotify", DEFAULT_ZAP_NOTIFY_ENABLED); root["nostrZapNotify"] = preferences.getBool("nostrZapNotify", DEFAULT_ZAP_NOTIFY_ENABLED);
root["nostrZapPubkey"] = preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY); root["nostrZapPubkey"] = preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY);
root["ledFlashOnZap"] = preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP);
root["gitReleaseUrl"] = preferences.getString("gitReleaseUrl", DEFAULT_GIT_RELEASE_URL);
root["bitaxeEnabled"] = preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED); root["bitaxeEnabled"] = preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED);
root["bitaxeHostname"] = preferences.getString("bitaxeHostname", DEFAULT_BITAXE_HOSTNAME); root["bitaxeHostname"] = preferences.getString("bitaxeHostname", DEFAULT_BITAXE_HOSTNAME);
@ -725,12 +716,8 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
root["flAlwaysOn"] = preferences.getBool("flAlwaysOn", DEFAULT_FL_ALWAYS_ON); root["flAlwaysOn"] = preferences.getBool("flAlwaysOn", DEFAULT_FL_ALWAYS_ON);
root["flEffectDelay"] = preferences.getUInt("flEffectDelay", DEFAULT_FL_EFFECT_DELAY); root["flEffectDelay"] = preferences.getUInt("flEffectDelay", DEFAULT_FL_EFFECT_DELAY);
root["flFlashOnUpd"] = preferences.getBool("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE); root["flFlashOnUpd"] = preferences.getBool("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE);
root["flFlashOnZap"] = preferences.getBool("flFlashOnZap", DEFAULT_FL_FLASH_ON_ZAP);
root["hasLightLevel"] = hasLightLevel(); root["hasLightLevel"] = hasLightLevel();
root["luxLightToggle"] = preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE); root["luxLightToggle"] = preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE);
root["flOffWhenDark"] = preferences.getBool("flOffWhenDark", DEFAULT_FL_OFF_WHEN_DARK);
#else #else
root["hasFrontlight"] = false; root["hasFrontlight"] = false;
root["hasLightLevel"] = false; root["hasLightLevel"] = false;

View file

@ -51,7 +51,7 @@ extern "C" void app_main()
if (hasLightLevel()) { if (hasLightLevel()) {
if (preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE) != 0) if (preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE) != 0)
{ {
if (hasLightLevel() && getLightLevel() <= 1 && preferences.getBool("flOffWhenDark", DEFAULT_FL_OFF_WHEN_DARK)) if (hasLightLevel() && getLightLevel() <= 2)
{ {
if (frontlightIsOn()) { if (frontlightIsOn()) {
frontlightFadeOutAll(); frontlightFadeOutAll();

View file

@ -33,17 +33,6 @@ void test_CorrectSatsPerDollarConversion(void)
TEST_ASSERT_EQUAL_STRING("4", output[NUM_SCREENS - 1].c_str()); TEST_ASSERT_EQUAL_STRING("4", output[NUM_SCREENS - 1].c_str());
} }
void test_SatsPerDollarAfter1B(void)
{
std::array<std::string, NUM_SCREENS> output = parseSatsPerCurrency(120000000, CURRENCY_USD, false);
TEST_ASSERT_EQUAL_STRING("SATS/USD", output[0].c_str());
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS - 5].c_str());
TEST_ASSERT_EQUAL_STRING(".", output[NUM_SCREENS - 4].c_str());
TEST_ASSERT_EQUAL_STRING("8", output[NUM_SCREENS - 3].c_str());
TEST_ASSERT_EQUAL_STRING("3", output[NUM_SCREENS - 2].c_str());
TEST_ASSERT_EQUAL_STRING("3", output[NUM_SCREENS - 1].c_str());
}
void test_CorrectSatsPerPoundConversion(void) void test_CorrectSatsPerPoundConversion(void)
{ {
std::array<std::string, NUM_SCREENS> output = parseSatsPerCurrency(37253, CURRENCY_GBP, false); std::array<std::string, NUM_SCREENS> output = parseSatsPerCurrency(37253, CURRENCY_GBP, false);
@ -97,81 +86,6 @@ void test_PriceOf1MillionUsd(void)
TEST_ASSERT_EQUAL_STRING("M", output[NUM_SCREENS - 1].c_str()); TEST_ASSERT_EQUAL_STRING("M", output[NUM_SCREENS - 1].c_str());
} }
void test_PriceSuffixMode(void)
{
std::array<std::string, NUM_SCREENS> output = parsePriceData(93000, '$', true, false);
TEST_ASSERT_EQUAL_STRING("BTC/USD", output[0].c_str());
TEST_ASSERT_EQUAL_STRING("9", output[NUM_SCREENS - 5].c_str());
TEST_ASSERT_EQUAL_STRING("3", output[NUM_SCREENS - 4].c_str());
TEST_ASSERT_EQUAL_STRING(".", output[NUM_SCREENS - 3].c_str());
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS - 2].c_str());
TEST_ASSERT_EQUAL_STRING("K", output[NUM_SCREENS - 1].c_str());
}
void test_PriceSuffixModeCompact1(void)
{
std::array<std::string, NUM_SCREENS> output = parsePriceData(100000, '$', true, false, true);
std::string joined = joinArrayWithBrackets(output);
TEST_ASSERT_EQUAL_STRING_MESSAGE("BTC/USD", output[0].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("$", output[NUM_SCREENS - 6].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("1", output[NUM_SCREENS - 5].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 4].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0.", output[NUM_SCREENS - 3].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 2].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("K", output[NUM_SCREENS - 1].c_str(), joined.c_str());
}
void test_PriceSuffixModeCompact2(void)
{
std::array<std::string, NUM_SCREENS> output = parsePriceData(1000000, '$', true, false, true);
std::string joined = joinArrayWithBrackets(output);
TEST_ASSERT_EQUAL_STRING_MESSAGE("BTC/USD", output[0].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("$", output[NUM_SCREENS - 6].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("1.", output[NUM_SCREENS - 5].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 4].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 3].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 2].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("M", output[NUM_SCREENS - 1].c_str(), joined.c_str());
}
void test_PriceSuffixModeMow(void)
{
std::array<std::string, NUM_SCREENS> output = parsePriceData(93600, '$', true, true);
std::string joined = joinArrayWithBrackets(output);
TEST_ASSERT_EQUAL_STRING_MESSAGE("$", output[0].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE(".", output[NUM_SCREENS - 5].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 4].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("9", output[NUM_SCREENS - 3].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("3", output[NUM_SCREENS - 2].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("M", output[NUM_SCREENS - 1].c_str(), joined.c_str());
}
void test_PriceSuffixModeMowCompact(void)
{
std::array<std::string, NUM_SCREENS> output = parsePriceData(93600, '$', true, true, true);
std::string joined = joinArrayWithBrackets(output);
TEST_ASSERT_EQUAL_STRING_MESSAGE("MOW/UNITS", output[0].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("$", output[NUM_SCREENS - 6].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0.", output[NUM_SCREENS - 5].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 4].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("9", output[NUM_SCREENS - 3].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("3", output[NUM_SCREENS - 2].c_str(), joined.c_str());
TEST_ASSERT_EQUAL_STRING_MESSAGE("M", output[NUM_SCREENS - 1].c_str(), joined.c_str());
}
void test_McapLowerUsd(void) void test_McapLowerUsd(void)
{ {
std::array<std::string, NUM_SCREENS> output = parseMarketCap(810000, 26000, '$', true); std::array<std::string, NUM_SCREENS> output = parseMarketCap(810000, 26000, '$', true);
@ -278,7 +192,6 @@ int runUnityTests(void)
UNITY_BEGIN(); UNITY_BEGIN();
RUN_TEST(test_CorrectSatsPerDollarConversion); RUN_TEST(test_CorrectSatsPerDollarConversion);
RUN_TEST(test_CorrectSatsPerPoundConversion); RUN_TEST(test_CorrectSatsPerPoundConversion);
RUN_TEST(test_SatsPerDollarAfter1B);
RUN_TEST(test_SixCharacterBlockHeight); RUN_TEST(test_SixCharacterBlockHeight);
RUN_TEST(test_SevenCharacterBlockHeight); RUN_TEST(test_SevenCharacterBlockHeight);
RUN_TEST(test_FeeRateDisplay); RUN_TEST(test_FeeRateDisplay);
@ -290,11 +203,6 @@ int runUnityTests(void)
RUN_TEST(test_Mcap1TrillionEurSmallChars); RUN_TEST(test_Mcap1TrillionEurSmallChars);
RUN_TEST(test_Mcap1TrillionJpy); RUN_TEST(test_Mcap1TrillionJpy);
RUN_TEST(test_Mcap1TrillionJpySmallChars); RUN_TEST(test_Mcap1TrillionJpySmallChars);
RUN_TEST(test_PriceSuffixMode);
RUN_TEST(test_PriceSuffixModeCompact1);
RUN_TEST(test_PriceSuffixModeCompact2);
RUN_TEST(test_PriceSuffixModeMow);
RUN_TEST(test_PriceSuffixModeMowCompact);
return UNITY_END(); return UNITY_END();
} }

Binary file not shown.