forked from btclock/btclock_v3
Compare commits
32 commits
feature/bt
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
ae2e6656df | ||
|
c989169ff4 | ||
|
1a4bc9b711 | ||
|
0dcde59fb4 | ||
|
de8fe2e26e | ||
|
af4c466659 | ||
|
83d293c58e | ||
|
da25c7de90 | ||
|
4a52fc0bf2 | ||
db0ec01c86 | |||
|
34b77ea105 | ||
|
dbf2c53083 | ||
|
2a116d97ed | ||
3b6f1db3c5 | |||
9ada991ab1 | |||
132aa835cd | |||
|
d6604d28d6 | ||
|
33c06c86a1 | ||
|
f0f591a16f | ||
|
41b5fcf1c1 | ||
|
981895d315 | ||
|
031b506fed | ||
|
4cda081d05 | ||
|
2951055f68 | ||
|
d37307cccf | ||
|
239297c26d | ||
|
3b47c81cfe | ||
|
9f3351f85b | ||
|
1ccd5f18fb | ||
|
82dd70a38d | ||
|
a614bd15db | ||
|
b0ec0685a1 |
40 changed files with 1109 additions and 220 deletions
190
.forgejo/workflows/push.yaml
Normal file
190
.forgejo/workflows/push.yaml
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
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
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -10,4 +10,5 @@ data/.yarn
|
||||||
data/node_modules
|
data/node_modules
|
||||||
node_modules
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.bin
|
*.bin
|
||||||
|
ci/cache
|
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -1,3 +1,3 @@
|
||||||
[submodule "data"]
|
[submodule "data"]
|
||||||
path = data
|
path = data
|
||||||
url = https://github.com/btclock/webui.git
|
url = https://git.btclock.dev/btclock/webui.git
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# BTClock v3
|
# BTClock v3
|
||||||
|
|
||||||
[![BTClock CI](https://github.com/btclock/btclock_v3/actions/workflows/tagging.yml/badge.svg)](https://github.com/btclock/btclock_v3/actions/workflows/tagging.yml)
|
[![Latest release](https://git.btclock.dev/btclock/btclock_v3/badges/release.svg)](https://git.btclock.dev/btclock/btclock_v3/releases/latest)
|
||||||
|
|
||||||
|
[![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.
|
||||||
|
|
||||||
|
|
15
ci/Dockerfile
Normal file
15
ci/Dockerfile
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# 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
2
data
|
@ -1 +1 @@
|
||||||
Subproject commit 95aa9d67d17dde32dab3216810e7b4e4086feb03
|
Subproject commit 85b9b17506f89696b89ab6f6e6ed231b7a8f6e91
|
|
@ -4,6 +4,6 @@ dependencies:
|
||||||
source:
|
source:
|
||||||
type: idf
|
type: idf
|
||||||
version: 4.4.7
|
version: 4.4.7
|
||||||
manifest_hash: 841ba2a95f4b32d39636bf4fdf07c48a2052f71c9728a5b7f263083a3b430a4f
|
manifest_hash: cd2f3ee15e776d949eb4ea4eddc8f39b30c2a7905050850eed01ab4928143cff
|
||||||
target: esp32s3
|
target: esp32s3
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
|
|
@ -24,7 +24,7 @@ std::array<std::string, NUM_SCREENS> parseBitaxeHashRate(std::string text)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret[NUM_SCREENS - 1] = "GH/S";
|
ret[NUM_SCREENS - 1] = "GH/S";
|
||||||
ret[0] = "BIT/AXE";
|
ret[0] = "mdi:bitaxe";
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,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] = "BIT/AXE";
|
ret[0] = "mdi:bitaxe";
|
||||||
ret[1] = "mdi:rocket";
|
ret[1] = "mdi:rocket";
|
||||||
firstIndex = 2;
|
firstIndex = 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,33 +67,72 @@ 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)
|
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> 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)
|
||||||
{
|
{
|
||||||
priceString = getCurrencySymbol(currencySymbol) + formatNumberWithSuffix(price, NUM_SCREENS - 2);
|
int numScreens = shareDot || mowMode ? NUM_SCREENS - 1 : 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 (priceString.length() < (NUM_SCREENS))
|
if ((shareDot && priceString.length() <= (NUM_SCREENS)) || priceString.length() < (NUM_SCREENS))
|
||||||
{
|
{
|
||||||
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
||||||
|
|
||||||
ret[0] = "BTC/" + getCurrencyCode(currencySymbol);
|
if (mowMode)
|
||||||
|
{
|
||||||
|
ret[0] = "MOW/UNITS";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret[0] = "BTC/" + getCurrencyCode(currencySymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
firstIndex = 1;
|
firstIndex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t dotPosition = priceString.find('.');
|
||||||
|
|
||||||
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
if (shareDot && dotPosition != std::string::npos && dotPosition > 0)
|
||||||
{
|
{
|
||||||
ret[i] = priceString[i];
|
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++)
|
||||||
|
{
|
||||||
|
ret[i] = std::string(1, priceString[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -107,9 +146,26 @@ std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price,ch
|
||||||
|
|
||||||
if (priceString.length() < (NUM_SCREENS))
|
if (priceString.length() < (NUM_SCREENS))
|
||||||
{
|
{
|
||||||
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
if (currencySymbol != CURRENCY_USD)
|
// Pad the string with spaces if necessary
|
||||||
|
if (priceString.length() < NUM_SCREENS)
|
||||||
|
{
|
||||||
|
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currencySymbol != CURRENCY_USD || price >= 100000000) // no time anymore when earlier than 1
|
||||||
ret[0] = "SATS/" + getCurrencyCode(currencySymbol);
|
ret[0] = "SATS/" + getCurrencyCode(currencySymbol);
|
||||||
else
|
else
|
||||||
ret[0] = "MSCW/TIME";
|
ret[0] = "MSCW/TIME";
|
||||||
|
@ -292,9 +348,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 ¤cySymbol, bool useSuffixFormat = false)
|
emscripten::val parsePriceDataArray(std::uint32_t price, const std::string ¤cySymbol, bool useSuffixFormat = false, bool mowMode = false, bool shareDot = false)
|
||||||
{
|
{
|
||||||
return arrayToStringArray(parsePriceData(price, currencySymbol[0], useSuffixFormat));
|
return arrayToStringArray(parsePriceData(price, currencySymbol[0], useSuffixFormat, mowMode, shareDot));
|
||||||
}
|
}
|
||||||
|
|
||||||
emscripten::val parseHalvingCountdownArray(std::uint32_t blockHeight, bool asBlocks)
|
emscripten::val parseHalvingCountdownArray(std::uint32_t blockHeight, bool asBlocks)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
@ -19,7 +20,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);
|
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> 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);
|
||||||
|
|
|
@ -28,7 +28,12 @@ double getSupplyAtBlock(std::uint32_t blockNr)
|
||||||
return totalBitcoinInCirculation;
|
return totalBitcoinInCirculation;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -56,30 +61,53 @@ std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters)
|
||||||
numDouble /= billion;
|
numDouble /= billion;
|
||||||
suffix = 'B';
|
suffix = 'B';
|
||||||
}
|
}
|
||||||
else if (num >= million || numDigits > 6)
|
else if (num >= million || numDigits > 6 || (mowMode && num >= thousand))
|
||||||
{
|
{
|
||||||
numDouble /= million;
|
numDouble /= million;
|
||||||
suffix = 'M';
|
suffix = 'M';
|
||||||
}
|
}
|
||||||
else if (num >= thousand || numDigits > 3)
|
else if (!mowMode && (num >= thousand || numDigits > 3))
|
||||||
{
|
{
|
||||||
numDouble /= thousand;
|
numDouble /= thousand;
|
||||||
suffix = 'K';
|
suffix = 'K';
|
||||||
}
|
}
|
||||||
else
|
else if (!mowMode)
|
||||||
{
|
{
|
||||||
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 = snprintf(result, sizeof(result), "%.0f%c", numDouble, suffix);
|
int len;
|
||||||
|
|
||||||
// If there's room, add decimal places
|
// Mow Mode always uses string truncation to avoid rounding
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
snprintf(result, sizeof(result), "%.*f%c", numCharacters - len - 1, numDouble, suffix);
|
int restLen = mowMode ? numCharacters - len : numCharacters - len - 1;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
|
@ -11,4 +11,5 @@ 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);
|
20
maintainers.yaml
Normal file
20
maintainers.yaml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
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/
|
|
@ -1,7 +1,7 @@
|
||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, 36K, 20K,
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
otadata, data, ota, 56K, 8K,
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
app0, app, ota_0, 64K, 1700K,
|
app0, app, ota_0, 0x10000, 0x1b8000,
|
||||||
app1, app, ota_1, , 1700K,
|
app1, app, ota_1, , 0x1b8000,
|
||||||
spiffs, data, spiffs, , 400K,
|
spiffs, data, spiffs, , 0x66C00,
|
||||||
coredump, data, coredump,, 64K,
|
coredump, data, coredump,, 0x10000,
|
||||||
|
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, 36K, 20K,
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
otadata, data, ota, 56K, 8K,
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
app0, app, ota_0, 64K, 4096K,
|
app0, app, ota_0, 0x10000, 0x6F0000,
|
||||||
app1, app, ota_1, , 4096K,
|
app1, app, ota_1, , 0x6F0000,
|
||||||
spiffs, data, spiffs, , 400K,
|
spiffs, data, spiffs, , 0x200000,
|
||||||
coredump, data, coredump,, 64K,
|
coredump, data, coredump,, 0x10000,
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, 36K, 20K,
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
otadata, data, ota, 56K, 8K,
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
app0, app, ota_0, 64K, 1700K,
|
app0, app, ota_0, 0x10000, 0x370000,
|
||||||
app1, app, ota_1, , 1700K,
|
app1, app, ota_1, , 0x370000,
|
||||||
spiffs, data, spiffs, , 400K,
|
spiffs, data, spiffs, , 0xCD000,
|
||||||
coredump, data, coredump,, 64K,
|
coredump, data, coredump,, 0x10000,
|
|
|
@ -15,12 +15,14 @@ default_envs = lolin_s3_mini_213epd, lolin_s3_mini_29epd, btclock_rev_b_213epd,
|
||||||
|
|
||||||
|
|
||||||
[btclock_base]
|
[btclock_base]
|
||||||
platform = espressif32 @ ^6.8.1
|
platform = espressif32 @ ^6.9.0
|
||||||
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 = post:scripts/extra_script.py
|
extra_scripts = pre:scripts/pre_script.py, 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
|
||||||
|
@ -32,16 +34,15 @@ 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.1.0
|
bblanchon/ArduinoJson@^7.2.1
|
||||||
mathieucarbou/ESPAsyncWebServer @ 3.3.1
|
mathieucarbou/ESPAsyncWebServer @ 3.3.23
|
||||||
adafruit/Adafruit BusIO@^1.16.1
|
robtillaart/MCP23017@^0.8.0
|
||||||
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
|
https://github.com/dsbaars/universal_pin#feature/mcp23017_rt
|
||||||
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
|
||||||
|
|
||||||
[env:lolin_s3_mini]
|
[env:lolin_s3_mini]
|
||||||
extends = btclock_base
|
extends = btclock_base
|
||||||
board = lolin_s3_mini
|
board = lolin_s3_mini
|
||||||
|
@ -63,7 +64,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.csv
|
board_build.partitions = partition_8mb.csv
|
||||||
build_flags =
|
build_flags =
|
||||||
${btclock_base.build_flags}
|
${btclock_base.build_flags}
|
||||||
-D MCP_INT_PIN=8
|
-D MCP_INT_PIN=8
|
||||||
|
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
platformio
|
|
@ -5,6 +5,9 @@ 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()
|
||||||
|
@ -43,5 +46,15 @@ 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"] = ""
|
||||||
env.AddPreAction("$BUILD_DIR/littlefs.bin", before_buildfs)
|
fs_name = env.get("ESP32_FS_IMAGE_NAME", "littlefs.bin")
|
||||||
|
# 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)
|
||||||
|
|
7
scripts/pre_script.py
Normal file
7
scripts/pre_script.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
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)
|
||||||
|
|
|
@ -1015,11 +1015,267 @@ 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 = 4;
|
const int epd_icons_allArray_LEN = 5;
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
char *wsServer;
|
char *wsServer;
|
||||||
esp_websocket_client_handle_t blockNotifyClient = NULL;
|
esp_websocket_client_handle_t blockNotifyClient = NULL;
|
||||||
uint currentBlockHeight = 860000;
|
uint currentBlockHeight = 873400;
|
||||||
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.setCACert(mempoolWsCert);
|
client.setCACertBundle(rootca_crt_bundle_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
String mempoolInstance =
|
String mempoolInstance =
|
||||||
|
|
|
@ -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 0
|
#define BTN_1 256
|
||||||
#define BTN_2 1
|
#define BTN_2 512
|
||||||
#define BTN_3 2
|
#define BTN_3 1024
|
||||||
#define BTN_4 3
|
#define BTN_4 2048
|
||||||
#else
|
#else
|
||||||
#define BTN_1 3
|
#define BTN_1 2048
|
||||||
#define BTN_2 2
|
#define BTN_2 1024
|
||||||
#define BTN_3 1
|
#define BTN_3 512
|
||||||
#define BTN_4 0
|
#define BTN_4 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void buttonTask(void *parameter) {
|
void buttonTask(void *parameter) {
|
||||||
|
@ -22,11 +22,12 @@ 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.getLastInterruptPin();
|
uint pin = mcp1.getInterruptFlagRegister();
|
||||||
|
|
||||||
switch (pin) {
|
switch (pin) {
|
||||||
case BTN_1:
|
case BTN_1:
|
||||||
|
@ -43,12 +44,12 @@ void buttonTask(void *parameter) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mcp1.clearInterrupts();
|
mcp1.getInterruptCaptureRegister();
|
||||||
} 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.clearInterrupts();
|
mcp1.getInterruptCaptureRegister();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
#define MAX_ATTEMPTS_WIFI_CONNECTION 20
|
#define MAX_ATTEMPTS_WIFI_CONNECTION 20
|
||||||
|
|
||||||
|
// zlib_turbo zt;
|
||||||
|
|
||||||
Preferences preferences;
|
Preferences preferences;
|
||||||
Adafruit_MCP23X17 mcp1;
|
MCP23017 mcp1(0x20);
|
||||||
#ifdef IS_BTCLOCK_V8
|
#ifdef IS_BTCLOCK_V8
|
||||||
Adafruit_MCP23X17 mcp2;
|
MCP23017 mcp2(0x21);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
|
@ -35,7 +37,7 @@ void setup()
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
||||||
if (mcp1.digitalRead(3) == LOW)
|
if (mcp1.read1(3) == LOW)
|
||||||
{
|
{
|
||||||
preferences.putBool("wifiConfigured", false);
|
preferences.putBool("wifiConfigured", false);
|
||||||
preferences.remove("txPower");
|
preferences.remove("txPower");
|
||||||
|
@ -46,7 +48,7 @@ void setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
if (mcp1.digitalRead(0) == LOW)
|
if (mcp1.read1(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)
|
||||||
|
@ -54,7 +56,7 @@ void setup()
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mcp1.digitalRead(1) == LOW)
|
else if (mcp1.read1(1) == LOW)
|
||||||
{
|
{
|
||||||
preferences.clear();
|
preferences.clear();
|
||||||
queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
|
queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
|
||||||
|
@ -66,6 +68,7 @@ void setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
setupWifi();
|
setupWifi();
|
||||||
|
// loadIcons();
|
||||||
|
|
||||||
setupWebserver();
|
setupWebserver();
|
||||||
|
|
||||||
|
@ -106,6 +109,7 @@ void setup()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
forceFullRefresh();
|
forceFullRefresh();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupWifi()
|
void setupWifi()
|
||||||
|
@ -132,7 +136,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.digitalRead(2) == LOW);
|
buttonPress = (mcp1.read1(2) == LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -145,7 +149,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[5], 16) + String(mac[1], 16) + String(mac[3], 16))
|
||||||
.substring(2, 10));
|
.substring(2, 10));
|
||||||
|
|
||||||
wm.setConfigPortalTimeout(preferences.getUInt("wpTimeout", DEFAULT_WP_TIMEOUT));
|
wm.setConfigPortalTimeout(preferences.getUInt("wpTimeout", DEFAULT_WP_TIMEOUT));
|
||||||
|
@ -155,10 +159,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);
|
||||||
|
@ -284,6 +288,10 @@ 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);
|
||||||
|
@ -503,7 +511,7 @@ void setupHardware()
|
||||||
|
|
||||||
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
|
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
|
||||||
|
|
||||||
if (!mcp1.begin_I2C(0x20))
|
if (!mcp1.begin())
|
||||||
{
|
{
|
||||||
Serial.println(F("Error MCP23017 1"));
|
Serial.println(F("Error MCP23017 1"));
|
||||||
|
|
||||||
|
@ -513,17 +521,20 @@ 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.pinMode(i, INPUT_PULLUP);
|
mcp1.pinMode1(i, INPUT_PULLUP);
|
||||||
mcp1.setupInterruptPin(i, LOW);
|
mcp1.enableInterrupt(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.pinMode(i, OUTPUT);
|
mcp1.pinMode1(i, OUTPUT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -534,7 +545,7 @@ void setupHardware()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IS_BTCLOCK_V8
|
#ifdef IS_BTCLOCK_V8
|
||||||
if (!mcp2.begin_I2C(0x21))
|
if (!mcp2.begin())
|
||||||
{
|
{
|
||||||
Serial.println(F("Error MCP23017 2"));
|
Serial.println(F("Error MCP23017 2"));
|
||||||
|
|
||||||
|
@ -786,4 +797,32 @@ const char* getFirmwareFilename() {
|
||||||
} else {
|
} else {
|
||||||
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");
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Adafruit_MCP23X17.h>
|
#include <MCP23017.h>
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
|
@ -83,4 +83,6 @@ 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();
|
|
@ -18,6 +18,9 @@
|
||||||
#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
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,6 +45,8 @@
|
||||||
#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
|
||||||
|
|
||||||
|
@ -55,9 +60,14 @@
|
||||||
|
|
||||||
#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
|
||||||
|
|
|
@ -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.digitalRead(0) == LOW)
|
if (mcp1.read1(0) == LOW)
|
||||||
{
|
{
|
||||||
setFgColor(GxEPD_BLACK);
|
setFgColor(GxEPD_BLACK);
|
||||||
setBgColor(GxEPD_WHITE);
|
setBgColor(GxEPD_WHITE);
|
||||||
|
@ -283,7 +283,10 @@ void prepareDisplayUpdateTask(void *pvParameters)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (epdContent[epdIndex].length() > 1 && epdContent[epdIndex].indexOf(".") == -1)
|
if (epdContent[epdIndex].length() == 2) {
|
||||||
|
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"))
|
||||||
{
|
{
|
||||||
|
@ -370,7 +373,11 @@ 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)
|
||||||
{
|
{
|
||||||
displays[dispNum].setRotation(2);
|
if(preferences.getBool("verticalDesc", DEFAULT_VERTICAL_DESC) && dispNum == 0) {
|
||||||
|
displays[dispNum].setRotation(1);
|
||||||
|
} else {
|
||||||
|
displays[dispNum].setRotation(2);
|
||||||
|
}
|
||||||
displays[dispNum].setFont(&FONT_SMALL);
|
displays[dispNum].setFont(&FONT_SMALL);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
|
|
||||||
|
@ -407,6 +414,32 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -466,6 +499,18 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -475,12 +520,35 @@ 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].setCursor(x, y);
|
||||||
displays[dispNum].print(chars);
|
// 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].print(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move x-position for the next character
|
||||||
|
x += font->glyph[c - font->first].xAdvance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getBgColor() { return bgColor; }
|
int getBgColor() { return bgColor; }
|
||||||
|
@ -539,15 +607,26 @@ 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
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#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>
|
||||||
|
|
|
@ -285,7 +285,7 @@ void ledTask(void *parameter)
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
bool frontlightWasOn = false;
|
bool frontlightWasOn = false;
|
||||||
|
|
||||||
if (preferences.getBool("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE))
|
if (preferences.getBool("flFlashOnZap", DEFAULT_FL_FLASH_ON_ZAP))
|
||||||
{
|
{
|
||||||
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("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE))
|
if (preferences.getBool("flFlashOnZap", DEFAULT_FL_FLASH_ON_ZAP))
|
||||||
{
|
{
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
if (frontlightWasOn)
|
if (frontlightWasOn)
|
||||||
|
|
|
@ -4,16 +4,20 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -27,20 +31,7 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
|
||||||
|
|
||||||
if (zapNotify)
|
if (zapNotify)
|
||||||
{
|
{
|
||||||
String subIdZap = pool->subscribeMany(
|
subscribeZaps(pool, relay, 60);
|
||||||
{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)
|
||||||
|
@ -50,7 +41,7 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
|
||||||
{// First filter
|
{// First filter
|
||||||
{
|
{
|
||||||
{"kinds", {"1"}},
|
{"kinds", {"1"}},
|
||||||
{"since", {String(timestamp60MinutesAgo)}},
|
{"since", {String(getMinutesAgo(60))}},
|
||||||
{"authors", {pubKey}},
|
{"authors", {pubKey}},
|
||||||
}},
|
}},
|
||||||
handleNostrEventCallback,
|
handleNostrEventCallback,
|
||||||
|
@ -72,11 +63,12 @@ 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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,8 +80,10 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
|
||||||
|
|
||||||
void nostrTask(void *pvParameters)
|
void nostrTask(void *pvParameters)
|
||||||
{
|
{
|
||||||
int blockFetch = getBlockFetch();
|
if(preferences.getBool("useNostr", DEFAULT_USE_NOSTR)) {
|
||||||
processNewBlock(blockFetch);
|
int blockFetch = getBlockFetch();
|
||||||
|
processNewBlock(blockFetch);
|
||||||
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +92,10 @@ 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));
|
||||||
}
|
}
|
||||||
|
@ -125,6 +123,8 @@ 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,6 +183,34 @@ 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
|
||||||
|
@ -224,7 +252,10 @@ 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));
|
||||||
queueLedEffect(LED_EFFECT_NOSTR_ZAP);
|
if (preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP))
|
||||||
|
{
|
||||||
|
queueLedEffect(LED_EFFECT_NOSTR_ZAP);
|
||||||
|
}
|
||||||
if (timerPeriod > 0)
|
if (timerPeriod > 0)
|
||||||
{
|
{
|
||||||
esp_timer_start_periodic(screenRotateTimer,
|
esp_timer_start_periodic(screenRotateTimer,
|
||||||
|
|
|
@ -24,4 +24,7 @@ void handleNostrEventCallback(const String &subId, nostr::SignedNostrEvent *even
|
||||||
void handleNostrZapCallback(const String &subId, nostr::SignedNostrEvent *event);
|
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);
|
|
@ -106,9 +106,12 @@ void handleOTATask(void *parameter)
|
||||||
|
|
||||||
ReleaseInfo getLatestRelease(const String &fileToDownload)
|
ReleaseInfo getLatestRelease(const String &fileToDownload)
|
||||||
{
|
{
|
||||||
String releaseUrl = "https://api.github.com/repos/btclock/btclock_v3/releases/latest";
|
String releaseUrl = preferences.getString("gitReleaseUrl");
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
client.setCACert(github_root_ca);
|
// client.setCACert(isrg_root_x1cert);
|
||||||
|
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);
|
||||||
|
@ -153,7 +156,7 @@ ReleaseInfo getLatestRelease(const String &fileToDownload)
|
||||||
int downloadUpdateHandler(char updateType)
|
int downloadUpdateHandler(char updateType)
|
||||||
{
|
{
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
client.setCACert(github_root_ca);
|
client.setCACertBundle(rootca_crt_bundle_start);
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
|
|
||||||
|
@ -168,14 +171,13 @@ int downloadUpdateHandler(char updateType)
|
||||||
break;
|
break;
|
||||||
case UPDATE_WEBUI:
|
case UPDATE_WEBUI:
|
||||||
{
|
{
|
||||||
latestRelease = getLatestRelease("littlefs.bin");
|
latestRelease = getLatestRelease(getWebUiFilename());
|
||||||
// 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())
|
||||||
|
@ -303,7 +305,7 @@ int downloadUpdateHandler(char updateType)
|
||||||
void updateWebUi(String latestRelease, int command)
|
void updateWebUi(String latestRelease, int command)
|
||||||
{
|
{
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
client.setCACert(github_root_ca);
|
client.setCACertBundle(rootca_crt_bundle_start);
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
http.begin(client, latestRelease);
|
http.begin(client, latestRelease);
|
||||||
|
@ -421,7 +423,7 @@ String downloadSHA256(const String &sha256Url)
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
client.setCACert(github_root_ca);
|
client.setCACertBundle(rootca_crt_bundle_start);
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
http.begin(client, sha256Url);
|
http.begin(client, sha256Url);
|
||||||
|
|
|
@ -5,44 +5,10 @@ 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 = 50000;
|
uint currentPrice = 90000;
|
||||||
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;
|
||||||
|
@ -60,7 +26,8 @@ void setupPriceNotify()
|
||||||
{
|
{
|
||||||
config = {.uri = wsServerPrice,
|
config = {.uri = wsServerPrice,
|
||||||
.user_agent = USER_AGENT};
|
.user_agent = USER_AGENT};
|
||||||
config.cert_pem = coincapWsCert;
|
config.cert_pem = isrg_root_x1cert;
|
||||||
|
|
||||||
config.task_stack = (6*1024);
|
config.task_stack = (6*1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +126,11 @@ void processNewPrice(uint newPrice, char currency)
|
||||||
{
|
{
|
||||||
// const unsigned long oldPrice = currentPrice;
|
// const unsigned long oldPrice = currentPrice;
|
||||||
currencyMap[currency] = newPrice;
|
currencyMap[currency] = newPrice;
|
||||||
// if (lastUpdateMap[currency] == 0 ||
|
if (currency == CURRENCY_USD && ( 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 ||
|
||||||
|
|
|
@ -41,7 +41,10 @@ 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 {
|
||||||
|
|
|
@ -1,44 +1,79 @@
|
||||||
#include "shared.hpp"
|
#include "shared.hpp"
|
||||||
|
|
||||||
const char *github_root_ca =
|
// const char *github_root_ca =
|
||||||
"-----BEGIN CERTIFICATE-----\n"
|
// "-----BEGIN CERTIFICATE-----\n"
|
||||||
"MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL\n"
|
// "MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL\n"
|
||||||
"MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl\n"
|
// "MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl\n"
|
||||||
"eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT\n"
|
// "eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT\n"
|
||||||
"JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx\n"
|
// "JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx\n"
|
||||||
"MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\n"
|
// "MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\n"
|
||||||
"Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg\n"
|
// "Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg\n"
|
||||||
"VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm\n"
|
// "VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm\n"
|
||||||
"aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo\n"
|
// "aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo\n"
|
||||||
"I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng\n"
|
// "I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng\n"
|
||||||
"o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G\n"
|
// "o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G\n"
|
||||||
"A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD\n"
|
// "A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD\n"
|
||||||
"VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB\n"
|
// "VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB\n"
|
||||||
"zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW\n"
|
// "zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW\n"
|
||||||
"RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=\n"
|
// "RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=\n"
|
||||||
"-----END CERTIFICATE-----\n"
|
// "-----END CERTIFICATE-----\n"
|
||||||
"-----BEGIN CERTIFICATE-----\n"
|
// "-----BEGIN CERTIFICATE-----\n"
|
||||||
"MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n"
|
// "MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n"
|
||||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
|
// "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
|
||||||
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
|
// "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
|
||||||
"MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n"
|
// "MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n"
|
||||||
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
|
// "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
|
||||||
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n"
|
// "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n"
|
||||||
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n"
|
// "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n"
|
||||||
"2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n"
|
// "2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n"
|
||||||
"1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n"
|
// "1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n"
|
||||||
"q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n"
|
// "q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n"
|
||||||
"tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n"
|
// "tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n"
|
||||||
"vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n"
|
// "vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n"
|
||||||
"BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n"
|
// "BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n"
|
||||||
"5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n"
|
// "5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n"
|
||||||
"1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n"
|
// "1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n"
|
||||||
"NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n"
|
// "NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n"
|
||||||
"Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n"
|
// "Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n"
|
||||||
"8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n"
|
// "8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n"
|
||||||
"pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n"
|
// "pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n"
|
||||||
"MrY=\n"
|
// "MrY=\n"
|
||||||
"-----END CERTIFICATE-----\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";
|
||||||
|
|
||||||
|
|
||||||
#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
|
||||||
|
@ -108,4 +143,12 @@ 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);
|
||||||
|
// }
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Adafruit_MCP23X17.h>
|
#include "MCP23017.h"
|
||||||
|
// #include <zlib_turbo.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
|
@ -9,6 +10,7 @@
|
||||||
#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>
|
||||||
|
@ -16,9 +18,9 @@
|
||||||
|
|
||||||
#include "defaults.hpp"
|
#include "defaults.hpp"
|
||||||
|
|
||||||
extern Adafruit_MCP23X17 mcp1;
|
extern MCP23017 mcp1;
|
||||||
#ifdef IS_BTCLOCK_V8
|
#ifdef IS_BTCLOCK_V8
|
||||||
extern Adafruit_MCP23X17 mcp2;
|
extern MCP23017 mcp2;
|
||||||
#endif
|
#endif
|
||||||
extern Preferences preferences;
|
extern Preferences preferences;
|
||||||
extern std::mutex mcpMutex;
|
extern std::mutex mcpMutex;
|
||||||
|
@ -68,7 +70,16 @@ 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 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;
|
||||||
|
|
|
@ -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"};
|
String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname", "nostrZapPubkey", "httpAuthUser", "httpAuthPass", "gitReleaseUrl"};
|
||||||
|
|
||||||
for (String setting : strSettings)
|
for (String setting : strSettings)
|
||||||
{
|
{
|
||||||
|
@ -546,8 +546,10 @@ 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)
|
||||||
|
@ -687,6 +689,10 @@ 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();
|
||||||
|
@ -701,6 +707,9 @@ 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);
|
||||||
|
@ -716,8 +725,12 @@ 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;
|
||||||
|
|
|
@ -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() <= 2)
|
if (hasLightLevel() && getLightLevel() <= 1 && preferences.getBool("flOffWhenDark", DEFAULT_FL_OFF_WHEN_DARK))
|
||||||
{
|
{
|
||||||
if (frontlightIsOn()) {
|
if (frontlightIsOn()) {
|
||||||
frontlightFadeOutAll();
|
frontlightFadeOutAll();
|
||||||
|
|
|
@ -33,6 +33,17 @@ 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);
|
||||||
|
@ -86,6 +97,81 @@ 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);
|
||||||
|
@ -192,6 +278,7 @@ 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);
|
||||||
|
@ -203,6 +290,11 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
BIN
x509_crt_bundle
Normal file
BIN
x509_crt_bundle
Normal file
Binary file not shown.
Loading…
Reference in a new issue