mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 14:06:31 +01:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e102f8e4e9 | ||
|
|
0fb0c6f74d | ||
|
|
5dfd0e4582 | ||
|
|
f311239c9c | ||
|
|
c3e729744a | ||
|
|
447611ba4a | ||
|
|
6637405358 | ||
|
|
32c74ba5b4 | ||
|
|
177f93844c | ||
|
|
d76d110f39 | ||
|
|
1584f35624 | ||
|
|
ac0c3ccfc9 | ||
|
|
3810fbf68c | ||
|
|
20b4f728e4 | ||
|
|
047230de25 | ||
|
|
107764c6be | ||
|
|
0819b19db2 | ||
|
|
4aedce7839 | ||
|
|
2d486d7c66 | ||
|
|
ba8a5c6990 | ||
|
|
1ae015c65f | ||
|
|
92681aa4c5 | ||
|
|
004438cee9 | ||
|
|
b7546cf6d4 | ||
|
|
cce5f56d67 | ||
|
|
eb58b7fc02 | ||
|
|
8f0362455a | ||
|
|
79fe05581c | ||
|
|
658b3b8635 | ||
|
|
77da5964bf | ||
|
|
0232725711 | ||
|
|
ff7f397705 | ||
|
|
d8fa96b20e | ||
|
|
15a9728f45 | ||
|
|
6c9439822b | ||
|
|
4b667d0039 | ||
|
|
19bbba5202 | ||
|
|
ad76d122e5 | ||
|
|
5ec69153b5 | ||
|
|
45427148f6 | ||
|
|
c5fb16836f | ||
|
|
63b6f911b6 | ||
|
|
dec9b17655 | ||
|
|
b8c4d4420e | ||
|
|
0b064a9cee | ||
|
|
4d186c81ff | ||
|
|
5cc7869c0f | ||
|
|
6a8450cbcb | ||
|
|
ca8781f956 | ||
|
|
311ae1a570 | ||
|
|
06b2718d7d | ||
|
|
0f574bc3e8 | ||
|
|
7e49c2a09e | ||
|
|
23cbadb9f6 | ||
|
|
fce2e43ef7 | ||
|
|
4f7a381eed | ||
|
|
6a0f1310e1 | ||
|
|
bb36185066 | ||
|
|
be8eac2fc5 | ||
|
|
e4ecf08e29 | ||
|
|
99c048a29d | ||
|
|
f49731a240 | ||
|
|
375662c69e | ||
|
|
e246ac578d | ||
|
|
d8dcd498a3 | ||
|
|
91b01c5fca | ||
|
|
30812dff49 | ||
|
|
31a90d1498 | ||
|
|
2d02da1574 | ||
|
|
33f77b2192 | ||
|
|
e079c30c54 | ||
|
|
eba9f54454 | ||
|
|
a0a39e98cd |
8
.github/workflows/conditional-build-test.yml
vendored
8
.github/workflows/conditional-build-test.yml
vendored
@@ -70,16 +70,22 @@ jobs:
|
||||
#- OpenEPaperLink_AP_and_Flasher
|
||||
- ESP32_S3_16_8_YELLOW_AP
|
||||
- OpenEPaperLink_Mini_AP_v4
|
||||
- OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup-pio
|
||||
|
||||
- name: Build ${{ matrix.environment }}
|
||||
- name: Build ${{ matrix.environment }} binary
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment ${{ matrix.environment }}
|
||||
- name: Build ${{ matrix.environment }} filesystem
|
||||
if: ${{ matrix.environment != 'OpenEPaperLink_ESP32-PoE-ISO_AP' }}
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --target buildfs --environment ${{ matrix.environment }}
|
||||
|
||||
|
||||
|
||||
|
||||
103
.github/workflows/release.yml
vendored
103
.github/workflows/release.yml
vendored
@@ -5,6 +5,12 @@ on:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
INCLUDE_C6_H2: true
|
||||
INCLUDE_MINI_AP: false
|
||||
INCLUDE_Nano_AP: false
|
||||
INCLUDE_S2_Tag_Flasher: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -20,14 +26,14 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
# - name: Commit zipped files
|
||||
|
||||
# - name: Commit zipped files
|
||||
# run: |
|
||||
# git config --global user.name 'Bot'
|
||||
# git config --global user.email "bot@openepaperlink.de"
|
||||
# git commit -am "Zipped web files"
|
||||
# git push origin HEAD:master
|
||||
|
||||
|
||||
- name: Install PlatformIO Core
|
||||
run: pip install --upgrade platformio
|
||||
|
||||
@@ -41,37 +47,45 @@ jobs:
|
||||
run: |
|
||||
mkdir espbinaries
|
||||
|
||||
#- name: esp-idf build
|
||||
# uses: espressif/esp-idf-ci-action@v1
|
||||
# with:
|
||||
# esp_idf_version: latest
|
||||
# target: esp32c6
|
||||
# path: 'ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/'
|
||||
- name: build ESP32-C6 firmware
|
||||
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
esp_idf_version: latest
|
||||
target: esp32c6
|
||||
path: 'ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/'
|
||||
|
||||
# - name: esp-idf build
|
||||
# uses: espressif/esp-idf-ci-action@v1
|
||||
# with:
|
||||
# esp_idf_version: latest
|
||||
# target: esp32h2
|
||||
# path: 'ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/'
|
||||
- name: Add C6 files to release
|
||||
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
|
||||
run: |
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/OpenEPaperLink_esp32_C6.bin espbinaries/OpenEPaperLink_esp32_C6.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/bootloader/bootloader.bin espbinaries/bootloader_C6.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/partition_table/partition-table.bin espbinaries/partition-table_C6.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink//binaries/ESP32-C6/firmware_C6.json espbinaries
|
||||
|
||||
#- name: Add C6 files to release
|
||||
# run: |
|
||||
# cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/OpenEPaperLink_esp32_C6.bin espbinaries/OpenEPaperLink_esp32_C6.bin
|
||||
- name: build ESP32-H2 firmware
|
||||
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
esp_idf_version: latest
|
||||
target: esp32h2
|
||||
path: 'ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/'
|
||||
|
||||
#- name: Add H2 files to release
|
||||
# run: |
|
||||
# cd ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/
|
||||
# dir build
|
||||
# esptool.py --chip esp32h2 merge_bin -o merged-firmware.bin --flash_mode dio --flash_size 4MB --flash_freq 48m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/OpenEPaperLink_esp32_H2.bin
|
||||
# cp merged-firmware.bin ../../espbinaries/OpenEPaperLink_esp32_H2.bin
|
||||
- name: Add H2 files to release
|
||||
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
|
||||
run: |
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/OpenEPaperLink_esp32_H2.bin espbinaries/OpenEPaperLink_esp32_H2.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/bootloader/bootloader.bin espbinaries/bootloader_H2.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/partition_table/partition-table.bin espbinaries/partition-table_H2.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink//binaries/ESP32-H2/firmware_H2.json espbinaries
|
||||
|
||||
# - name: Zip web files
|
||||
# run: |
|
||||
# run: |
|
||||
# cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_AP-Flasher
|
||||
# python gzip_wwwfiles.py
|
||||
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_Mini_AP
|
||||
if: ${{ env.INCLUDE_MINI_AP == 'true' }}
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
@@ -88,8 +102,9 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_Mini_AP/firmware.bin espbinaries/OpenEPaperLink_Mini_AP.bin
|
||||
cp OpenEPaperLink_Mini_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Mini_AP_full.bin
|
||||
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_Nano_AP
|
||||
if: ${{ env.INCLUDE_Nano_AP == 'true' }}
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
@@ -106,11 +121,10 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_Nano_AP/firmware.bin espbinaries/OpenEPaperLink_Nano_AP.bin
|
||||
cp OpenEPaperLink_Nano_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_AP_full.bin
|
||||
|
||||
# - name: move files for big APs
|
||||
# run: |
|
||||
# cp -a binaries/ESP32-C6/. ESP32_AP-Flasher/data/
|
||||
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_AP_and_Flasher
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
@@ -128,7 +142,6 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_AP_and_Flasher/firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher.bin
|
||||
cp OpenEPaperLink_AP_and_Flasher/merged-firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher_full.bin
|
||||
|
||||
- name: Build firmware for ESP32_S3_16_8_YELLOW_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
@@ -200,7 +213,7 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_Nano_TLSR/firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR.bin
|
||||
cp OpenEPaperLink_Nano_TLSR/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR_full.bin
|
||||
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_PoE_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
@@ -254,7 +267,29 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp BLE_ONLY_AP/firmware.bin espbinaries/BLE_ONLY_AP.bin
|
||||
cp BLE_ONLY_AP/merged-firmware.bin espbinaries/BLE_ONLY_AP_full.bin
|
||||
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
pio run --environment OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
mv data data.bak
|
||||
mkdir data
|
||||
pio run --target buildfs --environment OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
rmdir data
|
||||
mv data.bak data
|
||||
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/boot_app0.bin
|
||||
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin
|
||||
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/bootloader.bin
|
||||
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/partitions.bin
|
||||
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode qio --flash_freq 80m --flash_size 4MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xD000 boot_app0.bin 0x10000 firmware.bin 0x3D0000 littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin espbinaries/OpenEPaperLink_ESP32-PoE-ISO_AP.bin
|
||||
cp OpenEPaperLink_ESP32-PoE-ISO_AP/merged-firmware.bin espbinaries/OpenEPaperLink_ESP32-PoE-ISO_AP_full.bin
|
||||
|
||||
- name: generate release json file
|
||||
run: |
|
||||
mkdir jsonfiles
|
||||
@@ -268,10 +303,11 @@ jobs:
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
||||
overwrite: true
|
||||
|
||||
|
||||
# this is down here intentionally to be able to modify the binary folder before adding it to the Tag_Flasher later (ota binaries can be removed)
|
||||
|
||||
- name: Build firmware for Tag_Flasher
|
||||
if: ${{ env.INCLUDE_S2_Tag_Flasher == 'true' }}
|
||||
run: |
|
||||
cd Tag_Flasher/ESP32_Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
@@ -288,7 +324,6 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp S2_Tag_Flasher/firmware.bin espbinaries/S2_Tag_Flasher.bin
|
||||
cp S2_Tag_Flasher/merged-firmware.bin espbinaries/S2_Tag_Flasher_full.bin
|
||||
|
||||
- name: Add esp bins to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
menu "OEPL Hardware config"
|
||||
menu "OEPL config"
|
||||
|
||||
choice OEPL_HARDWARE_PROFILE
|
||||
prompt "Hardware profile"
|
||||
@@ -16,6 +16,12 @@ menu "OEPL Hardware config"
|
||||
config OEPL_HARDWARE_PROFILE_LILYGO
|
||||
bool "LILYGO-AP"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_4inch
|
||||
bool "4inchAP"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_ELECROW_C6
|
||||
bool "ELECROW-C6-AP"
|
||||
|
||||
endchoice
|
||||
|
||||
config OEPL_HARDWARE_UART_TX
|
||||
@@ -28,6 +34,16 @@ menu "OEPL Hardware config"
|
||||
int "GPIO - UART RX"
|
||||
default 2
|
||||
|
||||
config OEPL_HARDWARE_UART_TX
|
||||
depends on OEPL_HARDWARE_PROFILE_4inch
|
||||
int "GPIO - UART TX"
|
||||
default 16
|
||||
|
||||
config OEPL_HARDWARE_UART_RX
|
||||
depends on OEPL_HARDWARE_PROFILE_4inch
|
||||
int "GPIO - UART RX"
|
||||
default 17
|
||||
|
||||
config OEPL_SUBGIG_SUPPORT
|
||||
bool "Enable SubGhz Support"
|
||||
default "n"
|
||||
@@ -102,6 +118,16 @@ menu "OEPL Hardware config"
|
||||
USE SPI3_HOST. This is also called VSPI_HOST
|
||||
endchoice
|
||||
endmenu
|
||||
|
||||
config OEPL_DEBUG_PRINT
|
||||
bool "Enable OEPL Debug logging"
|
||||
default "n"
|
||||
|
||||
config OEPL_VERBOSE_DEBUG
|
||||
depends on OEPL_DEBUG_PRINT
|
||||
bool "Enable OEPL Verbose Debug logging"
|
||||
default "n"
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
|
||||
@@ -13,24 +13,16 @@
|
||||
|
||||
#include "radio.h"
|
||||
#include "proto.h"
|
||||
#include "utils.h"
|
||||
#include "second_uart.h"
|
||||
#include "cc1101_radio.h"
|
||||
#include "logging.h"
|
||||
#include "SubGigRadio.h"
|
||||
|
||||
void DumpHex(void *AdrIn,int Len);
|
||||
bool CC1101_QuickCheck(void);
|
||||
|
||||
#define LOGE(format, ... ) \
|
||||
printf("%s#%d: " format,__FUNCTION__,__LINE__,## __VA_ARGS__)
|
||||
|
||||
#if 0
|
||||
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#define LOG_HEX(x,y) DumpHex(x,y)
|
||||
#else
|
||||
#define LOG(format, ... )
|
||||
#define LOG_RAW(format, ... )
|
||||
#define LOG_HEX(x,y)
|
||||
#endif
|
||||
|
||||
#define wait_Miso(level) CC1101_WaitMISO(__FUNCTION__,__LINE__,level)
|
||||
|
||||
// SPI Stuff
|
||||
#if CONFIG_SPI2_HOST
|
||||
@@ -39,6 +31,9 @@ void DumpHex(void *AdrIn,int Len);
|
||||
#define HOST_ID SPI3_HOST
|
||||
#endif
|
||||
|
||||
// Wait for up to 2 milliseconds for MISO to go low
|
||||
#define MISO_WAIT_TIMEOUT 2
|
||||
|
||||
// Address Config = No address check
|
||||
// Base Frequency = xxx.xxx
|
||||
// CRC Enable = false
|
||||
@@ -247,10 +242,10 @@ SubGigErr SubGig_radio_init(uint8_t ch)
|
||||
SubGigErr Ret = SUBGIG_ERR_NONE;
|
||||
|
||||
do {
|
||||
gpio_reset_pin(CONFIG_CSN_GPIO);
|
||||
gpio_set_direction(CONFIG_CSN_GPIO, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(CONFIG_CSN_GPIO, 1);
|
||||
|
||||
if(!CC1101_QuickCheck()) {
|
||||
Ret = SUBGIG_CC1101_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
spi_bus_config_t buscfg = {
|
||||
.sclk_io_num = CONFIG_SCK_GPIO,
|
||||
.mosi_io_num = CONFIG_MOSI_GPIO,
|
||||
@@ -297,6 +292,7 @@ SubGigErr SubGig_radio_init(uint8_t ch)
|
||||
}
|
||||
// Check Chip ID
|
||||
if(!CC1101_Present()) {
|
||||
LOGE("CC1101 not detected\n");
|
||||
Ret = SUBGIG_CC1101_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
@@ -314,7 +310,7 @@ SubGigErr SubGig_radio_init(uint8_t ch)
|
||||
} while(false);
|
||||
|
||||
if(ErrLine != 0) {
|
||||
LOG("%s#%d: failed %d\n",__FUNCTION__,ErrLine,Err);
|
||||
LOGA("%s#%d: failed %d\n",__FUNCTION__,ErrLine,Err);
|
||||
if(Err == 0) {
|
||||
Ret = ESP_FAIL;
|
||||
}
|
||||
@@ -453,8 +449,6 @@ int8_t SubGig_commsRxUnencrypted(uint8_t *data)
|
||||
if(RxBytes >= 2) {
|
||||
// NB: RxBytes includes the CRC, deduct it
|
||||
Ret = (uint8_t) RxBytes - 2;
|
||||
LOG("Received %d byte subgig frame:\n",Ret);
|
||||
LOG_HEX(data,Ret);
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
@@ -477,7 +471,7 @@ int CheckSubGigState()
|
||||
}
|
||||
|
||||
if(Err != SUBGIG_ERR_NONE) {
|
||||
LOG("CheckSubGigState: returing %d\n",Err);
|
||||
LOGE("Returning %d\n",Err);
|
||||
}
|
||||
|
||||
return Err;
|
||||
@@ -558,5 +552,96 @@ void DumpHex(void *AdrIn,int Len)
|
||||
LOG_RAW("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Quick and hopefully safe check if a CC1101 is present.
|
||||
// Only the CSN and MISO GPIOs are configured for this test.
|
||||
// If they are and there's a CC1101 then MISO should go low when
|
||||
// CSN is low
|
||||
bool CC1101_QuickCheck()
|
||||
{
|
||||
// Init CSn and MISO
|
||||
esp_err_t Err = ESP_OK;
|
||||
bool Ret = false;
|
||||
int Line = 0;
|
||||
int MisoLevel;
|
||||
|
||||
do {
|
||||
Err = gpio_reset_pin(CONFIG_MISO_GPIO);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
Err = gpio_set_direction(CONFIG_MISO_GPIO,GPIO_MODE_INPUT);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
Err = gpio_set_pull_mode(CONFIG_MISO_GPIO,GPIO_PULLUP_ONLY);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
Err = gpio_reset_pin(CONFIG_CSN_GPIO);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
Err = gpio_set_direction(CONFIG_CSN_GPIO,GPIO_MODE_OUTPUT);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
Err = gpio_set_level(CONFIG_CSN_GPIO,1);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
// The CC1101 is not selected and MISO has a pullup so it should be high
|
||||
if(wait_Miso(1) != 1) {
|
||||
LOGA("Error: SubGhz MISO stuck low\n");
|
||||
break;
|
||||
}
|
||||
// Select the CC1101
|
||||
Err = gpio_set_level(CONFIG_CSN_GPIO,0);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
MisoLevel = wait_Miso(0);
|
||||
|
||||
// Deselect the CC1101
|
||||
Err = gpio_set_level(CONFIG_CSN_GPIO,1);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
if(MisoLevel == 0) {
|
||||
Ret = true;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
|
||||
if(Line != 0) {
|
||||
LOGA("%s#%d: gpio call failed (0x%x)\n",__FUNCTION__,__LINE__,Err);
|
||||
}
|
||||
|
||||
if(Ret) {
|
||||
// Disable pullup, it's no longer needed
|
||||
gpio_set_pull_mode(CONFIG_MISO_GPIO,GPIO_FLOATING);
|
||||
}
|
||||
else {
|
||||
// CC1101 not present, deinit MISO and CSn GPIOs
|
||||
LOGE("CC1101 not detected\n");
|
||||
gpio_reset_pin(CONFIG_MISO_GPIO);
|
||||
gpio_reset_pin(CONFIG_CSN_GPIO);
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
#endif // CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
|
||||
|
||||
@@ -34,34 +34,12 @@
|
||||
#include <stdbool.h>
|
||||
#include <driver/spi_master.h>
|
||||
#include "proto.h"
|
||||
#include "utils.h"
|
||||
#include "second_uart.h"
|
||||
#include "cc1101_radio.h"
|
||||
#include "logging.h"
|
||||
#include "radio.h"
|
||||
|
||||
#define ENABLE_LOGGING 0
|
||||
|
||||
// LOGA - generic logging, always enabled
|
||||
#define LOGA(format, ... ) printf(format,## __VA_ARGS__)
|
||||
// LOGE - error logging, always enabled
|
||||
#define LOGE(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
|
||||
#if ENABLE_LOGGING
|
||||
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#else
|
||||
#define LOG(format, ... )
|
||||
#define LOG_RAW(format, ... )
|
||||
#endif
|
||||
|
||||
#define ENABLE_VERBOSE_LOGGING 0
|
||||
|
||||
#if ENABLE_VERBOSE_LOGGING
|
||||
#define LOGV(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOGV_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#else
|
||||
#define LOGV(format, ... )
|
||||
#define LOGB_RAW(format, ... )
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -197,7 +175,7 @@ uint8_t CC1101_readReg(uint8_t regAddr, uint8_t regType);
|
||||
void CC1101_writeReg(uint8_t regAddr, uint8_t value);
|
||||
void CC1101_setTxState(void);
|
||||
|
||||
void setIdleState(void);
|
||||
static void setIdleState(void);
|
||||
|
||||
spi_device_handle_t gSpiHndl;
|
||||
|
||||
@@ -288,7 +266,7 @@ static uint8_t gRfState;
|
||||
|
||||
#define cc1101_Select() gpio_set_level(CONFIG_CSN_GPIO, LOW)
|
||||
#define cc1101_Deselect() gpio_set_level(CONFIG_CSN_GPIO, HIGH)
|
||||
#define wait_Miso() while(gpio_get_level(CONFIG_MISO_GPIO)>0)
|
||||
#define wait_Miso() CC1101_WaitMISO(__FUNCTION__,__LINE__,0)
|
||||
#define getGDO0state() gpio_get_level(CONFIG_GDO0_GPIO)
|
||||
#define wait_GDO0_high() while(!getGDO0state())
|
||||
#define wait_GDO0_low() while(getGDO0state())
|
||||
@@ -633,14 +611,13 @@ int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi)
|
||||
// Any data waiting to be read and no overflow?
|
||||
do {
|
||||
if(rxBytes & CC1101_RXFIFO_OVERFLOW_MASK) {
|
||||
LOGE("RxFifo overflow\n");
|
||||
// This occurs occasionally due to random noise, so do don't log
|
||||
Ret = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
if(rxBytes < 2) {
|
||||
// should have at least 2 bytes, packet len and one byte of data
|
||||
LOGE("Internal error, rxBytes = %d\n",rxBytes);
|
||||
Ret = -2;
|
||||
break;
|
||||
}
|
||||
@@ -786,5 +763,24 @@ void CC1101_logState()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Wait for up to 2 milliseconds for MISO to go low
|
||||
#define MISO_WAIT_TIMEOUT 2
|
||||
int CC1101_WaitMISO(const char *Func,int Line,int level)
|
||||
{
|
||||
uint32_t Start = getMillis();
|
||||
int MisoLevel;
|
||||
|
||||
while((MisoLevel = gpio_get_level(CONFIG_MISO_GPIO)) != level) {
|
||||
if((getMillis() - Start) >= MISO_WAIT_TIMEOUT) {
|
||||
LOGA("%s#%d: timeout waiting for MISO to go %s\n",
|
||||
Func,Line,level ? "high" : "low");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return MisoLevel;
|
||||
}
|
||||
|
||||
#endif // CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
|
||||
|
||||
@@ -29,6 +29,14 @@
|
||||
#ifndef __CC1101_RADIO_H_
|
||||
#define __CC1101_RADIO_H_
|
||||
|
||||
// Log to all
|
||||
#define LOGA(format, ... ) \
|
||||
uart_printf(format "\r",## __VA_ARGS__)
|
||||
|
||||
// Error log to all
|
||||
#define LOGE(format, ... ) \
|
||||
uart_printf("%s#%d: " format "\r",__FUNCTION__,__LINE__,## __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* CC1101 configuration registers
|
||||
*/
|
||||
@@ -113,6 +121,7 @@ void CC1101_DumpRegs(void);
|
||||
void CC1101_reset(void);
|
||||
void CC1101_logState(void);
|
||||
void CC1101_setRxState(void);
|
||||
int CC1101_WaitMISO(const char *Func,int Line,int level);
|
||||
|
||||
#endif // __CC1101_RADIO_H_
|
||||
|
||||
|
||||
23
ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/logging.h
Executable file
23
ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/logging.h
Executable file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#if CONFIG_OEPL_DEBUG_PRINT
|
||||
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
void DumpHex(void *AdrIn,int Len);
|
||||
#define LOG_HEX(x,y) DumpHex(x,y)
|
||||
#else
|
||||
#define LOG(format, ... )
|
||||
#define LOG_RAW(format, ... )
|
||||
#define LOG_HEX(x,y)
|
||||
#endif
|
||||
|
||||
#if CONFIG_OEPL_VERBOSE_DEBUG
|
||||
#define LOGV(format, ... ) LOG(format,## __VA_ARGS__)
|
||||
#define LOGV_RAW(format, ... ) LOG_RAW(format,## __VA_ARGS__)
|
||||
#define LOGV_HEX(x,y) LOG_HEX(x,y)
|
||||
#else
|
||||
#define LOGV(format, ... )
|
||||
#define LOGV_RAW(format, ... )
|
||||
#define LOGV_HEX(x,y)
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "logging.h"
|
||||
#include "SubGigRadio.h"
|
||||
|
||||
|
||||
@@ -35,6 +36,30 @@ static const char *TAG = "MAIN";
|
||||
|
||||
const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
|
||||
|
||||
#if CONFIG_OEPL_VERBOSE_DEBUG
|
||||
const struct {
|
||||
uint8_t Type;
|
||||
const char *Name;
|
||||
} gPktTypeLookupTbl[] = {
|
||||
{PKT_TAG_RETURN_DATA, "TAG_RETURN_DATA"},
|
||||
{PKT_TAG_RETURN_DATA_ACK, "TAG_RETURN_DATA_ACK"},
|
||||
{PKT_AVAIL_DATA_SHORTREQ, "AVAIL_DATA_SHORTREQ"},
|
||||
{PKT_AVAIL_DATA_REQ, "AVAIL_DATA_REQ"},
|
||||
{PKT_AVAIL_DATA_INFO, "AVAIL_DATA_INFO"},
|
||||
{PKT_BLOCK_PARTIAL_REQUEST, "BLOCK_PARTIAL_REQUEST"},
|
||||
{PKT_BLOCK_REQUEST_ACK, "BLOCK_REQUEST_ACK"},
|
||||
{PKT_BLOCK_REQUEST, "BLOCK_REQUEST"},
|
||||
{PKT_BLOCK_PART, "BLOCK_PART"},
|
||||
{PKT_XFER_COMPLETE, "XFER_COMPLETE"},
|
||||
{PKT_XFER_COMPLETE_ACK, "XFER_COMPLETE_ACK"},
|
||||
{PKT_CANCEL_XFER, "CANCEL_XFER"},
|
||||
{PKT_PING, "PING"},
|
||||
{PKT_PONG, "PONG"},
|
||||
{0,NULL} // End of table
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#define DATATYPE_NOUPDATE 0
|
||||
#define HW_TYPE 0xC6
|
||||
|
||||
@@ -44,7 +69,7 @@ const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
|
||||
struct pendingData pendingDataArr[MAX_PENDING_MACS];
|
||||
|
||||
// VERSION GOES HERE!
|
||||
uint16_t version = 0x001e;
|
||||
uint16_t version = 0x001f;
|
||||
|
||||
#define RAW_PKT_PADDING 2
|
||||
|
||||
@@ -474,7 +499,7 @@ void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
|
||||
lastBlockRequest = getMillis();
|
||||
} else {
|
||||
// we're talking to another mac, let this mac know we can't accomodate another request right now
|
||||
pr("BUSY!\n");
|
||||
pr("BUSY!\n\r");
|
||||
sendCancelXfer(rxHeader->src);
|
||||
return;
|
||||
}
|
||||
@@ -496,9 +521,9 @@ void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
|
||||
if (forceBlockDownload) {
|
||||
if ((getMillis() - nextBlockAttempt) > 380) {
|
||||
requestDataDownload = true;
|
||||
pr("FORCED\n");
|
||||
pr("FORCED\n\r");
|
||||
} else {
|
||||
pr("IGNORED\n");
|
||||
pr("IGNORED\n\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -647,7 +672,7 @@ void sendPart(uint8_t partNo) {
|
||||
}
|
||||
void sendBlockData() {
|
||||
if (getBlockDataLength() == 0) {
|
||||
pr("Invalid block request received, 0 parts..\n");
|
||||
pr("Invalid block request received, 0 parts..\n\r");
|
||||
requestedData.requestedParts[0] |= 0x01;
|
||||
}
|
||||
|
||||
@@ -660,7 +685,7 @@ void sendBlockData() {
|
||||
pr(".");
|
||||
}
|
||||
}
|
||||
pr("\n");
|
||||
pr("\n\r");
|
||||
|
||||
uint8_t partNo = 0;
|
||||
while (partNo < BLOCK_MAX_PARTS) {
|
||||
@@ -766,8 +791,24 @@ void app_main(void) {
|
||||
int8_t ret = commsRxUnencrypted(radiorxbuffer);
|
||||
if (ret > 1) {
|
||||
led_flash(0);
|
||||
|
||||
uint8_t PktType = getPacketType(radiorxbuffer);
|
||||
#if CONFIG_OEPL_VERBOSE_DEBUG
|
||||
LOGV_RAW("Received %d byte ",ret);
|
||||
for(uint8_t i = 0; gPktTypeLookupTbl[i].Name != NULL; i++) {
|
||||
if(gPktTypeLookupTbl[i].Type == PktType) {
|
||||
LOGV_RAW("%s",gPktTypeLookupTbl[i].Name);
|
||||
break;
|
||||
}
|
||||
if(gPktTypeLookupTbl[i].Name == NULL) {
|
||||
LOGV_RAW("undefined (0x%02x)",PktType);
|
||||
}
|
||||
}
|
||||
LOGV_RAW(" packet:\n");
|
||||
LOGV_HEX(radiorxbuffer,ret);
|
||||
#endif
|
||||
// received a packet, lets see what it is
|
||||
switch (getPacketType(radiorxbuffer)) {
|
||||
switch (PktType) {
|
||||
case PKT_AVAIL_DATA_REQ:
|
||||
if (ret == 28) {
|
||||
// old version of the AvailDataReq struct, set all the new fields to zero, so it will pass the CRC
|
||||
|
||||
@@ -54,7 +54,11 @@ void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_erro
|
||||
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
|
||||
isInTransmit = 0;
|
||||
ESP_EARLY_LOGI(TAG, "TX %d", frame[0]);
|
||||
esp_ieee802154_receive_handle_done(ack);
|
||||
if(ack != NULL) {
|
||||
if(esp_ieee802154_receive_handle_done(ack)) {
|
||||
ESP_EARLY_LOGI(TAG, "esp_ieee802154_receive_handle_done() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
static bool zigbee_is_enabled = false;
|
||||
void radio_init(uint8_t ch) {
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include "soc/uart_struct.h"
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "soc/lp_uart_reg.h"
|
||||
static const char *TAG = "SECOND_UART";
|
||||
#endif
|
||||
static const char *TAG = "SECOND_UART";
|
||||
#include "second_uart.h"
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ void init_second_uart() {
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
ESP_LOGI(TAG, "HARDWARE_UART_TX %d, CONFIG_OEPL_HARDWARE_UART_RX %d",
|
||||
CONFIG_OEPL_HARDWARE_UART_TX,CONFIG_OEPL_HARDWARE_UART_RX);
|
||||
ESP_ERROR_CHECK(uart_driver_install(1, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0));
|
||||
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
|
||||
ESP_ERROR_CHECK(uart_set_pin(1, CONFIG_OEPL_HARDWARE_UART_TX, CONFIG_OEPL_HARDWARE_UART_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
@@ -21,6 +21,9 @@ void uart_printf(const char *format, ...);
|
||||
#elif defined(CONFIG_OEPL_HARDWARE_PROFILE_POE_AP)
|
||||
#define CONFIG_OEPL_HARDWARE_UART_TX 5
|
||||
#define CONFIG_OEPL_HARDWARE_UART_RX 18
|
||||
#elif defined(CONFIG_OEPL_HARDWARE_PROFILE_ELECROW_C6)
|
||||
#define CONFIG_OEPL_HARDWARE_UART_TX 0
|
||||
#define CONFIG_OEPL_HARDWARE_UART_RX 1
|
||||
#elif defined(CONFIG_OEPL_HARDWARE_PROFILE_CUSTOM)
|
||||
#if !defined(CONFIG_OEPL_HARDWARE_UART_TX) || !defined(CONFIG_OEPL_HARDWARE_UART_RX)
|
||||
#error "No UART TX / RX pins defined. Please check menuconfig"
|
||||
|
||||
@@ -7,4 +7,4 @@ CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_OEPL_SUBGIG_SUPPORT=y
|
||||
|
||||
CONFIG_IEEE802154_RX_BUFFER_SIZE=100
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
menu "OEPL Hardware config"
|
||||
menu "OEPL config"
|
||||
|
||||
choice OEPL_HARDWARE_PROFILE
|
||||
prompt "Hardware profile"
|
||||
default OEPL_HARDWARE_PROFILE_DEFAULT
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_DEFAULT
|
||||
bool "Default"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_POE_AP
|
||||
bool "PoE-AP"
|
||||
default OEPL_HARDWARE_PROFILE_LILYGO
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_CUSTOM
|
||||
bool "Custom"
|
||||
@@ -102,6 +96,16 @@ menu "OEPL Hardware config"
|
||||
USE SPI3_HOST. This is also called VSPI_HOST
|
||||
endchoice
|
||||
endmenu
|
||||
|
||||
config OEPL_DEBUG_PRINT
|
||||
bool "Enable OEPL Debug logging"
|
||||
default "n"
|
||||
|
||||
config OEPL_VERBOSE_DEBUG
|
||||
depends on OEPL_DEBUG_PRINT
|
||||
bool "Enable OEPL Verbose Debug logging"
|
||||
default "n"
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
|
||||
BIN
ESP32_AP-Flasher/data/fonts/tahoma11.vlw
Normal file
BIN
ESP32_AP-Flasher/data/fonts/tahoma11.vlw
Normal file
Binary file not shown.
Binary file not shown.
@@ -10,54 +10,6 @@
|
||||
"/www/painter.js",
|
||||
"/www/setup.html",
|
||||
"/www/setup.js",
|
||||
"/www/upload-demo.html",
|
||||
"/fonts/weathericons30.vlw",
|
||||
"/fonts/weathericons70.vlw",
|
||||
"/fonts/weathericons78.vlw",
|
||||
"/fonts/calibrib120.vlw",
|
||||
"/fonts/calibrib150.vlw",
|
||||
"/fonts/calibrib50.vlw",
|
||||
"/fonts/calibrib60.vlw",
|
||||
"/fonts/BellCent10.vlw",
|
||||
"/tagtypes/00.json",
|
||||
"/tagtypes/01.json",
|
||||
"/tagtypes/02.json",
|
||||
"/tagtypes/05.json",
|
||||
"/tagtypes/11.json",
|
||||
"/tagtypes/21.json",
|
||||
"/tagtypes/22.json",
|
||||
"/tagtypes/26.json",
|
||||
"/tagtypes/27.json",
|
||||
"/tagtypes/2E.json",
|
||||
"/tagtypes/2F.json",
|
||||
"/tagtypes/30.json",
|
||||
"/tagtypes/31.json",
|
||||
"/tagtypes/32.json",
|
||||
"/tagtypes/33.json",
|
||||
"/tagtypes/34.json",
|
||||
"/tagtypes/35.json",
|
||||
"/tagtypes/36.json",
|
||||
"/tagtypes/40.json",
|
||||
"/tagtypes/41.json",
|
||||
"/tagtypes/42.json",
|
||||
"/tagtypes/43.json",
|
||||
"/tagtypes/55.json",
|
||||
"/tagtypes/60.json",
|
||||
"/tagtypes/61.json",
|
||||
"/tagtypes/62.json",
|
||||
"/tagtypes/80.json",
|
||||
"/tagtypes/81.json",
|
||||
"/tagtypes/82.json",
|
||||
"/tagtypes/83.json",
|
||||
"/tagtypes/B0.json",
|
||||
"/tagtypes/B1.json",
|
||||
"/tagtypes/B2.json",
|
||||
"/tagtypes/B3.json",
|
||||
"/tagtypes/B5.json",
|
||||
"/tagtypes/BD.json",
|
||||
"/tagtypes/BE.json",
|
||||
"/tagtypes/E0.json",
|
||||
"/tagtypes/E1.json",
|
||||
"/tagtypes/F0.json"
|
||||
"/www/upload-demo.html"
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
ESP32_AP-Flasher/data/www/g5decoder.js.gz
Normal file
BIN
ESP32_AP-Flasher/data/www/g5decoder.js.gz
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
7
ESP32_AP-Flasher/esp32_sdcard_only.csv
Normal file
7
ESP32_AP-Flasher/esp32_sdcard_only.csv
Normal file
@@ -0,0 +1,7 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x1E0000,
|
||||
app1, app, ota_1, 0x1F0000,0x1E0000,
|
||||
spiffs, data, spiffs, 0x3D0000,0x20000,
|
||||
coredump, data, coredump,0x3F0000,0x10000,
|
||||
|
@@ -4,9 +4,9 @@
|
||||
|
||||
class SPIFFSEditor: public AsyncWebHandler {
|
||||
private:
|
||||
fs::FS _fs;
|
||||
mutable fs::FS _fs;
|
||||
String _username;
|
||||
String _password;
|
||||
String _password;
|
||||
bool _authenticated;
|
||||
uint32_t _startTime;
|
||||
public:
|
||||
@@ -15,10 +15,10 @@ class SPIFFSEditor: public AsyncWebHandler {
|
||||
#else
|
||||
SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS);
|
||||
#endif
|
||||
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
||||
virtual bool canHandle(AsyncWebServerRequest* request) const override final;
|
||||
virtual void handleRequest(AsyncWebServerRequest *request) override final;
|
||||
virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final;
|
||||
virtual bool isRequestHandlerTrivial() override final {return false;}
|
||||
virtual bool isRequestHandlerTrivial() const override final {return false;}
|
||||
virtual String listFilesRecursively(String path, bool recursive = false);
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ void checkVars();
|
||||
void drawNew(const uint8_t mac[8], tagRecord *&taginfo);
|
||||
bool updateTagImage(String &filename, const uint8_t *dst, uint16_t nextCheckin, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawString(TFT_eSprite &spr, String content, int16_t posx, int16_t posy, String font, byte align = 0, uint16_t color = TFT_BLACK, uint16_t size = 30, uint16_t bgcolor = TFT_WHITE);
|
||||
void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy, int16_t boxwidth, int16_t boxheight, String font, uint16_t color = TFT_BLACK, uint16_t bgcolor = TFT_WHITE, float lineheight = 1);
|
||||
void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy, int16_t boxwidth, int16_t boxheight, String font, uint16_t color = TFT_BLACK, uint16_t bgcolor = TFT_WHITE, float lineheight = 1, byte align = TL_DATUM);
|
||||
void initSprite(TFT_eSprite &spr, int w, int h, imgParam &imageParams);
|
||||
void drawDate(String &filename, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawNumber(String &filename, int32_t count, int32_t thresholdred, tagRecord *&taginfo, imgParam &imageParams);
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
#include <Arduino.h>
|
||||
#include <LittleFS.h>
|
||||
|
||||
bool doC6flash(uint8_t doDownload);
|
||||
#if defined HAS_H2
|
||||
#define SHORT_CHIP_NAME "H2"
|
||||
#define OTA_BIN_DIR "ESP32-H2"
|
||||
#define ESP_CHIP_TYPE ESP32H2_CHIP
|
||||
#elif defined HAS_TSLR
|
||||
#define SHORT_CHIP_NAME "TSLR"
|
||||
#elif defined HAS_ELECROW_C6
|
||||
#define SHORT_CHIP_NAME "ELECROW_C6"
|
||||
#define OTA_BIN_DIR "ESP32-C6"
|
||||
#define ESP_CHIP_TYPE ESP32C6_CHIP
|
||||
#elif defined C6_OTA_FLASHING
|
||||
#define SHORT_CHIP_NAME "C6"
|
||||
#define OTA_BIN_DIR "ESP32-C6"
|
||||
#define ESP_CHIP_TYPE ESP32C6_CHIP
|
||||
#endif
|
||||
|
||||
bool FlashC6_H2(const char *Url);
|
||||
|
||||
@@ -93,6 +93,46 @@ extern Arduino_RGB_Display *gfx;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAS_4inch_TPANEL
|
||||
|
||||
#define LV_ATTRIBUTE_TICK_INC IRAM_ATTR
|
||||
#define TOUCH_MODULES_CST_MUTUAL
|
||||
|
||||
// esp32-4848S040
|
||||
#define LCD_WIDTH 480
|
||||
#define LCD_HEIGHT 480
|
||||
#define LCD_VSYNC 17
|
||||
#define LCD_HSYNC 16
|
||||
#define LCD_PCLK 21
|
||||
#define LCD_R0 11
|
||||
#define LCD_R1 12
|
||||
#define LCD_R2 13
|
||||
#define LCD_R3 14
|
||||
#define LCD_R4 0
|
||||
#define LCD_G0 8
|
||||
#define LCD_G1 20
|
||||
#define LCD_G2 3
|
||||
#define LCD_G3 46
|
||||
#define LCD_G4 9
|
||||
#define LCD_G5 10
|
||||
#define LCD_B0 4
|
||||
#define LCD_B1 5
|
||||
#define LCD_B2 6
|
||||
#define LCD_B3 7
|
||||
#define LCD_B4 15
|
||||
#define LCD_BL 38
|
||||
#define LCD_DE 18
|
||||
|
||||
#define SPI_LCD_CS 39
|
||||
#define SPI_LCD_SCLK 48
|
||||
#define SPI_LCD_MOSI 47
|
||||
|
||||
#include "Arduino_GFX_Library.h"
|
||||
|
||||
extern Arduino_RGB_Display *gfx;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TFT
|
||||
|
||||
extern TFT_eSPI tft2;
|
||||
|
||||
@@ -26,6 +26,7 @@ const uint8_t PROGMEM gamma8[] = {
|
||||
void ledTask(void* parameter);
|
||||
void setBrightness(int brightness);
|
||||
void updateBrightnessFromConfig();
|
||||
void ledcSet(uint8_t channel, uint8_t brightness);
|
||||
|
||||
#ifdef HAS_RGB_LED
|
||||
extern CRGB rgbIdleColor;
|
||||
@@ -34,7 +35,6 @@ void shortBlink(CRGB cname);
|
||||
void showColorPattern(CRGB colorone, CRGB colortwo, CRGB colorthree);
|
||||
void rgbIdle();
|
||||
void addFadeColor(CRGB cname);
|
||||
|
||||
#endif
|
||||
|
||||
void quickBlink(uint8_t repeat);
|
||||
|
||||
@@ -17,7 +17,6 @@ struct imgParam {
|
||||
bool hasRed;
|
||||
uint8_t dataType;
|
||||
uint8_t dither;
|
||||
// bool grayLut = false;
|
||||
uint8_t bufferbpp = 8;
|
||||
uint8_t rotate = 0;
|
||||
uint16_t highlightColor = 2;
|
||||
|
||||
@@ -26,6 +26,7 @@ extern void processDataReq(struct espAvailDataReq* adr, bool local, IPAddress re
|
||||
extern void processTagReturnData(struct espTagReturnData* trd, uint8_t len, bool local);
|
||||
|
||||
extern bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local, const uint8_t* payload = nullptr);
|
||||
bool sendTagMac(const uint8_t* dst, const uint64_t newmac, bool local);
|
||||
extern bool sendAPSegmentedData(const uint8_t* dst, String data, uint16_t icons, bool inverted, bool local);
|
||||
extern bool showAPSegmentedInfo(const uint8_t* dst, bool local);
|
||||
extern void updateTaginfoitem(struct TagInfo* taginfoitem, IPAddress remoteIP);
|
||||
|
||||
@@ -12,8 +12,8 @@ extern struct espSetChannelPower curChannel;
|
||||
#define AP_STATE_NORADIO 7
|
||||
|
||||
struct APInfoS {
|
||||
bool isOnline = false;
|
||||
uint8_t state = AP_STATE_OFFLINE;
|
||||
volatile bool isOnline = false;
|
||||
volatile uint8_t state = AP_STATE_OFFLINE;
|
||||
uint8_t type;
|
||||
uint16_t version = 0;
|
||||
uint8_t channel;
|
||||
@@ -29,6 +29,17 @@ struct APInfoS {
|
||||
|
||||
extern struct APInfoS apInfo;
|
||||
|
||||
enum ApSerialState {
|
||||
SERIAL_STATE_NONE,
|
||||
SERIAL_STATE_INITIALIZED,
|
||||
SERIAL_STATE_STARTING,
|
||||
SERIAL_STATE_RUNNING,
|
||||
SERIAL_STATE_STOP,
|
||||
SERIAL_STATE_STOPPED
|
||||
};
|
||||
|
||||
extern volatile ApSerialState gSerialTaskState;
|
||||
|
||||
void APTask(void* parameter);
|
||||
|
||||
bool sendCancelPending(struct pendingData* pending);
|
||||
@@ -38,5 +49,5 @@ void APEnterEarlyReset();
|
||||
bool sendChannelPower(struct espSetChannelPower* scp);
|
||||
void rxSerialTask2(void* parameter);
|
||||
void APTagReset();
|
||||
bool bringAPOnline();
|
||||
bool bringAPOnline(uint8_t newState = AP_STATE_ONLINE);
|
||||
void setAPstate(bool isOnline, uint8_t state);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "FS.h"
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
#ifndef SD_CARD_SDMMC
|
||||
|
||||
#ifndef SD_CARD_SS
|
||||
#error SD_CARD_SS UNDEFINED
|
||||
#endif
|
||||
@@ -18,6 +20,8 @@
|
||||
|
||||
#ifndef SD_CARD_MOSI
|
||||
#define SD_CARD_MOSI 23
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -36,7 +40,9 @@ class DynStorage {
|
||||
extern SemaphoreHandle_t fsMutex;
|
||||
extern DynStorage Storage;
|
||||
extern fs::FS *contentFS;
|
||||
#ifndef SD_CARD_ONLY
|
||||
extern void copyFile(File in, File out);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define NO_SUBGHZ_CHANNEL 255
|
||||
class tagRecord {
|
||||
public:
|
||||
tagRecord() : mac{0}, version(0), alias(""), lastseen(0), nextupdate(0), contentMode(0), pendingCount(0), md5{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), apIp(IPAddress(0, 0, 0, 0)), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0), invert(0), updateCount(0), updateLast(0) {}
|
||||
tagRecord() : mac{0}, version(0), alias(""), lastseen(0), nextupdate(0), contentMode(0), pendingCount(0), md5{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), apIp(IPAddress(0, 0, 0, 0)), pendingIdle(0), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0), invert(0), updateCount(0), updateLast(0) {}
|
||||
|
||||
uint8_t mac[8];
|
||||
uint8_t version;
|
||||
@@ -38,7 +38,6 @@ class tagRecord {
|
||||
bool isExternal;
|
||||
IPAddress apIp;
|
||||
uint16_t pendingIdle;
|
||||
bool hasCustomLUT;
|
||||
uint8_t rotate;
|
||||
uint8_t lut;
|
||||
uint16_t tagSoftwareVersion;
|
||||
@@ -64,7 +63,7 @@ struct Config {
|
||||
uint8_t language;
|
||||
uint8_t maxsleep;
|
||||
uint8_t stopsleep;
|
||||
uint8_t runStatus;
|
||||
volatile uint8_t runStatus;
|
||||
uint8_t preview;
|
||||
uint8_t nightlyreboot;
|
||||
uint8_t lock;
|
||||
@@ -76,6 +75,7 @@ struct Config {
|
||||
uint8_t discovery;
|
||||
String repo;
|
||||
String env;
|
||||
uint8_t showtimestamp;
|
||||
};
|
||||
|
||||
struct Color {
|
||||
|
||||
@@ -16,7 +16,8 @@ enum WifiStatus {
|
||||
WAIT_CONNECTING,
|
||||
CONNECTED,
|
||||
WAIT_RECONNECT,
|
||||
AP
|
||||
AP,
|
||||
ETHERNET
|
||||
};
|
||||
|
||||
class WifiManager {
|
||||
@@ -41,6 +42,7 @@ class WifiManager {
|
||||
bool waitForConnection();
|
||||
void pollSerial();
|
||||
static void terminalLog(String text);
|
||||
static String buildHostname(esp_mac_type_t mac_type);
|
||||
|
||||
public:
|
||||
WifiManager();
|
||||
@@ -53,6 +55,8 @@ class WifiManager {
|
||||
void startManagementServer();
|
||||
void poll();
|
||||
static void WiFiEvent(WiFiEvent_t event);
|
||||
void initEth();
|
||||
IPAddress localIP();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
114
ESP32_AP-Flasher/lib2/gt911-touch/src/Touch_GT911.cpp
Normal file
114
ESP32_AP-Flasher/lib2/gt911-touch/src/Touch_GT911.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "Arduino.h"
|
||||
#include <Touch_GT911.h>
|
||||
#include <Wire.h>
|
||||
|
||||
Touch_GT911::Touch_GT911(uint8_t _sda, uint8_t _scl, uint16_t _width, uint16_t _height) :
|
||||
pinSda(_sda), pinScl(_scl), width(_width), height(_height) {
|
||||
}
|
||||
TPoint::TPoint(void) {
|
||||
id = x = y = size = 0;
|
||||
}
|
||||
TPoint::TPoint(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _size) {
|
||||
id = _id;
|
||||
x = _x;
|
||||
y = _y;
|
||||
size = _size;
|
||||
}
|
||||
bool TPoint::operator==(TPoint point) {
|
||||
return ((point.x == x) && (point.y == y) && (point.size == size));
|
||||
}
|
||||
bool TPoint::operator!=(TPoint point) {
|
||||
return ((point.x != x) || (point.y != y) || (point.size != size));
|
||||
}
|
||||
void Touch_GT911::begin(uint8_t _addr) {
|
||||
addr = _addr;
|
||||
Wire.begin(pinSda, pinScl);
|
||||
}
|
||||
void Touch_GT911::calculateChecksum() {
|
||||
uint8_t checksum;
|
||||
for (uint8_t i=0; i<GT911_CONFIG_SIZE; i++) {
|
||||
checksum += configBuf[i];
|
||||
}
|
||||
checksum = (~checksum) + 1;
|
||||
configBuf[GT911_CONFIG_CHKSUM - GT911_CONFIG_START] = checksum;
|
||||
}
|
||||
void Touch_GT911::reConfig() {
|
||||
calculateChecksum();
|
||||
writeByteData(GT911_CONFIG_CHKSUM, configBuf[GT911_CONFIG_CHKSUM-GT911_CONFIG_START]);
|
||||
writeByteData(GT911_CONFIG_FRESH, 1);
|
||||
}
|
||||
void Touch_GT911::setResolution(uint16_t _width, uint16_t _height) {
|
||||
configBuf[GT911_X_OUTPUT_MAX_LOW - GT911_CONFIG_START] = lowByte(_width);
|
||||
configBuf[GT911_X_OUTPUT_MAX_HIGH - GT911_CONFIG_START] = highByte(_width);
|
||||
configBuf[GT911_Y_OUTPUT_MAX_LOW - GT911_CONFIG_START] = lowByte(_height);
|
||||
configBuf[GT911_Y_OUTPUT_MAX_HIGH - GT911_CONFIG_START] = highByte(_height);
|
||||
reConfig();
|
||||
}
|
||||
void Touch_GT911::read(void) {
|
||||
uint8_t data[7];
|
||||
uint8_t id;
|
||||
uint16_t x, y, size;
|
||||
|
||||
uint8_t pointInfo = readByteData(GT911_POINT_INFO);
|
||||
uint8_t bufferStatus = pointInfo >> 7 & 1;
|
||||
uint8_t proximityValid = pointInfo >> 5 & 1;
|
||||
uint8_t haveKey = pointInfo >> 4 & 1;
|
||||
isLargeDetect = pointInfo >> 6 & 1;
|
||||
touches = pointInfo & 0xF;
|
||||
isTouched = touches > 0;
|
||||
if (bufferStatus == 1 && isTouched) {
|
||||
for (uint8_t i=0; i<touches; i++) {
|
||||
readBlockData(data, GT911_POINT_1 + i * 8, 7);
|
||||
points[i] = readPoint(data);
|
||||
}
|
||||
}
|
||||
writeByteData(GT911_POINT_INFO, 0);
|
||||
}
|
||||
TPoint Touch_GT911::readPoint(uint8_t *data) {
|
||||
uint16_t temp;
|
||||
uint8_t id = data[0];
|
||||
uint16_t x = data[1] + (data[2] << 8);
|
||||
uint16_t y = data[3] + (data[4] << 8);
|
||||
uint16_t size = data[5] + (data[6] << 8);
|
||||
x = width - x;
|
||||
y = height - y;
|
||||
return TPoint(id, x, y, size);
|
||||
}
|
||||
void Touch_GT911::writeByteData(uint16_t reg, uint8_t val) {
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(highByte(reg));
|
||||
Wire.write(lowByte(reg));
|
||||
Wire.write(val);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
uint8_t Touch_GT911::readByteData(uint16_t reg) {
|
||||
uint8_t x;
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(highByte(reg));
|
||||
Wire.write(lowByte(reg));
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(addr, (uint8_t)1);
|
||||
x = Wire.read();
|
||||
return x;
|
||||
}
|
||||
void Touch_GT911::writeBlockData(uint16_t reg, uint8_t *val, uint8_t size) {
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(highByte(reg));
|
||||
Wire.write(lowByte(reg));
|
||||
// Wire.write(val, size);
|
||||
for (uint8_t i=0; i<size; i++) {
|
||||
Wire.write(val[i]);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
}
|
||||
void Touch_GT911::readBlockData(uint8_t *buf, uint16_t reg, uint8_t size) {
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(highByte(reg));
|
||||
Wire.write(lowByte(reg));
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(addr, size);
|
||||
for (uint8_t i=0; i<size; i++) {
|
||||
buf[i] = Wire.read();
|
||||
}
|
||||
}
|
||||
|
||||
116
ESP32_AP-Flasher/lib2/gt911-touch/src/Touch_GT911.h
Normal file
116
ESP32_AP-Flasher/lib2/gt911-touch/src/Touch_GT911.h
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
#ifndef Touch_GT911_H
|
||||
#define Touch_GT911_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#define GT911_ADDR1 (uint8_t)0x5D
|
||||
#define GT911_ADDR2 (uint8_t)0x14
|
||||
|
||||
// Real-time command (Write only)
|
||||
#define GT911_COMMAND (uint16_t)0x8040
|
||||
#define GT911_ESD_CHECK (uint16_t)0x8041
|
||||
#define GT911_COMMAND_CHECK (uint16_t)0x8046
|
||||
|
||||
#define GT911_STRETCH_R0 (uint16_t)0x805E
|
||||
#define GT911_STRETCH_R1 (uint16_t)0x805F
|
||||
#define GT911_STRETCH_R2 (uint16_t)0x8060
|
||||
#define GT911_STRETCH_RM (uint16_t)0x8061
|
||||
#define GT911_DRV_GROUPA_NUM (uint16_t)0x8062
|
||||
#define GT911_CONFIG_START (uint16_t)0x8047
|
||||
#define GT911_CONFIG_VERSION (uint16_t)0x8047
|
||||
#define GT911_X_OUTPUT_MAX_LOW (uint16_t)0x8048
|
||||
#define GT911_X_OUTPUT_MAX_HIGH (uint16_t)0x8049
|
||||
#define GT911_Y_OUTPUT_MAX_LOW (uint16_t)0x804A
|
||||
#define GT911_Y_OUTPUT_MAX_HIGH (uint16_t)0x804B
|
||||
#define GT911_TOUCH_NUMBER (uint16_t)0x804C
|
||||
#define GT911_MODULE_SWITCH_1 (uint16_t)0x804D
|
||||
#define GT911_MODULE_SWITCH_2 (uint16_t)0x804E
|
||||
#define GT911_SHAKE_COUNT (uint16_t)0x804F
|
||||
#define GT911_FILTER (uint16_t)0x8050
|
||||
#define GT911_LARGE_TOUCH (uint16_t)0x8051
|
||||
#define GT911_NOISE_REDUCTION (uint16_t)0x8052
|
||||
#define GT911_SCREEN_TOUCH_LEVEL (uint16_t)0x8053
|
||||
#define GT911_SCREEN_RELEASE_LEVEL (uint16_t)0x8054
|
||||
#define GT911_LOW_POWER_CONTROL (uint16_t)0x8055
|
||||
#define GT911_REFRESH_RATE (uint16_t)0x8056
|
||||
#define GT911_X_THRESHOLD (uint16_t)0x8057
|
||||
#define GT911_Y_THRESHOLD (uint16_t)0x8058
|
||||
#define GT911_SPACE_TOP_BOTTOM (uint16_t)0x805B
|
||||
#define GT911_PANEL_TX_GAIN (uint16_t)0x806B
|
||||
#define GT911_PANEL_RX_GAIN (uint16_t)0x806C
|
||||
#define GT911_PANEL_DUMP_SHIFT (uint16_t)0x806D
|
||||
#define GT911_DRV_FRAME_CONTROL (uint16_t)0x806E
|
||||
#define GT911_CHARGING_LEVEL_UP (uint16_t)0x806F
|
||||
#define GT911_MODULE_SWITCH3 (uint16_t)0x8070
|
||||
#define GT911_GESTURE_DIS (uint16_t)0X8071
|
||||
#define GT911_GESTURE_LONG_PRESS_TIME (uint16_t)0x8072
|
||||
#define GT911_X_Y_SLOPE_ADJUST (uint16_t)0X8073
|
||||
#define GT911_GESTURE_CONTROL (uint16_t)0X8074
|
||||
#define GT911_GESTURE_SWITCH1 (uint16_t)0X8075
|
||||
#define GT911_GESTURE_SWITCH2 (uint16_t)0X8076
|
||||
#define GT911_GESTURE_REFRESH_RATE (uint16_t)0x8077
|
||||
#define GT911_GESTURE_TOUCH_LEVEL (uint16_t)0x8078
|
||||
#define GT911_NEWGREENWAKEUPLEVEL (uint16_t)0x8079
|
||||
#define GT911_FREQ_HOPPING_START (uint16_t)0x807A
|
||||
#define GT911_CONFIG_CHKSUM (uint16_t)0X80FF
|
||||
#define GT911_CONFIG_FRESH (uint16_t)0X8100
|
||||
#define GT911_CONFIG_SIZE (uint16_t)0xFF-0x46
|
||||
// Coordinate information
|
||||
#define GT911_PRODUCT_ID (uint16_t)0X8140
|
||||
#define GT911_FIRMWARE_VERSION (uint16_t)0X8140
|
||||
#define GT911_RESOLUTION (uint16_t)0X8140
|
||||
#define GT911_VENDOR_ID (uint16_t)0X8140
|
||||
#define GT911_IMFORMATION (uint16_t)0X8140
|
||||
#define GT911_POINT_INFO (uint16_t)0X814E
|
||||
#define GT911_POINT_1 (uint16_t)0X814F
|
||||
#define GT911_POINT_2 (uint16_t)0X8157
|
||||
#define GT911_POINT_3 (uint16_t)0X815F
|
||||
#define GT911_POINT_4 (uint16_t)0X8167
|
||||
#define GT911_POINT_5 (uint16_t)0X816F
|
||||
#define GT911_POINTS_REG {GT911_POINT_1, GT911_POINT_2, GT911_POINT_3, GT911_POINT_4, GT911_POINT_5}
|
||||
|
||||
class TPoint {
|
||||
public:
|
||||
TPoint(void);
|
||||
TPoint(uint8_t id, uint16_t x, uint16_t y, uint16_t size);
|
||||
|
||||
bool operator==(TPoint);
|
||||
bool operator!=(TPoint);
|
||||
|
||||
uint8_t id;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
class Touch_GT911 {
|
||||
public:
|
||||
Touch_GT911(uint8_t _sda, uint8_t _scl,uint16_t _width, uint16_t _height);
|
||||
void begin(uint8_t _addr=GT911_ADDR1);
|
||||
void setRotation(uint8_t rot);
|
||||
void setResolution(uint16_t _width, uint16_t _height);
|
||||
uint8_t getGesture(void);
|
||||
void read(void);
|
||||
uint8_t isLargeDetect;
|
||||
uint8_t touches = 0;
|
||||
bool isTouched = false;
|
||||
TPoint points[5];
|
||||
private:
|
||||
void calculateChecksum();
|
||||
void reConfig();
|
||||
TPoint readPoint(uint8_t *data);
|
||||
void writeByteData(uint16_t reg, uint8_t val);
|
||||
uint8_t readByteData(uint16_t reg);
|
||||
void writeBlockData(uint16_t reg, uint8_t *val, uint8_t size);
|
||||
void readBlockData(uint8_t *buf, uint16_t reg, uint8_t size);
|
||||
uint8_t addr;
|
||||
uint8_t pinSda;
|
||||
uint8_t pinScl;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint8_t configBuf[GT911_CONFIG_SIZE];
|
||||
};
|
||||
|
||||
#endif // Touch_GT911_H
|
||||
@@ -1,21 +1,20 @@
|
||||
; Try to not create new configs if possible, if in doubt, please ask
|
||||
; OTA on the official repo will only be published for mass-produced APs, feel free to experiment on your own fork
|
||||
[env]
|
||||
platform = espressif32
|
||||
; Choose below between platformio/espressif32 (Arduino 2.x) and pioarduino (Arduino 3.x)
|
||||
platform = platformio/espressif32@^6.10.0
|
||||
;platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
https://github.com/esphome/ESPAsyncWebServer
|
||||
https://github.com/esphome/AsyncTCP
|
||||
|
||||
bblanchon/ArduinoJson@^6.19.4
|
||||
lib_deps =
|
||||
ESP32Async/AsyncTCP
|
||||
ESP32Async/ESPAsyncWebServer
|
||||
bblanchon/ArduinoJson
|
||||
bodmer/TFT_eSPI
|
||||
https://github.com/Bodmer/TJpg_Decoder.git
|
||||
https://github.com/nlimper/shoddyxml2
|
||||
https://github.com/nlimper/shoddyxml2#d19a4e5
|
||||
https://github.com/nlimper/QRCodeGenerator
|
||||
fastled/FastLED@3.7.8
|
||||
fastled/FastLED@3.9.13
|
||||
https://github.com/MajenkoLibraries/SoftSPI
|
||||
platform_packages =
|
||||
platformio/framework-arduinoespressif32 @ 3.20014.231204
|
||||
board_build.filesystem = littlefs
|
||||
monitor_filters = esp32_exception_decoder
|
||||
monitor_speed = 115200
|
||||
@@ -30,82 +29,9 @@ build_flags =
|
||||
-D DISABLE_ALL_LIBRARY_WARNINGS
|
||||
-D ILI9341_DRIVER
|
||||
-D SMOOTH_FONT
|
||||
upload_port = COM26
|
||||
monitor_port = COM26
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the Mini_AP
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:OpenEPaperLink_Mini_AP]
|
||||
platform = https://github.com/platformio/platform-espressif32.git
|
||||
board=lolin_s2_mini
|
||||
board_build.partitions = default.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D OPENEPAPERLINK_MINI_AP_PCB
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D HAS_RGB_LED
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D SAVE_SPACE
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D FLASHER_AP_SS=11
|
||||
-D FLASHER_AP_CLK=9
|
||||
-D FLASHER_AP_MOSI=10
|
||||
-D FLASHER_AP_MISO=8
|
||||
-D FLASHER_AP_RESET=13
|
||||
-D FLASHER_AP_POWER={-1} ;this board has no soft power control
|
||||
-D FLASHER_AP_TXD=7
|
||||
-D FLASHER_AP_RXD=6
|
||||
-D FLASHER_AP_TEST=12
|
||||
-D FLASHER_LED=15
|
||||
-D FLASHER_RGB_LED=33
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>-<ips_display.cpp>-<webflasher.cpp>
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 4MB
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the Nano_AP
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:OpenEPaperLink_Nano_AP]
|
||||
platform = https://github.com/platformio/platform-espressif32.git
|
||||
board=lolin_s2_mini
|
||||
board_build.partitions = default.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D OPENEPAPERLINK_NANO_AP_PCB
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D SAVE_SPACE
|
||||
-D FLASHER_AP_SS=38
|
||||
-D FLASHER_AP_CLK=40
|
||||
-D FLASHER_AP_MOSI=39
|
||||
-D FLASHER_AP_MISO=33
|
||||
-D FLASHER_AP_RESET=37
|
||||
-D FLASHER_AP_POWER={16,17,18,21}
|
||||
-D FLASHER_AP_TXD=35
|
||||
-D FLASHER_AP_RXD=34
|
||||
-D FLASHER_AP_TEST=36
|
||||
-D FLASHER_LED=15
|
||||
-D FLASHER_RGB_LED=-1
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>-<ips_display.cpp>-<webflasher.cpp>
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 4MB
|
||||
-D LOAD_FONT2
|
||||
-D LOAD_GLCD
|
||||
-D ARDUINOJSON_ENABLE_COMMENTS=1
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the 16MB Flash / 8MB Ram version of the ESP32-S3-DevkitC1
|
||||
; ----------------------------------------------------------------------------------------
|
||||
@@ -117,7 +43,7 @@ build_unflags =
|
||||
-std=gnu++11
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
build_flags =
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_EXT_FLASHER
|
||||
@@ -136,7 +62,7 @@ build_flags =
|
||||
-D FLASHER_AP_MOSI=7
|
||||
-D FLASHER_AP_MISO=6
|
||||
-D FLASHER_AP_RESET=15
|
||||
-D FLASHER_AP_POWER={0}
|
||||
-D FLASHER_AP_POWER={0}
|
||||
-D FLASHER_AP_TXD=16
|
||||
-D FLASHER_AP_RXD=18
|
||||
-D FLASHER_AP_TEST=17
|
||||
@@ -160,7 +86,7 @@ build_flags =
|
||||
-D FLASHER_ALT_TEST=13
|
||||
-D FLASHER_LED=21
|
||||
-D FLASHER_RGB_LED=48
|
||||
build_src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<espflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
@@ -169,32 +95,6 @@ board_upload.maximum_size = 16777216
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 16MB
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an esp32 (depricated)
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:Simple_AP]
|
||||
board = esp32dev
|
||||
board_build.partitions = default.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D SIMPLE_AP
|
||||
-D SAVE_SPACE
|
||||
-D FLASHER_AP_SS=5
|
||||
-D FLASHER_AP_CLK=18
|
||||
-D FLASHER_AP_MOSI=23
|
||||
-D FLASHER_AP_MISO=19
|
||||
-D FLASHER_AP_RESET=2
|
||||
-D FLASHER_AP_POWER={13,15}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=17
|
||||
-D FLASHER_AP_RXD=16
|
||||
-D FLASHER_LED=22
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>-<ips_display.cpp>-<webflasher.cpp>
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:ESP32_S3_16_8_YELLOW_AP]
|
||||
@@ -202,12 +102,12 @@ board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ILI9341_DRIVER
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ILI9341_DRIVER
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_TFT
|
||||
@@ -245,14 +145,13 @@ build_flags =
|
||||
-D TFT_RST=1
|
||||
-D TFT_RGB_ORDER=TFT_BGR
|
||||
-D USE_HSPI_PORT
|
||||
-D LOAD_FONT2
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
|
||||
-D C6_OTA_FLASHING
|
||||
-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
@@ -270,45 +169,52 @@ monitor_dtr = 0
|
||||
monitor_rts = 0
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;-D ILI9341_DRIVER
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;-D ILI9341_DRIVER
|
||||
lib_deps = ${env.lib_deps}
|
||||
lib_extra_dirs = lib2/Arduino_GFX-1.3.7
|
||||
build_flags =
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_TFT
|
||||
-D HAS_LILYGO_TPANEL
|
||||
-D CORE_DEBUG_LEVEL=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D HAS_BLE_WRITER
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=34
|
||||
-D FLASHER_AP_POWER={-1}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
; NB: FLASHER_DEBUG_TXD and FLASHER_DEBUG_RXD use the same pins as
|
||||
; FLASHER_AP_TXD and FLASHER_AP_RXD but the naming convention is different
|
||||
-D FLASHER_DEBUG_SHARED
|
||||
-D FLASHER_DEBUG_PORT=1
|
||||
-D FLASHER_AP_TXD=48
|
||||
-D FLASHER_DEBUG_RXD=48
|
||||
-D FLASHER_AP_RXD=47
|
||||
-D FLASHER_DEBUG_TXD=43
|
||||
-D FLASHER_DEBUG_RXD=44
|
||||
-D FLASHER_DEBUG_TXD=47
|
||||
;
|
||||
-D FLASHER_DEBUG_PROG=33
|
||||
-D FLASHER_LED=-1
|
||||
-D TFT_HEIGHT=480
|
||||
-D TFT_HW_TYPE=226
|
||||
-D USE_HSPI_PORT
|
||||
-D LOAD_FONT2
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200
|
||||
-D HAS_H2
|
||||
-D C6_OTA_FLASHING
|
||||
-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_qspi ;Enable external PSRAM
|
||||
@@ -319,20 +225,83 @@ board_upload.flash_size = 16MB
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:ESP32_S3_16_8_4inch_AP]
|
||||
board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
monitor_dtr = 0
|
||||
monitor_rts = 0
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
lib_deps = ${env.lib_deps}
|
||||
lib_extra_dirs = lib2/Arduino_GFX-1.3.7
|
||||
lib2/gt911-touch
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_TFT
|
||||
-D HAS_4inch_TPANEL
|
||||
-D HAS_GT911_TOUCH
|
||||
-D CORE_DEBUG_LEVEL=1
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D HAS_BLE_WRITER
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=1
|
||||
-D FLASHER_AP_POWER={-1}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
; NB: FLASHER_DEBUG_TXD and FLASHER_DEBUG_RXD use the same pins as
|
||||
; FLASHER_AP_TXD and FLASHER_AP_RXD but the naming convention is different
|
||||
-D FLASHER_DEBUG_SHARED
|
||||
-D FLASHER_DEBUG_PORT=1
|
||||
-D FLASHER_AP_TXD=40
|
||||
-D FLASHER_AP_RXD=44
|
||||
-D FLASHER_DEBUG_TXD=44
|
||||
-D FLASHER_DEBUG_RXD=40
|
||||
-D FLASHER_DEBUG_PROG=2
|
||||
-D FLASHER_LED=-1
|
||||
; In this case we only got one TX Pin and no RX so lets only use that.
|
||||
-D UART_LOGGING_TX_ONLY_PIN=43
|
||||
-D TFT_HEIGHT=480
|
||||
-D TFT_HW_TYPE=226
|
||||
-D USE_HSPI_PORT
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200
|
||||
-D C6_OTA_FLASHING
|
||||
-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi ;Enable external PSRAM
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 16777216
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 16MB
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:ESP32_S3_C6_BIG_AP]
|
||||
board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_BLE_WRITER
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
@@ -357,7 +326,7 @@ build_flags =
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
|
||||
-D C6_OTA_FLASHING
|
||||
build_src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
@@ -373,15 +342,15 @@ board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_BLE_WRITER
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
@@ -406,7 +375,7 @@ build_flags =
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
|
||||
-D C6_OTA_FLASHING
|
||||
-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
@@ -422,15 +391,15 @@ board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_BLE_WRITER
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
@@ -457,7 +426,7 @@ build_flags =
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
|
||||
-D C6_OTA_FLASHING
|
||||
-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
@@ -474,16 +443,16 @@ board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ILI9341_DRIVER
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_TFT
|
||||
-D CORE_DEBUG_LEVEL=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
@@ -518,15 +487,12 @@ build_flags =
|
||||
-D TFT_RST=1
|
||||
-D TFT_RGB_ORDER=TFT_BGR
|
||||
-D USE_HSPI_PORT
|
||||
-D LOAD_FONT2
|
||||
-D LOAD_FONT4
|
||||
-D LOAD_GLCD
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200
|
||||
-D C6_OTA_FLASHING
|
||||
-D HAS_SUBGHZ
|
||||
-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
@@ -543,16 +509,16 @@ board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ILI9341_DRIVER
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_TFT
|
||||
-D CORE_DEBUG_LEVEL=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
@@ -587,15 +553,12 @@ build_flags =
|
||||
-D TFT_RST=1
|
||||
-D TFT_RGB_ORDER=TFT_BGR
|
||||
-D USE_HSPI_PORT
|
||||
-D LOAD_FONT2
|
||||
-D LOAD_FONT4
|
||||
-D LOAD_GLCD
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200
|
||||
-D C6_OTA_FLASHING
|
||||
-D HAS_SUBGHZ
|
||||
-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
@@ -612,10 +575,10 @@ board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
@@ -643,7 +606,7 @@ build_flags =
|
||||
-D HAS_RGB_LED
|
||||
-D FLASHER_RGB_LED=48
|
||||
-D BLE_ONLY
|
||||
build_src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>-<espflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
@@ -662,7 +625,7 @@ build_unflags =
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-std=gnu++11
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
@@ -689,7 +652,7 @@ build_flags =
|
||||
-D SD_CARD_MISO=36
|
||||
-D SD_CARD_MOSI=14
|
||||
-D SD_CARD_SS=12
|
||||
build_src_filter =
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_upload.maximum_size = 16777216
|
||||
@@ -705,17 +668,17 @@ monitor_dtr = 0
|
||||
monitor_rts = 0
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ILI9341_DRIVER
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_TFT
|
||||
-D HAS_EXT_FLASHER
|
||||
-D CORE_DEBUG_LEVEL=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
@@ -770,15 +733,12 @@ build_flags =
|
||||
-D TFT_RST=1
|
||||
-D TFT_RGB_ORDER=TFT_BGR
|
||||
-D USE_HSPI_PORT
|
||||
-D LOAD_FONT2
|
||||
-D LOAD_FONT4
|
||||
-D LOAD_GLCD
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200
|
||||
-D C6_OTA_FLASHING
|
||||
-D HAS_SUBGHZ
|
||||
-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
+<*>
|
||||
board_build.flash_mode=qio
|
||||
@@ -787,41 +747,60 @@ board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 16777216
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 16MB
|
||||
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an ESP32-S3 4MB Flash 2MB RAM aka The Official Espressif Zigbee Gateway PCB
|
||||
; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:ESP_THREAD_BORDER_ROUTER]
|
||||
[env:ESP32_S3_16_8_ELECROW_ADV_2_8]
|
||||
board = esp32-s3-devkitc-1
|
||||
board_build.partitions = default.csv
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ILI9341_DRIVER
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
;-D HAS_BLE_WRITER
|
||||
-D HAS_TFT
|
||||
-D HAS_ELECROW_ADV_2_8
|
||||
-D HAS_ELECROW_C6
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D HAS_BLE_WRITER
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=7
|
||||
-D FLASHER_AP_RESET=46
|
||||
-D FLASHER_AP_POWER={-1}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=4
|
||||
-D FLASHER_AP_RXD=5
|
||||
-D FLASHER_DEBUG_TXD=17
|
||||
-D FLASHER_DEBUG_RXD=18
|
||||
-D FLASHER_DEBUG_PROG=8
|
||||
-D FLASHER_AP_TXD=9
|
||||
-D FLASHER_AP_RXD=10
|
||||
-D FLASHER_DEBUG_TXD=2
|
||||
-D FLASHER_DEBUG_RXD=1
|
||||
-D FLASHER_DEBUG_PROG=3
|
||||
-D FLASHER_LED=-1
|
||||
-D ST7789_DRIVER
|
||||
-D TFT_WIDTH=240
|
||||
-D TFT_HEIGHT=320
|
||||
-D TFT_HW_TYPE=229
|
||||
-D TFT_MISO=-1
|
||||
-D TFT_MOSI=39
|
||||
-D TFT_SCLK=42
|
||||
-D TFT_CS=40
|
||||
-D TFT_DC=41
|
||||
-D TFT_RST=-1
|
||||
-D TFT_RGB_ORDER=TFT_BGR
|
||||
-D USE_HSPI_PORT
|
||||
-D LOAD_FONT2
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
|
||||
@@ -829,7 +808,65 @@ build_flags =
|
||||
-D C6_OTA_FLASHING
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 16777216
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 16MB
|
||||
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an ESP32-S3 4MB Flash 8MB RAM
|
||||
; Hardware is https://www.olimex.com/Products/IoT/ESP32/ESP32-POE-ISO/open-source-hardware
|
||||
; with ESP32-C6-WROOM-1U modem
|
||||
; all data is stored on SDCARD only
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:OpenEPaperLink_ESP32-PoE-ISO_AP]
|
||||
board=esp32-poe-iso
|
||||
board_build.partitions = esp32_sdcard_only.csv
|
||||
build_unflags =
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-std=gnu++11
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D OPENEPAPERLINK_MINI_AP_PCB
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D BOARD_HAS_PSRAM
|
||||
-mfix-esp32-psram-cache-issue
|
||||
-D HAS_SDCARD
|
||||
-D SD_CARD_SDMMC
|
||||
-D SD_CARD_ONLY
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=5
|
||||
-D FLASHER_AP_POWER={-1} ;this board has no soft power control
|
||||
-D FLASHER_AP_TXD=4
|
||||
-D FLASHER_AP_RXD=36
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_LED=-1
|
||||
-D FLASHER_DEBUG_TXD=32
|
||||
-D FLASHER_DEBUG_RXD=33
|
||||
-D FLASHER_DEBUG_PROG=13
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
|
||||
-D C6_OTA_FLASHING
|
||||
-D ETHERNET_PHY_POWER=12
|
||||
-D ETHERNET_CLK_MODE=ETH_CLOCK_GPIO0_OUT
|
||||
-D ETHERNET_PHY_MDC=ETH_PHY_MDC
|
||||
-D ETHERNET_PHY_MDIO=ETH_PHY_MDIO
|
||||
-D ETHERNET_PHY_TYPE=ETH_PHY_TYPE
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 4MB
|
||||
@@ -841,7 +878,7 @@ board_upload.flash_size = 4MB
|
||||
;board_build.partitions = default.csv
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
;build_flags =
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D CORE_DEBUG_LEVEL=0
|
||||
@@ -858,7 +895,7 @@ board_upload.flash_size = 4MB
|
||||
; -D FLASHER_AP_TXD=19
|
||||
; -D FLASHER_AP_RXD=23
|
||||
; -D FLASHER_LED=2
|
||||
;build_src_filter =
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>
|
||||
;board_build.psram_type=qspi_opi
|
||||
;board_upload.maximum_size = 4194304
|
||||
@@ -874,7 +911,7 @@ board_upload.flash_size = 4MB
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
; -D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;build_flags =
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D OPENEPAPERLINK_MINI_AP_PCB
|
||||
@@ -894,7 +931,7 @@ board_upload.flash_size = 4MB
|
||||
; -D FLASHER_AP_TEST=-1
|
||||
; -D FLASHER_LED=2
|
||||
; -D FLASHER_RGB_LED=-1
|
||||
;build_src_filter =
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>
|
||||
;board_build.psram_type=qspi_opi
|
||||
;board_upload.maximum_size = 4194304
|
||||
@@ -910,7 +947,7 @@ board_upload.flash_size = 4MB
|
||||
; -std=gnu++11
|
||||
; -D ARDUINO_USB_MODE=1
|
||||
; -D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;build_flags =
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D OutdoorAP
|
||||
@@ -933,7 +970,7 @@ board_upload.flash_size = 4MB
|
||||
; -D FLASHER_AP_RXD=18
|
||||
; -D FLASHER_LED=21
|
||||
; -D FLASHER_RGB_LED=38
|
||||
;build_src_filter =
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>
|
||||
;board_build.flash_mode=opi
|
||||
;board_build.arduino.memory_type = opi_opi
|
||||
@@ -941,7 +978,7 @@ board_upload.flash_size = 4MB
|
||||
;board_upload.maximum_size = 16777216
|
||||
;board_upload.maximum_ram_size = 327680
|
||||
;board_upload.flash_size = 32MB
|
||||
#upload_flags = --no-stub
|
||||
;#upload_flags = --no-stub
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an wemos_d1_mini32
|
||||
; ----------------------------------------------------------------------------------------
|
||||
@@ -950,7 +987,7 @@ board_upload.flash_size = 4MB
|
||||
;board_build.partitions = default.csv
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
;build_flags =
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D CORE_DEBUG_LEVEL=0
|
||||
@@ -965,7 +1002,7 @@ board_upload.flash_size = 4MB
|
||||
; -D FLASHER_AP_TXD=16
|
||||
; -D FLASHER_AP_RXD=17
|
||||
; -D FLASHER_LED=22
|
||||
;build_src_filter =
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an m5stack esp32
|
||||
@@ -976,7 +1013,7 @@ board_upload.flash_size = 4MB
|
||||
;board_build.partitions = esp32_sdcard.csv
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
;build_flags =
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D CORE_DEBUG_LEVEL=0
|
||||
@@ -1002,7 +1039,7 @@ board_upload.flash_size = 4MB
|
||||
; -D DISABLE_ALL_LIBRARY_WARNINGS
|
||||
; -D ILI9341_DRIVER
|
||||
; -D SMOOTH_FONT
|
||||
;build_src_filter =
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the Nano_C6
|
||||
@@ -1014,7 +1051,7 @@ board_upload.flash_size = 4MB
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
; -D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;build_flags =
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D OPENEPAPERLINK_NANO_AP_PCB
|
||||
@@ -1038,9 +1075,167 @@ board_upload.flash_size = 4MB
|
||||
; -D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
; -D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
|
||||
; -D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
|
||||
;build_src_filter =
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>
|
||||
;board_build.psram_type=qspi_opi
|
||||
;board_upload.maximum_size = 4194304
|
||||
;board_upload.maximum_ram_size = 327680
|
||||
;board_upload.flash_size = 4MB
|
||||
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! Release 2.75 was the last release that supported ESP32-S2 based APs or ESP32-S3 APs
|
||||
; !!! with less than 16Mb flash and 8MB RAM.
|
||||
; ----------------------------------------------------------------------------------------
|
||||
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the Mini_AP (deprecated)
|
||||
; ----------------------------------------------------------------------------------------
|
||||
;[env:OpenEPaperLink_Mini_AP]
|
||||
;platform = https://github.com/platformio/platform-espressif32.git
|
||||
;board=lolin_s2_mini
|
||||
;board_build.partitions = default.csv
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
; -D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D OPENEPAPERLINK_MINI_AP_PCB
|
||||
; -D ARDUINO_USB_MODE=0
|
||||
; -D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
; -D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
; -D HAS_RGB_LED
|
||||
; -D BOARD_HAS_PSRAM
|
||||
; -D SAVE_SPACE
|
||||
; -D POWER_NO_SOFT_POWER
|
||||
; -D FLASHER_AP_SS=11
|
||||
; -D FLASHER_AP_CLK=9
|
||||
; -D FLASHER_AP_MOSI=10
|
||||
; -D FLASHER_AP_MISO=8
|
||||
; -D FLASHER_AP_RESET=13
|
||||
; -D FLASHER_AP_POWER={-1} ;this board has no soft power control
|
||||
; -D FLASHER_AP_TXD=7
|
||||
; -D FLASHER_AP_RXD=6
|
||||
; -D FLASHER_AP_TEST=12
|
||||
; -D FLASHER_LED=15
|
||||
; -D FLASHER_RGB_LED=33
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>-<ips_display.cpp>-<webflasher.cpp>
|
||||
;board_build.psram_type=qspi_opi
|
||||
;board_upload.maximum_size = 4194304
|
||||
;board_upload.maximum_ram_size = 327680
|
||||
;board_upload.flash_size = 4MB
|
||||
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the Nano_AP
|
||||
; ----------------------------------------------------------------------------------------
|
||||
;[env:OpenEPaperLink_Nano_AP]
|
||||
;platform = https://github.com/platformio/platform-espressif32.git
|
||||
;board=lolin_s2_mini
|
||||
;board_build.partitions = default.csv
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
; -D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D OPENEPAPERLINK_NANO_AP_PCB
|
||||
; -D ARDUINO_USB_MODE=0
|
||||
; -D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
; -D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
; -D BOARD_HAS_PSRAM
|
||||
; -D SAVE_SPACE
|
||||
; -D FLASHER_AP_SS=38
|
||||
; -D FLASHER_AP_CLK=40
|
||||
; -D FLASHER_AP_MOSI=39
|
||||
; -D FLASHER_AP_MISO=33
|
||||
; -D FLASHER_AP_RESET=37
|
||||
; -D FLASHER_AP_POWER={16,17,18,21}
|
||||
; -D FLASHER_AP_TXD=35
|
||||
; -D FLASHER_AP_RXD=34
|
||||
; -D FLASHER_AP_TEST=36
|
||||
; -D FLASHER_LED=15
|
||||
; -D FLASHER_RGB_LED=-1
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>-<ips_display.cpp>-<webflasher.cpp>
|
||||
;board_build.psram_type=qspi_opi
|
||||
;board_upload.maximum_size = 4194304
|
||||
;board_upload.maximum_ram_size = 327680
|
||||
;board_upload.flash_size = 4MB
|
||||
|
||||
;; ----------------------------------------------------------------------------------------
|
||||
;; !!! this configuration expects an esp32 (deprecated)
|
||||
;; ----------------------------------------------------------------------------------------
|
||||
;[env:Simple_AP]
|
||||
;board = esp32dev
|
||||
;board_build.partitions = default.csv
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; -D CORE_DEBUG_LEVEL=0
|
||||
; -D SIMPLE_AP
|
||||
; -D SAVE_SPACE
|
||||
; -D FLASHER_AP_SS=5
|
||||
; -D FLASHER_AP_CLK=18
|
||||
; -D FLASHER_AP_MOSI=23
|
||||
; -D FLASHER_AP_MISO=19
|
||||
; -D FLASHER_AP_RESET=2
|
||||
; -D FLASHER_AP_POWER={13,15}
|
||||
; -D FLASHER_AP_TEST=-1
|
||||
; -D FLASHER_AP_TXD=17
|
||||
; -D FLASHER_AP_RXD=16
|
||||
; -D FLASHER_LED=22
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<espflasher.cpp>-<ips_display.cpp>-<webflasher.cpp>
|
||||
;
|
||||
;; ----------------------------------------------------------------------------------------
|
||||
;; !!! this configuration expects an ESP32-S3 4MB Flash 2MB RAM aka The Official Espressif Zigbee Gateway PCB (deprecated)
|
||||
;; ----------------------------------------------------------------------------------------
|
||||
;[env:ESP_THREAD_BORDER_ROUTER]
|
||||
;board = esp32-s3-devkitc-1
|
||||
;board_build.partitions = default.csv
|
||||
;build_unflags =
|
||||
; -std=gnu++11
|
||||
; -D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;lib_deps =
|
||||
; ${env.lib_deps}
|
||||
;build_flags =
|
||||
; -std=gnu++17
|
||||
; ${env.build_flags}
|
||||
; ;-D HAS_BLE_WRITER
|
||||
; -D CORE_DEBUG_LEVEL=0
|
||||
; -D ARDUINO_USB_CDC_ON_BOOT
|
||||
; -D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
; -D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
; -D POWER_NO_SOFT_POWER
|
||||
; -D BOARD_HAS_PSRAM
|
||||
; -D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
; -D FLASHER_AP_SS=-1
|
||||
; -D FLASHER_AP_CLK=-1
|
||||
; -D FLASHER_AP_MOSI=-1
|
||||
; -D FLASHER_AP_MISO=-1
|
||||
; -D FLASHER_AP_RESET=7
|
||||
; -D FLASHER_AP_POWER={-1}
|
||||
; -D FLASHER_AP_TEST=-1
|
||||
; -D FLASHER_AP_TXD=4
|
||||
; -D FLASHER_AP_RXD=5
|
||||
; -D FLASHER_DEBUG_TXD=17
|
||||
; -D FLASHER_DEBUG_RXD=18
|
||||
; -D FLASHER_DEBUG_PROG=8
|
||||
; -D FLASHER_LED=-1
|
||||
; -D MD5_ENABLED=1
|
||||
; -D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
; -D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
|
||||
; -D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
|
||||
; -D C6_OTA_FLASHING
|
||||
;build_src_filter =
|
||||
; +<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
;board_build.psram_type=qspi_opi
|
||||
;board_upload.maximum_size = 4194304
|
||||
;board_upload.maximum_ram_size = 327680
|
||||
;board_upload.flash_size = 4MB
|
||||
;
|
||||
|
||||
|
||||
|
||||
23
ESP32_AP-Flasher/prepare_sdcard.sh
Executable file
23
ESP32_AP-Flasher/prepare_sdcard.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [[ -d $1 ]]; then
|
||||
rm -rf $1/*
|
||||
cp -r data/* $1
|
||||
rm $1/www/*
|
||||
cp -r wwwroot/* $1/www/
|
||||
cp ../binaries/ESP32-C6/firmware.json $1
|
||||
for f in bootloader partition-table OpenEPaperLink_esp32_C6
|
||||
do
|
||||
if [[ -e ../ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/bootloader/${f}.bin ]]; then
|
||||
cp ../ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/bootloader/${f}.bin $1
|
||||
else
|
||||
cp ../binaries/ESP32-C6/${f}.bin $1
|
||||
fi
|
||||
done
|
||||
mkdir $1/current
|
||||
echo "[[]]" > $1/current/tagDB.json
|
||||
echo "OK"
|
||||
else
|
||||
echo "$1 is not a directory"
|
||||
exit 1
|
||||
fi
|
||||
@@ -8,7 +8,7 @@ SPIFFSEditor::SPIFFSEditor(const fs::FS &fs, const String &username, const Strin
|
||||
: _fs(fs), _username(username), _password(password), _authenticated(false), _startTime(0) {
|
||||
}
|
||||
|
||||
bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request) {
|
||||
bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request) const {
|
||||
if (request->url().equalsIgnoreCase("/edit")) {
|
||||
if (request->method() == HTTP_GET) {
|
||||
if (request->hasParam("list")) {
|
||||
@@ -34,7 +34,6 @@ bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
request->addInterestingHeader("If-Modified-Since");
|
||||
return true;
|
||||
} else if (request->method() == HTTP_POST || request->method() == HTTP_DELETE || request->method() == HTTP_PUT) {
|
||||
return true;
|
||||
@@ -91,7 +90,7 @@ void SPIFFSEditor::handleRequest(AsyncWebServerRequest *request) {
|
||||
if (request->header("If-Modified-Since").equals(buildTime)) {
|
||||
request->send(304);
|
||||
} else {
|
||||
AsyncWebServerResponse *response = request->beginResponse(_fs, "/www/edit.html");
|
||||
AsyncWebServerResponse *response = request->beginResponse(_fs, "/www/edit.html", "text/html");
|
||||
response->addHeader("Last-Modified", buildTime);
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,12 @@ bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) {
|
||||
for (int i = 0; i < advertisedDevice.getManufacturerData().length(); i++)
|
||||
Serial.printf("%02X", manuData[i]);
|
||||
Serial.printf("\r\n");
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
memcpy(&manuData, (uint8_t*)advertisedDevice.getManufacturerData().data(), manuDatalen);
|
||||
#else
|
||||
// [Nic] suggested fix for arduino 3.x by copilot, but I cannot test it
|
||||
memcpy(&manuData, (uint8_t*)advertisedDevice.getManufacturerData().c_str(), manuDatalen);
|
||||
#endif
|
||||
if (manuDatalen == 7 && manuData[0] == 0x53 && manuData[1] == 0x50) { // Lets check for a Gicisky E-Paper display
|
||||
|
||||
struct espAvailDataReq theAdvData;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#ifdef CONTENT_RSS
|
||||
#include <rssClass.h>
|
||||
#endif
|
||||
#include <TJpg_Decoder.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <map>
|
||||
@@ -53,17 +54,22 @@ void contentRunner() {
|
||||
|
||||
time_t now;
|
||||
time(&now);
|
||||
uint8_t wifimac[8];
|
||||
WiFi.macAddress(wifimac);
|
||||
memset(&wifimac[6], 0, 2);
|
||||
|
||||
for (tagRecord *taginfo : tagDB) {
|
||||
|
||||
const bool isAp = memcmp(taginfo->mac, wifimac, 8) == 0;
|
||||
if (taginfo->RSSI &&
|
||||
(now >= taginfo->nextupdate || needRedraw(taginfo->contentMode, taginfo->wakeupReason)) &&
|
||||
config.runStatus == RUNSTATUS_RUN &&
|
||||
Storage.freeSpace() > 31000 && !util::isSleeping(config.sleepTime1, config.sleepTime2)) {
|
||||
config.runStatus == RUNSTATUS_RUN && (taginfo->expectedNextCheckin < now + 300 || isAp) &&
|
||||
Storage.freeSpace() > 31000 && !util::isSleeping(config.sleepTime1, config.sleepTime2)) {
|
||||
drawNew(taginfo->mac, taginfo);
|
||||
taginfo->wakeupReason = 0;
|
||||
}
|
||||
|
||||
if (taginfo->expectedNextCheckin > now - 10 && taginfo->expectedNextCheckin < now + 30 && taginfo->pendingIdle == 0 && taginfo->pendingCount == 0) {
|
||||
if (taginfo->expectedNextCheckin > now - 10 && taginfo->expectedNextCheckin < now + 30 && taginfo->pendingIdle == 0 && taginfo->pendingCount == 0 && !isAp) {
|
||||
int32_t minutesUntilNextUpdate = (taginfo->nextupdate - now) / 60;
|
||||
if (minutesUntilNextUpdate > config.maxsleep) {
|
||||
minutesUntilNextUpdate = config.maxsleep;
|
||||
@@ -81,6 +87,7 @@ void contentRunner() {
|
||||
}
|
||||
if (minutesUntilNextUpdate > 1 && (wsClientCount() == 0 || config.stopsleep == 0)) {
|
||||
taginfo->pendingIdle = minutesUntilNextUpdate * 60;
|
||||
taginfo->expectedNextCheckin = now + taginfo->pendingIdle;
|
||||
if (taginfo->isExternal == false) {
|
||||
prepareIdleReq(taginfo->mac, minutesUntilNextUpdate);
|
||||
}
|
||||
@@ -92,7 +99,7 @@ void contentRunner() {
|
||||
}
|
||||
|
||||
void checkVars() {
|
||||
DynamicJsonDocument cfgobj(500);
|
||||
JsonDocument cfgobj;
|
||||
for (tagRecord *tag : tagDB) {
|
||||
if (tag->contentMode == 19) {
|
||||
deserializeJson(cfgobj, tag->modeConfigJson);
|
||||
@@ -168,14 +175,14 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
taginfo->contentMode = 21;
|
||||
taginfo->nextupdate = 0;
|
||||
} else if (contentFS->exists("/tag_defaults.json")) {
|
||||
DynamicJsonDocument doc(1000);
|
||||
JsonDocument doc;
|
||||
fs::File tagDefaults = contentFS->open("/tag_defaults.json", "r");
|
||||
DeserializationError err = deserializeJson(doc, tagDefaults);
|
||||
if (!err) {
|
||||
if (doc.containsKey("contentMode")) {
|
||||
if (doc["contentMode"].is<uint8_t>()) {
|
||||
taginfo->contentMode = doc["contentMode"];
|
||||
}
|
||||
if (doc.containsKey("modecfgjson")) {
|
||||
if (doc["modecfgjson"].is<String>()) {
|
||||
taginfo->modeConfigJson = doc["modecfgjson"].as<String>();
|
||||
}
|
||||
}
|
||||
@@ -192,7 +199,7 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
}
|
||||
#endif
|
||||
|
||||
DynamicJsonDocument doc(500);
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, taginfo->modeConfigJson);
|
||||
JsonObject cfgobj = doc.as<JsonObject>();
|
||||
char buffer[64];
|
||||
@@ -212,7 +219,6 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
imageParams.hasRed = false;
|
||||
imageParams.dataType = DATATYPE_IMG_RAW_1BPP;
|
||||
imageParams.dither = 2;
|
||||
// if (taginfo->hasCustomLUT && taginfo->lut != 1) imageParams.grayLut = true;
|
||||
|
||||
imageParams.invert = taginfo->invert;
|
||||
imageParams.symbols = 0;
|
||||
@@ -222,11 +228,15 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
} else {
|
||||
imageParams.zlib = 0;
|
||||
}
|
||||
#ifdef SAVE_SPACE
|
||||
imageParams.g5 = 0;
|
||||
#else
|
||||
if (hwdata.g5 != 0 && taginfo->tagSoftwareVersion >= hwdata.g5) {
|
||||
imageParams.g5 = 1;
|
||||
} else {
|
||||
imageParams.g5 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
imageParams.lut = EPD_LUT_NO_REPEATS;
|
||||
if (taginfo->lut == 2) imageParams.lut = EPD_LUT_FAST_NO_REDS;
|
||||
@@ -236,10 +246,6 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
imageParams.lut = EPD_LUT_DEFAULT;
|
||||
taginfo->lastfullupdate = now;
|
||||
}
|
||||
if (taginfo->hasCustomLUT && taginfo->capabilities & CAPABILITY_SUPPORTS_CUSTOM_LUTS && taginfo->lut != 1) {
|
||||
Serial.println("using custom LUT");
|
||||
imageParams.lut = EPD_LUT_OTA;
|
||||
}
|
||||
|
||||
int32_t interval = cfgobj["interval"].as<int>() * 60;
|
||||
if (interval == -1440 * 60) {
|
||||
@@ -285,6 +291,9 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
if (imageParams.bpp == 3) {
|
||||
imageParams.dataType = DATATYPE_IMG_RAW_3BPP;
|
||||
Serial.println("datatype: DATATYPE_IMG_RAW_3BPP");
|
||||
} else if (imageParams.bpp == 4) {
|
||||
imageParams.dataType = DATATYPE_IMG_RAW_4BPP;
|
||||
Serial.println("datatype: DATATYPE_IMG_RAW_4BPP");
|
||||
} else if (imageParams.zlib) {
|
||||
imageParams.dataType = DATATYPE_IMG_ZLIB;
|
||||
Serial.println("datatype: DATATYPE_IMG_ZLIB");
|
||||
@@ -448,13 +457,6 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
taginfo->nextupdate = 3216153600;
|
||||
prepareNFCReq(mac, cfgobj["url"].as<const char *>());
|
||||
break;
|
||||
|
||||
case 15: // send gray LUT
|
||||
|
||||
taginfo->nextupdate = 3216153600;
|
||||
prepareLUTreq(mac, cfgobj["bytes"]);
|
||||
taginfo->hasCustomLUT = true;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONTENT_BUIENRADAR
|
||||
@@ -490,8 +492,16 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
if (!util::isEmptyOrNull(configFilename)) {
|
||||
String configUrl = cfgobj["url"].as<String>();
|
||||
if (!util::isEmptyOrNull(configUrl)) {
|
||||
DynamicJsonDocument json(1000);
|
||||
JsonDocument json;
|
||||
Serial.println("Get json url + file");
|
||||
|
||||
int index = configUrl.indexOf("{mac}");
|
||||
if (index != -1) {
|
||||
char macStr[17];
|
||||
mac2hex(mac, macStr);
|
||||
configUrl.replace("{mac}", macStr);
|
||||
}
|
||||
|
||||
if (util::httpGetJson(configUrl, json, 1000)) {
|
||||
taginfo->nextupdate = now + interval;
|
||||
if (getJsonTemplateFileExtractVariables(filename, configFilename, json, taginfo, imageParams)) {
|
||||
@@ -555,6 +565,14 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 28: // tag command
|
||||
{
|
||||
uint64_t newmac;
|
||||
sscanf(cfgobj["mac"].as<String>().c_str(), "%llx", &newmac);
|
||||
sendTagMac(mac, newmac, (taginfo->isExternal == false));
|
||||
taginfo->nextupdate = 3216153600;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
taginfo->modeConfigJson = doc.as<String>();
|
||||
@@ -571,6 +589,9 @@ bool updateTagImage(String &filename, const uint8_t *dst, uint16_t nextCheckin,
|
||||
if (imageParams.bpp == 3) {
|
||||
imageParams.dataType = DATATYPE_IMG_RAW_3BPP;
|
||||
Serial.println("datatype: DATATYPE_IMG_RAW_3BPP");
|
||||
} else if (imageParams.bpp == 4) {
|
||||
imageParams.dataType = DATATYPE_IMG_RAW_4BPP;
|
||||
Serial.println("datatype: DATATYPE_IMG_RAW_4BPP");
|
||||
} else if (imageParams.zlib) {
|
||||
imageParams.dataType = DATATYPE_IMG_ZLIB;
|
||||
Serial.println("datatype: DATATYPE_IMG_ZLIB");
|
||||
@@ -693,7 +714,7 @@ void drawString(TFT_eSprite &spr, String content, int16_t posx, int16_t posy, St
|
||||
}
|
||||
}
|
||||
|
||||
void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy, int16_t boxwidth, int16_t boxheight, String font, uint16_t color, uint16_t bgcolor, float lineheight) {
|
||||
void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy, int16_t boxwidth, int16_t boxheight, String font, uint16_t color, uint16_t bgcolor, float lineheight, byte align) {
|
||||
replaceVariables(content);
|
||||
switch (processFontPath(font)) {
|
||||
case 2: {
|
||||
@@ -703,7 +724,7 @@ void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy
|
||||
case 3: {
|
||||
// vlw bitmap font
|
||||
// spr.drawRect(posx, posy, boxwidth, boxheight, TFT_BLACK);
|
||||
spr.setTextDatum(TL_DATUM);
|
||||
spr.setTextDatum(align);
|
||||
if (font != "") spr.loadFont(font.substring(1), *contentFS);
|
||||
spr.setTextWrap(false, false);
|
||||
spr.setTextColor(color, bgcolor);
|
||||
@@ -776,7 +797,7 @@ void drawDate(String &filename, tagRecord *&taginfo, imgParam &imageParams) {
|
||||
return;
|
||||
}
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 1, taginfo->hwType);
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
@@ -823,7 +844,7 @@ void drawNumber(String &filename, int32_t count, int32_t thresholdred, tagRecord
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 2, taginfo->hwType);
|
||||
|
||||
initSprite(spr, imageParams.width, imageParams.height, imageParams);
|
||||
@@ -862,25 +883,7 @@ const String getWeatherIcon(const uint8_t id, const bool isNight = false) {
|
||||
return weatherIcons[id];
|
||||
}
|
||||
|
||||
void drawWeather(String &filename, JsonObject &cfgobj, const tagRecord *taginfo, imgParam &imageParams) {
|
||||
wsLog("get weather");
|
||||
|
||||
getLocation(cfgobj);
|
||||
|
||||
const String lat = cfgobj["#lat"];
|
||||
const String lon = cfgobj["#lon"];
|
||||
const String tz = cfgobj["#tz"];
|
||||
String units = "";
|
||||
if (cfgobj["units"] == "1") {
|
||||
units += "&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch";
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(1000);
|
||||
const bool success = util::httpGetJson("https://api.open-meteo.com/v1/forecast?latitude=" + lat + "&longitude=" + lon + "¤t_weather=true&windspeed_unit=ms&timezone=" + tz + units, doc, 5000);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
void drawWeatherContent(JsonDocument &doc, JsonDocument &loc, TFT_eSprite &spr, JsonObject &cfgobj, imgParam &imageParams, bool isForecast = false) {
|
||||
const auto ¤tWeather = doc["current_weather"];
|
||||
const double temperature = currentWeather["temperature"].as<double>();
|
||||
float windspeed = currentWeather["windspeed"].as<float>();
|
||||
@@ -897,52 +900,62 @@ void drawWeather(String &filename, JsonObject &cfgobj, const tagRecord *taginfo,
|
||||
windval = int(windspeed);
|
||||
}
|
||||
|
||||
doc.clear();
|
||||
|
||||
if (taginfo->hwType == SOLUM_SEG_UK) {
|
||||
const String weatherText[] = {"sun", "sun", "sun", "CLDY", "CLDY", "FOG", "", "", "FOG", "", "",
|
||||
"DRZL", "", "DRZL", "", "DRZL", "ice", "ice", "", "", "",
|
||||
"rain", "", "rain", "", "rain", "ice", "ice", "", "", "",
|
||||
"SNOW", "", "SNOW", "", "SNOW", "", "SNOW", "", "", "rain",
|
||||
"rain", "rain", "", "", "SNOW", "SNOW", "", "", "", "",
|
||||
"", "", "", "", "STRM", "HAIL", "", "", "HAIL"};
|
||||
if (temperature < -9.9) {
|
||||
sprintf(imageParams.segments, "%3d^%2d%-4.4s", static_cast<int>(temperature), windval, weatherText[weathercode].c_str());
|
||||
imageParams.symbols = 0x00;
|
||||
} else {
|
||||
sprintf(imageParams.segments, "%3d^%2d%-4.4s", static_cast<int>(temperature * 10), windval, weatherText[weathercode].c_str());
|
||||
imageParams.symbols = 0x04;
|
||||
}
|
||||
return;
|
||||
if (!isForecast) {
|
||||
const auto &location = loc["location"];
|
||||
drawString(spr, cfgobj["location"], location[0], location[1], location[2]);
|
||||
}
|
||||
|
||||
getTemplate(doc, 4, taginfo->hwType);
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
tft.setTextWrap(false, false);
|
||||
|
||||
initSprite(spr, imageParams.width, imageParams.height, imageParams);
|
||||
const auto &location = doc["location"];
|
||||
drawString(spr, cfgobj["location"], location[0], location[1], location[2]);
|
||||
const auto &wind = doc["wind"];
|
||||
const auto &wind = isForecast ? loc["currentwind"] : loc["wind"];
|
||||
drawString(spr, String(windval), wind[0], wind[1], wind[2], TR_DATUM, (beaufort > 4 ? imageParams.highlightColor : TFT_BLACK));
|
||||
|
||||
char tmpOutput[5];
|
||||
dtostrf(temperature, 2, 1, tmpOutput);
|
||||
const auto &temp = doc["temp"];
|
||||
drawString(spr, String(tmpOutput), temp[0], temp[1], temp[2], TL_DATUM, (temperature < 0 ? imageParams.highlightColor : TFT_BLACK));
|
||||
const auto &temp = loc["temp"];
|
||||
|
||||
String temperatureStr = String(tmpOutput);
|
||||
if (temp[3] && temp[3] == 1) {
|
||||
temperatureStr += (cfgobj["units"] == "1") ? "°" : "°";
|
||||
}
|
||||
drawString(spr, temperatureStr, temp[0], temp[1], temp[2], TL_DATUM, (temperature < 0 ? imageParams.highlightColor : TFT_BLACK));
|
||||
|
||||
const int iconcolor = (weathercode == 55 || weathercode == 65 || weathercode == 75 || weathercode == 82 || weathercode == 86 || weathercode == 95 || weathercode == 96 || weathercode == 99)
|
||||
? imageParams.highlightColor
|
||||
: TFT_BLACK;
|
||||
const auto &icon = doc["icon"];
|
||||
const auto &icon = isForecast ? loc["currenticon"] : loc["icon"];
|
||||
drawString(spr, getWeatherIcon(weathercode, isNight), icon[0], icon[1], "/fonts/weathericons.ttf", icon[3], iconcolor, icon[2]);
|
||||
const auto &dir = doc["dir"];
|
||||
const auto &dir = loc["dir"];
|
||||
drawString(spr, windDirectionIcon(winddirection), dir[0], dir[1], "/fonts/weathericons.ttf", TC_DATUM, TFT_BLACK, dir[2]);
|
||||
if (weathercode > 10) {
|
||||
const auto &umbrella = doc["umbrella"];
|
||||
const auto &umbrella = loc["umbrella"];
|
||||
drawString(spr, "\uf084", umbrella[0], umbrella[1], "/fonts/weathericons.ttf", TC_DATUM, imageParams.highlightColor, umbrella[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void drawWeather(String &filename, JsonObject &cfgobj, const tagRecord *taginfo, imgParam &imageParams) {
|
||||
wsLog("get weather");
|
||||
|
||||
getLocation(cfgobj);
|
||||
|
||||
const String lat = cfgobj["#lat"];
|
||||
const String lon = cfgobj["#lon"];
|
||||
const String tz = cfgobj["#tz"];
|
||||
String units = "";
|
||||
if (cfgobj["units"] == "1") {
|
||||
units += "&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch";
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
const bool success = util::httpGetJson("https://api.open-meteo.com/v1/forecast?latitude=" + lat + "&longitude=" + lon + "¤t_weather=true&windspeed_unit=ms&timezone=" + tz + units, doc, 5000);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 4, taginfo->hwType);
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
tft.setTextWrap(false, false);
|
||||
initSprite(spr, imageParams.width, imageParams.height, imageParams);
|
||||
|
||||
drawWeatherContent(doc, loc, spr, cfgobj, imageParams);
|
||||
|
||||
spr2buffer(spr, filename, imageParams);
|
||||
spr.deleteSprite();
|
||||
@@ -960,8 +973,8 @@ void drawForecast(String &filename, JsonObject &cfgobj, const tagRecord *taginfo
|
||||
units += "&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch";
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(2000);
|
||||
const bool success = util::httpGetJson("https://api.open-meteo.com/v1/forecast?latitude=" + lat + "&longitude=" + lon + "&daily=weathercode,temperature_2m_max,temperature_2m_min,precipitation_sum,windspeed_10m_max,winddirection_10m_dominant&windspeed_unit=ms&timeformat=unixtime&timezone=" + tz + units, doc, 5000);
|
||||
JsonDocument doc;
|
||||
const bool success = util::httpGetJson("https://api.open-meteo.com/v1/forecast?latitude=" + lat + "&longitude=" + lon + "&daily=weathercode,temperature_2m_max,temperature_2m_min,precipitation_sum,windspeed_10m_max,winddirection_10m_dominant¤t_weather=true&windspeed_unit=ms&timeformat=unixtime&timezone=" + tz + units, doc, 5000);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
@@ -969,10 +982,12 @@ void drawForecast(String &filename, JsonObject &cfgobj, const tagRecord *taginfo
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
tft.setTextWrap(false, false);
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 8, taginfo->hwType);
|
||||
initSprite(spr, imageParams.width, imageParams.height, imageParams);
|
||||
|
||||
if (loc["temp"]) drawWeatherContent(doc, loc, spr, cfgobj, imageParams, true);
|
||||
|
||||
const auto &location = loc["location"];
|
||||
drawString(spr, cfgobj["location"], location[0], location[1], location[2], TL_DATUM, TFT_BLACK);
|
||||
const auto &daily = doc["daily"];
|
||||
@@ -1024,7 +1039,7 @@ void drawForecast(String &filename, JsonObject &cfgobj, const tagRecord *taginfo
|
||||
|
||||
drawString(spr, String(tmin) + " ", dag * column1 + day[0].as<int>(), day[4], day[2], TR_DATUM, (tmin < 0 ? imageParams.highlightColor : TFT_BLACK));
|
||||
drawString(spr, String(" ") + String(tmax), dag * column1 + day[0].as<int>(), day[4], day[2], TL_DATUM, (tmax < 0 ? imageParams.highlightColor : TFT_BLACK));
|
||||
drawString(spr, String(wind), dag * column1 + column1 - 10, day[3], day[2], TR_DATUM, (beaufort > 5 ? imageParams.highlightColor : TFT_BLACK));
|
||||
drawString(spr, " " + String(wind), dag * column1 + column1 / 2, day[3], day[2], TL_DATUM, (beaufort > 5 ? imageParams.highlightColor : TFT_BLACK));
|
||||
if (dag > 0) {
|
||||
for (int i = loc["line"][0]; i < loc["line"][1]; i += 3) {
|
||||
spr.drawPixel(dag * column1, i, TFT_BLACK);
|
||||
@@ -1044,6 +1059,7 @@ int getImgURL(String &filename, String URL, time_t fetched, imgParam &imageParam
|
||||
http.begin(URL);
|
||||
http.addHeader("If-Modified-Since", formatHttpDate(fetched));
|
||||
http.addHeader("X-ESL-MAC", MAC);
|
||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
http.setTimeout(5000); // timeout in ms
|
||||
const int httpCode = http.GET();
|
||||
if (httpCode == 200) {
|
||||
@@ -1118,7 +1134,7 @@ bool getRssFeed(String &filename, String URL, String title, tagRecord *&taginfo,
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 9, taginfo->hwType);
|
||||
initSprite(spr, imageParams.width, imageParams.height, imageParams);
|
||||
// stampTime(spr);
|
||||
@@ -1192,7 +1208,7 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
|
||||
wsLog("get calendar");
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 11, taginfo->hwType);
|
||||
|
||||
String URL = cfgobj["apps_script_url"].as<String>() + "?days=" + loc["days"].as<String>();
|
||||
@@ -1215,7 +1231,7 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
return false;
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(5000);
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, http.getString());
|
||||
if (error) {
|
||||
wsErr(error.c_str());
|
||||
@@ -1290,6 +1306,13 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
int calYOffset = loc["gridparam"][1].as<int>();
|
||||
int lineHeight = loc["gridparam"][5].as<int>();
|
||||
|
||||
uint16_t backgroundLight = getColor("lightgray");
|
||||
uint16_t backgroundDark = getColor("darkgray");
|
||||
if (imageParams.hwdata.bpp >= 3) {
|
||||
backgroundLight = getColor("#BEFAFF");
|
||||
backgroundDark = getColor("#79FAFF");
|
||||
}
|
||||
|
||||
// drawString(spr, String(timeinfo.tm_mday), calWidth / 2, -calHeight/5, "Signika-SB.ttf", TC_DATUM, imageParams.highlightColor, calHeight * 1.2);
|
||||
|
||||
for (int i = 0; i < calDays; i++) {
|
||||
@@ -1303,9 +1326,9 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
drawString(spr, String(languageDaysShort[dayInfo->tm_wday]) + " " + String(dayInfo->tm_mday), colStart + colWidth / 2, calTop, loc["gridparam"][3], TC_DATUM, TFT_BLACK);
|
||||
|
||||
if (dayInfo->tm_wday == 0 || dayInfo->tm_wday == 6) {
|
||||
spr.fillRect(colStart + 1, calTop + calYOffset, colWidth - 1, calHeight - 1, getColor("darkgray"));
|
||||
spr.fillRect(colStart + 1, calTop + calYOffset, colWidth - 1, calHeight - 1, backgroundDark);
|
||||
} else {
|
||||
spr.fillRect(colStart + 1, calTop + calYOffset, colWidth - 1, calHeight - 1, getColor("lightgray"));
|
||||
spr.fillRect(colStart + 1, calTop + calYOffset, colWidth - 1, calHeight - 1, backgroundLight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1326,6 +1349,7 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
const time_t startdatetime = obj["start"];
|
||||
const time_t enddatetime = obj["end"];
|
||||
const bool isallday = obj["isallday"];
|
||||
const int calendarId = obj["calendar"];
|
||||
|
||||
if (!isallday) {
|
||||
localtime_r(&startdatetime, &timeinfo);
|
||||
@@ -1357,9 +1381,17 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
|
||||
int16_t eventX = colLeft + fulldaystart * colWidth + 3;
|
||||
int16_t eventY = calTop + calYOffset + (line - 1) * lineHeight + 3;
|
||||
spr.drawRect(eventX - 2, eventY - 3, colWidth * (fulldayend - fulldaystart) - 1, lineHeight + 1, TFT_BLACK);
|
||||
spr.fillRect(eventX - 1, eventY - 2, colWidth * (fulldayend - fulldaystart) - 3, lineHeight - 1, TFT_WHITE);
|
||||
drawTextBox(spr, eventtitle, eventX, eventY, colWidth * (fulldayend - fulldaystart) - 3, 15, loc["gridparam"][4], TFT_BLACK);
|
||||
uint16_t background = TFT_WHITE;
|
||||
uint16_t border = TFT_BLACK;
|
||||
uint16_t textcolor = TFT_BLACK;
|
||||
if (loc["colors1"].is<JsonArray>() && loc["colors1"].size() > calendarId) {
|
||||
background = getColor(loc["colors1"][calendarId]);
|
||||
border = getColor(loc["colors2"][calendarId]);
|
||||
if (loc["colors3"][calendarId]) textcolor = getColor(loc["colors3"][calendarId]);
|
||||
}
|
||||
spr.fillRect(eventX - 1, eventY - 2, colWidth * (fulldayend - fulldaystart) - 3, lineHeight - 1, background);
|
||||
spr.drawRect(eventX - 2, eventY - 3, colWidth * (fulldayend - fulldaystart) - 1, lineHeight + 1, border);
|
||||
drawTextBox(spr, eventtitle, eventX, eventY, colWidth * (fulldayend - fulldaystart) - 3, 15, loc["gridparam"][4], textcolor);
|
||||
|
||||
block[i] = line;
|
||||
if (line > maxBlock) maxBlock = line;
|
||||
@@ -1390,6 +1422,7 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
const time_t startdatetime = obj["start"];
|
||||
const time_t enddatetime = obj["end"];
|
||||
const bool isallday = obj["isallday"];
|
||||
const int calendarId = obj["calendar"];
|
||||
|
||||
if (!isallday) {
|
||||
int fulldaystart = constrain((startdatetime - midnightEpoch) / (24 * 3600), 0, calDays);
|
||||
@@ -1428,16 +1461,27 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
block[i] = indent;
|
||||
int16_t eventX = colLeft + day * colWidth + (indent - 1) * 5;
|
||||
int16_t eventY = calTop + calYOffset + (starttime * hourHeight / 60);
|
||||
spr.drawRect(eventX + 1, eventY, colWidth - 1, (duration * hourHeight / 60) + 1, TFT_BLACK);
|
||||
spr.fillRect(eventX + 2, eventY + 1, colWidth - 3, (duration * hourHeight / 60) - 1, TFT_WHITE);
|
||||
uint16_t background = TFT_WHITE;
|
||||
uint16_t border = TFT_BLACK;
|
||||
uint16_t textcolor = TFT_BLACK;
|
||||
if (loc["colors1"].is<JsonArray>() && loc["colors1"].size() > calendarId) {
|
||||
background = getColor(loc["colors1"][calendarId]);
|
||||
border = getColor(loc["colors2"][calendarId]);
|
||||
if (loc["colors3"][calendarId]) textcolor = getColor(loc["colors3"][calendarId]);
|
||||
}
|
||||
spr.fillRect(eventX + 2, eventY + 1, colWidth - 3, (duration * hourHeight / 60) - 1, background);
|
||||
spr.drawRect(eventX + 1, eventY, colWidth - 1, (duration * hourHeight / 60) + 1, border);
|
||||
eventX += 2;
|
||||
eventY += 2;
|
||||
if (day == fulldaystart) {
|
||||
eventtitle = formattedTimeString + " " + String(eventtitle);
|
||||
drawTextBox(spr, formattedTimeString, eventX, eventY, colWidth - 1, (duration * hourHeight / 60) - 1, loc["gridparam"][4], textcolor, TFT_WHITE, 1);
|
||||
eventX++;
|
||||
eventY = calTop + calYOffset + (starttime * hourHeight / 60) + 2;
|
||||
} else {
|
||||
eventtitle = obj["title"].as<String>();
|
||||
}
|
||||
drawTextBox(spr, eventtitle, eventX, eventY, colWidth - 1, (duration * hourHeight / 60) - 1, loc["gridparam"][4], TFT_BLACK, TFT_WHITE, 1);
|
||||
drawTextBox(spr, eventtitle, eventX, eventY, colWidth - 1, (duration * hourHeight / 60) - 1, loc["gridparam"][4], textcolor, TFT_WHITE, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1466,7 +1510,7 @@ uint16_t getPercentileColor(const double *prices, int numPrices, double price, H
|
||||
const double *boundaries;
|
||||
int numColors, numBoundaries;
|
||||
|
||||
if (hwdata.bpp == 3) {
|
||||
if (hwdata.bpp == 3 || hwdata.bpp == 4) {
|
||||
colors = colors3bpp;
|
||||
boundaries = boundaries3bpp;
|
||||
numColors = sizeof(colors3bpp) / sizeof(colors3bpp[0]);
|
||||
@@ -1532,7 +1576,7 @@ YAxisScale calculateYAxisScale(double priceMin, double priceMax, int divisions)
|
||||
bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams) {
|
||||
wsLog("get dayahead prices");
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 27, taginfo->hwType);
|
||||
|
||||
// This is a link to a Google Apps Script script, which fetches (and caches) the tariff from https://transparency.entsoe.eu/
|
||||
@@ -1557,7 +1601,7 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
|
||||
return false;
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(5000);
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, http.getString());
|
||||
if (error) {
|
||||
wsErr(error.c_str());
|
||||
@@ -1578,7 +1622,7 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
|
||||
double maxPrice = std::numeric_limits<double>::lowest();
|
||||
double prices[n];
|
||||
|
||||
DynamicJsonDocument doc2(500);
|
||||
JsonDocument doc2;
|
||||
JsonArray tariffArray;
|
||||
std::string tariffString = cfgobj["tariffkwh"].as<std::string>();
|
||||
if (tariffString.front() == '[') {
|
||||
@@ -1610,12 +1654,16 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
|
||||
minPrice = yAxisScale.min;
|
||||
|
||||
uint16_t yAxisX = loc["yaxis"][1].as<int>();
|
||||
uint16_t yAxisY = loc["yaxis"][3].as<int>() | 9;
|
||||
uint16_t barBottom = loc["bars"][3].as<int>();
|
||||
|
||||
for (double i = minPrice; i <= maxPrice; i += yAxisScale.step) {
|
||||
int y = mapDouble(i, minPrice, maxPrice, spr.height() - barBottom, spr.height() - barBottom - loc["bars"][2].as<int>());
|
||||
spr.drawLine(0, y, spr.width(), y, TFT_BLACK);
|
||||
if (loc["yaxis"][0]) drawString(spr, String(int(i * units)), yAxisX, y - 9, loc["yaxis"][0], TL_DATUM, TFT_BLACK);
|
||||
if (loc["yaxis"][0]) {
|
||||
String label = (maxPrice * units < 10) ? String(i * units, 1) : String(int(i * units));
|
||||
drawString(spr, label, yAxisX, y - yAxisY, loc["yaxis"][0], TL_DATUM, TFT_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t barwidth = loc["bars"][1].as<int>() / n;
|
||||
@@ -1685,7 +1733,7 @@ void drawQR(String &filename, String qrcontent, String title, tagRecord *&taginf
|
||||
// https://github.com/ricmoo/QRCode
|
||||
qrcode_initText(&qrcode, qrcodeData, version, ECC_MEDIUM, text);
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 10, taginfo->hwType);
|
||||
initSprite(spr, imageParams.width, imageParams.height, imageParams);
|
||||
drawString(spr, title, loc["title"][0], loc["title"][1], loc["title"][2], TC_DATUM, TFT_BLACK, loc["title"][3]);
|
||||
@@ -1727,7 +1775,7 @@ uint8_t drawBuienradar(String &filename, JsonObject &cfgobj, tagRecord *&taginfo
|
||||
if (httpCode == 200) {
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 16, taginfo->hwType);
|
||||
initSprite(spr, imageParams.width, imageParams.height, imageParams);
|
||||
|
||||
@@ -1801,7 +1849,7 @@ void drawAPinfo(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
|
||||
}
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
DynamicJsonDocument loc(2048);
|
||||
JsonDocument loc;
|
||||
uint8_t screenCurrentOrientation = 0;
|
||||
getTemplate(loc, 21, taginfo->hwType);
|
||||
|
||||
@@ -1822,7 +1870,7 @@ void drawTimestamp(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, im
|
||||
time(&now);
|
||||
struct tm timeinfo;
|
||||
|
||||
StaticJsonDocument<512> loc;
|
||||
JsonDocument loc;
|
||||
getTemplate(loc, 1, taginfo->hwType);
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
@@ -2158,7 +2206,7 @@ void drawJsonStream(Stream &stream, String &filename, tagRecord *&taginfo, imgPa
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
initSprite(spr, imageParams.width, imageParams.height, imageParams);
|
||||
uint8_t screenCurrentOrientation = 0;
|
||||
DynamicJsonDocument doc(500);
|
||||
JsonDocument doc;
|
||||
if (stream.find("[")) {
|
||||
do {
|
||||
DeserializationError error = deserializeJson(doc, stream);
|
||||
@@ -2206,38 +2254,93 @@ void rotateBuffer(uint8_t rotation, uint8_t ¤tOrientation, TFT_eSprite &sp
|
||||
}
|
||||
}
|
||||
|
||||
TFT_eSprite sprDraw = TFT_eSprite(&tft);
|
||||
bool spr_draw(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap) {
|
||||
sprDraw.pushImage(x, y, w, h, bitmap);
|
||||
return 1;
|
||||
}
|
||||
void drawElement(const JsonObject &element, TFT_eSprite &spr, imgParam &imageParams, uint8_t ¤tOrientation) {
|
||||
if (element.containsKey("text")) {
|
||||
if (element["text"].is<JsonArray>()) {
|
||||
const JsonArray &textArray = element["text"];
|
||||
const uint16_t align = textArray[5] | 0;
|
||||
const uint16_t size = textArray[6] | 0;
|
||||
const String bgcolorstr = textArray[7].as<String>();
|
||||
const uint16_t bgcolor = (bgcolorstr.length() > 0) ? getColor(bgcolorstr) : TFT_WHITE;
|
||||
drawString(spr, textArray[2], textArray[0].as<int>(), textArray[1].as<int>(), textArray[3], align, getColor(textArray[4]), size, bgcolor);
|
||||
} else if (element.containsKey("textbox")) {
|
||||
} else if (element["textbox"].is<JsonArray>()) {
|
||||
// posx, posy, width, height, text, font, color, lineheight, align
|
||||
const JsonArray &textArray = element["textbox"];
|
||||
float lineheight = textArray[7].as<float>();
|
||||
if (lineheight == 0) lineheight = 1;
|
||||
int16_t posx = textArray[0] | 0;
|
||||
int16_t posy = textArray[1] | 0;
|
||||
String text = textArray[4];
|
||||
drawTextBox(spr, text, posx, posy, textArray[2], textArray[3], textArray[5], getColor(textArray[6]), TFT_WHITE, lineheight);
|
||||
} else if (element.containsKey("box")) {
|
||||
const uint16_t align = textArray[8] | 0;
|
||||
drawTextBox(spr, text, posx, posy, textArray[2], textArray[3], textArray[5], getColor(textArray[6]), TFT_WHITE, lineheight, align);
|
||||
} else if (element["box"].is<JsonArray>()) {
|
||||
const JsonArray &boxArray = element["box"];
|
||||
spr.fillRect(boxArray[0].as<int>(), boxArray[1].as<int>(), boxArray[2].as<int>(), boxArray[3].as<int>(), getColor(boxArray[4]));
|
||||
} else if (element.containsKey("rbox")) {
|
||||
if (boxArray.size()>=7) {
|
||||
for (int i=0; i < boxArray[6].as<int>(); i++) {
|
||||
spr.drawRect(boxArray[0].as<int>() + i, boxArray[1].as<int>() + i, boxArray[2].as<int>() - 2 * i, boxArray[3].as<int>() - 2 * i, getColor(boxArray[5]));
|
||||
}
|
||||
}
|
||||
} else if (element["rbox"].is<JsonArray>()) {
|
||||
const JsonArray &rboxArray = element["rbox"];
|
||||
spr.fillRoundRect(rboxArray[0].as<int>(), rboxArray[1].as<int>(), rboxArray[2].as<int>(), rboxArray[3].as<int>(), rboxArray[4].as<int>(), getColor(rboxArray[5]));
|
||||
} else if (element.containsKey("line")) {
|
||||
if (rboxArray.size() >= 8) {
|
||||
for (int i = 0; i < rboxArray[7].as<int>(); i++) {
|
||||
spr.drawRoundRect(rboxArray[0].as<int>() + i, rboxArray[1].as<int>() + i, rboxArray[2].as<int>() - 2 * i, rboxArray[3].as<int>() - 2 * i, rboxArray[4].as<int>() - i / 1.41, getColor(rboxArray[6]));
|
||||
if (i > 0) {
|
||||
spr.drawRoundRect(rboxArray[0].as<int>() + i - 1, rboxArray[1].as<int>() + i, rboxArray[2].as<int>() - 2 * i + 2, rboxArray[3].as<int>() - 2 * i, rboxArray[4].as<int>() - i / 1.41, getColor(rboxArray[6]));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (element["line"].is<JsonArray>()) {
|
||||
const JsonArray &lineArray = element["line"];
|
||||
spr.drawLine(lineArray[0].as<int>(), lineArray[1].as<int>(), lineArray[2].as<int>(), lineArray[3].as<int>(), getColor(lineArray[4]));
|
||||
} else if (element.containsKey("triangle")) {
|
||||
} else if (element["triangle"].is<JsonArray>()) {
|
||||
const JsonArray &lineArray = element["triangle"];
|
||||
spr.fillTriangle(lineArray[0].as<int>(), lineArray[1].as<int>(), lineArray[2].as<int>(), lineArray[3].as<int>(), lineArray[4].as<int>(), lineArray[5].as<int>(), getColor(lineArray[6]));
|
||||
} else if (element.containsKey("circle")) {
|
||||
} else if (element["circle"].is<JsonArray>()) {
|
||||
const JsonArray &circleArray = element["circle"];
|
||||
spr.fillCircle(circleArray[0].as<int>(), circleArray[1].as<int>(), circleArray[2].as<int>(), getColor(circleArray[3]));
|
||||
} else if (element.containsKey("rotate")) {
|
||||
if (circleArray.size() >= 6) {
|
||||
for (int i = 0; i < circleArray[5].as<int>(); i++) {
|
||||
spr.drawCircle(circleArray[0].as<int>(), circleArray[1].as<int>(), circleArray[2].as<int>() - i, getColor(circleArray[4]));
|
||||
if (i > 0) {
|
||||
spr.drawCircle(circleArray[0].as<int>(), circleArray[1].as<int>(), circleArray[2].as<int>() - i - 0.5, getColor(circleArray[4]));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (element["image"].is<JsonArray>()) {
|
||||
const JsonArray &imgArray = element["image"];
|
||||
|
||||
TJpgDec.setSwapBytes(true);
|
||||
TJpgDec.setJpgScale(1);
|
||||
TJpgDec.setCallback(spr_draw);
|
||||
uint16_t w = 0, h = 0;
|
||||
String filename = imgArray[0];
|
||||
if (filename[0] != '/') {
|
||||
filename = "/" + filename;
|
||||
}
|
||||
TJpgDec.getFsJpgSize(&w, &h, filename, *contentFS);
|
||||
if (w == 0 && h == 0) {
|
||||
wsErr("invalid jpg");
|
||||
return;
|
||||
}
|
||||
Serial.println("jpeg conversion " + String(w) + "x" + String(h));
|
||||
sprDraw.setColorDepth(16);
|
||||
sprDraw.createSprite(w, h);
|
||||
if (sprDraw.getPointer() == nullptr) {
|
||||
wsErr("Failed to create sprite in contentmanager");
|
||||
} else {
|
||||
TJpgDec.drawFsJpg(0, 0, filename, *contentFS);
|
||||
sprDraw.pushToSprite(&spr, imgArray[1].as<int>(), imgArray[2].as<int>());
|
||||
sprDraw.deleteSprite();
|
||||
}
|
||||
|
||||
} else if (element["rotate"].is<uint8_t>()) {
|
||||
uint8_t rotation = element["rotate"].as<int>();
|
||||
rotateBuffer(rotation, currentOrientation, spr, imageParams);
|
||||
}
|
||||
@@ -2318,11 +2421,11 @@ void getLocation(JsonObject &cfgobj) {
|
||||
|
||||
if (util::isEmptyOrNull(lat) || util::isEmptyOrNull(lon)) {
|
||||
wsLog("get location");
|
||||
StaticJsonDocument<80> filter;
|
||||
JsonDocument filter;
|
||||
filter["results"][0]["latitude"] = true;
|
||||
filter["results"][0]["longitude"] = true;
|
||||
filter["results"][0]["timezone"] = true;
|
||||
DynamicJsonDocument doc(1000);
|
||||
JsonDocument doc;
|
||||
if (util::httpGetJson("https://geocoding-api.open-meteo.com/v1/search?name=" + urlEncode(cfgobj["location"]) + "&count=1", doc, 5000, &filter)) {
|
||||
cfgobj["#lat"] = doc["results"][0]["latitude"].as<String>();
|
||||
cfgobj["#lon"] = doc["results"][0]["longitude"].as<String>();
|
||||
@@ -2353,20 +2456,6 @@ void prepareNFCReq(const uint8_t *dst, const char *url) {
|
||||
len = 1 + len;
|
||||
prepareDataAvail(data, len, DATATYPE_NFC_RAW_CONTENT, dst);
|
||||
}
|
||||
|
||||
void prepareLUTreq(const uint8_t *dst, const String &input) {
|
||||
constexpr const char *delimiters = ", \t";
|
||||
constexpr const int maxValues = 76;
|
||||
uint8_t waveform[maxValues];
|
||||
char *ptr = strtok(const_cast<char *>(input.c_str()), delimiters);
|
||||
int i = 0;
|
||||
while (ptr != nullptr && i < maxValues) {
|
||||
waveform[i++] = static_cast<uint8_t>(strtol(ptr, nullptr, 16));
|
||||
ptr = strtok(nullptr, delimiters);
|
||||
}
|
||||
const size_t waveformLen = sizeof(waveform);
|
||||
prepareDataAvail(waveform, waveformLen, DATATYPE_CUSTOM_LUT_OTA, dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONTENT_TAGCFG
|
||||
@@ -2389,8 +2478,8 @@ void prepareConfigFile(const uint8_t *dst, const JsonObject &config) {
|
||||
#endif
|
||||
|
||||
void getTemplate(JsonDocument &json, const uint8_t id, const uint8_t hwtype) {
|
||||
StaticJsonDocument<80> filter;
|
||||
DynamicJsonDocument doc(2048);
|
||||
JsonDocument filter;
|
||||
JsonDocument doc;
|
||||
|
||||
const String idstr = String(id);
|
||||
constexpr const char *templateKey = "template";
|
||||
@@ -2404,11 +2493,11 @@ void getTemplate(JsonDocument &json, const uint8_t id, const uint8_t hwtype) {
|
||||
filter["usetemplate"] = true;
|
||||
const DeserializationError error = deserializeJson(doc, jsonFile, DeserializationOption::Filter(filter));
|
||||
jsonFile.close();
|
||||
if (!error && doc.containsKey(templateKey) && doc[templateKey].containsKey(idstr)) {
|
||||
if (!error && doc[templateKey].is<JsonVariant>() && doc[templateKey][idstr].is<JsonVariant>()) {
|
||||
json.set(doc[templateKey][idstr]);
|
||||
return;
|
||||
}
|
||||
if (!error && doc.containsKey("usetemplate")) {
|
||||
if (!error && doc["usetemplate"].is<uint8_t>()) {
|
||||
getTemplate(json, id, doc["usetemplate"]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
#include "storage.h"
|
||||
#include "tag_db.h"
|
||||
#include "web.h"
|
||||
#include "espflasher.h"
|
||||
#include "util.h"
|
||||
|
||||
#define LOG(format, ... ) Serial.printf(format,## __VA_ARGS__)
|
||||
|
||||
#ifndef FLASHER_DEBUG_PORT
|
||||
#define FLASHER_DEBUG_PORT 2
|
||||
#endif
|
||||
|
||||
esp_loader_error_t connect_to_target(uint32_t higher_transmission_rate) {
|
||||
esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
|
||||
@@ -120,150 +128,197 @@ esp_loader_error_t flash_binary(String &file_path, size_t address) {
|
||||
|
||||
bool downloadAndWriteBinary(String &filename, const char *url) {
|
||||
HTTPClient binaryHttp;
|
||||
Serial.println(url);
|
||||
bool Ret = false;
|
||||
bool bHaveFsMutex = false;
|
||||
|
||||
LOG("downloadAndWriteBinary: url %s\n",url);
|
||||
binaryHttp.begin(url);
|
||||
binaryHttp.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
|
||||
int binaryResponseCode = binaryHttp.GET();
|
||||
Serial.println(binaryResponseCode);
|
||||
if (binaryResponseCode == HTTP_CODE_OK) {
|
||||
do {
|
||||
int binaryResponseCode = binaryHttp.GET();
|
||||
if(binaryResponseCode != HTTP_CODE_OK) {
|
||||
wsSerial("http error " + String(binaryResponseCode) + " fetching " + String(url));
|
||||
break;
|
||||
}
|
||||
int contentLength = binaryHttp.getSize();
|
||||
Serial.println(contentLength);
|
||||
LOG("contentLength %d\r\n",contentLength);
|
||||
if(contentLength < 0) {
|
||||
wsSerial("Couldn't get contentLength");
|
||||
break;
|
||||
}
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
bHaveFsMutex = true;
|
||||
File file = contentFS->open(filename, "wb");
|
||||
if (file) {
|
||||
wsSerial("downloading " + String(filename));
|
||||
WiFiClient *stream = binaryHttp.getStreamPtr();
|
||||
uint8_t buffer[1024];
|
||||
size_t totalBytesRead = 0;
|
||||
time_t timeOut = millis() + 5000;
|
||||
// while (stream->available()) {
|
||||
while (millis() < timeOut) {
|
||||
size_t bytesRead = stream->readBytes(buffer, sizeof(buffer));
|
||||
if(!file) {
|
||||
wsSerial("file open error " + String(filename));
|
||||
break;
|
||||
}
|
||||
wsSerial("downloading " + String(filename));
|
||||
WiFiClient *stream = binaryHttp.getStreamPtr();
|
||||
uint8_t buffer[1024];
|
||||
size_t totalBytesRead = 0;
|
||||
// timeout if we don't average at least 1k bytes/second
|
||||
unsigned long timeOut = millis() + contentLength;
|
||||
while(stream->connected() && totalBytesRead < contentLength) {
|
||||
size_t bytesRead;
|
||||
size_t bytesToRead;
|
||||
if(stream->available()) {
|
||||
bytesToRead = min(sizeof(buffer), (size_t) stream->available());
|
||||
bytesRead = stream->readBytes(buffer, bytesToRead);
|
||||
if(bytesRead == 0 || millis() > timeOut) {
|
||||
wsSerial("Download time out");
|
||||
break;
|
||||
}
|
||||
file.write(buffer, bytesRead);
|
||||
totalBytesRead += bytesRead;
|
||||
if (totalBytesRead == contentLength) break;
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
file.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
binaryHttp.end();
|
||||
|
||||
file = contentFS->open(filename, "r");
|
||||
if (file) {
|
||||
if (totalBytesRead == contentLength || (contentLength == 0 && file.size() > 0)) {
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
wsSerial("Download failed, " + String(file.size()) + " bytes");
|
||||
file.close();
|
||||
}
|
||||
} else {
|
||||
xSemaphoreGive(fsMutex);
|
||||
wsSerial("file open error " + String(filename));
|
||||
}
|
||||
} else {
|
||||
wsSerial("http error " + String(binaryResponseCode) + " fetching " + String(url));
|
||||
}
|
||||
file.close();
|
||||
|
||||
if(!stream->connected()) {
|
||||
wsSerial("Connection dropped during transfer");
|
||||
break;
|
||||
}
|
||||
file = contentFS->open(filename, "r");
|
||||
if(!file) {
|
||||
wsSerial("file open error " + String(filename));
|
||||
break;
|
||||
}
|
||||
if(file.size() == contentLength) {
|
||||
Ret = true;
|
||||
} else {
|
||||
wsSerial("Download failed, " + String(file.size()) + " bytes");
|
||||
}
|
||||
file.close();
|
||||
} while(false);
|
||||
binaryHttp.setReuse(false);
|
||||
binaryHttp.end();
|
||||
return false;
|
||||
if(bHaveFsMutex) {
|
||||
xSemaphoreGive(fsMutex);
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
bool doC6flash(uint8_t doDownload) {
|
||||
String filenameFirmwareLocal = "/firmware.json";
|
||||
DynamicJsonDocument jsonDoc(1024);
|
||||
if (doDownload) {
|
||||
const String githubUrl = "https://raw.githubusercontent.com/" + config.repo + "/master/binaries/ESP32-C6/firmware.json";
|
||||
if (downloadAndWriteBinary(filenameFirmwareLocal, githubUrl.c_str())) {
|
||||
File readfile = contentFS->open(filenameFirmwareLocal, "r");
|
||||
if (!readfile) {
|
||||
Serial.println("load firmware.json: Failed to open file");
|
||||
return false;
|
||||
}
|
||||
DeserializationError jsonError = deserializeJson(jsonDoc, readfile);
|
||||
bool FlashC6_H2(const char *RepoUrl) {
|
||||
String JsonFilename = "/firmware_" SHORT_CHIP_NAME ".json" ;
|
||||
bool Ret = false;
|
||||
bool bLoaderInit = false;
|
||||
bool bDownload = strlen(RepoUrl) > 0;
|
||||
int retry;
|
||||
JsonDocument jsonDoc;
|
||||
|
||||
if (!jsonError) {
|
||||
JsonArray jsonArray = jsonDoc.as<JsonArray>();
|
||||
for (JsonObject obj : jsonArray) {
|
||||
String filename = "/" + obj["filename"].as<String>();
|
||||
// String binaryUrl = "https://raw.githubusercontent.com/" + config.repo + "/master/binaries/ESP32-C6" + String(filename);
|
||||
String binaryUrl = "http://www.openepaperlink.eu/binaries/ESP32-C6" + String(filename);
|
||||
for (int retry = 0; retry < 10; retry++) {
|
||||
if (downloadAndWriteBinary(filename, binaryUrl.c_str())) {
|
||||
break;
|
||||
}
|
||||
wsSerial("Retry " + String(retry));
|
||||
if (retry < 9) {
|
||||
delay(1000);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wsSerial("json error fetching " + String(githubUrl));
|
||||
return false;
|
||||
LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap();
|
||||
|
||||
do {
|
||||
if(bDownload) {
|
||||
String FileUrl = RepoUrl + JsonFilename;
|
||||
if(!downloadAndWriteBinary(JsonFilename, FileUrl.c_str())) {
|
||||
LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
File readfile = contentFS->open(filenameFirmwareLocal, "r");
|
||||
if (!readfile) {
|
||||
Serial.println("load local firmware.json: Failed to open file");
|
||||
return false;
|
||||
|
||||
File readfile = contentFS->open(JsonFilename, "r");
|
||||
if(!readfile) {
|
||||
wsSerial("load " + JsonFilename + ": Failed to open file");
|
||||
return true;
|
||||
}
|
||||
DeserializationError jsonError = deserializeJson(jsonDoc, readfile);
|
||||
}
|
||||
|
||||
const loader_esp32_config_t config = {
|
||||
.baud_rate = 115200,
|
||||
.uart_port = 2,
|
||||
.uart_rx_pin = FLASHER_DEBUG_TXD,
|
||||
.uart_tx_pin = FLASHER_DEBUG_RXD,
|
||||
.reset_trigger_pin = FLASHER_AP_RESET,
|
||||
.gpio0_trigger_pin = FLASHER_DEBUG_PROG,
|
||||
};
|
||||
if(jsonError) {
|
||||
wsSerial(String("json error parsing") + JsonFilename);
|
||||
break;
|
||||
}
|
||||
|
||||
if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
|
||||
wsSerial("Serial initialization failed");
|
||||
loader_port_esp32_deinit();
|
||||
return false;
|
||||
}
|
||||
if(!bDownload) {
|
||||
Ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (connect_to_target(115200) == ESP_LOADER_SUCCESS) {
|
||||
if (esp_loader_get_target() == ESP32C6_CHIP) {
|
||||
wsSerial("Connected to ESP32-C6");
|
||||
int maxRetries = 5;
|
||||
esp_loader_error_t err;
|
||||
JsonArray jsonArray = jsonDoc.as<JsonArray>();
|
||||
for(JsonObject obj : jsonArray) {
|
||||
String filename = "/" + obj["filename"].as<String>();
|
||||
String binaryUrl = RepoUrl + filename;
|
||||
|
||||
JsonArray jsonArray = jsonDoc.as<JsonArray>();
|
||||
for (JsonObject obj : jsonArray) {
|
||||
String filename = "/" + obj["filename"].as<String>();
|
||||
const char *addressStr = obj["address"];
|
||||
uint32_t address = strtoul(addressStr, NULL, 16);
|
||||
|
||||
for (int retry = 0; retry < maxRetries; retry++) {
|
||||
err = flash_binary(filename, address);
|
||||
if (err == ESP_LOADER_SUCCESS) break;
|
||||
Serial.printf("Flash failed with error %d. Retrying...\n", err);
|
||||
for(retry = 0; retry < 10; retry++) {
|
||||
if(downloadAndWriteBinary(filename, binaryUrl.c_str())) {
|
||||
break;
|
||||
}
|
||||
wsSerial("Retry " + String(retry));
|
||||
if(retry < 9) {
|
||||
delay(1000);
|
||||
}
|
||||
if (err != ESP_LOADER_SUCCESS) {
|
||||
loader_port_esp32_deinit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println("Done!");
|
||||
} else {
|
||||
wsSerial("Connected to wrong ESP32 type");
|
||||
loader_port_esp32_deinit();
|
||||
return false;
|
||||
if(retry == 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wsSerial("Connection to the C6 failed");
|
||||
if(retry < 10) {
|
||||
Ret = true;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(Ret == true) do {
|
||||
Ret = false;
|
||||
const loader_esp32_config_t config = {
|
||||
.baud_rate = 115200,
|
||||
.uart_port = FLASHER_DEBUG_PORT,
|
||||
.uart_rx_pin = FLASHER_DEBUG_TXD,
|
||||
.uart_tx_pin = FLASHER_DEBUG_RXD,
|
||||
.reset_trigger_pin = FLASHER_AP_RESET,
|
||||
.gpio0_trigger_pin = FLASHER_DEBUG_PROG,
|
||||
};
|
||||
|
||||
bLoaderInit = true;
|
||||
if(loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
|
||||
wsSerial("Serial initialization failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if(connect_to_target(115200) != ESP_LOADER_SUCCESS) {
|
||||
wsSerial("Connection to the " SHORT_CHIP_NAME " failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if(esp_loader_get_target() != ESP_CHIP_TYPE) {
|
||||
wsSerial("Connected to wrong ESP32 type");
|
||||
break;
|
||||
}
|
||||
wsSerial("Connected to ESP32-" SHORT_CHIP_NAME);
|
||||
int maxRetries = 5;
|
||||
esp_loader_error_t err;
|
||||
|
||||
JsonArray jsonArray = jsonDoc.as<JsonArray>();
|
||||
for(JsonObject obj : jsonArray) {
|
||||
String filename = "/" + obj["filename"].as<String>();
|
||||
const char *addressStr = obj["address"];
|
||||
uint32_t address = strtoul(addressStr, NULL, 16);
|
||||
|
||||
for(int retry = 0; retry < maxRetries; retry++) {
|
||||
err = flash_binary(filename, address);
|
||||
if(err == ESP_LOADER_SUCCESS) {
|
||||
Ret = true;
|
||||
break;
|
||||
}
|
||||
Serial.printf("Flash failed with error %d. Retrying...\n", err);
|
||||
delay(1000);
|
||||
}
|
||||
if(err != ESP_LOADER_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Serial.println("Done!");
|
||||
} while(false);
|
||||
|
||||
if(bLoaderInit) {
|
||||
loader_port_esp32_deinit();
|
||||
return false;
|
||||
}
|
||||
loader_port_esp32_deinit();
|
||||
return true;
|
||||
|
||||
LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "storage.h"
|
||||
#include "time.h"
|
||||
#include "zbs_interface.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
#include "webflasher.h"
|
||||
@@ -178,7 +179,7 @@ bool flasher::getInfoBlockType() {
|
||||
}
|
||||
|
||||
bool flasher::findTagByMD5() {
|
||||
DynamicJsonDocument doc(3000);
|
||||
JsonDocument doc;
|
||||
fs::File readfile = contentFS->open("/tag_md5_db.json", "r");
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
@@ -207,7 +208,7 @@ bool flasher::findTagByMD5() {
|
||||
}
|
||||
|
||||
bool flasher::findTagByType(uint8_t type) {
|
||||
DynamicJsonDocument doc(3000);
|
||||
JsonDocument doc;
|
||||
fs::File readfile = contentFS->open("/tag_md5_db.json", "r");
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
@@ -265,7 +266,7 @@ bool flasher::getFirmwareMac() {
|
||||
void flasher::getMacFromWiFi() {
|
||||
mac[0] = 0x00;
|
||||
mac[1] = 0x00;
|
||||
esp_read_mac(mac + 2, ESP_MAC_WIFI_SOFTAP);
|
||||
WiFi.softAPmacAddress(mac + 2);
|
||||
}
|
||||
|
||||
bool flasher::backupFlash() {
|
||||
@@ -447,7 +448,7 @@ bool flasher::writeFlashFromPackOffset(fs::File *file, uint16_t length) {
|
||||
}
|
||||
|
||||
bool flasher::writeFlashFromPack(String filename, uint8_t type) {
|
||||
DynamicJsonDocument doc(1024);
|
||||
JsonDocument doc;
|
||||
fs::File readfile = contentFS->open(filename, "r");
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
@@ -507,7 +508,7 @@ bool flasher::writeBlock(uint16_t offset, uint8_t *data, uint16_t len, bool info
|
||||
|
||||
#ifndef C6_OTA_FLASHING
|
||||
uint16_t getAPUpdateVersion(uint8_t type) {
|
||||
StaticJsonDocument<512> doc;
|
||||
JsonDocument doc;
|
||||
fs::File readfile = contentFS->open("/AP_FW_Pack.bin", "r");
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
|
||||
@@ -12,16 +12,21 @@
|
||||
#include "ips_display.h"
|
||||
|
||||
#define YELLOW_SENSE 8 // sense AP hardware
|
||||
|
||||
#ifdef HAS_ELECROW_ADV_2_8
|
||||
#define TFT_BACKLIGHT 38
|
||||
#else
|
||||
#define TFT_BACKLIGHT 14
|
||||
#endif
|
||||
|
||||
TFT_eSPI tft2 = TFT_eSPI();
|
||||
uint8_t YellowSense = 0;
|
||||
bool tftLogscreen = true;
|
||||
bool tftOverride = false;
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL
|
||||
static const uint8_t st7701_type9_init_operations_lilygo[] = {
|
||||
|
||||
BEGIN_WRITE,
|
||||
@@ -41,14 +46,14 @@ static const uint8_t st7701_type9_init_operations_lilygo[] = {
|
||||
|
||||
WRITE_C8_D8, 0xCC, 0x10,
|
||||
|
||||
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
|
||||
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x0F, 0x16, 0x0E,
|
||||
0x11, 0x07, 0x09, 0x09,
|
||||
0x08, 0x23, 0x05, 0x11,
|
||||
0x0F, 0x28, 0x2D, 0x18,
|
||||
|
||||
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
|
||||
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x0F, 0x16, 0x0E,
|
||||
0x11, 0x07, 0x09, 0x08,
|
||||
@@ -142,7 +147,7 @@ static const uint8_t st7701_type9_init_operations_lilygo[] = {
|
||||
// WRITE_C8_D8, 0xD1, 0x81,//Test
|
||||
// WRITE_C8_D8, 0xD2, 0x08,//Test
|
||||
|
||||
WRITE_COMMAND_8, 0x29, // Display On
|
||||
WRITE_COMMAND_8, 0x29, // Display On
|
||||
|
||||
// WRITE_C8_D8, 0x35, 0x00,//Test
|
||||
// WRITE_C8_D8, 0xCE, 0x04,//Test
|
||||
@@ -152,41 +157,201 @@ static const uint8_t st7701_type9_init_operations_lilygo[] = {
|
||||
// 0xF0, 0xA3, 0xA3, 0x71,
|
||||
|
||||
END_WRITE};
|
||||
|
||||
Arduino_DataBus *bus = new Arduino_XL9535SWSPI(IIC_SDA /* SDA */, IIC_SCL /* SCL */, -1 /* XL PWD */,
|
||||
Arduino_DataBus* bus = new Arduino_XL9535SWSPI(IIC_SDA /* SDA */, IIC_SCL /* SCL */, -1 /* XL PWD */,
|
||||
XL95X5_CS /* XL CS */, XL95X5_SCLK /* XL SCK */, XL95X5_MOSI /* XL MOSI */);
|
||||
Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
|
||||
-1 /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
|
||||
LCD_B0 /* B0 */, LCD_B1 /* B1 */, LCD_B2 /* B2 */, LCD_B3 /* B3 */, LCD_B4 /* B4 */,
|
||||
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
|
||||
LCD_R0 /* R0 */, LCD_R1 /* R1 */, LCD_R2 /* R2 */, LCD_R3 /* R3 */, LCD_R4 /* R4 */,
|
||||
1 /* hsync_polarity */, 20 /* hsync_front_porch */, 2 /* hsync_pulse_width */, 0 /* hsync_back_porch */,
|
||||
1 /* vsync_polarity */, 30 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 1 /* vsync_back_porch */,
|
||||
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, true /* useBigEndian */,
|
||||
0 /* de_idle_high*/, 0 /* pclk_idle_high */);
|
||||
Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
|
||||
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
|
||||
bus, -1 /* RST */, st7701_type9_init_operations_lilygo, sizeof(st7701_type9_init_operations_lilygo));
|
||||
Arduino_ESP32RGBPanel* rgbpanel = new Arduino_ESP32RGBPanel(
|
||||
-1 /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
|
||||
LCD_B0 /* B0 */, LCD_B1 /* B1 */, LCD_B2 /* B2 */, LCD_B3 /* B3 */, LCD_B4 /* B4 */,
|
||||
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
|
||||
LCD_R0 /* R0 */, LCD_R1 /* R1 */, LCD_R2 /* R2 */, LCD_R3 /* R3 */, LCD_R4 /* R4 */,
|
||||
1 /* hsync_polarity */, 20 /* hsync_front_porch */, 2 /* hsync_pulse_width */, 0 /* hsync_back_porch */,
|
||||
1 /* vsync_polarity */, 30 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 1 /* vsync_back_porch */,
|
||||
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, true /* useBigEndian */,
|
||||
0 /* de_idle_high*/, 0 /* pclk_idle_high */);
|
||||
Arduino_RGB_Display* gfx = new Arduino_RGB_Display(
|
||||
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
|
||||
bus, -1 /* RST */, st7701_type9_init_operations_lilygo, sizeof(st7701_type9_init_operations_lilygo));
|
||||
|
||||
#else
|
||||
static const uint8_t st7701_4848S040_init[] = {
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x10,
|
||||
|
||||
WRITE_C8_D16, 0xC0, 0x3B, 0x00,
|
||||
WRITE_C8_D16, 0xC1, 0x0D, 0x02,
|
||||
WRITE_C8_D16, 0xC2, 0x31, 0x05,
|
||||
WRITE_C8_D8, 0xCD, 0x00, // 0xCD, 0x08 !!
|
||||
|
||||
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08,
|
||||
0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18,
|
||||
|
||||
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08,
|
||||
0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18,
|
||||
|
||||
// PAGE1
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x11,
|
||||
|
||||
WRITE_C8_D8, 0xB0, 0x60, // Vop=4.7375v
|
||||
WRITE_C8_D8, 0xB1, 0x32, // VCOM=32
|
||||
WRITE_C8_D8, 0xB2, 0x07, // VGH=15v
|
||||
WRITE_C8_D8, 0xB3, 0x80,
|
||||
WRITE_C8_D8, 0xB5, 0x49, // VGL=-10.17v
|
||||
WRITE_C8_D8, 0xB7, 0x85,
|
||||
WRITE_C8_D8, 0xB8, 0x21, // AVDD=6.6 & AVCL=-4.6
|
||||
WRITE_C8_D8, 0xC1, 0x78,
|
||||
WRITE_C8_D8, 0xC2, 0x78,
|
||||
|
||||
WRITE_COMMAND_8, 0xE0,
|
||||
WRITE_BYTES, 3, 0x00, 0x1B, 0x02,
|
||||
|
||||
WRITE_COMMAND_8, 0xE1,
|
||||
WRITE_BYTES, 11,
|
||||
0x08, 0xA0, 0x00, 0x00,
|
||||
0x07, 0xA0, 0x00, 0x00,
|
||||
0x00, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE2,
|
||||
WRITE_BYTES, 12,
|
||||
0x11, 0x11, 0x44, 0x44,
|
||||
0xED, 0xA0, 0x00, 0x00,
|
||||
0xEC, 0xA0, 0x00, 0x00,
|
||||
|
||||
WRITE_COMMAND_8, 0xE3,
|
||||
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
|
||||
|
||||
WRITE_C8_D16, 0xE4, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE5,
|
||||
WRITE_BYTES, 16,
|
||||
0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0,
|
||||
0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0,
|
||||
|
||||
WRITE_COMMAND_8, 0xE6,
|
||||
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
|
||||
|
||||
WRITE_C8_D16, 0xE7, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE8,
|
||||
WRITE_BYTES, 16,
|
||||
0x09, 0xE8, 0xD8, 0xA0,
|
||||
0x0B, 0xEA, 0xD8, 0xA0,
|
||||
0x0D, 0xEC, 0xD8, 0xA0,
|
||||
0x0F, 0xEE, 0xD8, 0xA0,
|
||||
|
||||
WRITE_COMMAND_8, 0xEB,
|
||||
WRITE_BYTES, 7, 0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40,
|
||||
|
||||
WRITE_C8_D16, 0xEC, 0x3C, 0x00,
|
||||
|
||||
WRITE_COMMAND_8, 0xED,
|
||||
WRITE_BYTES, 16,
|
||||
0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA,
|
||||
|
||||
//-----------VAP & VAN---------------
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x13,
|
||||
|
||||
WRITE_C8_D8, 0xE5, 0xE4,
|
||||
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x00,
|
||||
|
||||
// WRITE_COMMAND_8, 0x21, // 0x20 normal, 0x21 IPS !!
|
||||
WRITE_C8_D8, 0x3A, 0x50, // 0x70 RGB888, 0x60 RGB666, 0x50 RGB565
|
||||
WRITE_COMMAND_8, 0x11, // Sleep Out
|
||||
END_WRITE,
|
||||
|
||||
DELAY, 120,
|
||||
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8, 0x29, // Display On
|
||||
END_WRITE};
|
||||
Arduino_DataBus* bus = new Arduino_SWSPI(
|
||||
GFX_NOT_DEFINED /* DC */, SPI_LCD_CS /* CS */, SPI_LCD_SCLK /* SCK */, SPI_LCD_MOSI /* MOSI */, GFX_NOT_DEFINED /* MISO */);
|
||||
Arduino_ESP32RGBPanel* rgbpanel = new Arduino_ESP32RGBPanel(
|
||||
LCD_DE /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
|
||||
LCD_R0 /* B0 */, LCD_R1 /* B1 */, LCD_R2 /* B2 */, LCD_R3 /* B3 */, LCD_R4 /* B4 */,
|
||||
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
|
||||
LCD_B0 /* R0 */, LCD_B1 /* R1 */, LCD_B2 /* R2 */, LCD_B3 /* R3 */, LCD_B4 /* R4 */,
|
||||
1 /* hsync_polarity */, 10 /* hsync_front_porch */, 8 /* hsync_pulse_width */, 50 /* hsync_back_porch */,
|
||||
1 /* vsync_polarity */, 10 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 20 /* vsync_back_porch */,
|
||||
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, true);
|
||||
Arduino_RGB_Display* gfx = new Arduino_RGB_Display(
|
||||
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
|
||||
bus, -1 /* RST */, st7701_4848S040_init, sizeof(st7701_4848S040_init));
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined HAS_GT911_TOUCH
|
||||
#include <Wire.h>
|
||||
#include <Touch_GT911.h>
|
||||
#define TOUCH_GT911_SCL 45
|
||||
#define TOUCH_GT911_SDA 19
|
||||
int touch_last_x = 0, touch_last_y = 0;
|
||||
uint32_t last_touch_read = 0;
|
||||
uint8_t is_new_touch_checked = false;
|
||||
Touch_GT911 ts = Touch_GT911(TOUCH_GT911_SDA, TOUCH_GT911_SCL, max(480, 0), max(480, 0));
|
||||
|
||||
void touch_init()
|
||||
{
|
||||
ts.begin();
|
||||
}
|
||||
void touch_loop()
|
||||
{
|
||||
if (millis() - last_touch_read >= 50) {
|
||||
last_touch_read = millis();
|
||||
ts.read();
|
||||
if (ts.isTouched)
|
||||
{
|
||||
touch_last_x = map(ts.points[0].x, 480, 0, 0, 480 - 1);
|
||||
touch_last_y = map(ts.points[0].y, 480, 0, 0, 480 - 1);
|
||||
Serial.printf("Touch position X: %i Y: %i\r\n", touch_last_x, touch_last_y);
|
||||
if(is_new_touch_checked == false)
|
||||
{
|
||||
is_new_touch_checked = true;
|
||||
if(touch_last_x <= 240)
|
||||
sendAvail(WAKEUP_REASON_BUTTON1);
|
||||
else
|
||||
sendAvail(WAKEUP_REASON_BUTTON2);
|
||||
}
|
||||
}else{
|
||||
is_new_touch_checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void touch_init()
|
||||
{
|
||||
}
|
||||
void touch_loop()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void TFTLog(String text) {
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
|
||||
gfx->setTextSize(2);
|
||||
|
||||
gfx->setTextSize(2);
|
||||
|
||||
if (tftLogscreen == false) {
|
||||
gfx->fillScreen(BLACK);
|
||||
gfx->setCursor(0, 0);
|
||||
tftLogscreen = true;
|
||||
}
|
||||
}
|
||||
if (text.isEmpty()) return;
|
||||
gfx->setTextColor(WHITE);
|
||||
gfx->println(text);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#else
|
||||
|
||||
if (tftLogscreen == false) {
|
||||
tft2.fillScreen(TFT_BLACK);
|
||||
tft2.setCursor(0, 0, (tft2.width() == 160 ? 1 : 2));
|
||||
@@ -220,7 +385,7 @@ void TFTLog(String text) {
|
||||
tft2.setTextColor(TFT_GREEN);
|
||||
}
|
||||
tft2.println(text);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t findId(uint8_t mac[8]) {
|
||||
@@ -240,11 +405,13 @@ void sendAvail(uint8_t wakeupReason) {
|
||||
memcpy(&eadr.src, mac, 6);
|
||||
eadr.adr.lastPacketRSSI = WiFi.RSSI();
|
||||
eadr.adr.currentChannel = config.channel;
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
#ifdef TFT_HW_TYPE
|
||||
eadr.adr.hwType = TFT_HW_TYPE;
|
||||
#elif defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
eadr.adr.hwType = 0xE2;
|
||||
#else
|
||||
#else
|
||||
eadr.adr.hwType = (tft2.width() == 160 ? 0xE1 : 0xE0);
|
||||
#endif
|
||||
#endif
|
||||
eadr.adr.wakeupReason = wakeupReason;
|
||||
eadr.adr.capabilities = 0;
|
||||
eadr.adr.tagSoftwareVersion = 0;
|
||||
@@ -253,50 +420,65 @@ void sendAvail(uint8_t wakeupReason) {
|
||||
}
|
||||
|
||||
void yellow_ap_display_init(void) {
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
|
||||
tftLogscreen = true;
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
|
||||
tftLogscreen = true;
|
||||
|
||||
pinMode(LCD_BL, OUTPUT);
|
||||
digitalWrite(LCD_BL, HIGH);
|
||||
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcAttachPin(LCD_BL, 1);
|
||||
ledcSetup(1, 1000, 8);
|
||||
ledcWrite(1, config.tft); // brightness
|
||||
#else
|
||||
ledcAttachChannel(LCD_BL, 1000, 8, 1);
|
||||
ledcWriteChannel(1, config.tft);
|
||||
#endif
|
||||
|
||||
ledcWrite(1, config.tft); // brightness
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL
|
||||
Wire.begin(IIC_SDA, IIC_SCL);
|
||||
|
||||
#endif
|
||||
gfx->begin();
|
||||
gfx->fillScreen(BLACK);
|
||||
|
||||
#else
|
||||
|
||||
#else
|
||||
#ifdef HAS_ELECROW_C6
|
||||
YellowSense = 0;
|
||||
#else
|
||||
pinMode(YELLOW_SENSE, INPUT_PULLDOWN);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
if (digitalRead(YELLOW_SENSE) == HIGH) YellowSense = 1;
|
||||
#endif
|
||||
pinMode(TFT_BACKLIGHT, OUTPUT);
|
||||
digitalWrite(TFT_BACKLIGHT, LOW);
|
||||
|
||||
tft2.init();
|
||||
#ifdef ST7735_NANO_TLSR
|
||||
#ifdef ST7735_NANO_TLSR
|
||||
YellowSense = 0;
|
||||
tft2.setRotation(1);
|
||||
#else
|
||||
#else
|
||||
tft2.setRotation(YellowSense == 1 ? 1 : 3);
|
||||
#endif
|
||||
#endif
|
||||
tft2.fillScreen(TFT_BLACK);
|
||||
tft2.setCursor(12, 0, (tft2.width() == 160 ? 1 : 2));
|
||||
tft2.setTextColor(TFT_WHITE);
|
||||
tftLogscreen = true;
|
||||
|
||||
ledcSetup(6, 5000, 8);
|
||||
ledcAttachPin(TFT_BACKLIGHT, 6);
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcSetup(1, 5000, 8);
|
||||
ledcAttachPin(TFT_BACKLIGHT, 1);
|
||||
ledcWrite(1, config.tft);
|
||||
if (tft2.width() == 160) {
|
||||
GPIO.func_out_sel_cfg[TFT_BACKLIGHT].inv_sel = 1;
|
||||
}
|
||||
ledcWrite(6, config.tft);
|
||||
#endif
|
||||
#else
|
||||
ledcAttachChannel(TFT_BACKLIGHT, 5000, 8, 1);
|
||||
ledcWriteChannel(1, config.tft);
|
||||
if (tft2.width() == 160) ledcOutputInvert(TFT_BACKLIGHT, true);
|
||||
#endif
|
||||
#endif
|
||||
touch_init();
|
||||
}
|
||||
|
||||
void yellow_ap_display_loop(void) {
|
||||
@@ -338,19 +520,19 @@ void yellow_ap_display_loop(void) {
|
||||
void* spriteData = spr.getPointer();
|
||||
size_t bytesRead = file.readBytes((char*)spriteData, spr.width() * spr.height() * 2);
|
||||
file.close();
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
long dy = spr.height();
|
||||
long dx = spr.width();
|
||||
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
long dy = spr.height();
|
||||
long dx = spr.width();
|
||||
|
||||
uint16_t* data = static_cast<uint16_t*>(const_cast<void*>(spriteData));
|
||||
|
||||
gfx->draw16bitRGBBitmap(0, 0, (uint16_t *)spriteData, dx, dy);
|
||||
spr.deleteSprite();
|
||||
#else
|
||||
gfx->draw16bitRGBBitmap(0, 0, (uint16_t*)spriteData, dx, dy);
|
||||
spr.deleteSprite();
|
||||
#else
|
||||
spr.pushSprite(0, 0);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
tftLogscreen = false;
|
||||
|
||||
struct espXferComplete xfc = {0};
|
||||
@@ -359,6 +541,7 @@ void yellow_ap_display_loop(void) {
|
||||
}
|
||||
last_update = millis();
|
||||
}
|
||||
touch_loop();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -29,8 +29,8 @@ void updateLanguageFromConfig() {
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(1024);
|
||||
StaticJsonDocument<80> filter;
|
||||
JsonDocument doc;
|
||||
JsonDocument filter;
|
||||
filter[String(currentLanguage)] = true;
|
||||
const DeserializationError error = deserializeJson(doc, file, DeserializationOption::Filter(filter));
|
||||
file.close();
|
||||
|
||||
@@ -36,6 +36,14 @@ struct ledInstruction {
|
||||
bool reQueue = false;
|
||||
};
|
||||
|
||||
void ledcSet(uint8_t channel, uint8_t brightness) {
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcWrite(channel, brightness);
|
||||
#else
|
||||
ledcWriteChannel(channel, brightness);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAS_RGB_LED
|
||||
|
||||
void addToRGBQueue(struct ledInstructionRGB* rgb, bool requeue) {
|
||||
@@ -132,13 +140,9 @@ void rgbIdleStep() {
|
||||
|
||||
void setBrightness(int brightness) {
|
||||
maxledbrightness = brightness;
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
ledcWrite(1, config.tft);
|
||||
#else
|
||||
#ifdef HAS_TFT
|
||||
ledcWrite(6, config.tft);
|
||||
#endif
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL || HAS_TFT
|
||||
ledcSet(1, config.tft);
|
||||
#endif
|
||||
#ifdef HAS_RGB_LED
|
||||
FastLED.setBrightness(maxledbrightness);
|
||||
@@ -150,12 +154,8 @@ void updateBrightnessFromConfig() {
|
||||
if (newbrightness != maxledbrightness) {
|
||||
setBrightness(newbrightness);
|
||||
}
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
ledcWrite(1, config.tft);
|
||||
#else
|
||||
#ifdef HAS_TFT
|
||||
ledcWrite(6, config.tft);
|
||||
#endif
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL || HAS_TFT
|
||||
ledcSet(1, config.tft);
|
||||
#endif
|
||||
if (apInfo.state == AP_STATE_NORADIO) addFadeMono(config.led);
|
||||
}
|
||||
@@ -176,11 +176,9 @@ void addFadeMono(uint8_t value) {
|
||||
}
|
||||
|
||||
void showMono(uint8_t brightness) {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ledcWrite(7, 255 - gamma8[brightness]);
|
||||
#else
|
||||
ledcWrite(7, gamma8[brightness]);
|
||||
#endif
|
||||
if (FLASHER_LED != -1) {
|
||||
ledcSet(7, gamma8[brightness]);
|
||||
}
|
||||
}
|
||||
|
||||
void quickBlink(uint8_t repeat) {
|
||||
@@ -222,11 +220,13 @@ void ledTask(void* parameter) {
|
||||
|
||||
ledQueue = xQueueCreate(30, sizeof(struct ledInstruction*));
|
||||
|
||||
ledcSetup(7, 5000, 8);
|
||||
if (FLASHER_LED != -1) {
|
||||
digitalWrite(FLASHER_LED, HIGH);
|
||||
pinMode(FLASHER_LED, OUTPUT);
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcSetup(7, 5000, 8);
|
||||
ledcAttachPin(FLASHER_LED, 7);
|
||||
#else
|
||||
ledcAttachChannel(FLASHER_LED, 1000, 8, 7);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct ledInstruction* monoled = nullptr;
|
||||
@@ -297,7 +297,7 @@ void ledTask(void* parameter) {
|
||||
if (monoled->fadeTime <= 1) {
|
||||
showMono(monoled->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (monoled->fadeTime) {
|
||||
monoled->fadeTime--;
|
||||
@@ -313,4 +313,4 @@ void ledTask(void* parameter) {
|
||||
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include <time.h>
|
||||
#ifdef ETHERNET_CLK_MODE
|
||||
#include <ETH.h>
|
||||
#endif
|
||||
|
||||
#include "contentmanager.h"
|
||||
#include "flasher.h"
|
||||
@@ -48,7 +51,12 @@ void delayedStart(void* parameter) {
|
||||
}
|
||||
|
||||
void setup() {
|
||||
#ifdef UART_LOGGING_TX_ONLY_PIN
|
||||
Serial.begin(115200, SERIAL_8N1, -1, UART_LOGGING_TX_ONLY_PIN);
|
||||
gpio_set_drive_capability((gpio_num_t)FLASHER_AP_RXD, GPIO_DRIVE_CAP_0);
|
||||
#else
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
#if ARDUINO_USB_CDC_ON_BOOT == 1
|
||||
Serial.setTxTimeoutMs(0); // workaround bug in USB CDC that slows down serial output when no usb connected
|
||||
#endif
|
||||
@@ -114,6 +122,7 @@ void setup() {
|
||||
}
|
||||
*/
|
||||
|
||||
wm.initEth();
|
||||
initAPconfig();
|
||||
|
||||
updateLanguageFromConfig();
|
||||
@@ -150,7 +159,12 @@ void setup() {
|
||||
// We'll need to start the 'usbflasher' task for boards with a second (USB) port. This can be used as a 'flasher' interface, using a python script on the host
|
||||
xTaskCreate(usbFlasherTask, "usbflasher", 10000, NULL, 5, NULL);
|
||||
#else
|
||||
|
||||
#ifdef ETHERNET_CLK_MODE
|
||||
if (!(ETHERNET_CLK_MODE == ETH_CLOCK_GPIO0_IN || ETHERNET_CLK_MODE == ETH_CLOCK_GPIO0_OUT))
|
||||
#endif
|
||||
pinMode(0, INPUT_PULLUP);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
#endif
|
||||
|
||||
#include "commstructs.h"
|
||||
#ifndef SAVE_SPACE
|
||||
#include "g5/Group5.h"
|
||||
#include "g5/g5enc.inl"
|
||||
#endif
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
@@ -73,14 +75,43 @@ struct Error {
|
||||
int32_t b;
|
||||
};
|
||||
|
||||
uint32_t colorDistance(Color &c1, Color &c2, Error &e1) {
|
||||
e1.r = constrain(e1.r, -255, 255);
|
||||
e1.g = constrain(e1.g, -255, 255);
|
||||
e1.b = constrain(e1.b, -255, 255);
|
||||
uint32_t colorDistance(const Color &c1, const Color &c2, const Error &e1) {
|
||||
int32_t r_diff = c1.r + e1.r - c2.r;
|
||||
int32_t g_diff = c1.g + e1.g - c2.g;
|
||||
int32_t b_diff = c1.b + e1.b - c2.b;
|
||||
return 3 * r_diff * r_diff + 6 * g_diff * g_diff + b_diff * b_diff;
|
||||
if (abs(c1.r - c1.g) < 20 && abs(c1.b - c1.g) < 20) {
|
||||
if (abs(c2.r - c2.g) > 20 || abs(c2.b - c2.g) > 20) return 4294967295; // don't select color pixels on black and white
|
||||
}
|
||||
return 3 * r_diff * r_diff + 5.47 * g_diff * g_diff + 1.53 * b_diff * b_diff;
|
||||
}
|
||||
|
||||
std::tuple<int, int, float, float> findClosestColors(const Color &pixel, const std::vector<Color> &palette) {
|
||||
int closestIndex = -1, secondClosestIndex = -1;
|
||||
float closestDist = std::numeric_limits<float>::max();
|
||||
float secondClosestDist = std::numeric_limits<float>::max();
|
||||
for (size_t i = 0; i < palette.size(); ++i) {
|
||||
float dist = colorDistance(pixel, palette[i], (Error){0, 0, 0});
|
||||
if (dist < closestDist) {
|
||||
secondClosestIndex = closestIndex;
|
||||
secondClosestDist = closestDist;
|
||||
closestIndex = i;
|
||||
closestDist = dist;
|
||||
} else if (dist < secondClosestDist) {
|
||||
secondClosestIndex = i;
|
||||
secondClosestDist = dist;
|
||||
}
|
||||
}
|
||||
if (closestIndex != -1 && secondClosestIndex != -1) {
|
||||
auto rgbValue = [](const Color &color) {
|
||||
return (color.r << 16) | (color.g << 8) | color.b;
|
||||
};
|
||||
|
||||
if (rgbValue(palette[secondClosestIndex]) > rgbValue(palette[closestIndex])) {
|
||||
std::swap(closestIndex, secondClosestIndex);
|
||||
std::swap(closestDist, secondClosestDist);
|
||||
}
|
||||
}
|
||||
return { closestIndex, secondClosestIndex, closestDist, secondClosestDist};
|
||||
}
|
||||
|
||||
void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t buffer_size, bool is_red) {
|
||||
@@ -110,11 +141,6 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t
|
||||
Error *error_bufferold = new Error[bufw + 4];
|
||||
Error *error_buffernew = new Error[bufw + 4];
|
||||
|
||||
const uint8_t ditherMatrix[4][4] = {
|
||||
{0, 9, 2, 10},
|
||||
{12, 5, 14, 6},
|
||||
{3, 11, 1, 8},
|
||||
{15, 7, 13, 4}};
|
||||
size_t bitOffset = 0;
|
||||
|
||||
memset(error_bufferold, 0, bufw * sizeof(Error));
|
||||
@@ -136,27 +162,40 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t
|
||||
break;
|
||||
}
|
||||
|
||||
if (imageParams.dither == 2) {
|
||||
// Ordered dithering
|
||||
uint8_t ditherValue = ditherMatrix[y % 4][x % 4] << (imageParams.bpp == 3 ? 2 : 4);
|
||||
error_bufferold[x].r = ditherValue - (imageParams.bpp == 3 ? 30 : 120); // * 256 / 16 - 128 + 8
|
||||
error_bufferold[x].g = ditherValue - (imageParams.bpp == 3 ? 30 : 120);
|
||||
error_bufferold[x].b = ditherValue - (imageParams.bpp == 3 ? 30 : 120);
|
||||
}
|
||||
|
||||
int best_color_index = 0;
|
||||
uint32_t best_color_distance = colorDistance(color, palette[0], error_bufferold[x]);
|
||||
|
||||
for (int i = 1; i < num_colors; i++) {
|
||||
if (best_color_distance == 0) break;
|
||||
uint32_t distance = colorDistance(color, palette[i], error_bufferold[x]);
|
||||
if (distance < best_color_distance) {
|
||||
best_color_distance = distance;
|
||||
best_color_index = i;
|
||||
if (imageParams.dither == 2) {
|
||||
// special ordered dithering
|
||||
auto [c1Index, c2Index, distC1, distC2] = findClosestColors(color, palette);
|
||||
Color c1 = palette[c1Index];
|
||||
Color c2 = palette[c2Index];
|
||||
float weight = distC1 / (distC1 + distC2);
|
||||
if (weight <= 0.03) {
|
||||
best_color_index = c1Index;
|
||||
} else if (weight < 0.30) {
|
||||
best_color_index = ((y % 2 && ((y / 2 + x) % 2)) ? c2Index : c1Index);
|
||||
} else if (weight < 0.70) {
|
||||
best_color_index = ((x + y) % 2 ? c2Index : c1Index);
|
||||
} else if (weight < 0.97) {
|
||||
best_color_index = ((y % 2 && ((y / 2 + x) % 2)) % 2 ? c1Index : c2Index);
|
||||
} else {
|
||||
best_color_index = c2Index;
|
||||
}
|
||||
}
|
||||
|
||||
if (imageParams.bpp == 3) {
|
||||
if (imageParams.dither == 1 || imageParams.dither == 0) {
|
||||
uint32_t best_color_distance = colorDistance(color, palette[0], error_bufferold[x]);
|
||||
|
||||
for (int i = 1; i < num_colors; i++) {
|
||||
if (best_color_distance == 0) break;
|
||||
uint32_t distance = colorDistance(color, palette[i], error_bufferold[x]);
|
||||
if (distance < best_color_distance) {
|
||||
best_color_distance = distance;
|
||||
best_color_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imageParams.bpp == 3 || imageParams.bpp == 4) {
|
||||
size_t byteIndex = bitOffset / 8;
|
||||
uint8_t bitIndex = bitOffset % 8;
|
||||
|
||||
@@ -199,34 +238,44 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t
|
||||
color.g + error_bufferold[x].g - palette[best_color_index].g,
|
||||
color.b + error_bufferold[x].b - palette[best_color_index].b};
|
||||
|
||||
error_buffernew[x].r += error.r >> 2;
|
||||
error_buffernew[x].g += error.g >> 2;
|
||||
error_buffernew[x].b += error.b >> 2;
|
||||
float scaling_factor = 255.0f / std::max(std::abs(error.r), std::max(std::abs(error.g), std::abs(error.b)));
|
||||
if (scaling_factor < 1.0f) {
|
||||
error.r *= scaling_factor;
|
||||
error.g *= scaling_factor;
|
||||
error.b *= scaling_factor;
|
||||
}
|
||||
|
||||
error_buffernew[x].r += error.r / 4;
|
||||
error_buffernew[x].g += error.g / 4;
|
||||
error_buffernew[x].b += error.b / 4;
|
||||
|
||||
if (x > 0) {
|
||||
error_buffernew[x - 1].r += error.r >> 3;
|
||||
error_buffernew[x - 1].g += error.g >> 3;
|
||||
error_buffernew[x - 1].b += error.b >> 3;
|
||||
error_buffernew[x - 1].r += error.r / 8;
|
||||
error_buffernew[x - 1].g += error.g / 8;
|
||||
error_buffernew[x - 1].b += error.b / 8;
|
||||
}
|
||||
|
||||
if (x > 1) {
|
||||
error_buffernew[x - 2].r += error.r >> 4;
|
||||
error_buffernew[x - 2].g += error.g >> 4;
|
||||
error_buffernew[x - 2].b += error.b >> 4;
|
||||
error_buffernew[x - 2].r += error.r / 16;
|
||||
error_buffernew[x - 2].g += error.g / 16;
|
||||
error_buffernew[x - 2].b += error.b / 16;
|
||||
}
|
||||
error_buffernew[x + 1].r += error.r >> 3;
|
||||
error_buffernew[x + 1].g += error.g >> 3;
|
||||
error_buffernew[x + 1].b += error.b >> 3;
|
||||
|
||||
error_bufferold[x + 1].r += error.r >> 2;
|
||||
error_bufferold[x + 1].g += error.g >> 2;
|
||||
error_bufferold[x + 1].b += error.b >> 2;
|
||||
error_buffernew[x + 1].r += error.r / 8;
|
||||
error_buffernew[x + 1].g += error.g / 8;
|
||||
error_buffernew[x + 1].b += error.b / 8;
|
||||
|
||||
error_buffernew[x + 2].r += error.r >> 4;
|
||||
error_buffernew[x + 2].g += error.g >> 4;
|
||||
error_buffernew[x + 2].b += error.b >> 4;
|
||||
error_bufferold[x + 1].r += error.r / 4;
|
||||
error_bufferold[x + 1].g += error.g / 4;
|
||||
error_bufferold[x + 1].b += error.b / 4;
|
||||
|
||||
error_bufferold[x + 2].r += error.r >> 3;
|
||||
error_bufferold[x + 2].g += error.g >> 3;
|
||||
error_bufferold[x + 2].b += error.b >> 3;
|
||||
error_buffernew[x + 2].r += error.r / 16;
|
||||
error_buffernew[x + 2].g += error.g / 16;
|
||||
error_buffernew[x + 2].b += error.b / 16;
|
||||
|
||||
error_bufferold[x + 2].r += error.r / 8;
|
||||
error_bufferold[x + 2].g += error.g / 8;
|
||||
error_bufferold[x + 2].b += error.b / 8;
|
||||
}
|
||||
}
|
||||
memcpy(error_bufferold, error_buffernew, bufw * sizeof(Error));
|
||||
@@ -246,9 +295,9 @@ size_t prepareHeader(uint8_t headerbuf[], uint16_t bufw, uint16_t bufh, imgParam
|
||||
memcpy(headerbuf + (imageParams.rotatebuffer % 2 == 1 ? 3 : 1), &bufw, sizeof(uint16_t));
|
||||
memcpy(headerbuf + (imageParams.rotatebuffer % 2 == 1 ? 1 : 3), &bufh, sizeof(uint16_t));
|
||||
|
||||
if (imageParams.bpp == 3) {
|
||||
totalbytes = buffer_size * 3 + headersize;
|
||||
headerbuf[5] = 3;
|
||||
if (imageParams.bpp == 3 || imageParams.bpp == 4) {
|
||||
totalbytes = buffer_size * imageParams.bpp + headersize;
|
||||
headerbuf[5] = imageParams.bpp;
|
||||
} else if (imageParams.hasRed && imageParams.bpp > 1) {
|
||||
totalbytes = buffer_size * 2 + headersize;
|
||||
headerbuf[5] = 2;
|
||||
@@ -289,19 +338,21 @@ void rewriteHeader(File &f_out) {
|
||||
f_out.write(flg);
|
||||
}
|
||||
|
||||
#ifndef SAVE_SPACE
|
||||
uint8_t *g5Compress(uint16_t width, uint16_t height, uint8_t *buffer, uint16_t buffersize, uint16_t &outBufferSize) {
|
||||
G5ENCIMAGE g5enc;
|
||||
int rc;
|
||||
uint8_t *outbuffer = (uint8_t *)ps_malloc(buffersize + 16384);
|
||||
uint8_t *outbuffer = (uint8_t *)ps_malloc(buffersize+16384);
|
||||
if (outbuffer == NULL) {
|
||||
Serial.println("Failed to allocate the output buffer for the G5 encoder");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rc = g5_encode_init(&g5enc, width, height, outbuffer, buffersize + 16384);
|
||||
rc = g5_encode_init(&g5enc, width, height, outbuffer, buffersize);
|
||||
for (int y = 0; y < height && rc == G5_SUCCESS; y++) {
|
||||
rc = g5_encode_encodeLine(&g5enc, buffer);
|
||||
buffer += (width / 8);
|
||||
if (rc != G5_SUCCESS) break;
|
||||
}
|
||||
if (rc == G5_ENCODE_COMPLETE) {
|
||||
outBufferSize = g5_encode_getOutSize(&g5enc);
|
||||
@@ -312,10 +363,25 @@ uint8_t *g5Compress(uint16_t width, uint16_t height, uint8_t *buffer, uint16_t b
|
||||
}
|
||||
return outbuffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
void doTimestamp(TFT_eSprite *spr) {
|
||||
time_t now = time(nullptr);
|
||||
struct tm *timeinfo = localtime(&now);
|
||||
char buffer[20];
|
||||
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M", timeinfo);
|
||||
|
||||
// spr->drawRect(spr->width() - 16 * 6 - 4, spr->height() - 10 - 2, 16 * 6 + 3, 11, TFT_BLACK);
|
||||
spr->drawRect(spr->width() - 16 * 6 - 3, spr->height() - 10 - 1, 16 * 6 + 1, 9, TFT_WHITE);
|
||||
spr->setTextColor(TFT_BLACK, TFT_WHITE);
|
||||
spr->setCursor(spr->width() - 16 * 6 - 2, spr->height() - 10, 1);
|
||||
spr->print(buffer);
|
||||
}
|
||||
|
||||
void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
long t = millis();
|
||||
|
||||
if (config.showtimestamp) doTimestamp(&spr);
|
||||
#ifdef HAS_TFT
|
||||
extern uint8_t YellowSense;
|
||||
if (fileout == "direct") {
|
||||
@@ -334,7 +400,7 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
size_t dataSize = spr.width() * spr.height() * (spr.getColorDepth() / 8);
|
||||
memcpy(spriteData2, spriteData, dataSize);
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
if (spr.getColorDepth() == 16) {
|
||||
long dy = spr.height();
|
||||
long dx = spr.width();
|
||||
@@ -406,6 +472,7 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
free(comp);
|
||||
|
||||
rewriteHeader(f_out);
|
||||
#ifndef SAVE_SPACE
|
||||
} else if (imageParams.g5) {
|
||||
// handling for G5-compressed image data
|
||||
|
||||
@@ -434,7 +501,6 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
} else {
|
||||
height *= 2;
|
||||
}
|
||||
|
||||
}
|
||||
uint16_t outbufferSize = 0;
|
||||
uint8_t *outBuffer;
|
||||
@@ -452,7 +518,6 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
if (outbufferSize > buffer_size) {
|
||||
printf("That wasn't very useful, falling back to raw\n");
|
||||
compressionSuccessful = false;
|
||||
f_out.seek(0);
|
||||
} else {
|
||||
f_out.write(outBuffer, outbufferSize);
|
||||
}
|
||||
@@ -466,8 +531,10 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
} else {
|
||||
imageParams.dataType = DATATYPE_IMG_RAW_1BPP;
|
||||
}
|
||||
f_out.seek(0);
|
||||
f_out.write(buffer, buffer_size);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
f_out.write(buffer, buffer_size);
|
||||
if (imageParams.hasRed && imageParams.bpp > 1) {
|
||||
@@ -479,9 +546,10 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
free(buffer);
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
case 3:
|
||||
case 4: {
|
||||
long bufw = spr.width(), bufh = spr.height();
|
||||
size_t buffer_size = (bufw * bufh) / 8 * 3;
|
||||
size_t buffer_size = (bufw * bufh) / 8 * imageParams.bpp;
|
||||
uint8_t *buffer = (uint8_t *)ps_malloc(buffer_size);
|
||||
if (!buffer) {
|
||||
Serial.println("Failed to allocate buffer");
|
||||
|
||||
@@ -275,7 +275,8 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
case DATATYPE_IMG_RAW_1BPP:
|
||||
case DATATYPE_IMG_RAW_2BPP:
|
||||
case DATATYPE_IMG_G5:
|
||||
case DATATYPE_IMG_RAW_3BPP: {
|
||||
case DATATYPE_IMG_RAW_3BPP:
|
||||
case DATATYPE_IMG_RAW_4BPP: {
|
||||
char hexmac[17];
|
||||
mac2hex(pending->targetMac, hexmac);
|
||||
String filename = "/current/" + String(hexmac) + "_" + String(millis() % 1000000) + ".pending";
|
||||
@@ -338,8 +339,7 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
break;
|
||||
}
|
||||
case DATATYPE_NFC_RAW_CONTENT:
|
||||
case DATATYPE_NFC_URL_DIRECT:
|
||||
case DATATYPE_CUSTOM_LUT_OTA: {
|
||||
case DATATYPE_NFC_URL_DIRECT: {
|
||||
char hexmac[17];
|
||||
mac2hex(pending->targetMac, hexmac);
|
||||
char dataUrl[80];
|
||||
@@ -348,7 +348,7 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
snprintf(dataUrl, sizeof(dataUrl), "http://%s/getdata?mac=%s&md5=%s", remoteIP.toString().c_str(), hexmac, md5);
|
||||
wsLog("GET " + String(dataUrl));
|
||||
HTTPClient http;
|
||||
logLine("http DATATYPE_CUSTOM_LUT_OTA " + String(dataUrl));
|
||||
logLine("http DATATYPE_NFC_* " + String(dataUrl));
|
||||
http.begin(dataUrl);
|
||||
int httpCode = http.GET();
|
||||
if (httpCode == 200) {
|
||||
@@ -447,9 +447,11 @@ void processXferComplete(struct espXferComplete* xfc, bool local) {
|
||||
contentFS->remove(dst_path);
|
||||
}
|
||||
if (contentFS->exists(queueItem->filename)) {
|
||||
if (config.preview && (queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_RAW_3BPP || queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_RAW_2BPP || queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_RAW_1BPP || queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_G5 || queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_ZLIB)) {
|
||||
uint8_t dataType = queueItem->pendingdata.availdatainfo.dataType;
|
||||
if (config.preview && dataType != DATATYPE_FW_UPDATE && dataType != DATATYPE_NOUPDATE) {
|
||||
contentFS->rename(queueItem->filename, String(dst_path));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (queueItem->pendingdata.availdatainfo.dataType != DATATYPE_FW_UPDATE) contentFS->remove(queueItem->filename);
|
||||
}
|
||||
}
|
||||
@@ -505,9 +507,9 @@ void processXferTimeout(struct espXferComplete* xfc, bool local) {
|
||||
if (taginfo != nullptr) {
|
||||
taginfo->pendingIdle = 60;
|
||||
clearPending(taginfo);
|
||||
while (dequeueItem(xfc->src)) {
|
||||
};
|
||||
}
|
||||
while (dequeueItem(xfc->src)) {
|
||||
};
|
||||
|
||||
checkQueue(xfc->src);
|
||||
|
||||
@@ -558,15 +560,14 @@ void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP
|
||||
taginfo->apIp = IPAddress(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (taginfo->pendingIdle == 0) {
|
||||
taginfo->expectedNextCheckin = now + 60;
|
||||
if (taginfo->pendingIdle == 0 || countQueueItem(eadr->src) > 0) {
|
||||
if (taginfo->expectedNextCheckin < now + 60) taginfo->expectedNextCheckin = now + 60;
|
||||
} else if (taginfo->pendingIdle == 9999) {
|
||||
taginfo->expectedNextCheckin = 3216153600;
|
||||
taginfo->pendingIdle = 0;
|
||||
} else {
|
||||
taginfo->expectedNextCheckin = now + taginfo->pendingIdle;
|
||||
taginfo->pendingIdle = 0;
|
||||
}
|
||||
taginfo->pendingIdle = 0;
|
||||
taginfo->lastseen = now;
|
||||
|
||||
if (eadr->adr.lastPacketRSSI != 0) {
|
||||
@@ -605,6 +606,7 @@ void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP
|
||||
if (local) {
|
||||
sprintf(buffer, "<ADR %02X%02X%02X%02X%02X%02X%02X%02X\r\n\0", eadr->src[7], eadr->src[6], eadr->src[5], eadr->src[4], eadr->src[3], eadr->src[2], eadr->src[1], eadr->src[0]);
|
||||
Serial.print(buffer);
|
||||
checkQueue(eadr->src); // experiemental 3/26/25: redundant check
|
||||
}
|
||||
|
||||
if (local) {
|
||||
@@ -750,6 +752,35 @@ bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local, const uint8_t*
|
||||
}
|
||||
}
|
||||
|
||||
bool sendTagMac(const uint8_t* dst, const uint64_t newmac, bool local) {
|
||||
struct pendingData pending = {0};
|
||||
memcpy(pending.targetMac, dst, 8);
|
||||
pending.availdatainfo.dataType = DATATYPE_COMMAND_DATA;
|
||||
pending.availdatainfo.dataTypeArgument = 0x23;
|
||||
pending.availdatainfo.nextCheckIn = 0;
|
||||
|
||||
|
||||
pending.availdatainfo.dataVer = newmac;
|
||||
pending.availdatainfo.dataSize = 0;
|
||||
|
||||
pending.attemptsLeft = MAX_XFER_ATTEMPTS;
|
||||
Serial.printf(">Tag %02X%02X%02X%02X%02X%02X%02X%02X Mac set\r\n\0", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
|
||||
|
||||
tagRecord* taginfo = tagRecord::findByMAC(dst);
|
||||
if (taginfo != nullptr) {
|
||||
taginfo->pendingCount++;
|
||||
wsSendTaginfo(taginfo->mac, SYNC_TAGSTATUS);
|
||||
}
|
||||
|
||||
if (local) {
|
||||
return queueDataAvail(&pending, true);
|
||||
} else {
|
||||
queueDataAvail(&pending, false);
|
||||
udpsync.netSendDataAvail(&pending);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void updateTaginfoitem(struct TagInfo* taginfoitem, IPAddress remoteIP) {
|
||||
tagRecord* taginfo = tagRecord::findByMAC(taginfoitem->mac);
|
||||
|
||||
@@ -802,7 +833,7 @@ bool checkMirror(struct tagRecord* taginfo, struct pendingData* pending) {
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* taginfo2 = tagDB.at(c);
|
||||
if (taginfo2->contentMode == 20 && taginfo2->version == 0) {
|
||||
DynamicJsonDocument doc(500);
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, taginfo2->modeConfigJson);
|
||||
JsonObject cfgobj = doc.as<JsonObject>();
|
||||
uint8_t mac[8] = {0};
|
||||
@@ -955,20 +986,23 @@ bool queueDataAvail(struct pendingData* pending, bool local) {
|
||||
taginfo->data = nullptr;
|
||||
} else {
|
||||
newPending.data = nullptr;
|
||||
|
||||
// optional: read data early, don't wait for block request.
|
||||
fs::File file = contentFS->open(newPending.filename);
|
||||
if (file) {
|
||||
newPending.data = getDataForFile(file);
|
||||
Serial.println("Reading file " + String(newPending.filename));
|
||||
file.close();
|
||||
} else {
|
||||
Serial.println("Warning: not found: " + String(newPending.filename));
|
||||
|
||||
if (pendingQueue.size() < 5) { // maximized to 5 to save some memory
|
||||
// optional: read data early, don't wait for block request.
|
||||
fs::File file = contentFS->open(newPending.filename);
|
||||
if (file) {
|
||||
newPending.data = getDataForFile(file);
|
||||
Serial.println("Reading file " + String(newPending.filename));
|
||||
file.close();
|
||||
} else {
|
||||
Serial.println("Warning: not found: " + String(newPending.filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
newPending.len = taginfo->len;
|
||||
|
||||
if ((pending->availdatainfo.dataType == DATATYPE_IMG_RAW_1BPP || pending->availdatainfo.dataType == DATATYPE_IMG_RAW_2BPP || pending->availdatainfo.dataType == DATATYPE_IMG_RAW_3BPP || pending->availdatainfo.dataType == DATATYPE_IMG_ZLIB || pending->availdatainfo.dataType == DATATYPE_IMG_G5) && (pending->availdatainfo.dataTypeArgument & 0xF8) == 0x00) {
|
||||
uint8_t dataType = pending->availdatainfo.dataType;
|
||||
if (dataType != DATATYPE_FW_UPDATE && dataType != DATATYPE_NOUPDATE && pending->availdatainfo.dataTypeArgument & 0xF8 == 0x00) {
|
||||
// in case of an image (no preload), remove already queued images
|
||||
pendingQueue.erase(std::remove_if(pendingQueue.begin(), pendingQueue.end(),
|
||||
[pending](const PendingItem& item) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <MD5Builder.h>
|
||||
#include <Update.h>
|
||||
|
||||
#include "flasher.h"
|
||||
#include "espflasher.h"
|
||||
#include "leds.h"
|
||||
#include "serialap.h"
|
||||
@@ -15,6 +16,7 @@
|
||||
#include "util.h"
|
||||
#include "web.h"
|
||||
|
||||
|
||||
#ifndef BUILD_ENV_NAME
|
||||
#define BUILD_ENV_NAME unknown
|
||||
#endif
|
||||
@@ -30,9 +32,11 @@
|
||||
|
||||
#define STR_IMPL(x) #x
|
||||
#define STR(x) STR_IMPL(x)
|
||||
#define LOG(format, ... ) Serial.printf(format,## __VA_ARGS__)
|
||||
|
||||
|
||||
void handleSysinfoRequest(AsyncWebServerRequest* request) {
|
||||
StaticJsonDocument<250> doc;
|
||||
JsonDocument doc;
|
||||
doc["alias"] = config.alias;
|
||||
doc["env"] = STR(BUILD_ENV_NAME);
|
||||
doc["buildtime"] = STR(BUILD_TIME);
|
||||
@@ -41,11 +45,20 @@ void handleSysinfoRequest(AsyncWebServerRequest* request) {
|
||||
doc["psramsize"] = ESP.getPsramSize();
|
||||
doc["flashsize"] = ESP.getFlashChipSize();
|
||||
doc["rollback"] = Update.canRollBack();
|
||||
#if defined C6_OTA_FLASHING
|
||||
doc["hasC6"] = 1;
|
||||
#else
|
||||
doc["ap_version"] = apInfo.version;
|
||||
|
||||
doc["hasC6"] = 0;
|
||||
doc["hasH2"] = 0;
|
||||
doc["hasTslr"] = 0;
|
||||
|
||||
#if defined HAS_H2
|
||||
doc["hasH2"] = 1;
|
||||
#elif defined HAS_TSLR
|
||||
doc["hasTslr"] = 1;
|
||||
#elif defined C6_OTA_FLASHING
|
||||
doc["hasC6"] = 1;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
doc["hasFlasher"] = 1;
|
||||
#else
|
||||
@@ -66,7 +79,7 @@ void handleCheckFile(AsyncWebServerRequest* request) {
|
||||
const String filePath = request->getParam("path")->value();
|
||||
File file = contentFS->open(filePath, "r");
|
||||
if (!file) {
|
||||
StaticJsonDocument<64> doc;
|
||||
JsonDocument doc;
|
||||
doc["filesize"] = 0;
|
||||
doc["md5"] = "";
|
||||
String jsonResponse;
|
||||
@@ -85,7 +98,7 @@ void handleCheckFile(AsyncWebServerRequest* request) {
|
||||
|
||||
file.close();
|
||||
|
||||
StaticJsonDocument<128> doc;
|
||||
JsonDocument doc;
|
||||
doc["filesize"] = fileSize;
|
||||
doc["md5"] = md5Hash;
|
||||
String jsonResponse;
|
||||
@@ -135,12 +148,13 @@ void handleLittleFSUpload(AsyncWebServerRequest* request, String filename, size_
|
||||
file.write(uploadInfo->buffer, uploadInfo->bufferSize);
|
||||
file.close();
|
||||
uploadInfo->bufferSize = 0;
|
||||
xSemaphoreGive(fsMutex);
|
||||
} else {
|
||||
xSemaphoreGive(fsMutex);
|
||||
logLine("Failed to open file for appending: " + uploadfilename);
|
||||
final = true;
|
||||
error = true;
|
||||
}
|
||||
xSemaphoreGive(fsMutex);
|
||||
|
||||
memcpy(uploadInfo->buffer, data, len);
|
||||
uploadInfo->bufferSize = len;
|
||||
@@ -153,11 +167,12 @@ void handleLittleFSUpload(AsyncWebServerRequest* request, String filename, size_
|
||||
if (file) {
|
||||
file.write(uploadInfo->buffer, uploadInfo->bufferSize);
|
||||
file.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
} else {
|
||||
xSemaphoreGive(fsMutex);
|
||||
logLine("Failed to open file for appending: " + uploadfilename);
|
||||
error = true;
|
||||
}
|
||||
xSemaphoreGive(fsMutex);
|
||||
request->_tempObject = nullptr;
|
||||
delete uploadInfo;
|
||||
}
|
||||
@@ -289,22 +304,29 @@ void handleRollback(AsyncWebServerRequest* request) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef C6_OTA_FLASHING
|
||||
void C6firmwareUpdateTask(void* parameter) {
|
||||
uint8_t doDownload = *((uint8_t*)parameter);
|
||||
char* urlPtr = reinterpret_cast<char*>(parameter);
|
||||
|
||||
LOG("C6firmwareUpdateTask: url '%s'\n", urlPtr);
|
||||
wsSerial("Stopping AP service");
|
||||
|
||||
setAPstate(false, AP_STATE_FLASHING);
|
||||
gSerialTaskState = SERIAL_STATE_STOP;
|
||||
config.runStatus = RUNSTATUS_STOP;
|
||||
setAPstate(false, AP_STATE_FLASHING);
|
||||
#ifndef FLASHER_DEBUG_SHARED
|
||||
extern bool rxSerialStopTask2;
|
||||
rxSerialStopTask2 = true;
|
||||
#endif
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
Serial1.end();
|
||||
setAPstate(false, AP_STATE_FLASHING);
|
||||
|
||||
wsSerial("C6 flash starting");
|
||||
wsSerial(SHORT_CHIP_NAME " flash starting");
|
||||
|
||||
bool result = doC6flash(doDownload);
|
||||
bool result = FlashC6_H2(urlPtr);
|
||||
|
||||
wsSerial("C6 flash end");
|
||||
wsSerial(SHORT_CHIP_NAME " flash end");
|
||||
|
||||
if (result) {
|
||||
setAPstate(false, AP_STATE_OFFLINE);
|
||||
@@ -314,36 +336,65 @@ void C6firmwareUpdateTask(void* parameter) {
|
||||
|
||||
wsSerial("starting monitor");
|
||||
Serial1.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#ifndef FLASHER_DEBUG_SHARED
|
||||
rxSerialStopTask2 = false;
|
||||
#ifdef FLASHER_DEBUG_RXD
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1750, NULL, 2, NULL);
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1850, NULL, 2, NULL);
|
||||
#endif
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
wsSerial("resetting AP");
|
||||
APTagReset();
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
apInfo.version = 0;
|
||||
wsSerial("bringing AP online");
|
||||
if (bringAPOnline()) config.runStatus = RUNSTATUS_RUN;
|
||||
// if (bringAPOnline(AP_STATE_REQUIRED_POWER_CYCLE)) config.runStatus = RUNSTATUS_STOP;
|
||||
if (bringAPOnline(AP_STATE_ONLINE)) {
|
||||
config.runStatus = RUNSTATUS_RUN;
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
}
|
||||
|
||||
wsSerial("Finished!");
|
||||
} else {
|
||||
wsSerial("Flashing failed. :-(");
|
||||
// Wait for version info to arrive
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
if(apInfo.version == 0) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
wsSerial("Finished!");
|
||||
char buffer[50];
|
||||
snprintf(buffer,sizeof(buffer),
|
||||
"ESP32-" SHORT_CHIP_NAME " version is now %04x", apInfo.version);
|
||||
wsSerial(String(buffer));
|
||||
}
|
||||
else if(apInfo.version == 0) {
|
||||
wsSerial("AP failed to come online. :-(");
|
||||
}
|
||||
else {
|
||||
wsSerial("Flashing failed. :-(");
|
||||
}
|
||||
// wsSerial("Reboot system now");
|
||||
// wsSerial("[reboot]");
|
||||
free(urlPtr);
|
||||
vTaskDelay(30000 / portTICK_PERIOD_MS);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void handleUpdateC6(AsyncWebServerRequest* request) {
|
||||
#if defined C6_OTA_FLASHING
|
||||
uint8_t doDownload = 1;
|
||||
if (request->hasParam("download", true)) {
|
||||
doDownload = atoi(request->getParam("download", true)->value().c_str());
|
||||
if (request->hasParam("url",true)) {
|
||||
const char* urlStr = request->getParam("url", true)->value().c_str();
|
||||
char* urlCopy = strdup(urlStr);
|
||||
xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6400, urlCopy, 10, NULL);
|
||||
request->send(200, "Ok");
|
||||
}
|
||||
xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6144, &doDownload, 10, NULL);
|
||||
request->send(200, "Ok");
|
||||
else {
|
||||
LOG("Sending bad request");
|
||||
request->send(400, "Bad request");
|
||||
}
|
||||
#elif defined(SHORT_CHIP_NAME)
|
||||
request->send(400, SHORT_CHIP_NAME " flashing not implemented");
|
||||
#else
|
||||
request->send(400, "C6 flashing not implemented");
|
||||
request->send(400, "C6/H2 flashing not implemented");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -355,7 +406,7 @@ void handleUpdateActions(AsyncWebServerRequest* request) {
|
||||
request->send(200, "No update actions needed");
|
||||
return;
|
||||
}
|
||||
DynamicJsonDocument doc(1000);
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, file);
|
||||
const JsonArray deleteFiles = doc["deletefile"].as<JsonArray>();
|
||||
for (const auto& filePath : deleteFiles) {
|
||||
@@ -367,4 +418,4 @@ void handleUpdateActions(AsyncWebServerRequest* request) {
|
||||
wsSerial("Cleanup finished");
|
||||
request->send(200, "Clean up finished");
|
||||
contentFS->remove("/update_actions.json");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "settings.h"
|
||||
#include "leds.h"
|
||||
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
@@ -34,16 +35,21 @@ void rampTagPower(uint8_t* pin, bool up) {
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
|
||||
#endif
|
||||
if (up) {
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcSetup(0, 50000, 8);
|
||||
ledcWrite(0, 254);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
pinMode(pin[0], OUTPUT);
|
||||
ledcAttachPin(pin[0], 0);
|
||||
#else
|
||||
ledcWriteChannel(0, 254);
|
||||
ledcAttachChannel(pin[0], 50000, 8, 0);
|
||||
#endif
|
||||
pinMode(FLASHER_EXT_RESET, OUTPUT);
|
||||
digitalWrite(FLASHER_EXT_RESET, LOW);
|
||||
ledcAttachPin(pin[0], 0);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
for (uint8_t c = 254; c != 0xFF; c--) {
|
||||
ledcWrite(0, c);
|
||||
ledcSet(0, c);
|
||||
delayMicroseconds(700);
|
||||
}
|
||||
digitalWrite(pin[0], LOW);
|
||||
@@ -52,14 +58,14 @@ void rampTagPower(uint8_t* pin, bool up) {
|
||||
digitalWrite(FLASHER_EXT_RESET, INPUT_PULLUP);
|
||||
} else {
|
||||
ledcSetup(0, 50000, 8);
|
||||
ledcWrite(0, 0);
|
||||
ledcSet(0, 0);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
pinMode(pin[0], OUTPUT);
|
||||
pinMode(FLASHER_EXT_RESET, INPUT_PULLDOWN);
|
||||
ledcAttachPin(pin[0], 0);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
for (uint8_t c = 0; c < 0xFF; c++) {
|
||||
ledcWrite(0, c);
|
||||
ledcSet(0, c);
|
||||
if (c > 250) {
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HardwareSerial.h>
|
||||
#include <system.h>
|
||||
|
||||
#include "commstructs.h"
|
||||
#include "contentmanager.h"
|
||||
@@ -14,6 +15,8 @@
|
||||
#include "web.h"
|
||||
#include "zbs_interface.h"
|
||||
|
||||
#define LOG(format, ...) printf(format, ##__VA_ARGS__)
|
||||
|
||||
QueueHandle_t rxCmdQueue;
|
||||
SemaphoreHandle_t txActive;
|
||||
|
||||
@@ -25,7 +28,9 @@ SemaphoreHandle_t txActive;
|
||||
volatile uint8_t cmdReplyValue = CMD_REPLY_WAIT;
|
||||
|
||||
#define AP_SERIAL_PORT Serial1
|
||||
#ifndef FLASHER_DEBUG_SHARED
|
||||
volatile bool rxSerialStopTask2 = false;
|
||||
#endif
|
||||
|
||||
uint8_t channelList[6];
|
||||
struct espSetChannelPower curChannel = {0, 11, 10};
|
||||
@@ -42,6 +47,8 @@ struct espSetChannelPower curChannel = {0, 11, 10};
|
||||
volatile uint32_t lastAPActivity = 0;
|
||||
struct APInfoS apInfo;
|
||||
|
||||
volatile ApSerialState gSerialTaskState;
|
||||
|
||||
struct rxCmd {
|
||||
uint8_t* data;
|
||||
uint8_t len;
|
||||
@@ -150,12 +157,28 @@ void setAPstate(bool isOnline, uint8_t state) {
|
||||
CRGB::Red,
|
||||
CRGB::YellowGreen};
|
||||
rgbIdleColor = colorMap[state];
|
||||
#ifdef BLE_ONLY
|
||||
rgbIdleColor = CRGB::Green;
|
||||
#endif
|
||||
#ifdef BLE_ONLY
|
||||
rgbIdleColor = CRGB::Green;
|
||||
#endif
|
||||
rgbIdlePeriod = (isOnline ? 767 : 255);
|
||||
if (isOnline) rgbIdle();
|
||||
#endif
|
||||
#ifdef FLASHER_DEBUG_SHARED
|
||||
// Flasher shares port with AP comms
|
||||
if (state == AP_STATE_FLASHING) {
|
||||
LOG("Shared COM port, gSerialTaskState %d\n", gSerialTaskState);
|
||||
gSerialTaskState = SERIAL_STATE_STOP;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
vTaskDelay(1 / portTICK_RATE_MS);
|
||||
if (gSerialTaskState == SERIAL_STATE_STOPPED) {
|
||||
gSerialTaskState = SERIAL_STATE_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOG("gSerialTaskState %d\n", gSerialTaskState);
|
||||
}
|
||||
#endif
|
||||
wsSendSysteminfo();
|
||||
}
|
||||
|
||||
// Reset the tag
|
||||
@@ -384,46 +407,49 @@ void rxCmdProcessor(void* parameter) {
|
||||
txActive = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(txActive);
|
||||
while (1) {
|
||||
struct rxCmd* rxcmd = nullptr;
|
||||
BaseType_t q = xQueueReceive(rxCmdQueue, &rxcmd, 10);
|
||||
if (q == pdTRUE) {
|
||||
switch (rxcmd->type) {
|
||||
case RX_CMD_RQB:
|
||||
processBlockRequest((struct espBlockRequest*)rxcmd->data);
|
||||
if (apInfo.isOnline) {
|
||||
struct rxCmd* rxcmd = nullptr;
|
||||
BaseType_t q = xQueueReceive(rxCmdQueue, &rxcmd, 10);
|
||||
if (q == pdTRUE) {
|
||||
switch (rxcmd->type) {
|
||||
case RX_CMD_RQB:
|
||||
processBlockRequest((struct espBlockRequest*)rxcmd->data);
|
||||
#ifdef HAS_RGB_LED
|
||||
// shortBlink(CRGB::Blue);
|
||||
// shortBlink(CRGB::Blue);
|
||||
#endif
|
||||
quickBlink(3);
|
||||
break;
|
||||
case RX_CMD_ADR:
|
||||
processDataReq((struct espAvailDataReq*)rxcmd->data, true);
|
||||
quickBlink(3);
|
||||
break;
|
||||
case RX_CMD_ADR:
|
||||
processDataReq((struct espAvailDataReq*)rxcmd->data, true);
|
||||
#ifdef HAS_RGB_LED
|
||||
// shortBlink(CRGB::Aqua);
|
||||
// shortBlink(CRGB::Aqua);
|
||||
#endif
|
||||
quickBlink(1);
|
||||
break;
|
||||
case RX_CMD_XFC:
|
||||
processXferComplete((struct espXferComplete*)rxcmd->data, true);
|
||||
quickBlink(1);
|
||||
break;
|
||||
case RX_CMD_XFC:
|
||||
processXferComplete((struct espXferComplete*)rxcmd->data, true);
|
||||
#ifdef HAS_RGB_LED
|
||||
// shortBlink(CRGB::Purple);
|
||||
// shortBlink(CRGB::Purple);
|
||||
#endif
|
||||
break;
|
||||
case RX_CMD_XTO:
|
||||
processXferTimeout((struct espXferComplete*)rxcmd->data, true);
|
||||
break;
|
||||
case RX_CMD_RSET:
|
||||
Serial.println("AP did reset, resending pending\r\n");
|
||||
refreshAllPending();
|
||||
sendChannelPower(&curChannel);
|
||||
break;
|
||||
case RX_CMD_TRD:
|
||||
// received tag return data
|
||||
processTagReturnData((struct espTagReturnData*)rxcmd->data, rxcmd->len, true);
|
||||
break;
|
||||
break;
|
||||
case RX_CMD_XTO:
|
||||
processXferTimeout((struct espXferComplete*)rxcmd->data, true);
|
||||
break;
|
||||
case RX_CMD_RSET:
|
||||
Serial.println("AP did reset, resending pending\r\n");
|
||||
refreshAllPending();
|
||||
sendChannelPower(&curChannel);
|
||||
break;
|
||||
case RX_CMD_TRD:
|
||||
// received tag return data
|
||||
processTagReturnData((struct espTagReturnData*)rxcmd->data, rxcmd->len, true);
|
||||
break;
|
||||
}
|
||||
if (rxcmd->data) free(rxcmd->data);
|
||||
if (rxcmd) free(rxcmd);
|
||||
}
|
||||
if (rxcmd->data) free(rxcmd->data);
|
||||
if (rxcmd) free(rxcmd);
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
void rxSerialTask(void* parameter) {
|
||||
@@ -435,7 +461,9 @@ void rxSerialTask(void* parameter) {
|
||||
static char lastchar = 0;
|
||||
static uint8_t charindex = 0;
|
||||
|
||||
while (1) {
|
||||
gSerialTaskState = SERIAL_STATE_RUNNING;
|
||||
LOG("rxSerialTask starting\n");
|
||||
while (gSerialTaskState == SERIAL_STATE_RUNNING) {
|
||||
while (AP_SERIAL_PORT.available()) {
|
||||
lastchar = AP_SERIAL_PORT.read();
|
||||
switch (RXState) {
|
||||
@@ -506,8 +534,8 @@ void rxSerialTask(void* parameter) {
|
||||
packetp = (uint8_t*)calloc(sizeof(struct espBlockRequest) + 8, 1);
|
||||
memset(cmdbuffer, 0x00, 4);
|
||||
lastAPActivity = millis();
|
||||
if (apInfo.isOnline == false)
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
// don't set APstate heree, as it interferes with the flashing process
|
||||
// if (apInfo.isOnline == false && config.runStatus == RUNSTATUS_RUN) setAPstate(true, AP_STATE_ONLINE);
|
||||
}
|
||||
if (strncmp(cmdbuffer, "ADR>", 4) == 0) {
|
||||
RXState = ZBS_RX_WAIT_DATA_REQ;
|
||||
@@ -516,8 +544,8 @@ void rxSerialTask(void* parameter) {
|
||||
packetp = (uint8_t*)calloc(sizeof(struct espAvailDataReq) + 8, 1);
|
||||
memset(cmdbuffer, 0x00, 4);
|
||||
lastAPActivity = millis();
|
||||
if (apInfo.isOnline == false)
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
// don't set APstate heree, as it interferes with the flashing process
|
||||
// if (apInfo.isOnline == false && config.runStatus == RUNSTATUS_RUN) setAPstate(true, AP_STATE_ONLINE);
|
||||
}
|
||||
if (strncmp(cmdbuffer, "XFC>", 4) == 0) {
|
||||
RXState = ZBS_RX_WAIT_XFERCOMPLETE;
|
||||
@@ -540,8 +568,6 @@ void rxSerialTask(void* parameter) {
|
||||
packetp = (uint8_t*)calloc(sizeof(struct espTagReturnData) + 8, 1);
|
||||
memset(cmdbuffer, 0x00, 4);
|
||||
lastAPActivity = millis();
|
||||
if (apInfo.isOnline == false)
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
}
|
||||
break;
|
||||
case ZBS_RX_BLOCK_REQUEST:
|
||||
@@ -666,10 +692,26 @@ void rxSerialTask(void* parameter) {
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
} // end of while(1)
|
||||
|
||||
AP_SERIAL_PORT.end();
|
||||
gSerialTaskState = SERIAL_STATE_STOPPED;
|
||||
LOG("rxSerialTask stopped\n");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
#if defined(FLASHER_DEBUG_RXD) && !defined(FLASHER_DEBUG_SHARED)
|
||||
uint32_t millisDiff(uint32_t m) {
|
||||
uint32_t ms = millis();
|
||||
if (ms >= m)
|
||||
return ms - m;
|
||||
else
|
||||
return UINT32_MAX - m + ms + 1;
|
||||
}
|
||||
|
||||
#ifdef FLASHER_DEBUG_RXD
|
||||
void rxSerialTask2(void* parameter) {
|
||||
char rxStr[100] = {0};
|
||||
int rxStrCount = 0;
|
||||
uint32_t modemResetHoldoff = millis();
|
||||
char lastchar = 0;
|
||||
time_t startTime = millis();
|
||||
int charCount = 0;
|
||||
@@ -681,6 +723,33 @@ void rxSerialTask2(void* parameter) {
|
||||
|
||||
// debug info
|
||||
Serial.write(lastchar);
|
||||
|
||||
rxStr[rxStrCount] = lastchar;
|
||||
if (lastchar == '\n' || lastchar == '\r') {
|
||||
if (strncmp(rxStr, "receive buffer full, drop the current frame", 43) == 0 && millisDiff(modemResetHoldoff) > 20000) {
|
||||
modemResetHoldoff = millis();
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
config.runStatus = RUNSTATUS_STOP;
|
||||
Serial.println("IEEE802.15.4 modem stuck case detected, resetting...");
|
||||
APTagReset();
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
Serial.println("bringing AP online again");
|
||||
if (bringAPOnline()) {
|
||||
config.runStatus = RUNSTATUS_RUN;
|
||||
Serial.println("Finished!");
|
||||
} else {
|
||||
Serial.println("Failed!");
|
||||
}
|
||||
logLine("IEEE802.15.4 modem reset " + (config.runStatus == RUNSTATUS_RUN) ? ("ok") : ("failed"));
|
||||
}
|
||||
rxStrCount = 0;
|
||||
memset(rxStr, 0, sizeof(rxStr));
|
||||
} else if (rxStrCount < sizeof(rxStr) - 2) {
|
||||
rxStrCount++;
|
||||
} else {
|
||||
rxStrCount = 0;
|
||||
memset(rxStr, 0, sizeof(rxStr));
|
||||
}
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
|
||||
@@ -688,7 +757,7 @@ void rxSerialTask2(void* parameter) {
|
||||
if (currentTime - startTime >= 1000) {
|
||||
if (charCount > 6000) {
|
||||
rxSerialStopTask2 = true;
|
||||
Serial.println("Serial monitor stopped because of flooding (" + String(charCount) + " characters per second");
|
||||
Serial.println("Serial monitor stopped because of flooding (" + String(charCount) + " characters per second)");
|
||||
}
|
||||
startTime = currentTime;
|
||||
charCount = 0;
|
||||
@@ -746,12 +815,36 @@ void segmentedShowIp() {
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
bool bringAPOnline() {
|
||||
#ifdef BLE_ONLY
|
||||
bool bringAPOnline(uint8_t newState) {
|
||||
#ifdef BLE_ONLY
|
||||
apInfo.state = AP_STATE_NORADIO;
|
||||
#endif
|
||||
#endif
|
||||
if (apInfo.state == AP_STATE_NORADIO) return true;
|
||||
if (apInfo.state == AP_STATE_FLASHING) return false;
|
||||
|
||||
if (gSerialTaskState != SERIAL_STATE_INITIALIZED) {
|
||||
#ifdef HAS_ELECROW_ADV_2_8
|
||||
// Set GPIO45 low to connect the wireless interface to the multiplexed pins
|
||||
pinMode(45, OUTPUT);
|
||||
digitalWrite(45, LOW);
|
||||
#endif
|
||||
|
||||
#if (AP_PROCESS_PORT == FLASHER_AP_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#elif defined(HAS_EXT_FLASHER)
|
||||
#if (AP_PROCESS_PORT == FLASHER_EXT_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD);
|
||||
#elif (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#endif
|
||||
#endif
|
||||
gSerialTaskState = SERIAL_STATE_INITIALIZED;
|
||||
}
|
||||
if (gSerialTaskState != SERIAL_STATE_RUNNING) {
|
||||
gSerialTaskState = SERIAL_STATE_STARTING;
|
||||
xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL);
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
setAPstate(false, AP_STATE_OFFLINE);
|
||||
// try without rebooting
|
||||
AP_SERIAL_PORT.updateBaudRate(115200);
|
||||
@@ -788,18 +881,18 @@ bool bringAPOnline() {
|
||||
}
|
||||
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
setAPstate(newState == AP_STATE_ONLINE ? true : false, newState);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool checkRadio() {
|
||||
#ifdef BLE_ONLY
|
||||
#ifdef BLE_ONLY
|
||||
return false;
|
||||
#endif
|
||||
#ifndef C6_OTA_FLASHING
|
||||
#endif
|
||||
#ifndef C6_OTA_FLASHING
|
||||
return true;
|
||||
#endif
|
||||
#endif
|
||||
// make a short between FLASHER_AP_TXD and FLASHER_AP_RXD to indicate that no radio is present
|
||||
// e.g. for flasher only, or just to use the S3 to generate images for smaller AP's
|
||||
pinMode(FLASHER_AP_TXD, OUTPUT);
|
||||
@@ -823,25 +916,11 @@ void APTask(void* parameter) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if (AP_PROCESS_PORT == FLASHER_AP_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#endif
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
#if (AP_PROCESS_PORT == FLASHER_EXT_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD);
|
||||
#endif
|
||||
#if (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
xTaskCreate(rxCmdProcessor, "rxCmdProcessor", 6000, NULL, 15, NULL);
|
||||
xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL);
|
||||
#ifdef FLASHER_DEBUG_RXD
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1750, NULL, 2, NULL);
|
||||
#endif
|
||||
|
||||
#if defined(FLASHER_DEBUG_RXD) && !defined(FLASHER_DEBUG_SHARED)
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1850, NULL, 2, NULL);
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
#endif
|
||||
bringAPOnline();
|
||||
|
||||
#ifndef C6_OTA_FLASHING
|
||||
@@ -876,7 +955,7 @@ void APTask(void* parameter) {
|
||||
if (FLASHER_AP_MOSI != -1) {
|
||||
fsversion = getAPUpdateVersion(apInfo.type);
|
||||
if ((fsversion) && (apInfo.version != fsversion)) {
|
||||
Serial.printf("Firmware version on LittleFS: %04X\r\n", fsversion);
|
||||
Serial.printf("Firmware version on FS: %04X\r\n", fsversion);
|
||||
|
||||
Serial.printf("We're going to try to update the AP's FW in\r\n");
|
||||
flashCountDown(30);
|
||||
|
||||
@@ -2,22 +2,63 @@
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
#include "FS.h"
|
||||
#ifdef SD_CARD_SDMMC
|
||||
#include "SD_MMC.h"
|
||||
#define SDCARD SD_MMC
|
||||
#else
|
||||
#include "SD.h"
|
||||
#include "SPI.h"
|
||||
#define SDCARD SD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SD_CARD_ONLY
|
||||
#include "LittleFS.h"
|
||||
#endif
|
||||
|
||||
DynStorage::DynStorage() : isInited(0) {}
|
||||
|
||||
SemaphoreHandle_t fsMutex;
|
||||
SemaphoreHandle_t fsMutex = NULL;
|
||||
|
||||
#ifndef SD_CARD_ONLY
|
||||
static void initLittleFS() {
|
||||
LittleFS.begin();
|
||||
contentFS = &LittleFS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
static bool sd_init_done = false;
|
||||
#ifdef SD_CARD_SDMMC
|
||||
static void initSDCard() {
|
||||
if(!SD_MMC.begin("/sdcard", true, true, BOARD_MAX_SDMMC_FREQ, 5)){
|
||||
Serial.println("Card Mount Failed");
|
||||
return;
|
||||
}
|
||||
uint8_t cardType = SD_MMC.cardType();
|
||||
|
||||
if(cardType == CARD_NONE){
|
||||
Serial.println("No SD_MMC card attached");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("SD_MMC Card Type: ");
|
||||
if(cardType == CARD_MMC){
|
||||
Serial.println("MMC");
|
||||
} else if(cardType == CARD_SD){
|
||||
Serial.println("SDSC");
|
||||
} else if(cardType == CARD_SDHC){
|
||||
Serial.println("SDHC");
|
||||
} else {
|
||||
Serial.println("UNKNOWN");
|
||||
}
|
||||
|
||||
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
|
||||
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
|
||||
|
||||
contentFS = &SD_MMC;
|
||||
}
|
||||
#else
|
||||
static SPIClass* spi;
|
||||
|
||||
static void initSDCard() {
|
||||
@@ -45,15 +86,19 @@ static void initSDCard() {
|
||||
contentFS = &SD;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint64_t DynStorage::freeSpace(){
|
||||
this->begin();
|
||||
#ifdef HAS_SDCARD
|
||||
return SD.totalBytes() - SD.usedBytes();
|
||||
return SDCARD.totalBytes() - SDCARD.usedBytes();
|
||||
#endif
|
||||
#ifndef SD_CARD_ONLY
|
||||
return LittleFS.totalBytes() - LittleFS.usedBytes();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef SD_CARD_ONLY
|
||||
void copyFile(File in, File out) {
|
||||
Serial.print("Copying ");
|
||||
Serial.print(in.path());
|
||||
@@ -127,14 +172,25 @@ void copyIfNeeded(const char* path) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void DynStorage::begin() {
|
||||
fsMutex = xSemaphoreCreateMutex();
|
||||
if(fsMutex == NULL) {
|
||||
fsMutex = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
#ifndef SD_CARD_ONLY
|
||||
initLittleFS();
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
initSDCard();
|
||||
|
||||
if(!sd_init_done) {
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
initSDCard();
|
||||
xSemaphoreGive(fsMutex);
|
||||
sd_init_done = true;
|
||||
}
|
||||
#ifndef SD_CARD_ONLY
|
||||
copyIfNeeded("/index.html");
|
||||
copyIfNeeded("/fonts");
|
||||
copyIfNeeded("/www");
|
||||
@@ -143,6 +199,7 @@ void DynStorage::begin() {
|
||||
copyIfNeeded("/tag_md5_db.json");
|
||||
copyIfNeeded("/update_actions.json");
|
||||
copyIfNeeded("/content_template.json");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!contentFS->exists("/current")) {
|
||||
@@ -155,7 +212,17 @@ void DynStorage::begin() {
|
||||
|
||||
void DynStorage::end() {
|
||||
#ifdef HAS_SDCARD
|
||||
#ifndef SD_CARD_ONLY
|
||||
initLittleFS();
|
||||
#endif
|
||||
#ifdef SD_CARD_SDMMC
|
||||
#ifndef SD_CARD_ONLY
|
||||
contentFS = &LittleFS;
|
||||
#endif
|
||||
SD_MMC.end();
|
||||
sd_init_done = false;
|
||||
#else
|
||||
#ifndef SD_CARD_ONLY
|
||||
if (SD_CARD_CLK == FLASHER_AP_CLK ||
|
||||
SD_CARD_MISO == FLASHER_AP_MISO ||
|
||||
SD_CARD_MOSI == FLASHER_AP_MOSI) {
|
||||
@@ -171,7 +238,8 @@ void DynStorage::end() {
|
||||
|
||||
contentFS = &LittleFS;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ void timeSyncCallback(struct timeval* tv) {
|
||||
}
|
||||
|
||||
void initTime(void* parameter) {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
if (!(WiFi.status() == WL_CONNECTED || wm.wifiStatus == ETHERNET)) {
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
sntp_set_time_sync_notification_cb(timeSyncCallback);
|
||||
|
||||
@@ -67,25 +67,24 @@ bool hex2mac(const String& hexString, uint8_t* mac) {
|
||||
}
|
||||
|
||||
String tagDBtoJson(const uint8_t mac[8], uint8_t startPos) {
|
||||
DynamicJsonDocument doc(5000);
|
||||
JsonArray tags = doc.createNestedArray("tags");
|
||||
JsonDocument doc;
|
||||
JsonArray tags = doc["tags"].to<JsonArray>();
|
||||
|
||||
for (uint32_t c = startPos; c < tagDB.size(); ++c) {
|
||||
const tagRecord* taginfo = tagDB.at(c);
|
||||
|
||||
const bool select = !mac || memcmp(taginfo->mac, mac, 8) == 0;
|
||||
if (select && taginfo->version == 0) {
|
||||
JsonObject tag = tags.createNestedObject();
|
||||
JsonObject tag = tags.add<JsonObject>();
|
||||
fillNode(tag, taginfo);
|
||||
if (measureJson(doc) > 5000) {
|
||||
doc["continu"] = c + 1;
|
||||
break;
|
||||
}
|
||||
if (mac) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.capacity() - doc.memoryUsage() < doc.memoryUsage() / (c + 1) + 500) {
|
||||
doc["continu"] = c + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return doc.as<String>();
|
||||
@@ -126,7 +125,7 @@ void fillNode(JsonObject& tag, const tagRecord* taginfo) {
|
||||
}
|
||||
|
||||
void saveDB(const String& filename) {
|
||||
DynamicJsonDocument doc(2500);
|
||||
JsonDocument doc;
|
||||
|
||||
const long t = millis();
|
||||
|
||||
@@ -138,8 +137,10 @@ void saveDB(const String& filename) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
String backupFilename = filename + ".bak";
|
||||
if (!contentFS->rename(filename.c_str(), backupFilename.c_str())) {
|
||||
xSemaphoreGive(fsMutex);
|
||||
logLine("error renaming tagDB to .bak");
|
||||
wsErr("error renaming tagDB to .bak");
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ void saveDB(const String& filename) {
|
||||
doc.clear();
|
||||
|
||||
if (taginfo->version == 0) {
|
||||
JsonObject tag = doc.createNestedObject();
|
||||
JsonObject tag = doc.add<JsonObject>();
|
||||
fillNode(tag, taginfo);
|
||||
if (c > 0) {
|
||||
file.write(',');
|
||||
@@ -186,7 +187,7 @@ bool loadDB(const String& filename) {
|
||||
bool parsing = true;
|
||||
|
||||
if (readfile.find("[")) {
|
||||
DynamicJsonDocument doc(1000);
|
||||
JsonDocument doc;
|
||||
while (parsing) {
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
@@ -210,7 +211,7 @@ bool loadDB(const String& filename) {
|
||||
taginfo->nextupdate = (uint32_t)tag["nextupdate"];
|
||||
taginfo->expectedNextCheckin = (uint32_t)tag["nextcheckin"];
|
||||
if (taginfo->expectedNextCheckin < now) {
|
||||
taginfo->expectedNextCheckin = now + 1800;
|
||||
taginfo->expectedNextCheckin = now + 60;
|
||||
}
|
||||
taginfo->pendingCount = 0;
|
||||
taginfo->alias = tag["alias"].as<String>();
|
||||
@@ -279,11 +280,11 @@ uint32_t getTagCount(uint32_t& timeoutcount, uint32_t& lowbattcount) {
|
||||
if (!taginfo->isExternal) tagcount++;
|
||||
const int32_t timeout = now - taginfo->lastseen;
|
||||
if (taginfo->expectedNextCheckin < 3600) {
|
||||
// not initialised, timeout if not seen last 10 minutes
|
||||
if (timeout > 600) timeoutcount++;
|
||||
} else if (now - taginfo->expectedNextCheckin > 600) {
|
||||
// expected checkin is behind, timeout if not seen last 10 minutes
|
||||
if (timeout > 600) timeoutcount++;
|
||||
// not initialised, timeout if not seen last 5 minutes
|
||||
if (timeout > config.maxsleep * 60 + 300) timeoutcount++;
|
||||
} else if (now - static_cast<time_t>(taginfo->expectedNextCheckin) > 600) {
|
||||
// expected checkin is behind, timeout if not seen last 5 minutes
|
||||
if (timeout > config.maxsleep * 60 + 300) timeoutcount++;
|
||||
}
|
||||
if (taginfo->batteryMv < 2400 && taginfo->batteryMv != 0 && taginfo->batteryMv != 1337) lowbattcount++;
|
||||
}
|
||||
@@ -308,7 +309,7 @@ void clearPending(tagRecord* taginfo) {
|
||||
}
|
||||
|
||||
void initAPconfig() {
|
||||
DynamicJsonDocument APconfig(768);
|
||||
JsonDocument APconfig;
|
||||
File configFile = contentFS->open("/current/apconfig.json", "r");
|
||||
if (configFile) {
|
||||
DeserializationError error = deserializeJson(APconfig, configFile);
|
||||
@@ -319,29 +320,30 @@ void initAPconfig() {
|
||||
}
|
||||
configFile.close();
|
||||
}
|
||||
config.channel = APconfig.containsKey("channel") ? APconfig["channel"] : 0;
|
||||
config.subghzchannel = APconfig.containsKey("subghzchannel") ? APconfig["subghzchannel"] : 0;
|
||||
config.channel = APconfig["channel"].is<uint8_t>() ? APconfig["channel"] : 0;
|
||||
config.subghzchannel = APconfig["subghzchannel"].is<uint8_t>() ? APconfig["subghzchannel"] : 0;
|
||||
if (APconfig["alias"]) strlcpy(config.alias, APconfig["alias"], sizeof(config.alias));
|
||||
config.led = APconfig.containsKey("led") ? APconfig["led"] : 255;
|
||||
config.tft = APconfig.containsKey("tft") ? APconfig["tft"] : 255;
|
||||
config.language = APconfig.containsKey("language") ? APconfig["language"] : 0;
|
||||
config.maxsleep = APconfig.containsKey("maxsleep") ? APconfig["maxsleep"] : 10;
|
||||
config.stopsleep = APconfig.containsKey("stopsleep") ? APconfig["stopsleep"] : 1;
|
||||
config.preview = APconfig.containsKey("preview") ? APconfig["preview"] : 1;
|
||||
config.nightlyreboot = APconfig.containsKey("nightlyreboot") ? APconfig["nightlyreboot"] : 1;
|
||||
config.lock = APconfig.containsKey("lock") ? APconfig["lock"] : 0;
|
||||
config.sleepTime1 = APconfig.containsKey("sleeptime1") ? APconfig["sleeptime1"] : 0;
|
||||
config.sleepTime2 = APconfig.containsKey("sleeptime2") ? APconfig["sleeptime2"] : 0;
|
||||
config.ble = APconfig.containsKey("ble") ? APconfig["ble"] : 0;
|
||||
config.discovery = APconfig.containsKey("discovery") ? APconfig["discovery"] : 0;
|
||||
config.led = APconfig["led"].is<uint8_t>() ? APconfig["led"] : 255;
|
||||
config.tft = APconfig["tft"].is<uint8_t>() ? APconfig["tft"] : 255;
|
||||
config.language = APconfig["language"].is<uint8_t>() ? APconfig["language"] : 0;
|
||||
config.maxsleep = APconfig["maxsleep"].is<uint8_t>() ? APconfig["maxsleep"] : 10;
|
||||
config.stopsleep = APconfig["stopsleep"].is<uint8_t>() ? APconfig["stopsleep"] : 1;
|
||||
config.preview = APconfig["preview"].is<uint8_t>() ? APconfig["preview"] : 1;
|
||||
config.nightlyreboot = APconfig["nightlyreboot"].is<uint8_t>() ? APconfig["nightlyreboot"] : 1;
|
||||
config.lock = APconfig["lock"].is<uint8_t>() ? APconfig["lock"] : 0;
|
||||
config.sleepTime1 = APconfig["sleeptime1"].is<uint8_t>() ? APconfig["sleeptime1"] : 0;
|
||||
config.sleepTime2 = APconfig["sleeptime2"].is<uint8_t>() ? APconfig["sleeptime2"] : 0;
|
||||
config.ble = APconfig["ble"].is<uint8_t>() ? APconfig["ble"] : 0;
|
||||
config.discovery = APconfig["discovery"].is<uint8_t>() ? APconfig["discovery"] : 0;
|
||||
config.showtimestamp = APconfig["showtimestamp"].is<uint8_t>() ? APconfig["showtimestamp"] : 0;
|
||||
#ifdef BLE_ONLY
|
||||
config.ble = true;
|
||||
config.ble = true;
|
||||
#endif
|
||||
// default wifi power 8.5 dbM
|
||||
// see https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFiGeneric.h#L111
|
||||
config.wifiPower = APconfig.containsKey("wifipower") ? APconfig["wifipower"] : 34;
|
||||
config.repo = APconfig.containsKey("repo") ? APconfig["repo"].as<String>() : String("OpenEPaperLink/OpenEPaperLink");
|
||||
config.env = APconfig.containsKey("env") ? APconfig["env"].as<String>() : String(STR(BUILD_ENV_NAME));
|
||||
config.wifiPower = APconfig["wifipower"].is<uint8_t>() ? APconfig["wifipower"] : 34;
|
||||
config.repo = APconfig["repo"].is<String>() ? APconfig["repo"].as<String>() : String("OpenEPaperLink/OpenEPaperLink");
|
||||
config.env = APconfig["env"].is<String>() ? APconfig["env"].as<String>() : String(STR(BUILD_ENV_NAME));
|
||||
if (APconfig["timezone"]) {
|
||||
strlcpy(config.timeZone, APconfig["timezone"], sizeof(config.timeZone));
|
||||
} else {
|
||||
@@ -352,7 +354,7 @@ void initAPconfig() {
|
||||
void saveAPconfig() {
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
fs::File configFile = contentFS->open("/current/apconfig.json", "w");
|
||||
DynamicJsonDocument APconfig(500);
|
||||
JsonDocument APconfig;
|
||||
APconfig["channel"] = config.channel;
|
||||
APconfig["subghzchannel"] = config.subghzchannel;
|
||||
APconfig["alias"] = config.alias;
|
||||
@@ -372,6 +374,7 @@ void saveAPconfig() {
|
||||
APconfig["repo"] = config.repo;
|
||||
APconfig["env"] = config.env;
|
||||
APconfig["discovery"] = config.discovery;
|
||||
APconfig["showtimestamp"] = config.showtimestamp;
|
||||
serializeJsonPretty(APconfig, configFile);
|
||||
configFile.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
@@ -388,7 +391,7 @@ HwType getHwType(const uint8_t id) {
|
||||
File jsonFile = contentFS->open(filename, "r");
|
||||
|
||||
if (jsonFile) {
|
||||
StaticJsonDocument<150> filter;
|
||||
JsonDocument filter;
|
||||
filter["width"] = true;
|
||||
filter["height"] = true;
|
||||
filter["rotatebuffer"] = true;
|
||||
@@ -398,7 +401,7 @@ HwType getHwType(const uint8_t id) {
|
||||
filter["g5_compression"] = true;
|
||||
filter["highlight_color"] = true;
|
||||
filter["colortable"] = true;
|
||||
StaticJsonDocument<1000> doc;
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, jsonFile, DeserializationOption::Filter(filter));
|
||||
jsonFile.close();
|
||||
if (error) {
|
||||
@@ -412,17 +415,17 @@ HwType getHwType(const uint8_t id) {
|
||||
hwType.rotatebuffer = doc["rotatebuffer"];
|
||||
hwType.bpp = doc["bpp"];
|
||||
hwType.shortlut = doc["shortlut"];
|
||||
if (doc.containsKey("zlib_compression")) {
|
||||
if (doc["zlib_compression"].is<const char*>()) {
|
||||
hwType.zlib = strtol(doc["zlib_compression"], nullptr, 16);
|
||||
} else {
|
||||
hwType.zlib = 0;
|
||||
}
|
||||
if (doc.containsKey("g5_compression")) {
|
||||
if (doc["g5_compression"].is<const char*>()) {
|
||||
hwType.g5 = strtol(doc["g5_compression"], nullptr, 16);
|
||||
} else {
|
||||
hwType.g5 = 0;
|
||||
}
|
||||
hwType.highlightColor = doc.containsKey("highlight_color") ? doc["highlight_color"].as<uint16_t>() : 2;
|
||||
hwType.highlightColor = doc["highlight_color"].is<uint16_t>() ? doc["highlight_color"].as<uint16_t>() : 2;
|
||||
JsonObject colorTable = doc["colortable"];
|
||||
for (auto kv : colorTable) {
|
||||
JsonArray color = kv.value();
|
||||
|
||||
@@ -10,6 +10,9 @@ std::unordered_map<size_t, TagData::Parser> TagData::parsers = {};
|
||||
void TagData::loadParsers(const String& filename) {
|
||||
const long start = millis();
|
||||
|
||||
if (!contentFS->exists(filename)) {
|
||||
return;
|
||||
}
|
||||
fs::File file = contentFS->open(filename, "r");
|
||||
if (!file) {
|
||||
return;
|
||||
@@ -17,7 +20,7 @@ void TagData::loadParsers(const String& filename) {
|
||||
Serial.println("Reading parsers from file");
|
||||
|
||||
if (file.find("[")) {
|
||||
DynamicJsonDocument doc(1000);
|
||||
JsonDocument doc;
|
||||
bool parsing = true;
|
||||
while (parsing) {
|
||||
DeserializationError err = deserializeJson(doc, file);
|
||||
@@ -145,4 +148,4 @@ void TagData::parse(const uint8_t src[8], const size_t id, const uint8_t* data,
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "serialap.h"
|
||||
#include "tag_db.h"
|
||||
#include "web.h"
|
||||
#include "wifimanager.h"
|
||||
|
||||
#define UDPIP IPAddress(239, 10, 0, 1)
|
||||
#define UDPPORT 16033
|
||||
@@ -34,7 +35,7 @@ void UDPcomm::init() {
|
||||
if (config.discovery == 0) {
|
||||
if (udp.listenMulticast(UDPIP, UDPPORT)) {
|
||||
udp.onPacket([this](AsyncUDPPacket packet) {
|
||||
if (packet.remoteIP() != WiFi.localIP()) {
|
||||
if (packet.remoteIP() != wm.localIP()) {
|
||||
this->processPacket(packet);
|
||||
}
|
||||
});
|
||||
@@ -42,7 +43,7 @@ void UDPcomm::init() {
|
||||
} else {
|
||||
if (udp.listen(UDPPORT)) {
|
||||
udp.onPacket([this](AsyncUDPPacket packet) {
|
||||
if (packet.isBroadcast() && packet.remoteIP() != WiFi.localIP()) {
|
||||
if (packet.isBroadcast() && packet.remoteIP() != wm.localIP()) {
|
||||
this->processPacket(packet);
|
||||
}
|
||||
});
|
||||
@@ -88,7 +89,7 @@ void UDPcomm::processPacket(AsyncUDPPacket packet) {
|
||||
}
|
||||
case PKT_APLIST_REQ: {
|
||||
APlist APitem;
|
||||
APitem.src = WiFi.localIP();
|
||||
APitem.src = wm.localIP();
|
||||
strcpy(APitem.alias, config.alias);
|
||||
APitem.channelId = curChannel.channel;
|
||||
APitem.tagCount = getTagCount();
|
||||
@@ -154,7 +155,7 @@ void autoselect(void* pvParameters) {
|
||||
|
||||
void UDPcomm::getAPList() {
|
||||
APlist APitem;
|
||||
APitem.src = WiFi.localIP();
|
||||
APitem.src = wm.localIP();
|
||||
strcpy(APitem.alias, config.alias);
|
||||
APitem.channelId = curChannel.channel;
|
||||
APitem.tagCount = getTagCount();
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#include "webflasher.h"
|
||||
#endif
|
||||
|
||||
extern uint8_t data_to_send[];
|
||||
|
||||
AsyncWebServer server(80);
|
||||
AsyncWebSocket ws("/ws");
|
||||
WifiManager wm;
|
||||
@@ -41,7 +39,7 @@ SemaphoreHandle_t wsMutex;
|
||||
uint32_t lastssidscan = 0;
|
||||
|
||||
void wsLog(const String &text) {
|
||||
StaticJsonDocument<250> doc;
|
||||
JsonDocument doc;
|
||||
doc["logMsg"] = text;
|
||||
if (wsMutex) xSemaphoreTake(wsMutex, portMAX_DELAY);
|
||||
ws.textAll(doc.as<String>());
|
||||
@@ -49,7 +47,7 @@ void wsLog(const String &text) {
|
||||
}
|
||||
|
||||
void wsErr(const String &text) {
|
||||
StaticJsonDocument<250> doc;
|
||||
JsonDocument doc;
|
||||
doc["errMsg"] = text;
|
||||
if (wsMutex) xSemaphoreTake(wsMutex, portMAX_DELAY);
|
||||
ws.textAll(doc.as<String>());
|
||||
@@ -68,8 +66,8 @@ size_t dbSize() {
|
||||
}
|
||||
|
||||
void wsSendSysteminfo() {
|
||||
DynamicJsonDocument doc(300);
|
||||
JsonObject sys = doc.createNestedObject("sys");
|
||||
JsonDocument doc;
|
||||
JsonObject sys = doc["sys"].to<JsonObject>();
|
||||
time_t now;
|
||||
time(&now);
|
||||
static int freeSpaceLastRun = 0;
|
||||
@@ -109,7 +107,7 @@ void wsSendSysteminfo() {
|
||||
strftime(timeBuffer, sizeof(timeBuffer), languageDateFormat[0].c_str(), &timeinfo);
|
||||
setVarDB("ap_date", timeBuffer);
|
||||
}
|
||||
setVarDB("ap_ip", WiFi.localIP().toString());
|
||||
setVarDB("ap_ip", wm.localIP().toString());
|
||||
|
||||
#ifdef HAS_SUBGHZ
|
||||
String ApChanString = String(apInfo.channel);
|
||||
@@ -208,8 +206,8 @@ void wsSendTaginfo(const uint8_t *mac, uint8_t syncMode) {
|
||||
}
|
||||
|
||||
void wsSendAPitem(struct APlist *apitem) {
|
||||
DynamicJsonDocument doc(250);
|
||||
JsonObject ap = doc.createNestedObject("apitem");
|
||||
JsonDocument doc;
|
||||
JsonObject ap = doc["apitem"].to<JsonObject>();
|
||||
|
||||
char version_str[6];
|
||||
sprintf(version_str, "%04X", apitem->version);
|
||||
@@ -230,7 +228,7 @@ void wsSerial(const String &text) {
|
||||
}
|
||||
|
||||
void wsSerial(const String &text, const String &color) {
|
||||
StaticJsonDocument<250> doc;
|
||||
JsonDocument doc;
|
||||
doc["console"] = text;
|
||||
if (!color.isEmpty()) doc["color"] = color;
|
||||
Serial.println(text);
|
||||
@@ -324,7 +322,7 @@ void init_web() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
request->send_P(200, "application/octet-stream", queueItem->data, queueItem->len);
|
||||
request->send(200, "application/octet-stream", queueItem->data, queueItem->len);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -338,7 +336,7 @@ void init_web() {
|
||||
taginfo->data = getDataForFile(file);
|
||||
file.close();
|
||||
}
|
||||
request->send_P(200, "application/octet-stream", taginfo->data, taginfo->len);
|
||||
request->send(200, "application/octet-stream", taginfo->data, taginfo->len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -516,13 +514,21 @@ void init_web() {
|
||||
UDPcomm udpsync;
|
||||
udpsync.getAPList();
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
String HasC6 = "0";
|
||||
String HasH2 = "0";
|
||||
String HasTSLR = "0";
|
||||
|
||||
response->print("{");
|
||||
#ifdef C6_OTA_FLASHING
|
||||
response->print("\"C6\": \"1\", ");
|
||||
#else
|
||||
response->print("\"C6\": \"0\", ");
|
||||
#ifdef HAS_H2
|
||||
HasH2 = "1";
|
||||
#elif defined(HAS_TSLR)
|
||||
HasTSLR = "1";
|
||||
#elif defined(C6_OTA_FLASHING)
|
||||
HasC6 = "1";
|
||||
#endif
|
||||
response->print("\"C6\": \"" + HasC6 + "\", ");
|
||||
response->print("\"H2\": \"" + HasH2 + "\", ");
|
||||
response->print("\"TLSR\": \"" + HasTSLR + "\", ");
|
||||
#ifdef SAVE_SPACE
|
||||
response->print("\"savespace\": \"1\", ");
|
||||
#else
|
||||
@@ -628,6 +634,9 @@ void init_web() {
|
||||
if (request->hasParam("discovery", true)) {
|
||||
config.discovery = static_cast<uint8_t>(request->getParam("discovery", true)->value().toInt());
|
||||
}
|
||||
if (request->hasParam("showtimestamp", true)) {
|
||||
config.showtimestamp = static_cast<uint8_t>(request->getParam("showtimestamp", true)->value().toInt());
|
||||
}
|
||||
if (request->hasParam("repo", true)) {
|
||||
config.repo = request->getParam("repo", true)->value();
|
||||
}
|
||||
@@ -652,7 +661,7 @@ void init_web() {
|
||||
});
|
||||
server.on("/set_vars", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||
if (request->hasParam("json", true)) {
|
||||
DynamicJsonDocument jsonDocument(2048);
|
||||
JsonDocument jsonDocument;
|
||||
DeserializationError error = deserializeJson(jsonDocument, request->getParam("json", true)->value());
|
||||
if (error) {
|
||||
request->send(400, "text/plain", "Failed to parse JSON");
|
||||
@@ -679,7 +688,7 @@ void init_web() {
|
||||
server.on("/get_wifi_config", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
Preferences preferences;
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
StaticJsonDocument<250> doc;
|
||||
JsonDocument doc;
|
||||
preferences.begin("wifi", false);
|
||||
const char *keys[] = {"ssid", "pw", "ip", "mask", "gw", "dns"};
|
||||
const size_t numKeys = sizeof(keys) / sizeof(keys[0]);
|
||||
@@ -693,13 +702,13 @@ void init_web() {
|
||||
|
||||
server.on("/get_ssid_list", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
DynamicJsonDocument doc(5000);
|
||||
JsonDocument doc;
|
||||
|
||||
doc["scanstatus"] = WiFi.scanComplete();
|
||||
JsonArray networks = doc.createNestedArray("networks");
|
||||
JsonArray networks = doc["networks"].to<JsonArray>();
|
||||
for (int i = 0; i < (WiFi.scanComplete() > 50 ? 50 : WiFi.scanComplete()); ++i) {
|
||||
if (WiFi.SSID(i) != "") {
|
||||
JsonObject network = networks.createNestedObject();
|
||||
JsonObject network = networks.add<JsonObject>();
|
||||
network["ssid"] = WiFi.SSID(i);
|
||||
network["ch"] = WiFi.channel(i);
|
||||
network["rssi"] = WiFi.RSSI(i);
|
||||
@@ -725,7 +734,7 @@ void init_web() {
|
||||
const size_t numKeys = sizeof(keys) / sizeof(keys[0]);
|
||||
for (size_t i = 0; i < numKeys; i++) {
|
||||
String key = keys[i];
|
||||
if (jsonObj.containsKey(key)) {
|
||||
if (jsonObj[key].is<String>()) {
|
||||
preferences.putString(key.c_str(), jsonObj[key].as<String>());
|
||||
}
|
||||
}
|
||||
@@ -868,10 +877,11 @@ void doImageUpload(AsyncWebServerRequest *request, String filename, size_t index
|
||||
file.write(uploadInfo->buffer, uploadInfo->bufferSize);
|
||||
file.close();
|
||||
uploadInfo->bufferSize = 0;
|
||||
xSemaphoreGive(fsMutex);
|
||||
} else {
|
||||
xSemaphoreGive(fsMutex);
|
||||
logLine("Failed to open file for appending: " + uploadfilename);
|
||||
}
|
||||
xSemaphoreGive(fsMutex);
|
||||
|
||||
memcpy(uploadInfo->buffer, data, len);
|
||||
uploadInfo->bufferSize = len;
|
||||
@@ -885,10 +895,11 @@ void doImageUpload(AsyncWebServerRequest *request, String filename, size_t index
|
||||
if (file) {
|
||||
file.write(uploadInfo->buffer, uploadInfo->bufferSize);
|
||||
file.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
} else {
|
||||
xSemaphoreGive(fsMutex);
|
||||
logLine("Failed to open file for appending: " + uploadfilename);
|
||||
}
|
||||
xSemaphoreGive(fsMutex);
|
||||
request->_tempObject = nullptr;
|
||||
delete uploadInfo;
|
||||
}
|
||||
@@ -903,6 +914,18 @@ void doImageUpload(AsyncWebServerRequest *request, String filename, size_t index
|
||||
if (request->hasParam("dither", true)) {
|
||||
dither = request->getParam("dither", true)->value().toInt();
|
||||
}
|
||||
if (request->hasParam("alias", true)) {
|
||||
taginfo->alias = request->getParam("alias", true)->value();
|
||||
}
|
||||
if (request->hasParam("rotate", true)) {
|
||||
taginfo->rotate = atoi(request->getParam("rotate", true)->value().c_str());
|
||||
}
|
||||
if (request->hasParam("lut", true)) {
|
||||
taginfo->lut = atoi(request->getParam("lut", true)->value().c_str());
|
||||
}
|
||||
if (request->hasParam("invert", true)) {
|
||||
taginfo->invert = atoi(request->getParam("invert", true)->value().c_str());
|
||||
}
|
||||
uint32_t ttl = 0;
|
||||
if (request->hasParam("ttl", true)) {
|
||||
ttl = request->getParam("ttl", true)->value().toInt();
|
||||
@@ -946,7 +969,7 @@ void doJsonUpload(AsyncWebServerRequest *request) {
|
||||
uint8_t mac[8];
|
||||
if (hex2mac(dst, mac)) {
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
File file = LittleFS.open("/current/" + dst + ".json", "w");
|
||||
File file = contentFS->open("/current/" + dst + ".json", "w");
|
||||
if (!file) {
|
||||
request->send(400, "text/plain", "Failed to create file");
|
||||
xSemaphoreGive(fsMutex);
|
||||
|
||||
@@ -466,9 +466,9 @@ void webFlasherTask(void* parameter) {
|
||||
}
|
||||
|
||||
void handleWSdata(uint8_t* data, size_t len, AsyncWebSocketClient* client) {
|
||||
StaticJsonDocument<200> doc;
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, (const char*)data);
|
||||
StaticJsonDocument<250> response;
|
||||
JsonDocument response;
|
||||
response["flashstatus"] = 1;
|
||||
|
||||
if (error) {
|
||||
@@ -476,7 +476,7 @@ void handleWSdata(uint8_t* data, size_t len, AsyncWebSocketClient* client) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (doc.containsKey("flashcmd")) {
|
||||
if (doc["flashcmd"].is<int>()) {
|
||||
uint16_t flashcmd = doc["flashcmd"].as<int>();
|
||||
switch (flashcmd) {
|
||||
case WEBFLASH_ENABLE_AUTOFLASH:
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
|
||||
#include <ETH.h>
|
||||
|
||||
#include "newproto.h"
|
||||
#include "system.h"
|
||||
#include "tag_db.h"
|
||||
@@ -16,6 +18,13 @@ uint8_t WifiManager::apClients = 0;
|
||||
uint8_t x_buffer[100];
|
||||
uint8_t x_position = 0;
|
||||
|
||||
#if defined(ETHERNET_PHY_POWER) && defined(ETHERNET_PHY_MDC) && defined(ETHERNET_PHY_MDIO) && defined(ETHERNET_PHY_TYPE) && defined(ETHERNET_CLK_MODE)
|
||||
static bool eth_init = false;
|
||||
static bool eth_connected = false;
|
||||
static bool eth_ip_ok = false;
|
||||
static long eth_timeout = 0;
|
||||
#endif
|
||||
|
||||
WifiManager::WifiManager() {
|
||||
_reconnectIntervalCheck = 5000;
|
||||
_retryIntervalCheck = 5 * 60000;
|
||||
@@ -43,6 +52,24 @@ void WifiManager::terminalLog(String text) {
|
||||
}
|
||||
|
||||
void WifiManager::poll() {
|
||||
|
||||
#if defined(ETHERNET_PHY_POWER) && defined(ETHERNET_PHY_MDC) && defined(ETHERNET_PHY_MDIO) && defined(ETHERNET_PHY_TYPE) && defined(ETHERNET_CLK_MODE)
|
||||
|
||||
if (eth_connected) {
|
||||
wifiStatus = ETHERNET;
|
||||
if(!eth_ip_ok && eth_timeout != 0 && millis() - eth_timeout > 2000) {
|
||||
eth_timeout = 0;
|
||||
eth_connected = false;
|
||||
}
|
||||
} else if(!eth_connected && wifiStatus == ETHERNET) {
|
||||
wifiStatus = NOINIT;
|
||||
_APstarted = false;
|
||||
WiFi.mode(WIFI_STA);
|
||||
connectToWifi();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (wifiStatus == AP && millis() > _nextReconnectCheck && _ssid != "") {
|
||||
if (apClients == 0) {
|
||||
terminalLog("Attempting to reconnect to WiFi.");
|
||||
@@ -68,6 +95,10 @@ void WifiManager::poll() {
|
||||
}
|
||||
|
||||
#ifndef HAS_USB
|
||||
|
||||
#ifdef ETHERNET_CLK_MODE
|
||||
if (!(ETHERNET_CLK_MODE == ETH_CLOCK_GPIO0_IN || ETHERNET_CLK_MODE == ETH_CLOCK_GPIO0_OUT)) {
|
||||
#endif
|
||||
// ap_and_flasher has gpio0 in use as FLASHER_AP_POWER
|
||||
if (digitalRead(0) == LOW) {
|
||||
Serial.println("GPIO0 LOW");
|
||||
@@ -99,12 +130,37 @@ void WifiManager::poll() {
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
#ifdef ETHERNET_CLK_MODE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
pollSerial();
|
||||
}
|
||||
|
||||
void WifiManager::initEth() {
|
||||
#if defined(ETHERNET_PHY_POWER) && defined(ETHERNET_PHY_MDC) && defined(ETHERNET_PHY_MDIO) && defined(ETHERNET_PHY_TYPE) && defined(ETHERNET_CLK_MODE)
|
||||
if(!eth_init) {
|
||||
eth_init = true;
|
||||
ETH.begin(
|
||||
ETH_PHY_ADDR,
|
||||
ETHERNET_PHY_POWER,
|
||||
ETHERNET_PHY_MDC,
|
||||
ETHERNET_PHY_MDIO,
|
||||
ETHERNET_PHY_TYPE,
|
||||
ETHERNET_CLK_MODE,
|
||||
false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WifiManager::connectToWifi() {
|
||||
#if defined(ETHERNET_PHY_POWER) && defined(ETHERNET_PHY_MDC) && defined(ETHERNET_PHY_MDIO) && defined(ETHERNET_PHY_TYPE) && defined(ETHERNET_CLK_MODE)
|
||||
if (wifiStatus == ETHERNET || eth_connected)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
Preferences preferences;
|
||||
preferences.begin("wifi", false);
|
||||
_ssid = preferences.getString("ssid", WiFi_SSID());
|
||||
@@ -136,6 +192,11 @@ bool WifiManager::connectToWifi() {
|
||||
}
|
||||
|
||||
bool WifiManager::connectToWifi(String ssid, String pass, bool savewhensuccessfull) {
|
||||
#if defined(ETHERNET_PHY_POWER) && defined(ETHERNET_PHY_MDC) && defined(ETHERNET_PHY_MDIO) && defined(ETHERNET_PHY_TYPE) && defined(ETHERNET_CLK_MODE)
|
||||
if (wifiStatus == ETHERNET)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
_ssid = ssid;
|
||||
_pass = pass;
|
||||
_savewhensuccessfull = savewhensuccessfull;
|
||||
@@ -145,26 +206,7 @@ bool WifiManager::connectToWifi(String ssid, String pass, bool savewhensuccessfu
|
||||
delay(100);
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
delay(100);
|
||||
char hostname[32] = "OpenEpaperLink-";
|
||||
uint8_t mac[6];
|
||||
esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
||||
char lastTwoBytes[5];
|
||||
sprintf(lastTwoBytes, "%02X%02X", mac[4], mac[5]);
|
||||
strcat(hostname, lastTwoBytes);
|
||||
|
||||
if (config.alias[0] != '\0') {
|
||||
int len = strlen(config.alias);
|
||||
int j = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = config.alias[i];
|
||||
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-') {
|
||||
hostname[j] = c;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
hostname[j] = '\0';
|
||||
}
|
||||
WiFi.setHostname(hostname);
|
||||
WiFi.setHostname(buildHostname(ESP_MAC_WIFI_STA).c_str());
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.setSleep(WIFI_PS_MIN_MODEM);
|
||||
|
||||
@@ -177,6 +219,11 @@ bool WifiManager::connectToWifi(String ssid, String pass, bool savewhensuccessfu
|
||||
}
|
||||
|
||||
bool WifiManager::waitForConnection() {
|
||||
#if defined(ETHERNET_PHY_POWER) && defined(ETHERNET_PHY_MDC) && defined(ETHERNET_PHY_MDIO) && defined(ETHERNET_PHY_TYPE) && defined(ETHERNET_CLK_MODE)
|
||||
if (wifiStatus == ETHERNET)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
unsigned long timeout = millis() + _connectionTimeout;
|
||||
wifiStatus = WAIT_CONNECTING;
|
||||
|
||||
@@ -209,7 +256,7 @@ bool WifiManager::waitForConnection() {
|
||||
}
|
||||
|
||||
void WifiManager::startManagementServer() {
|
||||
if (!_APstarted) {
|
||||
if (!_APstarted && wifiStatus != ETHERNET) {
|
||||
terminalLog("Starting config AP, ssid: OpenEPaperLink");
|
||||
logLine("Starting configuration AP, ssid OpenEPaperLink");
|
||||
WiFi.disconnect(true, true);
|
||||
@@ -225,6 +272,37 @@ void WifiManager::startManagementServer() {
|
||||
}
|
||||
}
|
||||
|
||||
String WifiManager::buildHostname(esp_mac_type_t mac_type) {
|
||||
char hostname[32] = "OpenEpaperLink-";
|
||||
uint8_t mac[6];
|
||||
esp_read_mac(mac, mac_type);
|
||||
char lastTwoBytes[5];
|
||||
sprintf(lastTwoBytes, "%02X%02X", mac[4], mac[5]);
|
||||
strcat(hostname, lastTwoBytes);
|
||||
|
||||
if (config.alias[0] != '\0') {
|
||||
int len = strlen(config.alias);
|
||||
int j = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = config.alias[i];
|
||||
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-') {
|
||||
hostname[j] = c;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
hostname[j] = '\0';
|
||||
}
|
||||
return String(hostname);
|
||||
}
|
||||
|
||||
IPAddress WifiManager::localIP() {
|
||||
if (wifiStatus == ETHERNET) {
|
||||
return ETH.localIP();
|
||||
} else {
|
||||
return WiFi.localIP();
|
||||
}
|
||||
}
|
||||
|
||||
String WifiManager::WiFi_SSID() {
|
||||
wifi_config_t conf;
|
||||
esp_wifi_get_config(WIFI_IF_STA, &conf);
|
||||
@@ -296,6 +374,46 @@ void WifiManager::WiFiEvent(WiFiEvent_t event) {
|
||||
// eventname = "Assigned IP address to client";
|
||||
break;
|
||||
|
||||
#if defined(ETHERNET_PHY_POWER) && defined(ETHERNET_PHY_MDC) && defined(ETHERNET_PHY_MDIO) && defined(ETHERNET_PHY_TYPE) && defined(ETHERNET_CLK_MODE)
|
||||
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
eventname = "ETH Started";
|
||||
//set eth hostname here
|
||||
ETH.setHostname(buildHostname(ESP_MAC_ETH).c_str());
|
||||
eth_timeout = 0;
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
eventname = "ETH Connected";
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
WiFi.disconnect();
|
||||
eth_connected = true;
|
||||
eth_timeout = millis();
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
if (ETH.fullDuplex()) {
|
||||
eventname = "ETH MAC: " + ETH.macAddress() + ", IPv4: " + ETH.localIP().toString() + ", FULL_DUPLEX, " + ETH.linkSpeed() + "Mbps";
|
||||
} else {
|
||||
eventname = "ETH MAC: " + ETH.macAddress() + ", IPv4: " + ETH.localIP().toString() + ", " + ETH.linkSpeed() + "Mbps";
|
||||
}
|
||||
eth_ip_ok = true;
|
||||
init_udp();
|
||||
eth_timeout = 0;
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
eventname = "ETH Disconnected";
|
||||
eth_connected = false;
|
||||
eth_ip_ok = false;
|
||||
eth_timeout = 0;
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_STOP:
|
||||
eventname = "ETH Stopped";
|
||||
eth_connected = false;
|
||||
eth_ip_ok = false;
|
||||
eth_timeout = 0;
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Weather forecast",
|
||||
"desc": "Weather forecast for the next five days. Weather data by Open-Meteo.com. Parameters Lat, Lon and Time Zone are filled automatically from the entered location. In case of an ambiguous location, you can alter those manually.",
|
||||
"desc": "Weather forecast for the next five days. Weather data by Open-Meteo.com. Parameters Lat, Lon and Time Zone are filled automatically from the entered location. In case of an ambiguous location, choose from the drop down list.",
|
||||
"param": [
|
||||
{
|
||||
"key": "location",
|
||||
@@ -389,6 +389,7 @@
|
||||
"NO4": "Norway NO4",
|
||||
"NO5": "Norway NO5",
|
||||
"PL": "Poland",
|
||||
"PT": "Portugal",
|
||||
"RO": "Romania",
|
||||
"SK": "Slovakia",
|
||||
"SI": "Slovenia",
|
||||
@@ -593,21 +594,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Send custom LUT",
|
||||
"desc": "EXPERIMENTAL. Don't use. YOU RISK DAMAGING YOUR SCREEN.",
|
||||
"capabilities": 4,
|
||||
"properties": [ "savespace" ],
|
||||
"param": [
|
||||
{
|
||||
"key": "bytes",
|
||||
"name": "bytes",
|
||||
"desc": "76 bytes, formatted as 0x00,0x00,...",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Send Command",
|
||||
@@ -621,6 +607,19 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"name": "Set Tag Mac",
|
||||
"desc": "Sets the tags mac-address to a specific value. Must be 16 characters, hexdecimal (8 bytes)",
|
||||
"param": [
|
||||
{
|
||||
"key": "mac",
|
||||
"name": "MAC",
|
||||
"desc": "Set Mac address",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"name": "Set Tag Config",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<!--This is the plain html source of the hex encoded Editor-Page embedded in SPIFFSEditor.cpp -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
@@ -462,26 +461,23 @@
|
||||
imageData.data[i * 4 + 2] = is16Bit ? (rgb & 0x1F) << 3 : ((rgb & 0x03) << 6) * 1.3;
|
||||
imageData.data[i * 4 + 3] = 255;
|
||||
}
|
||||
} else if (tagTypes[hwtype].bpp == 3) {
|
||||
} else if ([3, 4].includes(tagTypes[hwtype].bpp)) {
|
||||
const bpp = tagTypes[hwtype].bpp;
|
||||
const colorTable = tagTypes[hwtype].colortable;
|
||||
|
||||
let pixelIndex = 0;
|
||||
for (let i = 0; i < data.length; i += 3) {
|
||||
for (let j = 0; j < 8; j++) {
|
||||
let bitPos = j * 3;
|
||||
let bytePos = Math.floor(bitPos / 8);
|
||||
let bitOffset = bitPos % 8;
|
||||
let pixelValue = (data[i + bytePos] >> (5 - bitOffset)) & 0x07;
|
||||
if (bitOffset > 5) {
|
||||
pixelValue = ((data[i + bytePos] & (0xFF >> bitOffset)) << (bitOffset - 5)) |
|
||||
(data[i + bytePos + 1] >> (13 - bitOffset));
|
||||
}
|
||||
imageData.data[pixelIndex * 4] = colorTable[pixelValue][0];
|
||||
imageData.data[pixelIndex * 4 + 1] = colorTable[pixelValue][1];
|
||||
imageData.data[pixelIndex * 4 + 2] = colorTable[pixelValue][2];
|
||||
imageData.data[pixelIndex * 4 + 3] = 255;
|
||||
pixelIndex++;
|
||||
}
|
||||
let bitOffset = 0;
|
||||
|
||||
while (bitOffset < data.length * 8) {
|
||||
let byteIndex = bitOffset >> 3;
|
||||
let startBit = bitOffset & 7;
|
||||
let pixelValue = (data[byteIndex] << 8 | data[byteIndex + 1] || 0) >> (16 - bpp - startBit) & ((1 << bpp) - 1);
|
||||
let color = colorTable[pixelValue];
|
||||
imageData.data[pixelIndex * 4] = color[0];
|
||||
imageData.data[pixelIndex * 4 + 1] = color[1];
|
||||
imageData.data[pixelIndex * 4 + 2] = color[2];
|
||||
imageData.data[pixelIndex * 4 + 3] = 255;
|
||||
pixelIndex++;
|
||||
bitOffset += bpp;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -629,9 +625,9 @@
|
||||
leaf.onclick = function (e) {
|
||||
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||
if (name == "..") {
|
||||
httpGet(treeRoot, "/");
|
||||
httpGet(treeRoot, path === "/" ? "/" : path.substring(0, path.lastIndexOf('/')) || "/");
|
||||
} else {
|
||||
httpGet(treeRoot, "/" + name);
|
||||
httpGet(treeRoot, path + (path != "/" ? "/" : "") + name);
|
||||
}
|
||||
};
|
||||
leaf.oncontextmenu = function (e) {
|
||||
@@ -657,9 +653,6 @@
|
||||
sortByKey(items, 'name');
|
||||
var list = ce("ul");
|
||||
parent.appendChild(list);
|
||||
if (path != "/") {
|
||||
list.appendChild(createDirLeaf("/", "..", 0));
|
||||
}
|
||||
var ll = items.length;
|
||||
for (var i = 0; i < ll; i++) {
|
||||
if (items[i].type === "file") {
|
||||
@@ -669,7 +662,9 @@
|
||||
list.insertBefore(createDirLeaf(path, items[i].name, items[i].size), list.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
if (path != "/") {
|
||||
list.insertBefore(createDirLeaf(path, "..", 0), list.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
function isTextFile(path) {
|
||||
@@ -866,7 +861,7 @@
|
||||
editor.loadUrl(vars.file);
|
||||
};
|
||||
</script>
|
||||
<script id='ace' src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js" type="text/javascript"
|
||||
<script id='ace' src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.37.2/ace.js" type="text/javascript"
|
||||
charset="utf-8"></script>
|
||||
<script>
|
||||
if (typeof ace.edit == "undefined") {
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
|
||||
|
||||
<title>Open EPaper Link Access Point</title>
|
||||
<script src="main.js" defer></script>
|
||||
<script src="g5decoder.js?2"></script>
|
||||
<link rel="stylesheet" href="main.css" type="text/css" />
|
||||
<script src="main.js?2.74" defer></script>
|
||||
<script src="g5decoder.js?2.74"></script>
|
||||
<link rel="stylesheet" href="main.css?2.74" type="text/css" />
|
||||
<!--<link rel="icon" type="image/vnd.icon" href="favicon.ico">-->
|
||||
<link rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
|
||||
@@ -182,6 +182,7 @@
|
||||
<div class="nextcheckin"></div>
|
||||
<div class="nextupdate"></div>
|
||||
<div class="corner">
|
||||
<div class="waitingicon" title="New content is scheduled to be generated (as soon as possible, or shortly before the next expected checkin time)">⏳</div>
|
||||
<div class="pendingicon" title="A new message is waiting for the tag to pick up">↻</div>
|
||||
<div class="warningicon" title="This tag has not been seen for a long time">⚠
|
||||
</div>
|
||||
@@ -290,24 +291,24 @@ options:
|
||||
<option value="27">27</option>
|
||||
</select>
|
||||
</p>
|
||||
<p title="Enable SubGhz support and select channel. This requires an AP that has an optional CC1101 SubGhz radio module attached.">
|
||||
<label for="apcfgsubgigchid">SubGhz channel</label>
|
||||
<select id="apcfgsubgigchid">
|
||||
<option value="0" selected>disabled</option>
|
||||
<option value="100">100 - 864.000 Mhz (Europe, etc)</option>
|
||||
<option value="101">101 - 865.006 Mhz (Europe, etc)</option>
|
||||
<option value="102">102 - 866.014 Mhz (Europe, etc)</option>
|
||||
<option value="103">103 - 867.020 Mhz (Europe, etc)</option>
|
||||
<option value="104">104 - 868.027 Mhz (Europe, etc)</option>
|
||||
<option value="105">105 - 869.034 Mhz (Europe, etc)</option>
|
||||
<option value="200">200 - 903.000 Mhz (US, etc)</option>
|
||||
<option value="201">201 - 907.027 Mhz (US, etc)</option>
|
||||
<option value="202">202 - 911.054 Mhz (US, etc)</option>
|
||||
<option value="203">203 - 915.083 Mhz (US, etc)</option>
|
||||
<option value="204">204 - 919.110 Mhz (US, etc)</option>
|
||||
<option value="205">205 - 923.138 Mhz (US, etc)</option>
|
||||
</select>
|
||||
</p>
|
||||
<p title="Enable SubGhz support and select channel. This requires an AP that has an optional CC1101 SubGhz radio module attached.">
|
||||
<label for="apcfgsubgigchid">SubGhz channel</label>
|
||||
<select id="apcfgsubgigchid">
|
||||
<option value="0" selected>disabled</option>
|
||||
<option value="100">100 - 864.000 Mhz (Europe, etc)</option>
|
||||
<option value="101">101 - 865.006 Mhz (Europe, etc)</option>
|
||||
<option value="102">102 - 866.014 Mhz (Europe, etc)</option>
|
||||
<option value="103">103 - 867.020 Mhz (Europe, etc)</option>
|
||||
<option value="104">104 - 868.027 Mhz (Europe, etc)</option>
|
||||
<option value="105">105 - 869.034 Mhz (Europe, etc)</option>
|
||||
<option value="200">200 - 903.000 Mhz (US, etc)</option>
|
||||
<option value="201">201 - 907.027 Mhz (US, etc)</option>
|
||||
<option value="202">202 - 911.054 Mhz (US, etc)</option>
|
||||
<option value="203">203 - 915.083 Mhz (US, etc)</option>
|
||||
<option value="204">204 - 919.110 Mhz (US, etc)</option>
|
||||
<option value="205">205 - 923.138 Mhz (US, etc)</option>
|
||||
</select>
|
||||
</p>
|
||||
<p title="Enable Bluetooth (BLE) support. Only enable this if you have BLE capable tags. Changing this value requires a reboot to take effect.">
|
||||
<label for="apcfgble">Bluetooth</label>
|
||||
<select id="apcfgble">
|
||||
@@ -479,6 +480,13 @@ options:
|
||||
<option value="1">Broadcast</option>
|
||||
</select>
|
||||
</p>
|
||||
<p title="Show a timestamp on the screen when the tag is updated">
|
||||
<label for="apcshowtimestamp">Enable timestamp</label>
|
||||
<select id="apcshowtimestamp">
|
||||
<option value="0" selected>no</option>
|
||||
<option value="1">yes</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<input type="button" value="Save" id="apcfgsave"><span id="apcfgmsg"></span>
|
||||
</p>
|
||||
@@ -522,7 +530,10 @@ options:
|
||||
<button id="confirmSelectRepo">Confirm</button><button id="cancelSelectRepo">Cancel</button>
|
||||
</div>
|
||||
<h4>Releases</h4>
|
||||
<div id="releasetable"></div>
|
||||
<div id="releasetable" class="releasetable"></div>
|
||||
<h4 id="radio_release_title"></h4>
|
||||
<div id="radio_releasetable" class="releasetable"></div>
|
||||
<div id="radio_releasetable1" class="releasetable"></div>
|
||||
<h4>Other actions</h4>
|
||||
<div>
|
||||
<p id="rollbackOption" style="display:none">
|
||||
|
||||
@@ -651,6 +651,16 @@ select {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.waitingicon {
|
||||
display: none;
|
||||
font-size: 1.2em;
|
||||
background-color: lightgreen;
|
||||
color: black;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
}
|
||||
ul.messages {
|
||||
padding: 5px;
|
||||
}
|
||||
@@ -825,37 +835,37 @@ h4 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#releasetable {
|
||||
.releasetable {
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
#releasetable table {
|
||||
.releasetable table {
|
||||
border-spacing: 1px;
|
||||
}
|
||||
|
||||
#releasetable th {
|
||||
.releasetable th {
|
||||
text-align: left;
|
||||
background-color: #ffffff;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
#releasetable td {
|
||||
.releasetable td {
|
||||
background-color: #ffffff;
|
||||
padding: 1px 5px;
|
||||
min-width: 70px;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
#releasetable td:nth-child(2) {
|
||||
.releasetable td:nth-child(2) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#releasetable button {
|
||||
.releasetable button {
|
||||
padding: 3px 10px;
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
#releasetable button:hover {
|
||||
.releasetable button:hover {
|
||||
background-color: #a0a0a0;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ const apstate = [
|
||||
{ state: "online", color: "green", icon: "check_circle" },
|
||||
{ state: "flashing", color: "orange", icon: "flash_on" },
|
||||
{ state: "wait for reset", color: "blue", icon: "hourglass" },
|
||||
{ state: "AP requires power cycle", color: "purple", icon: "refresh" },
|
||||
{ state: "AP requires reboot", color: "purple", icon: "refresh" },
|
||||
{ state: "failed", color: "red", icon: "error" },
|
||||
{ state: "coming online...", color: "orange", icon: "hourglass" },
|
||||
{ state: "AP without radio", color: "green", icon: "wifi_off" }
|
||||
@@ -54,10 +54,9 @@ window.addEventListener("loadConfig", function () {
|
||||
$(".logo").innerHTML = data.alias;
|
||||
this.document.title = data.alias;
|
||||
}
|
||||
if (data.C6 == 1) {
|
||||
if (data.C6 == 1 || (data.H2 && data.H2 == 1)) {
|
||||
var optionToRemove = $("#apcfgchid").querySelector('option[value="27"]');
|
||||
if (optionToRemove) $("#apcfgchid").removeChild(optionToRemove);
|
||||
$('#updateC6Option').style.display = 'block';
|
||||
}
|
||||
if (data.hasFlasher == 1) {
|
||||
$('[data-target="flashtab"]').style.display = 'block';
|
||||
@@ -133,6 +132,7 @@ function initTabs() {
|
||||
tabLinks.forEach(link => {
|
||||
link.classList.remove("active");
|
||||
});
|
||||
if (targetId == "logtab") document.getElementById(targetId).scrollTop = 0;
|
||||
document.getElementById(targetId).style.display = "block";
|
||||
this.classList.add("active");
|
||||
});
|
||||
@@ -299,7 +299,7 @@ function processTags(tagArray) {
|
||||
if (alias.match(/^4467/)) {
|
||||
let macdigit = Number.parseInt(alias.substr(4, 2), 16) & 0x1f;
|
||||
let model = String.fromCharCode(macdigit + 65);
|
||||
if (model == 'J' || model == 'M') {
|
||||
if (model >= 'A' && model <= 'Z') {
|
||||
macdigit = Number.parseInt(alias.substr(6, 2), 16) & 0x1f;
|
||||
model += String.fromCharCode(macdigit + 65);
|
||||
alias = model + alias.substr(8, 8) + 'x'
|
||||
@@ -371,11 +371,16 @@ function processTags(tagArray) {
|
||||
} else {
|
||||
$('#tag' + tagmac + ' .nextupdate').innerHTML = "";
|
||||
}
|
||||
if (element.nextupdate < (Date.now() / 1000) - servertimediff) {
|
||||
$('#tag' + tagmac + ' .waitingicon').style.display = 'inline-block';
|
||||
} else {
|
||||
$('#tag' + tagmac + ' .waitingicon').style.display = 'none';
|
||||
}
|
||||
|
||||
if (element.nextcheckin > 1672531200) {
|
||||
div.dataset.nextcheckin = element.nextcheckin;
|
||||
} else {
|
||||
div.dataset.nextcheckin = element.lastseen + 1800;
|
||||
div.dataset.nextcheckin = element.lastseen + 60;
|
||||
}
|
||||
|
||||
div.style.opacity = '1';
|
||||
@@ -461,7 +466,7 @@ function updatecards() {
|
||||
if (item.dataset.lastseen && item.dataset.lastseen > (Date.now() / 1000) - servertimediff - 30 * 24 * 3600 * 60) {
|
||||
let idletime = (Date.now() / 1000) - servertimediff - item.dataset.lastseen;
|
||||
$('#tag' + tagmac + ' .lastseen').innerHTML = "<span>last seen</span>" + displayTime(Math.floor(idletime)) + " ago";
|
||||
if ((Date.now() / 1000) - servertimediff - 600 > item.dataset.nextcheckin) {
|
||||
if ((Date.now() / 1000) - servertimediff - apConfig.maxsleep * 60 - 300 > item.dataset.nextcheckin) {
|
||||
$('#tag' + tagmac + ' .warningicon').style.display = 'inline-block';
|
||||
$('#tag' + tagmac).classList.remove("tagpending")
|
||||
$('#tag' + tagmac).style.background = '#e0e0a0';
|
||||
@@ -793,6 +798,7 @@ document.addEventListener("loadTab", function (event) {
|
||||
$("#apcnight1").value = data.sleeptime1;
|
||||
$("#apcnight2").value = data.sleeptime2;
|
||||
$("#apcdiscovery").value = data.discovery;
|
||||
$("#apcshowtimestamp").value = data.showtimestamp;
|
||||
}
|
||||
})
|
||||
$('#apcfgmsg').innerHTML = '';
|
||||
@@ -830,7 +836,8 @@ $('#apcfgsave').onclick = function () {
|
||||
formData.append('timezone', $('#apctimezone').value);
|
||||
formData.append('sleeptime1', $('#apcnight1').value);
|
||||
formData.append('sleeptime2', $('#apcnight2').value);
|
||||
formData.append('discovery', $('#apcdiscovery').value)
|
||||
formData.append('discovery', $('#apcdiscovery').value);
|
||||
formData.append('showtimestamp', $('#apcshowtimestamp').value);
|
||||
fetch("save_apcfg", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
@@ -1253,28 +1260,24 @@ function drawCanvas(buffer, canvas, hwtype, tagmac, doRotate) {
|
||||
imageData.data[i * 4 + 3] = 255;
|
||||
}
|
||||
|
||||
} else if (tagTypes[hwtype].bpp == 3) {
|
||||
} else if ([3, 4].includes(tagTypes[hwtype].bpp)) {
|
||||
const bpp = tagTypes[hwtype].bpp;
|
||||
const colorTable = tagTypes[hwtype].colortable;
|
||||
|
||||
let pixelIndex = 0;
|
||||
for (let i = 0; i < data.length; i += 3) {
|
||||
for (let j = 0; j < 8; j++) {
|
||||
let bitPos = j * 3;
|
||||
let bytePos = Math.floor(bitPos / 8);
|
||||
let bitOffset = bitPos % 8;
|
||||
let pixelValue = (data[i + bytePos] >> (5 - bitOffset)) & 0x07;
|
||||
if (bitOffset > 5) {
|
||||
pixelValue = ((data[i + bytePos] & (0xFF >> bitOffset)) << (bitOffset - 5)) |
|
||||
(data[i + bytePos + 1] >> (13 - bitOffset));
|
||||
}
|
||||
imageData.data[pixelIndex * 4] = colorTable[pixelValue][0];
|
||||
imageData.data[pixelIndex * 4 + 1] = colorTable[pixelValue][1];
|
||||
imageData.data[pixelIndex * 4 + 2] = colorTable[pixelValue][2];
|
||||
imageData.data[pixelIndex * 4 + 3] = 255;
|
||||
pixelIndex++;
|
||||
}
|
||||
}
|
||||
let bitOffset = 0;
|
||||
|
||||
while (bitOffset < data.length * 8) {
|
||||
let byteIndex = bitOffset >> 3;
|
||||
let startBit = bitOffset & 7;
|
||||
let pixelValue = (data[byteIndex] << 8 | data[byteIndex + 1] || 0) >> (16 - bpp - startBit) & ((1 << bpp) - 1);
|
||||
let color = colorTable[pixelValue];
|
||||
imageData.data[pixelIndex * 4] = color[0];
|
||||
imageData.data[pixelIndex * 4 + 1] = color[1];
|
||||
imageData.data[pixelIndex * 4 + 2] = color[2];
|
||||
imageData.data[pixelIndex * 4 + 3] = 255;
|
||||
pixelIndex++;
|
||||
bitOffset += bpp;
|
||||
}
|
||||
} else {
|
||||
|
||||
const offsetRed = (data.length >= (canvas.width * canvas.height / 8) * 2) ? canvas.width * canvas.height / 8 : 0;
|
||||
@@ -1527,7 +1530,7 @@ async function getTagtype(hwtype) {
|
||||
height: parseInt(jsonData.height),
|
||||
bpp: parseInt(jsonData.bpp),
|
||||
rotatebuffer: jsonData.rotatebuffer,
|
||||
colortable: Object.values(jsonData.colortable),
|
||||
colortable: Object.values(jsonData.perceptual ?? jsonData.colortable),
|
||||
contentids: Object.values(jsonData.contentids ?? []),
|
||||
options: Object.values(jsonData.options ?? []),
|
||||
zlib: parseInt(jsonData.zlib_compression || "0", 16),
|
||||
@@ -1571,6 +1574,7 @@ function dropUpload() {
|
||||
|
||||
dropZone.addEventListener('drop', (event) => {
|
||||
event.preventDefault();
|
||||
const shiftKey = event.shiftKey;
|
||||
const file = event.dataTransfer.files[0];
|
||||
const tagCard = event.target.closest('.tagcard');
|
||||
const mac = tagCard.dataset.mac;
|
||||
@@ -1604,6 +1608,7 @@ function dropUpload() {
|
||||
canvas.toBlob(async (blob) => {
|
||||
const formData = new FormData();
|
||||
formData.append('mac', mac);
|
||||
if (shiftKey) formData.append('dither', '2');
|
||||
formData.append('file', blob, 'image.jpg');
|
||||
|
||||
try {
|
||||
@@ -1790,12 +1795,25 @@ function populateAPInfo(apip) {
|
||||
})
|
||||
.then(data => {
|
||||
if (data.env) {
|
||||
let gModuleType = "";
|
||||
if (data.hasC6 == 1) {
|
||||
gModuleType = "esp32-C6";
|
||||
}
|
||||
if (data.hasH2 == 1) {
|
||||
gModuleType = "esp32-H2";
|
||||
}
|
||||
if (data.hasTslr == 1) {
|
||||
gModuleType = "TSLR";
|
||||
}
|
||||
let version = '';
|
||||
version += `env: ${data.env}<br>`;
|
||||
version += `build date: ${formatEpoch(data.buildtime)}<br>`;
|
||||
version += `esp32 version: ${data.buildversion}<br>`;
|
||||
version += `psram size: ${data.psramsize}<br>`;
|
||||
version += `flash size: ${data.flashsize}<br>`;
|
||||
if (gModuleType) {
|
||||
version += `${gModuleType} version: 0x${parseInt(data.ap_version).toString(16).toUpperCase()}<br>`;
|
||||
}
|
||||
$('#ap' + apid + ' .apswversion').innerHTML = version;
|
||||
}
|
||||
})
|
||||
@@ -1906,7 +1924,7 @@ function openPreview(mac, w, h) {
|
||||
previewWindow.document.body.style.backgroundColor = "#dddddd";
|
||||
previewWindow.document.body.style.margin = "15px";
|
||||
previewWindow.document.body.style.overflow = "hidden";
|
||||
previewWindow.document.body.innerHTML = `<canvas id="preview" style="border:1px solid #888888;"></canvas>`;
|
||||
previewWindow.document.body.innerHTML = `<canvas id="preview" style="border:1px solid #888888;image-rendering: pixelated;"></canvas>`;
|
||||
|
||||
showPreview(previewWindow, element);
|
||||
|
||||
|
||||
@@ -7,8 +7,27 @@ let running = false;
|
||||
let errors = 0;
|
||||
let env = '', currentVer = '', currentBuildtime = 0;
|
||||
let buttonState = false;
|
||||
let gIsC6 = false;
|
||||
let gIsH2 = false;
|
||||
let gModuleType = '';
|
||||
let gShortName = '';
|
||||
let gCurrentRfVer = 0;
|
||||
|
||||
export async function initUpdate() {
|
||||
if (apConfig.C6 == 1) {
|
||||
gIsC6 = true;
|
||||
gModuleType = "ESP32-C6";
|
||||
gShortName = "C6";
|
||||
}
|
||||
else if(apConfig?.H2 && apConfig.H2 == 1) {
|
||||
gIsH2 = true;
|
||||
gModuleType = "ESP32-H2";
|
||||
gShortName = "H2";
|
||||
}
|
||||
else {
|
||||
gModuleType = "Unknown"
|
||||
}
|
||||
$('#radio_release_title').innerHTML = gModuleType + " Firmware";
|
||||
|
||||
const response = await fetch("version.txt");
|
||||
let filesystemversion = await response.text();
|
||||
@@ -30,7 +49,7 @@ export async function initUpdate() {
|
||||
$('#selectRepo').style.display = 'inline-block';
|
||||
$('#repoWarning').style.display = 'none';
|
||||
|
||||
const sysinfoPromise = fetch("sysinfo")
|
||||
const sdata = await fetch("sysinfo")
|
||||
.then(response => {
|
||||
if (response.status != 200) {
|
||||
print("Error fetching sysinfo: " + response.status, "red");
|
||||
@@ -48,95 +67,170 @@ export async function initUpdate() {
|
||||
print('Error fetching sysinfo: ' + error, "red");
|
||||
});
|
||||
|
||||
const repoPromise = fetch(repoUrl)
|
||||
.then(response => response.json())
|
||||
if (sdata.env) {
|
||||
print(`current env: ${sdata.env}`);
|
||||
print(`build date: ${formatEpoch(sdata.buildtime)}`);
|
||||
print(`esp32 version: ${sdata.buildversion}`);
|
||||
if(gModuleType != '') {
|
||||
var hex_ver = '0000' + sdata.ap_version.toString(16);
|
||||
print(`${gModuleType} version: ${hex_ver.slice(-4)}`);
|
||||
}
|
||||
print(`filesystem version: ${filesystemversion}`);
|
||||
print(`psram size: ${sdata.psramsize}`);
|
||||
print(`flash size: ${sdata.flashsize}`);
|
||||
print("--------------------------", "gray");
|
||||
env = apConfig.env || sdata.env;
|
||||
if (sdata.env != env) {
|
||||
print(`Warning: you selected a build environment ${env} which is\ndifferent than the currently used ${sdata.env}.\nOnly update the firmware with a mismatched build environment if\nyou know what you're doing.`, "yellow");
|
||||
}
|
||||
currentVer = sdata.buildversion;
|
||||
currentBuildtime = sdata.buildtime;
|
||||
gCurrentRfVer = sdata.ap_version;
|
||||
if (sdata.rollback) $("#rollbackOption").style.display = 'block';
|
||||
$('#environment').value = env;
|
||||
}
|
||||
|
||||
|
||||
Promise.all([sysinfoPromise, repoPromise])
|
||||
.then(([sdata, rdata]) => {
|
||||
|
||||
if (sdata.env) {
|
||||
print(`current env: ${sdata.env}`);
|
||||
print(`build date: ${formatEpoch(sdata.buildtime)}`);
|
||||
print(`esp32 version: ${sdata.buildversion}`);
|
||||
print(`filesystem version: ${filesystemversion}`);
|
||||
print(`psram size: ${sdata.psramsize}`);
|
||||
print(`flash size: ${sdata.flashsize}`);
|
||||
print("--------------------------", "gray");
|
||||
env = apConfig.env || sdata.env;
|
||||
if (sdata.env != env) {
|
||||
print(`Warning: you selected a build environment ${env} which is\ndifferent than the currently used ${sdata.env}.\nOnly update the firmware with a mismatched build environment if\nyou know what you're doing.`, "yellow");
|
||||
}
|
||||
currentVer = sdata.buildversion;
|
||||
currentBuildtime = sdata.buildtime;
|
||||
if (sdata.rollback) $("#rollbackOption").style.display = 'block';
|
||||
$('#environment').value = env;
|
||||
const rdata = await fetch(repoUrl).then(response => response.json())
|
||||
const JsonName = 'firmware_' + gShortName + '.json';
|
||||
const releaseDetails = rdata.map(release => {
|
||||
const assets = release.assets;
|
||||
const filesJsonAsset = assets.find(asset => asset.name === 'filesystem.json');
|
||||
const binariesJsonAsset = assets.find(asset => asset.name === 'binaries.json');
|
||||
const containsEnv = assets.find(asset => asset.name === env + '.bin');
|
||||
const firmwareAsset = assets.find(asset => asset.name === JsonName);
|
||||
if (filesJsonAsset && binariesJsonAsset && containsEnv) {
|
||||
return {
|
||||
html_url: release.html_url,
|
||||
tag_name: release.tag_name,
|
||||
name: release.name,
|
||||
date: formatDateTime(release.published_at),
|
||||
author: release.author.login,
|
||||
file_url: filesJsonAsset.browser_download_url,
|
||||
bin_url: binariesJsonAsset.browser_download_url,
|
||||
firmware_url: firmwareAsset?.browser_download_url,
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
const releaseDetails = rdata.map(release => {
|
||||
const assets = release.assets;
|
||||
const filesJsonAsset = assets.find(asset => asset.name === 'filesystem.json');
|
||||
const binariesJsonAsset = assets.find(asset => asset.name === 'binaries.json');
|
||||
const containsEnv = assets.find(asset => asset.name === env + '.bin');
|
||||
if (filesJsonAsset && binariesJsonAsset && containsEnv) {
|
||||
return {
|
||||
html_url: release.html_url,
|
||||
tag_name: release.tag_name,
|
||||
name: release.name,
|
||||
date: formatDateTime(release.published_at),
|
||||
author: release.author.login,
|
||||
file_url: filesJsonAsset.browser_download_url,
|
||||
bin_url: binariesJsonAsset.browser_download_url
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const easyupdate = $('#easyupdate');
|
||||
if (releaseDetails.length === 0) {
|
||||
easyupdate.innerHTML = ("No releases found.");
|
||||
if (releaseDetails.length === 0) {
|
||||
easyupdate.innerHTML = ("No releases found.");
|
||||
} else {
|
||||
const release = releaseDetails[0];
|
||||
if (release?.tag_name) {
|
||||
if (release.tag_name == currentVer) {
|
||||
easyupdate.innerHTML = `Version ${currentVer}. You are up to date`;
|
||||
} else if (release.date < formatEpoch(currentBuildtime - 30 * 60)) {
|
||||
easyupdate.innerHTML = `Your version is newer than the latest release date.<br>Are you the developer? :-)`;
|
||||
} else {
|
||||
const release = releaseDetails[0];
|
||||
if (release?.tag_name) {
|
||||
if (parseInt(release.tag_name) == parseInt(currentVer)) {
|
||||
easyupdate.innerHTML = `Version ${currentVer}. You are up to date`;
|
||||
} else if (release.date < formatEpoch(currentBuildtime - 30 * 60)) {
|
||||
easyupdate.innerHTML = `Your version is newer than the latest release date.<br>Are you the developer? :-)`;
|
||||
} else {
|
||||
easyupdate.innerHTML = `An update from version ${currentVer} to version ${release.tag_name} is available.<button onclick="otamodule.updateAll('${release.bin_url}','${release.file_url}','${release.tag_name}')">Update now!</button>`;
|
||||
}
|
||||
}
|
||||
easyupdate.innerHTML = `An update from version ${currentVer} to version ${release.tag_name} is available.<button onclick="otamodule.updateAll('${release.bin_url}','${release.file_url}','${release.tag_name}')">Update now!</button>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const table = document.createElement('table');
|
||||
const tableHeader = document.createElement('tr');
|
||||
tableHeader.innerHTML = '<th>Release</th><th>Date</th><th>Name</th><th colspan="2">Update:</th><th>Remark</th>';
|
||||
table.appendChild(tableHeader);
|
||||
const table = document.createElement('table');
|
||||
const tableHeader = document.createElement('tr');
|
||||
tableHeader.innerHTML = '<th>Release</th><th>Date</th><th>Name</th><th colspan="2"><center>Update</center></th><th>Remark</th>';
|
||||
table.appendChild(tableHeader);
|
||||
|
||||
let rowCounter = 0;
|
||||
releaseDetails.forEach(release => {
|
||||
if (rowCounter < 4 && release?.html_url) {
|
||||
const tableRow = document.createElement('tr');
|
||||
let tablerow = `<td><a href="${release.html_url}" target="_new">${release.tag_name}</a></td><td>${release.date}</td><td>${release.name}</td><td><button type="button" onclick="otamodule.updateWebpage('${release.file_url}','${release.tag_name}', true)">Filesystem</button></td><td><button type="button" onclick="otamodule.updateESP('${release.bin_url}', true)">ESP32</button></td>`;
|
||||
if (release.tag_name == currentVer) {
|
||||
tablerow += "<td>current version</td>";
|
||||
} else if (release.date < formatEpoch(currentBuildtime)) {
|
||||
tablerow += "<td>older</td>";
|
||||
} else {
|
||||
tablerow += "<td>newer</td>";
|
||||
}
|
||||
tableRow.innerHTML = tablerow;
|
||||
table.appendChild(tableRow);
|
||||
rowCounter++;
|
||||
}
|
||||
});
|
||||
let rowCounter = 0;
|
||||
let radioFwCounter = 0;
|
||||
releaseDetails.forEach(release => {
|
||||
if (rowCounter < 4 && release?.html_url) {
|
||||
const tableRow = document.createElement('tr');
|
||||
let tablerow = `<td><a href="${release.html_url}" target="_new">${release.tag_name}</a></td><td>${release.date}</td><td>${release.name}</td><td><button type="button" onclick="otamodule.updateWebpage('${release.file_url}','${release.tag_name}', true)">Filesystem</button></td><td><button type="button" onclick="otamodule.updateESP('${release.bin_url}', true)">ESP32</button></td>`;
|
||||
if (release.tag_name == currentVer) {
|
||||
tablerow += "<td>current version</td>";
|
||||
} else if (release.date < formatEpoch(currentBuildtime)) {
|
||||
tablerow += "<td>older</td>";
|
||||
} else {
|
||||
tablerow += "<td>newer</td>";
|
||||
}
|
||||
tableRow.innerHTML = tablerow;
|
||||
table.appendChild(tableRow);
|
||||
rowCounter++;
|
||||
}
|
||||
if (release?.firmware_url) {
|
||||
radioFwCounter++;
|
||||
}
|
||||
});
|
||||
$('#releasetable').innerHTML = "";
|
||||
$('#releasetable').appendChild(table);
|
||||
|
||||
$('#releasetable').innerHTML = "";
|
||||
$('#releasetable').appendChild(table);
|
||||
disableButtons(buttonState);
|
||||
})
|
||||
.catch(error => {
|
||||
print('Error fetching releases:' + error, "red");
|
||||
});
|
||||
if(radioFwCounter > 0) {
|
||||
const table1 = document.createElement('table');
|
||||
const tableHeader1 = document.createElement('tr');
|
||||
|
||||
tableHeader1.innerHTML = '<th>Release</th><th>Date</th><th>Name</th><th><center>Update</center></th><th>Version</th><th>Remark</th>';
|
||||
table1.appendChild(tableHeader1);
|
||||
|
||||
rowCounter = 0;
|
||||
for (const release of releaseDetails) {
|
||||
if (rowCounter < 4 && release?.firmware_url) {
|
||||
const tableRow = document.createElement('tr');
|
||||
var tablerow;
|
||||
var firmwareVer = "unknown";
|
||||
var release_url = release.firmware_url;
|
||||
|
||||
tablerow = `<td><a href="${release.html_url}" target="_new">${release.tag_name}</a></td><td>${release.date}</td><td>${release.name}</td>`;
|
||||
tablerow += `<td><button type="button" onclick="otamodule.updateC6H2('${release_url}')">${gModuleType}</button></td>`;
|
||||
const firmwareUrl = 'http://proxy.openepaperlink.org/proxy.php?url=' + release.firmware_url;
|
||||
firmwareVer = await fetch(firmwareUrl, { method: 'GET'})
|
||||
.then(function (response) { return response.json(); })
|
||||
.then(function (response) {
|
||||
return response[2]['version']; })
|
||||
.catch(error => {
|
||||
print('Error fetching releases:' + error, "red");
|
||||
});
|
||||
tablerow += '<td>' + firmwareVer + '</td><td>';
|
||||
if(firmwareVer != 'unknown') {
|
||||
let Ver = Number('0x' + firmwareVer);
|
||||
if(Ver > gCurrentRfVer) {
|
||||
tablerow += 'newer';
|
||||
}
|
||||
else if (Ver < gCurrentRfVer) {
|
||||
tablerow += 'older';
|
||||
}
|
||||
else if(!Number.isNaN(Ver)){
|
||||
tablerow += 'current version';
|
||||
}
|
||||
}
|
||||
tablerow += '</td>';
|
||||
tableRow.innerHTML = tablerow;
|
||||
table1.appendChild(tableRow);
|
||||
rowCounter++;
|
||||
}
|
||||
};
|
||||
|
||||
$('#radio_releasetable').innerHTML = "";
|
||||
$('#radio_releasetable').appendChild(table1);
|
||||
}
|
||||
|
||||
const table2 = document.createElement('table');
|
||||
{
|
||||
const tableHeader2 = document.createElement('tr');
|
||||
tableHeader2.innerHTML = '<th>Firmware</th><th><center>Update</center></th>';
|
||||
table2.appendChild(tableHeader2);
|
||||
const tableRow = document.createElement('tr');
|
||||
tablerow = '<td title="manual upload, make sure all four files are present">Binaries from <a href="/edit" target="littlefs">file system</a></td>';
|
||||
tablerow += `<td><button type="button" onclick="otamodule.updateC6H2('')">${gModuleType}</button></td>`;
|
||||
tableRow.innerHTML = tablerow;
|
||||
table2.appendChild(tableRow);
|
||||
}
|
||||
{
|
||||
const tableRow = document.createElement('tr');
|
||||
const Url = "https://raw.githubusercontent.com/" + repo +
|
||||
"/master/binaries/ESP32-" + gShortName +
|
||||
"/firmware_" + gShortName + ".json";
|
||||
|
||||
tablerow = `<td><a href="https://github.com/${repo}/tree/master/binaries/ESP32-${gShortName}/" target="_new">Latest version from repo</a></td>`;
|
||||
tablerow += `<td><button type="button" onclick="otamodule.updateC6H2('${Url}')">${gModuleType}</button></td>`;
|
||||
tableRow.innerHTML = tablerow;
|
||||
table2.appendChild(tableRow);
|
||||
}
|
||||
$('#radio_releasetable1').innerHTML = "";
|
||||
$('#radio_releasetable1').appendChild(table2);
|
||||
|
||||
disableButtons(buttonState);
|
||||
}
|
||||
|
||||
export function updateAll(binUrl, fileUrl, tagname) {
|
||||
@@ -355,19 +449,18 @@ $('#rollbackBtn').onclick = function () {
|
||||
disableButtons(false);
|
||||
}
|
||||
|
||||
$('#updateC6Btn').onclick = function () {
|
||||
export async function updateC6H2(Url) {
|
||||
if (running) return;
|
||||
disableButtons(true);
|
||||
running = true;
|
||||
errors = 0;
|
||||
const ReleaseUrl = Url.substring(0,Url.lastIndexOf('/'));
|
||||
const consoleDiv = document.getElementById('updateconsole');
|
||||
consoleDiv.scrollTop = consoleDiv.scrollHeight;
|
||||
|
||||
print("Flashing ESP32-C6...");
|
||||
|
||||
const isChecked = $('#c6download').checked;
|
||||
const formData = new FormData();
|
||||
formData.append('download', isChecked ? '1' : '0');
|
||||
|
||||
print("Flashing " + gModuleType + " ...");
|
||||
formData.append('url', ReleaseUrl);
|
||||
|
||||
fetch("update_c6", {
|
||||
method: "POST",
|
||||
@@ -415,7 +508,7 @@ $('#selectRepo').onclick = function (event) {
|
||||
if (!responseBody.trim().startsWith("[")) {
|
||||
throw new Error("Failed to fetch the release info file");
|
||||
}
|
||||
const updateData = JSON.parse(responseBody).filter(item => !item.name.endsWith('_full.bin'));
|
||||
const updateData = JSON.parse(responseBody).filter(item => !item.name.endsWith('_full.bin') && !item.name.includes('_H2.') && !item.name.includes('_C6.'));
|
||||
|
||||
const inputParent = $('#environment').parentNode;
|
||||
const selectElement = document.createElement('select');
|
||||
@@ -638,3 +731,7 @@ async function fetchAndCheckTagtypes(cleanup) {
|
||||
print("Error: " + error, "red");
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeVersion(version) {
|
||||
return version.replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ platform = espressif32
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
https://github.com/MajenkoLibraries/SoftSPI
|
||||
bblanchon/ArduinoJson
|
||||
bblanchon/ArduinoJson@7.1.0
|
||||
|
||||
platform_packages =
|
||||
board_build.filesystem = littlefs
|
||||
@@ -61,4 +61,4 @@ build_src_filter =
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 4MB
|
||||
board_upload.flash_size = 4MB
|
||||
|
||||
@@ -106,9 +106,12 @@ python3 .\88MZ100-OEPL-Flasher.py COM31 write_flash '0130c8144117.bin'
|
||||
|
||||
## TI CC1110-based
|
||||
|
||||
Use with the -c option for CC1110. Neigher Autoflash is currently not implemented on the Tag_Flasher/S2 version.
|
||||
> [!IMPORTANT]
|
||||
> Tag flasher version 50 or later is required for CC1110 support.
|
||||
>
|
||||
Use with the -c option for CC1110.
|
||||
|
||||
The CC1110 does not have an infopage nor is the Tag's EEPROM accessable.
|
||||
The CC1110 does not have an infopage nor is the Tag's EEPROM accessable. Autoflash is currently not implemented for the CC1110.
|
||||
|
||||
```shell
|
||||
python3 OEPL-Flasher.py -e -c -p COM31 read blaat.bin --flash
|
||||
|
||||
Binary file not shown.
BIN
binaries/ESP32-C6/OpenEPaperLink_esp32_C6_Uart0.bin
Normal file
BIN
binaries/ESP32-C6/OpenEPaperLink_esp32_C6_Uart0.bin
Normal file
Binary file not shown.
@@ -1,12 +1,15 @@
|
||||
[{
|
||||
"filename": "bootloader.bin",
|
||||
"address": "0x0"
|
||||
"address": "0x0",
|
||||
"version": "0001"
|
||||
},
|
||||
{
|
||||
"filename": "partition-table.bin",
|
||||
"address": "0x8000"
|
||||
"address": "0x8000",
|
||||
"version": "0001"
|
||||
},
|
||||
{
|
||||
"filename": "OpenEPaperLink_esp32_C6.bin",
|
||||
"address": "0x10000"
|
||||
"address": "0x10000",
|
||||
"version": "001f"
|
||||
}]
|
||||
|
||||
15
binaries/ESP32-C6/firmware_C6.json
Normal file
15
binaries/ESP32-C6/firmware_C6.json
Normal file
@@ -0,0 +1,15 @@
|
||||
[{
|
||||
"filename": "bootloader_C6.bin",
|
||||
"address": "0x0",
|
||||
"version": "0001"
|
||||
},
|
||||
{
|
||||
"filename": "partition-table_C6.bin",
|
||||
"address": "0x8000",
|
||||
"version": "0001"
|
||||
},
|
||||
{
|
||||
"filename": "OpenEPaperLink_esp32_C6.bin",
|
||||
"address": "0x10000",
|
||||
"version": "001f"
|
||||
}]
|
||||
Binary file not shown.
@@ -1,12 +1,15 @@
|
||||
[{
|
||||
"filename": "bootloader.bin",
|
||||
"address": "0x0"
|
||||
"address": "0x0",
|
||||
"version": "0001"
|
||||
},
|
||||
{
|
||||
"filename": "partition-table.bin",
|
||||
"address": "0x8000"
|
||||
"address": "0x8000",
|
||||
"version": "0001"
|
||||
},
|
||||
{
|
||||
"filename": "OpenEPaperLink_esp32_H2.bin",
|
||||
"address": "0x10000"
|
||||
"address": "0x10000",
|
||||
"version": "001f"
|
||||
}]
|
||||
|
||||
15
binaries/ESP32-H2/firmware_H2.json
Normal file
15
binaries/ESP32-H2/firmware_H2.json
Normal file
@@ -0,0 +1,15 @@
|
||||
[{
|
||||
"filename": "bootloader_H2.bin",
|
||||
"address": "0x0",
|
||||
"version": "0001"
|
||||
},
|
||||
{
|
||||
"filename": "partition-table_H2.bin",
|
||||
"address": "0x8000",
|
||||
"version": "0001"
|
||||
},
|
||||
{
|
||||
"filename": "OpenEPaperLink_esp32_H2.bin",
|
||||
"address": "0x10000",
|
||||
"version": "001f"
|
||||
}]
|
||||
BIN
binaries/TLSR/OEPL_TLSR_AP.bin
Executable file
BIN
binaries/TLSR/OEPL_TLSR_AP.bin
Executable file
Binary file not shown.
BIN
binaries/Tag/ATC_Cheapo_BLE_OEPL_Watch.bin
Normal file
BIN
binaries/Tag/ATC_Cheapo_BLE_OEPL_Watch.bin
Normal file
Binary file not shown.
BIN
binaries/Tag/chroma29_8151_full_0013.bin
Normal file
BIN
binaries/Tag/chroma29_8151_full_0013.bin
Normal file
Binary file not shown.
1002
binaries/Tag/chroma29_8151_full_0013.hex
Normal file
1002
binaries/Tag/chroma29_8151_full_0013.hex
Normal file
File diff suppressed because it is too large
Load Diff
BIN
binaries/Tag/chroma29_8151_ota_0013.bin
Normal file
BIN
binaries/Tag/chroma29_8151_ota_0013.bin
Normal file
Binary file not shown.
@@ -128,7 +128,10 @@
|
||||
"82": {
|
||||
"type": "chroma29_ota",
|
||||
"version": "0010",
|
||||
"md5": "0d4af3e5285ca20ac56926e6fdd71dbc"
|
||||
"md5": "0d4af3e5285ca20ac56926e6fdd71dbc",
|
||||
"type_1": "chroma29_8151_ota",
|
||||
"version_1": "0013",
|
||||
"md5_1": "b3dffd044829449998edc1c91d537004"
|
||||
},
|
||||
"83": {
|
||||
"type": "chroma42_ota",
|
||||
|
||||
@@ -4,9 +4,12 @@ function doGet(e) {
|
||||
var country = e?.parameter?.country || 'NL';
|
||||
var cache = CacheService.getScriptCache();
|
||||
|
||||
ExchangeApp.setRatesEndpoint("https://openexchangerates.org/api/latest.json?app_id=*************", 3600)
|
||||
|
||||
var cachedData = cache.get("output" + country);
|
||||
if (false && cachedData != null) {
|
||||
if (cachedData != null) {
|
||||
logger('from cache');
|
||||
logger('All Data: ' + JSON.stringify(cachedData));
|
||||
return ContentService.createTextOutput(cachedData)
|
||||
.setMimeType(ContentService.MimeType.JSON);
|
||||
}
|
||||
@@ -16,8 +19,8 @@ function doGet(e) {
|
||||
// https://github.com/bkper/exchange-app
|
||||
factor = cache.get("currencyNOK");
|
||||
if (factor == null) {
|
||||
// factor = ExchangeApp.convert(1, 'EUR', 'NOK');
|
||||
factor = 11.4;
|
||||
factor = ExchangeApp.convert(1, 'EUR', 'NOK');
|
||||
// factor = 11.79;
|
||||
cache.put("currencyNOK", factor, 3600 * 24);
|
||||
}
|
||||
}
|
||||
@@ -26,8 +29,8 @@ function doGet(e) {
|
||||
// https://github.com/bkper/exchange-app
|
||||
factor = cache.get("currencyDKK");
|
||||
if (factor == null) {
|
||||
// factor = ExchangeApp.convert(1, 'EUR', 'DKK');
|
||||
factor = 7.45;
|
||||
factor = ExchangeApp.convert(1, 'EUR', 'DKK');
|
||||
// factor = 7.46;
|
||||
cache.put("currencyDKK", factor, 3600 * 24);
|
||||
}
|
||||
}
|
||||
@@ -36,8 +39,8 @@ function doGet(e) {
|
||||
// https://github.com/bkper/exchange-app
|
||||
factor = cache.get("currencySEK");
|
||||
if (factor == null) {
|
||||
// factor = ExchangeApp.convert(1, 'EUR', 'SEK');
|
||||
factor = 11.25;
|
||||
factor = ExchangeApp.convert(1, 'EUR', 'SEK');
|
||||
// factor = 11.59;
|
||||
cache.put("currencySEK", factor, 3600 * 24);
|
||||
}
|
||||
}
|
||||
@@ -45,10 +48,11 @@ function doGet(e) {
|
||||
var domain = lookupValue(country);
|
||||
logger(country + ': ' + domain + ' currency: ' + factor);
|
||||
|
||||
var xmlUrl = 'https://web-api.tp.entsoe.eu/api?documentType=A44&out_Domain=' + domain + '&in_Domain=' + domain + '&periodStart=' + getFormattedMidnightUTC(-1) + '&periodEnd=' + getFormattedMidnightUTC(2) + '&securityToken=*********';
|
||||
var xmlUrl = 'https://web-api.tp.entsoe.eu/api?documentType=A44&out_Domain=' + domain + '&in_Domain=' + domain + '&periodStart=' + getFormattedMidnightUTC(-1) + '&periodEnd=' + getFormattedMidnightUTC(2) + '&securityToken=57ba8658-37a5-4e23-9bee-e60fc3f954db';
|
||||
logger(xmlUrl);
|
||||
var cachedXml = cache.get(xmlUrl);
|
||||
|
||||
if (cachedXml) {
|
||||
if (true && cachedXml) {
|
||||
logger('Using cached XML content.');
|
||||
var xmlContent = cachedXml;
|
||||
} else {
|
||||
@@ -65,7 +69,7 @@ function doGet(e) {
|
||||
var root = document.getRootElement();
|
||||
|
||||
var timeSeriesList = getDescendantsByTagName(root, 'TimeSeries');
|
||||
|
||||
|
||||
if (timeSeriesList.length > 0) {
|
||||
var jsonData = [];
|
||||
|
||||
@@ -77,15 +81,18 @@ function doGet(e) {
|
||||
|
||||
if (period) {
|
||||
var startTime = period.getChild('timeInterval').getChildText('start');
|
||||
var resolution = period.getChildText('resolution');
|
||||
var stepSeconds = resolution === "PT15M" ? 900 : 3600;
|
||||
logger("Resolution: " + resolution + " (" + stepSeconds + " seconds per step)");
|
||||
logger(startTime);
|
||||
var points = period.getChildren('Point');
|
||||
|
||||
for (var i = 0; i < points.length; i++) {
|
||||
var position = points[i].getChildText('position');
|
||||
var position = parseInt(points[i].getChildText('position'), 10);
|
||||
var priceAmount = points[i].getChildText('price.amount') * factor;
|
||||
|
||||
// Convert ISO date to epoch time (in seconds)
|
||||
var epochTime = new Date(startTime).getTime() / 1000 + (position - 1) * 3600;
|
||||
var epochTime = new Date(startTime).getTime() / 1000 + (position - 1) * stepSeconds;
|
||||
|
||||
jsonData.push({
|
||||
time: epochTime,
|
||||
@@ -137,7 +144,6 @@ function getFormattedMidnightUTC(offsetDays) {
|
||||
var localMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + offsetDays, 0, 0, 0, 0);
|
||||
|
||||
var utcMidnight = new Date(localMidnight.getTime());
|
||||
|
||||
var year = utcMidnight.getUTCFullYear();
|
||||
var month = ('0' + (utcMidnight.getUTCMonth() + 1)).slice(-2); // Months are zero-based
|
||||
var day = ('0' + utcMidnight.getUTCDate()).slice(-2);
|
||||
@@ -149,6 +155,7 @@ function getFormattedMidnightUTC(offsetDays) {
|
||||
}
|
||||
|
||||
// https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html#_areas
|
||||
// https://transparencyplatform.zendesk.com/hc/en-us/articles/15885757676308-Area-List-with-Energy-Identification-Code-EIC
|
||||
|
||||
function lookupValue(country) {
|
||||
var countryValues = {
|
||||
@@ -173,6 +180,7 @@ function lookupValue(country) {
|
||||
'NO4': '10YNO-4--------9',
|
||||
'NO5': '10Y1001A1001A48H',
|
||||
'PL': '10YPL-AREA-----S',
|
||||
'PT': '10YPT-REN------W',
|
||||
'RO': '10YRO-TEL------P',
|
||||
'SE1': '10Y1001A1001A44P',
|
||||
'SE2': '10Y1001A1001A45N',
|
||||
@@ -184,6 +192,3 @@ function lookupValue(country) {
|
||||
var value = countryValues[country] || '10YNL----------L';
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ void setup() {
|
||||
|
||||
String str = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~°ÄÅÆÖØÚÜßáäåæéíöøúüýąČěľłńŘřŚŠź";
|
||||
char[] charsetbasic = str.toCharArray();
|
||||
str = "ABCDEFGHIJKLMNOPQRSTUVWXYZiortzÁÅÄÖØÚČŚŠ0123456789-";
|
||||
str = "ABCDEFGHIJKLMNOPQRSTUVWXYZminortzÁÅÄÖØÚČŚŠ0123456789-";
|
||||
char[] charsetdaynames = str.toCharArray();
|
||||
str = "0123456789.°-";
|
||||
char[] charsetnumbers = str.toCharArray();
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
#define SOLUM_42_SSD1619 0x02
|
||||
#define SOLUM_SEG_UK 0xF0
|
||||
#define SOLUM_SEG_EU 0xF1
|
||||
#define RESERVED_TESTING 0xFE
|
||||
#define SOLUM_NODISPLAY 0xFF
|
||||
#define ESP32_C6 0xC6
|
||||
|
||||
|
||||
|
||||
|
||||
// overflow
|
||||
#define SOLUM_M2_BWR_16 0x20
|
||||
@@ -24,8 +18,6 @@
|
||||
#define SOLUM_M2_BW_75 0x26
|
||||
#define SOLUM_M2_BW_29 0x27
|
||||
|
||||
|
||||
|
||||
#define SOLUM_M3_BWR_97 0x2E
|
||||
#define SOLUM_M3_BWR_43 0x2F
|
||||
|
||||
@@ -50,7 +42,6 @@
|
||||
#define SOLUM_M3_BWR_116 0x37
|
||||
#define SOLUM_M3_BWY_116 0x3F
|
||||
|
||||
|
||||
// M3 Tags overflow
|
||||
#define SOLUM_M3_BW_29 0x40
|
||||
#define SOLUM_M3_BWR_58 0x41
|
||||
@@ -80,7 +71,6 @@
|
||||
#define GICI_BLE_TFT_21_BW 0xBA
|
||||
#define GICI_BLE_EPD_BWR_29_SILABS 0xBD
|
||||
#define GICI_BLE_UNKNOWN 0xBF
|
||||
#define ATC_MI_THERMOMETER 0xBE
|
||||
|
||||
// Solum types - customer data byte 16 in M3 (nRF) UICR
|
||||
#define STYPE_SIZE_016 0x40
|
||||
@@ -98,6 +88,16 @@
|
||||
#define STYPE_SIZE_097 0x64
|
||||
#define STYPE_SIZE_013 0x4D
|
||||
|
||||
// Various types
|
||||
#define ATC_MI_THERMOMETER 0xBE
|
||||
#define RESERVED_TESTING 0xFE
|
||||
#define SOLUM_NODISPLAY 0xFF
|
||||
#define ESP32_C6 0xC6
|
||||
|
||||
#define BWRY_29 0xC0
|
||||
#define ACEP_40 0xC1
|
||||
#define SPECTRA_73 0xC2
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
#define DATATYPE_IMG_RAW_1BPP 0x20 // 2888 bytes for 1.54" / 4736 2.9" / 15000 4.2"
|
||||
#define DATATYPE_IMG_RAW_2BPP 0x21 // 5776 bytes for 1.54" / 9472 2.9" / 30000 4.2"
|
||||
#define DATATYPE_IMG_RAW_3BPP 0x22 // ACEP
|
||||
#define DATATYPE_IMG_RAW_4BPP 0x23 // Spectra
|
||||
#define DATATYPE_IMG_ZLIB 0x30 // compressed format.
|
||||
// [uint32_t uncompressed size][2 byte zlib header][zlib compressed image]
|
||||
// image format: [uint8_t header length][uint16_t width][uint16_t height][uint8_t bpp (lower 4)][img data]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 4,
|
||||
"name": "M2 1.54\"",
|
||||
"width": 152,
|
||||
"height": 152,
|
||||
@@ -13,7 +13,7 @@
|
||||
"g5_compression": "29",
|
||||
"shortlut": 2,
|
||||
"options": [ "button", "customlut" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 10, 14, 15, 17, 18, 19, 20, 21, 27 ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 10, 14, 17, 18, 19, 20, 21, 27 ],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 76, 9, "fonts/calibrib30" ],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 4,
|
||||
"name": "M2 2.9\"",
|
||||
"width": 296,
|
||||
"height": 128,
|
||||
@@ -13,7 +13,7 @@
|
||||
"g5_compression": "29",
|
||||
"shortlut": 2,
|
||||
"options": [ "button", "customlut" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 148, -3, "Signika-SB.ttf", 60 ],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 5,
|
||||
"version": 6,
|
||||
"name": "M2 2.2\"",
|
||||
"width": 212,
|
||||
"height": 104,
|
||||
@@ -13,7 +13,7 @@
|
||||
"g5_compression": "29",
|
||||
"shortlut": 2,
|
||||
"options": [ "button", "customlut" ],
|
||||
"contentids": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 19, 20, 21, 22, 23, 27 ],
|
||||
"contentids": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 16, 17, 19, 20, 21, 22, 23, 27 ],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 106, 5, "fonts/calibrib40", 40 ],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 4,
|
||||
"name": "M2 2.6\"",
|
||||
"width": 296,
|
||||
"height": 152,
|
||||
@@ -13,7 +13,7 @@
|
||||
"g5_compression": "29",
|
||||
"shortlut": 2,
|
||||
"options": [ "button", "customlut" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 148, 9, "Signika-SB.ttf", 60 ],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 2,
|
||||
"version": 4,
|
||||
"name": "Opticon 2.2\"",
|
||||
"width": 250,
|
||||
"height": 128,
|
||||
@@ -11,9 +11,14 @@
|
||||
"red": [ 255, 0, 0 ],
|
||||
"yellow": [ 255, 255, 0 ]
|
||||
},
|
||||
"perceptual": {
|
||||
"white": [ 255, 255, 255 ],
|
||||
"black": [ 0, 0, 0 ],
|
||||
"yellow": [ 200, 200, 0 ]
|
||||
},
|
||||
"g5_compression": "29",
|
||||
"shortlut": 0,
|
||||
"options": [ "led" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"usetemplate": 177
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 2,
|
||||
"version": 4,
|
||||
"name": "Opticon 2.9\"",
|
||||
"width": 296,
|
||||
"height": 128,
|
||||
@@ -11,9 +11,14 @@
|
||||
"red": [ 255, 0, 0 ],
|
||||
"yellow": [ 255, 255, 0 ]
|
||||
},
|
||||
"perceptual": {
|
||||
"white": [ 255, 255, 255 ],
|
||||
"black": [ 0, 0, 0 ],
|
||||
"yellow": [ 200, 200, 0 ]
|
||||
},
|
||||
"g5_compression": "29",
|
||||
"shortlut": 2,
|
||||
"options": [ "led" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"usetemplate": 1
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
"name": "M2 2.9\" (UC8151)",
|
||||
"width": 296,
|
||||
"height": 128,
|
||||
@@ -13,6 +13,6 @@
|
||||
"g5_compression": "29",
|
||||
"shortlut": 0,
|
||||
"options": [ "button" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 16, 17, 18, 19, 20, 21, 27 ],
|
||||
"usetemplate": 1
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 1,
|
||||
"version": 2,
|
||||
"name": "ST‐GM29XXF 2.9\"",
|
||||
"width": 296,
|
||||
"height": 128,
|
||||
@@ -12,6 +12,6 @@
|
||||
"highlight_color": 5,
|
||||
"shortlut": 0,
|
||||
"options": [ "button", "customlut" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21 ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21 ],
|
||||
"usetemplate": 1
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
"name": "ST‐GM29MT1 2.9\"",
|
||||
"width": 296,
|
||||
"height": 128,
|
||||
@@ -13,6 +13,6 @@
|
||||
"highlight_color": 5,
|
||||
"shortlut": 0,
|
||||
"options": [ "button", "customlut" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21 ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21 ],
|
||||
"usetemplate": 1
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 2,
|
||||
"version": 5,
|
||||
"name": "M3 9.7\"",
|
||||
"width": 960,
|
||||
"height": 672,
|
||||
@@ -21,6 +21,21 @@
|
||||
"month": [ 480, 480, "Signika-SB.ttf", 160 ],
|
||||
"day": [ 480, 110, "Signika-SB.ttf", 380 ]
|
||||
},
|
||||
"8": {
|
||||
"location": [ 25, 0, "fonts/calibrib60" ],
|
||||
"column": [ 7, 137 ],
|
||||
"day": [ 68, 245, "fonts/calibrib42", 335, 540 ],
|
||||
"rain": [ 72, 610 ],
|
||||
"icon": [ 67, 390, 90 ],
|
||||
"wind": [ 45, 300 ],
|
||||
"line": [ 240, 672 ],
|
||||
|
||||
"currentwind": [ 470, 130, "fonts/calibrib60" ],
|
||||
"temp": [ 25, 70, "fonts/calibrib120", 1 ],
|
||||
"currenticon": [ 900, 0, 160, 2 ],
|
||||
"dir": [ 400, 100, 90 ],
|
||||
"umbrella": [ 390, 50, 60 ]
|
||||
},
|
||||
"9": {
|
||||
"title": [ 6, 0, "Signika-SB.ttf", 32 ],
|
||||
"items": 12,
|
||||
@@ -35,7 +50,7 @@
|
||||
"rotate": 0,
|
||||
"mode": 1,
|
||||
"days": 7,
|
||||
"gridparam": [ 7, 19, 30, "calibrib16.vlw", "REFSAN12.vlw", 16 ]
|
||||
"gridparam": [ 3, 25, 40, "fonts/calibrib30", "REFSAN12.vlw", 16 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,56 @@
|
||||
{
|
||||
"version": 2,
|
||||
"name": "M3 4.3\"",
|
||||
"width": 522,
|
||||
"height": 152,
|
||||
"rotatebuffer": 3,
|
||||
"bpp": 2,
|
||||
"colortable": {
|
||||
"white": [ 255, 255, 255 ],
|
||||
"black": [ 0, 0, 0 ],
|
||||
"red": [ 255, 0, 0 ]
|
||||
},
|
||||
"shortlut": 0,
|
||||
"zlib_compression": "27",
|
||||
"options": [ "button" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 11, 17, 18, 19, 20, 27 ],
|
||||
"usetemplate": 1,
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 160, 5, "Signika-SB.ttf", 60 ],
|
||||
"month": [ 160, 75, "Signika-SB.ttf", 60 ],
|
||||
"day": [ 422, -27, "Signika-SB.ttf", 170 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "Signika-SB.ttf", 170, 170, 170, 170, 170, 170 ],
|
||||
"xy": [ 261, 63 ]
|
||||
},
|
||||
"9": {
|
||||
"title": [ 6, 0, "Signika-SB.ttf", 25 ],
|
||||
"items": 1,
|
||||
"line": [ 9, 40, "calibrib16.vlw" ],
|
||||
"desc": [ 2, 8, "REFSAN12.vlw", 1.2 ]
|
||||
},
|
||||
"11": {
|
||||
"rotate": 1,
|
||||
"mode": 1,
|
||||
"days": 1,
|
||||
"gridparam": [ 5, 17, 20, "calibrib16.vlw", "tahoma9.vlw", 14 ]
|
||||
},
|
||||
"27": {
|
||||
"bars": [ 27, 468, 100, 18 ],
|
||||
"time": [ "calibrib16.vlw" ],
|
||||
"yaxis": [ "tahoma9.vlw", 5, 6 ],
|
||||
"head": [ "calibrib30.vlw" ]
|
||||
}
|
||||
}
|
||||
"version": 4,
|
||||
"name": "M3 4.3\"",
|
||||
"width": 522,
|
||||
"height": 152,
|
||||
"rotatebuffer": 3,
|
||||
"bpp": 2,
|
||||
"colortable": {
|
||||
"white": [ 255, 255, 255 ],
|
||||
"black": [ 0, 0, 0 ],
|
||||
"red": [ 255, 0, 0 ]
|
||||
},
|
||||
"shortlut": 0,
|
||||
"zlib_compression": "27",
|
||||
"options": [ "button" ],
|
||||
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 11, 17, 18, 19, 20, 27 ],
|
||||
"usetemplate": 4,
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 160, 5, "Signika-SB.ttf", 60 ],
|
||||
"month": [ 160, 75, "Signika-SB.ttf", 60 ],
|
||||
"day": [ 422, -27, "Signika-SB.ttf", 170 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "Signika-SB.ttf", 170, 170, 170, 170, 170, 170 ],
|
||||
"xy": [ 261, 63 ]
|
||||
},
|
||||
"8": {
|
||||
"location": [ 5, 12, "t0_14b_tf" ],
|
||||
"column": [ 7, 74 ],
|
||||
"day": [ 37, 20, "fonts/twcondensed20", 41, 105 ],
|
||||
"rain": [ 34, 130 ],
|
||||
"icon": [ 30, 55, 30 ],
|
||||
"wind": [ 27, 26 ],
|
||||
"line": [ 20, 150 ]
|
||||
},
|
||||
"9": {
|
||||
"title": [ 6, 0, "Signika-SB.ttf", 25 ],
|
||||
"items": 1,
|
||||
"line": [ 9, 40, "calibrib16.vlw" ],
|
||||
"desc": [ 2, 8, "REFSAN12.vlw", 1.2 ]
|
||||
},
|
||||
"11": {
|
||||
"rotate": 1,
|
||||
"mode": 1,
|
||||
"days": 1,
|
||||
"gridparam": [ 5, 17, 20, "calibrib16.vlw", "tahoma9.vlw", 14 ]
|
||||
},
|
||||
"27": {
|
||||
"bars": [ 27, 468, 100, 18 ],
|
||||
"time": [ "calibrib16.vlw" ],
|
||||
"yaxis": [ "tahoma9.vlw", 5, 6 ],
|
||||
"head": [ "calibrib30.vlw" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user