Compare commits
2 Commits
v1.0.0
...
3648538cbc
| Author | SHA1 | Date | |
|---|---|---|---|
| 3648538cbc | |||
| a02e280f42 |
29
.gitea/workflows/release.yml
Normal file
29
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Build Release
|
||||
on:
|
||||
push:
|
||||
tags: ['v*']
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install PlatformIO
|
||||
run: pip install platformio
|
||||
|
||||
- name: Build firmware
|
||||
run: pio run
|
||||
|
||||
- name: Upload firmware.bin to release
|
||||
uses: actions/upload-release-asset@v1
|
||||
with:
|
||||
upload_url: ${{ gitea.release.upload_url }}
|
||||
asset_path: .pio/build/esp32dev/firmware.bin
|
||||
asset_name: firmware.bin
|
||||
asset_content_type: application/octet-stream
|
||||
11
src/config.h
11
src/config.h
@@ -37,7 +37,7 @@ namespace Config {
|
||||
// require a meaningful User-Agent instead of the HTTPClient
|
||||
// default, see https://operations.osmfoundation.org/policies/nominatim/.
|
||||
constexpr const char* NOMINATIM_HOST = "nominatim.openstreetmap.org";
|
||||
constexpr const char* NOMINATIM_USER_AGENT = "EiswolfsFlightradarCYD (github.com/Eiswolf-BG/eiswolfs-flightradar-CYD)";
|
||||
constexpr const char* NOMINATIM_USER_AGENT = "EiswolfsFlightradarCYD (git.rasmusbendtsen.dk/rasmus/flyradar)";
|
||||
|
||||
struct GpsPinPair { uint8_t rx; uint8_t tx; const char* label; };
|
||||
constexpr GpsPinPair GPS_PIN_CANDIDATES[] = {
|
||||
@@ -115,5 +115,12 @@ constexpr float RANGE_STEPS_KM[] = {10.0f, 25.0f, 50.0f, 100.0f};
|
||||
constexpr const char* EMERGENCY_SQUAWKS[] = {"7500", "7600", "7700"};
|
||||
constexpr uint8_t EMERGENCY_SQUAWK_COUNT = 3;
|
||||
|
||||
constexpr uint8_t MAX_WIFI_NETWORKS = 3;
|
||||
constexpr uint8_t MAX_WIFI_NETWORKS = 3;
|
||||
|
||||
// Gitea OTA update (Menu > System > "Check for update") - checks
|
||||
// the latest release in a private Gitea repository and downloads
|
||||
// firmware.bin from there. See ota_update.cpp.
|
||||
constexpr const char* GITEA_API_BASE = "git.rasmusbendtsen.dk";
|
||||
constexpr const char* GITEA_API_PATH = "/api/v1/repos/rasmus/flyradar/releases/latest";
|
||||
constexpr const char* GITEA_API_TOKEN = "YOUR_GITEA_TOKEN_HERE"; // set this!
|
||||
}
|
||||
@@ -255,7 +255,7 @@ static const char* const I18N_DE[] = {
|
||||
"Das Update konnte nicht heruntergeladen oder installiert werden. Das Gerät läuft unverändert mit der bisherigen Firmware weiter. Bitte WLAN-Verbindung prüfen und es später erneut versuchen.",
|
||||
"Bildschirm-Timeout",
|
||||
"Nach dieser Zeit ohne Berührung schaltet sich das Display ab, um Strom zu sparen. Ist der Ruhebildschirm aktiviert, zeigt es stattdessen einen gedimmten Sternenhimmel mit Uhrzeit.",
|
||||
"Eco Mode",
|
||||
"Eco Mode ",
|
||||
"Streckenfilter",
|
||||
"ICAO eingeben",
|
||||
};
|
||||
|
||||
@@ -256,7 +256,7 @@ static const char* const I18N_EN[] = {
|
||||
"The update could not be downloaded or installed. The device is still running the previous firmware, unchanged. Please check your WiFi connection and try again later.",
|
||||
"Screen Timeout",
|
||||
"After this time without touch, the display turns off to save power. With the screensaver on, it dims to a starfield with a clock instead.",
|
||||
"Eco Mode",
|
||||
"Eco Mode ",
|
||||
"Route Filter",
|
||||
"Enter ICAO",
|
||||
};
|
||||
|
||||
@@ -255,7 +255,7 @@ static const char* const I18N_ES[] = {
|
||||
"No se pudo descargar o instalar la actualización. El dispositivo sigue funcionando sin cambios con el firmware anterior. Comprueba tu conexión WiFi e inténtalo de nuevo más tarde.",
|
||||
"Tiempo de espera de pantalla",
|
||||
"Tras este tiempo sin toques, la pantalla se apaga para ahorrar energía. Con el salvapantallas activado, muestra en su lugar un cielo estrellado atenuado con la hora.",
|
||||
"Eco Mode",
|
||||
"Eco Mode ",
|
||||
"Filtro de ruta",
|
||||
"Ingresa OACI",
|
||||
};
|
||||
|
||||
@@ -255,7 +255,7 @@ static const char* const I18N_FR[] = {
|
||||
"La mise à jour n'a pas pu être téléchargée ou installée. L'appareil continue de fonctionner normalement avec le micrologiciel précédent. Merci de vérifier votre connexion WiFi et de réessayer plus tard.",
|
||||
"Délai d'inactivité",
|
||||
"Après ce délai sans contact, l'écran s'éteint pour économiser l'énergie. Avec l'écran de veille activé, il affiche à la place un ciel étoilé tamisé avec l'heure.",
|
||||
"Eco Mode",
|
||||
"Eco Mode ",
|
||||
"Filtre d'itinéraire",
|
||||
"Entrer code OACI",
|
||||
};
|
||||
|
||||
@@ -255,7 +255,7 @@ static const char* const I18N_IT[] = {
|
||||
"Non è stato possibile scaricare o installare l'aggiornamento. Il dispositivo continua a funzionare senza modifiche con il firmware precedente. Controlla la connessione WiFi e riprova più tardi.",
|
||||
"Timeout schermo",
|
||||
"Dopo questo tempo senza tocchi, lo schermo si spegne per risparmiare energia. Con il salvaschermo attivo, mostra invece un cielo stellato attenuato con l'orario.",
|
||||
"Eco Mode",
|
||||
"Eco Mode ",
|
||||
"Filtro rotta",
|
||||
"Inserisci ICAO",
|
||||
};
|
||||
|
||||
@@ -255,7 +255,7 @@ static const char* const I18N_TR[] = {
|
||||
"Güncelleme indirilemedi veya yüklenemedi. Cihaz değişmeden önceki donanım yazılımıyla çalışmaya devam ediyor. Lütfen WiFi bağlantınızı kontrol edip daha sonra tekrar deneyin.",
|
||||
"Ekran Zaman Aşımı",
|
||||
"Bu süre boyunca dokunulmazsa ekran güç tasarrufu için kapanır. Ekran koruyucu açıksa, bunun yerine saatli, sönük bir yıldızlı gökyüzü gösterir.",
|
||||
"Eco Mode",
|
||||
"Eco Mode ",
|
||||
"Rota Filtresi",
|
||||
"ICAO Girin",
|
||||
};
|
||||
|
||||
@@ -687,6 +687,7 @@ void run(TFT_eSPI& tft) {
|
||||
drawButton(tft, brightnessBtn, brightnessLabel(SettingsStore::brightnessPercent()));
|
||||
drawButton(tft, timeoutBtn, screenTimeoutLabel(SettingsStore::screenTimeoutMinutes()));
|
||||
drawButton(tft, nightDimBtn, I18n::t(StringId::MENU_NIGHT_DIMMING) + onOff(SettingsStore::nightDimmingEnabled()));
|
||||
drawButton(tft, ecoModeBtn, I18n::t(StringId::MENU_ECO_MODE) + onOff(SettingsStore::ecoModeEnabled()));
|
||||
drawButton(tft, webuiBtn, I18n::t(StringId::MENU_LOGBOOK_WEBUI));
|
||||
drawButton(tft, backupResetBtn, I18n::t(StringId::MENU_BACKUP_RESET));
|
||||
drawButton(tft, checkUpdateBtn, I18n::t(StringId::MENU_CHECK_UPDATE));
|
||||
|
||||
@@ -13,12 +13,11 @@ namespace OtaUpdate {
|
||||
|
||||
namespace {
|
||||
constexpr const char* RELEASES_API_URL =
|
||||
"https://api.github.com/repos/Eiswolf-BG/eiswolfs-flightradar-CYD/releases/latest";
|
||||
// GitHub requires a meaningful User-Agent for API requests
|
||||
// (otherwise HTTP 403) - same principle as Config::NOMINATIM_USER_AGENT
|
||||
// for address search.
|
||||
constexpr const char* USER_AGENT =
|
||||
"EiswolfsFlightradarCYD-OTA/1.0 (+https://github.com/Eiswolf-BG/eiswolfs-flightradar-CYD)";
|
||||
"https://git.rasmusbendtsen.dk/api/v1/repos/rasmus/flyradar/releases/latest";
|
||||
// Gitea API uses Authorization: token header instead of
|
||||
// User-Agent. The token is set in Config::GITEA_API_TOKEN.
|
||||
// Gitea serves downloads directly (no redirect), so
|
||||
// setFollowRedirects is not needed.
|
||||
|
||||
bool parseVersion(const char* s, int& major, int& minor, int& patch) {
|
||||
major = minor = patch = 0;
|
||||
@@ -56,7 +55,12 @@ CheckInfo checkForUpdate() {
|
||||
Serial.println("[OTA] Check failed: http.begin() returned false.");
|
||||
return info;
|
||||
}
|
||||
http.addHeader("User-Agent", USER_AGENT);
|
||||
http.addHeader("User-Agent", "EiswolfsFlightradarCYD-OTA/1.0");
|
||||
if (Config::GITEA_API_TOKEN[0]) {
|
||||
String auth = "token ";
|
||||
auth += Config::GITEA_API_TOKEN;
|
||||
http.addHeader("Authorization", auth);
|
||||
}
|
||||
|
||||
int code = http.GET();
|
||||
if (code != HTTP_CODE_OK) {
|
||||
@@ -121,21 +125,25 @@ bool performUpdate(const char* url, void (*onProgress)(uint8_t percent)) {
|
||||
Serial.printf("[OTA] Starting: url=%s freeHeap=%u RSSI=%ddBm\n", url,
|
||||
(unsigned)ESP.getFreeHeap(), WiFi.RSSI());
|
||||
|
||||
WiFiClientSecure client;
|
||||
WiFiClientSecure client;
|
||||
client.setInsecure();
|
||||
client.setTimeout(15000);
|
||||
|
||||
// IMPORTANT: GitHub's "browser_download_url" for release assets is NOT
|
||||
// a direct download link, but first returns an HTTP 301/302 redirect
|
||||
// to a signed objects.githubusercontent.com URL. HTTPUpdate does NOT
|
||||
// follow redirects by default (HTTPC_DISABLE_FOLLOW_REDIRECTS is the
|
||||
// default) - without this line the download aborts with HTTP_UPDATE_FAILED
|
||||
// because only the redirect response arrives instead of the .bin file. See
|
||||
// e.g. espressif/arduino-esp32#3020. HTTPC_STRICT_FOLLOW_REDIRECTS
|
||||
// suffices since we only use GET.
|
||||
httpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
// Gitea serves downloads directly (no redirect like GitHub's S3),
|
||||
// but private repos still need the Authorization header. Use the
|
||||
// HTTPClient overload of httpUpdate.update() so we can set it.
|
||||
HTTPClient http;
|
||||
if (!http.begin(client, url)) {
|
||||
Serial.println("[OTA] Failed: http.begin() returned false for download URL.");
|
||||
return false;
|
||||
}
|
||||
if (Config::GITEA_API_TOKEN[0]) {
|
||||
String auth = "token ";
|
||||
auth += Config::GITEA_API_TOKEN;
|
||||
http.addHeader("Authorization", auth);
|
||||
}
|
||||
|
||||
// We show a brief success message ourselves after successful installation,
|
||||
// We show a brief success message ourselves after successful installation,
|
||||
// before the device reboots - see
|
||||
// menu_screen.cpp::runOtaUpdateScreen().
|
||||
httpUpdate.rebootOnUpdate(false);
|
||||
@@ -156,7 +164,9 @@ bool performUpdate(const char* url, void (*onProgress)(uint8_t percent)) {
|
||||
}
|
||||
});
|
||||
|
||||
t_httpUpdate_return result = httpUpdate.update(client, url);
|
||||
t_httpUpdate_return result = httpUpdate.update(http);
|
||||
|
||||
http.end();
|
||||
|
||||
if (result != HTTP_UPDATE_OK) {
|
||||
Serial.printf("[OTA] Failed: result=%d error=%d (%s) freeHeap=%u\n", (int)result,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
// Firmware update over WiFi (Menu > System > "Check for update") -
|
||||
// checks against the latest version in the GitHub repository (Releases API) and
|
||||
// checks against the latest version in a private Gitea repository (Releases API) and
|
||||
// installs it on the device directly upon confirmation, without cable/
|
||||
// web flasher. Blocking, synchronous HTTPS calls - only executed on
|
||||
// explicit button press (no background polling), analogous to
|
||||
@@ -23,7 +23,7 @@ namespace OtaUpdate {
|
||||
char downloadUrl[192] = {0};
|
||||
};
|
||||
|
||||
// Queries the GitHub Releases API for the latest release, compares
|
||||
// Queries the Gitea Releases API for the latest release, compares
|
||||
// its version number (tag name, "v" prefix is ignored) against
|
||||
// Config::APP_VERSION and looks for the "firmware.bin" attachment in the release.
|
||||
// CheckResult::Error on any error along the way (no WiFi, timeout,
|
||||
|
||||
Reference in New Issue
Block a user