diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md
index 446c7b035..fa7e77d20 100644
--- a/CHANGELOG_LATEST.md
+++ b/CHANGELOG_LATEST.md
@@ -13,7 +13,7 @@ This release is based on the latest Espressif/Arduino core version 3. It brings
- option to disable factory reset [#3150](https://github.com/emsesp/EMS-ESP32/issues/3150)
- TLS support with 4MB boards without PSRAM
- added eth_10mbit to Network Settings, which forces 10BASE-T half-duplex & autonegotiation off, halving the PHY’s power draw. It’s off by default as it will cause issues on managed switches with a port forced to 100Mb [#3213](https://github.com/emsesp/EMS-ESP32/pull/3213)
-- cleaner MD5 and firmware uploading in WebUI [#3203](https://github.com/emsesp/EMS-ESP32/discussions/3203)
+- cleaner MD5 and firmware uploading in WebUI [#3222](https://github.com/emsesp/EMS-ESP32/issues/3222)
## Fixed
diff --git a/interface/src/api/system.ts b/interface/src/api/system.ts
index f12d5daa1..918929789 100644
--- a/interface/src/api/system.ts
+++ b/interface/src/api/system.ts
@@ -19,6 +19,7 @@ export const uploadFile = (file: File) => {
const formData = new FormData();
formData.append('file', file);
return alovaInstance.Post('/rest/uploadFile', formData, {
- timeout: UPLOAD_TIMEOUT
+ timeout: UPLOAD_TIMEOUT,
+ enableUpload: true
});
};
diff --git a/interface/src/app/settings/DownloadUpload.tsx b/interface/src/app/settings/DownloadUpload.tsx
index 24bbab1e8..3f2980451 100644
--- a/interface/src/app/settings/DownloadUpload.tsx
+++ b/interface/src/app/settings/DownloadUpload.tsx
@@ -165,11 +165,7 @@ const DownloadUpload = () => {
{LL.UPLOAD()}
-
- {LL.UPLOAD_TEXT()}:
-
-
-
+
);
};
diff --git a/interface/src/app/settings/Version.tsx b/interface/src/app/settings/Version.tsx
index 464bfd818..61a0cff22 100644
--- a/interface/src/app/settings/Version.tsx
+++ b/interface/src/app/settings/Version.tsx
@@ -846,7 +846,7 @@ const Version = () => {
{LL.UPLOAD()}
-
+
>
)}
diff --git a/interface/src/components/upload/SingleUpload.tsx b/interface/src/components/upload/SingleUpload.tsx
index 134cb9918..affc3c3cb 100644
--- a/interface/src/components/upload/SingleUpload.tsx
+++ b/interface/src/components/upload/SingleUpload.tsx
@@ -14,9 +14,10 @@ import { LinearProgressWithLabel } from './LinearProgressWithLabel';
interface SingleUploadProps {
doRestart: () => void;
+ text: string;
}
-const SingleUpload = ({ doRestart }: SingleUploadProps) => {
+const SingleUpload = ({ doRestart, text }: SingleUploadProps) => {
const [md5, setMd5] = useState();
const [file, setFile] = useState();
const { LL } = useI18nContext();
@@ -92,7 +93,7 @@ const SingleUpload = ({ doRestart }: SingleUploadProps) => {
>
) : (
)}
diff --git a/interface/src/i18n/cs/index.ts b/interface/src/i18n/cs/index.ts
index 6c8e67707..395a7cf77 100644
--- a/interface/src/i18n/cs/index.ts
+++ b/interface/src/i18n/cs/index.ts
@@ -178,10 +178,6 @@ const cs: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Vytvořte zálohu svého nastavení a konfigurace',
DOWNLOAD_SETTINGS_TEXT2: 'Exportovat všechny hodnoty',
DOWNLOAD_SYSTEM_BACKUP: 'Systémová záloha',
- UPLOAD_TEXT: 'Nahrajte nový soubor firmwaru (.bin) nebo záložní soubor (.json)',
- UPLOAD_DROP_TEXT: 'Přetáhněte soubor sem nebo klikněte pro výběr',
- UPLOAD_MD5_RECEIVED: 'Digest přijat, nyní nahrajte firmware .bin',
- UPLOAD_MD5_MATCHED: 'MD5 souhlasí, firmware se instaluje...',
ERROR: 'Neočekávaná chyba, zkuste to prosím znovu',
TIME_SET: 'Čas nastaven',
MANAGE_USERS: 'Spravovat uživatele',
@@ -351,7 +347,11 @@ const cs: Translation = {
COMMANDS_HELP_1: 'Definujte vlastní příkazy pro magistrali EMS',
COMMAND_EXECUTED: 'Příkaz úspěšně spuštěn',
RUN: 'Spustit příkaz',
- INTERNET_CONNECTION_CHECK: 'Kontrola online pro dostupné verze'
+ INTERNET_CONNECTION_CHECK: 'Kontrola online pro dostupné verze',
+ UPLOAD_BACKUP_TEXT: 'Klikněte, abyste vybrali nebo přetáhli a pustili soubor zálohy (.json) sem',
+ UPLOAD_FIRMWARE_TEXT: 'Klikněte, abyste vybrali nebo přetáhli a pustili soubor firmware .bin/.md5 sem',
+ UPLOAD_MD5_RECEIVED: 'Digest přijat, nyní nahrajte firmware .bin',
+ UPLOAD_MD5_MATCHED: 'MD5 souhlasí, firmware se instaluje...'
};
export default cs;
diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts
index f94a3573c..a356c4af0 100644
--- a/interface/src/i18n/de/index.ts
+++ b/interface/src/i18n/de/index.ts
@@ -178,10 +178,6 @@ const de: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Erstellen Sie eine Sicherung Ihrer Konfigurationen und Einstellungen',
DOWNLOAD_SETTINGS_TEXT2: 'Exportiere alle Werte',
DOWNLOAD_SYSTEM_BACKUP: 'Systemsicherung',
- UPLOAD_TEXT: 'Laden Sie eine neue Firmware-Datei (.bin) oder eine Sicherungsdatei (.json) hoch',
- UPLOAD_DROP_TEXT: 'Legen Sie eine Firmware-Datei (.bin) ab oder klicken Sie hier',
- UPLOAD_MD5_RECEIVED: 'Prüfsumme empfangen, jetzt die Firmware-Datei (.bin) hochladen',
- UPLOAD_MD5_MATCHED: 'MD5 stimmt überein, Firmware wird installiert...',
ERROR: 'Unerwarteter Fehler, bitte versuchen Sie es erneut.',
TIME_SET: 'Zeit gesetzt',
MANAGE_USERS: 'Nutzerverwaltung',
@@ -351,7 +347,11 @@ const de: Translation = {
COMMANDS_HELP_1: 'Definieren Sie eigene Befehle für die EMS-Magistral',
COMMAND_EXECUTED: 'Befehl erfolgreich ausgeführt',
RUN: 'Befehl ausführen',
- INTERNET_CONNECTION_CHECK: 'Online-Prüfung auf verfügbare Versionen'
+ INTERNET_CONNECTION_CHECK: 'Online-Prüfung auf verfügbare Versionen',
+ UPLOAD_BACKUP_TEXT: 'Klicken Sie, um eine Sicherungsdatei (.json) auszuwählen oder zu ziehen und abzulegen',
+ UPLOAD_FIRMWARE_TEXT: 'Klicken Sie, um eine Firmware-Datei (.bin/.md5) auszuwählen oder zu ziehen und abzulegen',
+ UPLOAD_MD5_RECEIVED: 'Prüfsumme empfangen, jetzt die Firmware-Datei (.bin) hochladen',
+ UPLOAD_MD5_MATCHED: 'MD5 stimmt überein, Firmware wird installiert...'
};
export default de;
diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts
index fdda0b131..ee4dde8b5 100644
--- a/interface/src/i18n/en/index.ts
+++ b/interface/src/i18n/en/index.ts
@@ -178,10 +178,6 @@ const en: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings',
DOWNLOAD_SETTINGS_TEXT2: 'Export all values',
DOWNLOAD_SYSTEM_BACKUP: 'System Backup',
- UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)',
- UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
- UPLOAD_MD5_RECEIVED: 'Digest received, now upload the firmware .bin file',
- UPLOAD_MD5_MATCHED: 'MD5 matches, installing firmware...',
ERROR: 'Unexpected Error, please try again',
TIME_SET: 'Time set',
MANAGE_USERS: 'Manage Users',
@@ -351,7 +347,11 @@ const en: Translation = {
COMMANDS_HELP_1: 'Define reusable named commands below. These can be executed from the console, API/MQTT, or referenced by the Scheduler',
COMMAND_EXECUTED: 'Command executed successfully',
RUN: 'Run',
- INTERNET_CONNECTION_CHECK: 'Checking online for available versions'
+ INTERNET_CONNECTION_CHECK: 'Checking online for available versions',
+ UPLOAD_BACKUP_TEXT: 'Click to select or Drag&Drop a backup file (.json) here',
+ UPLOAD_FIRMWARE_TEXT: 'Click to select or Drag&Drop a firmware .bin/.md5 file',
+ UPLOAD_MD5_RECEIVED: 'Digest received, now upload the firmware .bin file',
+ UPLOAD_MD5_MATCHED: 'MD5 matches, installing firmware...'
};
export default en;
diff --git a/interface/src/i18n/fr/index.ts b/interface/src/i18n/fr/index.ts
index 25953e148..b6245bfbe 100644
--- a/interface/src/i18n/fr/index.ts
+++ b/interface/src/i18n/fr/index.ts
@@ -178,10 +178,6 @@ const fr: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Créer une sauvegarde de vos paramètres et configurations',
DOWNLOAD_SETTINGS_TEXT2: 'Exporter toutes les valeurs',
DOWNLOAD_SYSTEM_BACKUP: 'Sauvegarde système',
- UPLOAD_TEXT: 'Télécharger un nouveau fichier firmware (.bin) ou une sauvegarde (.json)',
- UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
- UPLOAD_MD5_RECEIVED: 'Empreinte reçue, téléversez maintenant le fichier firmware .bin',
- UPLOAD_MD5_MATCHED: 'MD5 concordant, installation du firmware...',
ERROR: 'Erreur inattendue, veuillez réessayer',
TIME_SET: 'Time set',
MANAGE_USERS: 'Gérer les utilisateurs',
@@ -351,7 +347,11 @@ const fr: Translation = {
COMMANDS_HELP_1: 'Définir des commandes personnalisées pour la magistral EMS',
COMMAND_EXECUTED: 'Commande exécutée avec succès',
RUN: 'Exécuter une commande',
- INTERNET_CONNECTION_CHECK: 'Vérification en ligne pour les versions disponibles'
+ INTERNET_CONNECTION_CHECK: 'Vérification en ligne pour les versions disponibles',
+ UPLOAD_BACKUP_TEXT: 'Cliquez pour sélectionner ou faites glisser et déposez un fichier de sauvegarde (.json) ici',
+ UPLOAD_FIRMWARE_TEXT: 'Cliquez pour sélectionner ou faites glisser et déposez un fichier firmware .bin/.md5 ici',
+ UPLOAD_MD5_RECEIVED: 'Empreinte reçue, téléversez maintenant le fichier firmware .bin',
+ UPLOAD_MD5_MATCHED: 'MD5 concordant, installation du firmware...'
};
export default fr;
diff --git a/interface/src/i18n/it/index.ts b/interface/src/i18n/it/index.ts
index 78eb196a8..6a5bc8b00 100644
--- a/interface/src/i18n/it/index.ts
+++ b/interface/src/i18n/it/index.ts
@@ -178,10 +178,6 @@ const it: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings',
DOWNLOAD_SETTINGS_TEXT2: 'Esporta tutti i valori',
DOWNLOAD_SYSTEM_BACKUP: 'Backup sistema',
- UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)',
- UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
- UPLOAD_MD5_RECEIVED: 'Digest received, now upload the firmware .bin file',
- UPLOAD_MD5_MATCHED: 'MD5 matches, installing firmware...',
ERROR: 'Errore Inaspettato, prego tenta ancora',
TIME_SET: 'Imposta Ora',
MANAGE_USERS: 'Gestione Utenti',
@@ -351,7 +347,11 @@ const it: Translation = {
COMMANDS_HELP_1: 'Definisci comandi personalizzati per la magistrali EMS',
COMMAND_EXECUTED: 'Comando eseguito con successo',
RUN: 'Esegui comando',
- INTERNET_CONNECTION_CHECK: 'Controllo online per le versioni disponibili'
+ INTERNET_CONNECTION_CHECK: 'Controllo online per le versioni disponibili',
+ UPLOAD_BACKUP_TEXT: 'Klik per selezionare o trascinare e rilasciare un file di backup (.json) qui',
+ UPLOAD_FIRMWARE_TEXT: 'Klik per selezionare o trascinare e rilasciare un file firmware .bin/.md5 qui',
+ UPLOAD_MD5_RECEIVED: 'Digest ricevuto, ora caricare il file firmware .bin',
+ UPLOAD_MD5_MATCHED: 'MD5 corrispondente, installazione firmware...'
};
export default it;
diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts
index 2afeee95d..82ebaf690 100644
--- a/interface/src/i18n/nl/index.ts
+++ b/interface/src/i18n/nl/index.ts
@@ -178,10 +178,6 @@ const nl: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Maak een back-up van uw configuratie en instellingen',
DOWNLOAD_SETTINGS_TEXT2: 'Exporteer alle waarden',
DOWNLOAD_SYSTEM_BACKUP: 'Systeem Backup',
- UPLOAD_TEXT: 'Upload een nieuw firmwarebestand (.bin) of een back-upbestand (.json)',
- UPLOAD_DROP_TEXT: 'Sleep en firmware .bin bestand hierheen of klik hier',
- UPLOAD_MD5_RECEIVED: 'Digest ontvangen, upload nu het firmware .bin-bestand',
- UPLOAD_MD5_MATCHED: 'MD5 komt overeen, firmware wordt geïnstalleerd...',
ERROR: 'Onverwachte fout, probeer opnieuw',
TIME_SET: 'Tijd ingesteld',
MANAGE_USERS: 'Gebruikersbeheer',
@@ -351,7 +347,11 @@ const nl: Translation = {
COMMANDS_HELP_1: 'Definieer hergebruikbare benoemde commando\'s hieronder. Deze kunnen worden uitgevoerd vanuit de console, API/MQTT, of worden aangeroepen door de Scheduler',
COMMAND_EXECUTED: 'Commando uitgevoerd succesvol',
RUN: 'Commando uitvoeren',
- INTERNET_CONNECTION_CHECK: 'Controleren op online beschikbare versies'
+ INTERNET_CONNECTION_CHECK: 'Controleren op online beschikbare versies',
+ UPLOAD_BACKUP_TEXT: 'Klik voor selecteren of sleep en drop een back-upbestand (.json) hier',
+ UPLOAD_FIRMWARE_TEXT: 'Klik voor selecteren of sleep en drop een firmware .bin/.md5 bestand hier',
+ UPLOAD_MD5_RECEIVED: 'Digest ontvangen, upload nu het firmware .bin-bestand',
+ UPLOAD_MD5_MATCHED: 'MD5 komt overeen, firmware wordt geïnstalleerd...'
};
export default nl;
diff --git a/interface/src/i18n/no/index.ts b/interface/src/i18n/no/index.ts
index 7576d0c8b..e75c0156e 100644
--- a/interface/src/i18n/no/index.ts
+++ b/interface/src/i18n/no/index.ts
@@ -178,10 +178,6 @@ const no: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Lag en sikkerhetskopi av dine konfigurasjon og innstillinger',
DOWNLOAD_SETTINGS_TEXT2: 'Eksporter alle verdier',
DOWNLOAD_SYSTEM_BACKUP: 'System Sikkerhetskopi',
- UPLOAD_TEXT: 'Last opp en ny firmware fil (.bin) eller en sikkerhetskopi fil (.json)',
- UPLOAD_DROP_TEXT: 'Dropp en firmware fil (.bin) eller klikk her',
- UPLOAD_MD5_RECEIVED: 'Digest mottatt, last nå opp firmware .bin-filen',
- UPLOAD_MD5_MATCHED: 'MD5 stemmer, firmware installeres...',
ERROR: 'Ukjent feil, prøv igjen',
TIME_SET: 'Still in tid',
MANAGE_USERS: 'Administrer Brukere',
@@ -351,7 +347,11 @@ const no: Translation = {
COMMANDS_HELP_1: 'Definer egne kommandoer for EMS-Magistral',
COMMAND_EXECUTED: 'Kommando kjørt lykkes',
RUN: 'Kjør',
- INTERNET_CONNECTION_CHECK: 'Kontrollerer online for tilgjengelige versjoner'
+ INTERNET_CONNECTION_CHECK: 'Kontrollerer online for tilgjengelige versjoner',
+ UPLOAD_BACKUP_TEXT: 'Klikk for å velge eller dra og slipp en sikkerhetskopi (.json) her',
+ UPLOAD_FIRMWARE_TEXT: 'Klikk for å velge eller dra og slipp en firmware .bin/.md5 her',
+ UPLOAD_MD5_RECEIVED: 'MD5 mottatt, last nå opp firmware .bin-filen',
+ UPLOAD_MD5_MATCHED: 'MD5 stemmer, firmware installeres...'
};
export default no;
diff --git a/interface/src/i18n/pl/index.ts b/interface/src/i18n/pl/index.ts
index 3f0e4ab8e..a258e5e3a 100644
--- a/interface/src/i18n/pl/index.ts
+++ b/interface/src/i18n/pl/index.ts
@@ -178,10 +178,6 @@ const pl: BaseTranslation = {
DOWNLOAD_SETTINGS_TEXT: 'Utwórz kopię swoich ustawień i konfiguracji',
DOWNLOAD_SETTINGS_TEXT2: 'Eksportuj wszystkie wartości',
DOWNLOAD_SYSTEM_BACKUP: 'Kopia zapasowa systemu',
- UPLOAD_TEXT: 'Wgraj nowy plik firmware (.bin) lub kopię ustawień (.json)',
- UPLOAD_DROP_TEXT: 'Upuść plik firmware .bin lub kliknij tutaj',
- UPLOAD_MD5_RECEIVED: 'Suma MD5 odebrana, teraz wgraj plik firmware .bin',
- UPLOAD_MD5_MATCHED: 'MD5 zgodne, instalowanie firmware...',
ERROR: 'Nieoczekiwany błąd, spróbuj ponownie!',
TIME_SET: 'Zegar został ustawiony.',
MANAGE_USERS: 'Zarządzanie użytkownikami',
@@ -351,7 +347,11 @@ const pl: BaseTranslation = {
COMMANDS_HELP_1: 'Zdefiniuj niestandardowe komendy dla magistrali EMS',
COMMAND_EXECUTED: 'Komenda wykonana pomyślnie',
RUN: 'Wykonaj',
- INTERNET_CONNECTION_CHECK: 'Sprawdzanie online dla dostępnych wersji'
+ INTERNET_CONNECTION_CHECK: 'Sprawdzanie online dla dostępnych wersji',
+ UPLOAD_BACKUP_TEXT: 'Kliknij, aby wybrać lub przeciągnij i upuść plik kopii zapasowej (.json) tutaj',
+ UPLOAD_FIRMWARE_TEXT: 'Kliknij, aby wybrać lub przeciągnij i upuść plik firmware .bin/.md5',
+ UPLOAD_MD5_RECEIVED: 'Suma MD5 odebrana, teraz wgraj plik firmware .bin',
+ UPLOAD_MD5_MATCHED: 'MD5 zgodne, instalowanie firmware...'
};
export default pl;
diff --git a/interface/src/i18n/sk/index.ts b/interface/src/i18n/sk/index.ts
index d0ab4c72d..9e5efbd7c 100644
--- a/interface/src/i18n/sk/index.ts
+++ b/interface/src/i18n/sk/index.ts
@@ -178,10 +178,6 @@ const sk: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Vytvorte zálohu svojej konfigurácie a nastavení',
DOWNLOAD_SETTINGS_TEXT2: 'Exportovať všetky hodnoty',
DOWNLOAD_SYSTEM_BACKUP: 'Systémová záloha',
- UPLOAD_TEXT: 'Nahrajte nový súbor firmvéru (.bin) alebo súbor zálohy (.json)',
- UPLOAD_DROP_TEXT: 'Presuňte súbor .bin firmvéru alebo kliknite sem',
- UPLOAD_MD5_RECEIVED: 'Digest prijatý, teraz nahrajte firmware .bin',
- UPLOAD_MD5_MATCHED: 'MD5 súhlasí, firmvér sa inštaluje...',
ERROR: 'Neočakávaná chyba, prosím skúste to znova',
TIME_SET: 'Nastavený čas',
MANAGE_USERS: 'Správa používateľov',
@@ -351,7 +347,11 @@ const sk: Translation = {
COMMANDS_HELP_1: 'Definujte vlastné príkazy pre magistrali EMS',
COMMAND_EXECUTED: 'Príkaz vykonaný úspešne',
RUN: 'Volať príkaz',
- INTERNET_CONNECTION_CHECK: 'Kontrola online pre dostupné verzie'
+ INTERNET_CONNECTION_CHECK: 'Kontrola online pre dostupné verzie',
+ UPLOAD_BACKUP_TEXT: 'Kliknite, aby ste vybrali alebo presuňte a upustili súbor zálohy (.json) sem',
+ UPLOAD_FIRMWARE_TEXT: 'Kliknite, aby ste vybrali alebo presuňte a upustili súbor firmware .bin/.md5',
+ UPLOAD_MD5_RECEIVED: 'Suma MD5 prijatá, teraz nahrajte firmware .bin',
+ UPLOAD_MD5_MATCHED: 'MD5 súhlasí, firmvér sa inštaluje...'
};
export default sk;
diff --git a/interface/src/i18n/sv/index.ts b/interface/src/i18n/sv/index.ts
index 7d299d96a..af7351901 100644
--- a/interface/src/i18n/sv/index.ts
+++ b/interface/src/i18n/sv/index.ts
@@ -178,10 +178,6 @@ const sv: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Skapa en säkerhetskopia av din konfiguration och inställningar',
DOWNLOAD_SETTINGS_TEXT2: 'Exportera alla värden',
DOWNLOAD_SYSTEM_BACKUP: 'System säkerhetskopia',
- UPLOAD_TEXT: 'Ladda upp en ny firmwarefil (.bin) eller en säkerhetskopiafil (.json)',
- UPLOAD_DROP_TEXT: 'Droppa en firmware .bin fil eller klicka här',
- UPLOAD_MD5_RECEIVED: 'Digest mottagen, ladda nu upp firmware .bin-filen',
- UPLOAD_MD5_MATCHED: 'MD5 stämmer, firmware installeras...',
ERROR: 'Okänt fel, var god försök igen',
TIME_SET: 'Ställ in tid',
MANAGE_USERS: 'Användare',
@@ -351,7 +347,11 @@ const sv: Translation = {
COMMANDS_HELP_1: 'Definiera egna kommandon för EMS-Magistral',
COMMAND_EXECUTED: 'Kommando kört lyckades',
RUN: 'Kör kommando',
- INTERNET_CONNECTION_CHECK: 'Kontrollerar online för tillgängliga versioner'
+ INTERNET_CONNECTION_CHECK: 'Kontrollerar online för tillgängliga versioner',
+ UPLOAD_BACKUP_TEXT: 'Klicka för att välja eller dra och släpp en säkerhetskopia (.json) här',
+ UPLOAD_FIRMWARE_TEXT: 'Klicka för att välja eller dra och släpp en firmware .bin/.md5 här',
+ UPLOAD_MD5_RECEIVED: 'MD5 mottagen, ladda nu upp firmware .bin-filen',
+ UPLOAD_MD5_MATCHED: 'MD5 stämmer, firmware installeras...'
};
export default sv;
diff --git a/interface/src/i18n/tr/index.ts b/interface/src/i18n/tr/index.ts
index 3525b3efd..c214abe47 100644
--- a/interface/src/i18n/tr/index.ts
+++ b/interface/src/i18n/tr/index.ts
@@ -178,10 +178,6 @@ const tr: Translation = {
DOWNLOAD_SETTINGS_TEXT: 'Yapılandırma ve ayarlarınızın yedekleme yapın',
DOWNLOAD_SETTINGS_TEXT2: 'Tüm değerleri dışarı al',
DOWNLOAD_SYSTEM_BACKUP: 'Sistem yedekleme',
- UPLOAD_TEXT: 'Yeni bir firmware dosyası (.bin) veya yedek dosyası (.json) yükle',
- UPLOAD_DROP_TEXT: 'Bir firmware .bin dosyası veya buraya tıklayın',
- UPLOAD_MD5_RECEIVED: 'Özet alındı, şimdi firmware .bin dosyasını yükleyin',
- UPLOAD_MD5_MATCHED: 'MD5 eşleşti, firmware yükleniyor...',
ERROR: 'Beklenemedik hata, lütfen tekrar deneyin.',
TIME_SET: 'Zaman ayarı',
MANAGE_USERS: 'Kullanıcıları yönet',
@@ -351,7 +347,11 @@ const tr: Translation = {
COMMANDS_HELP_1: 'Özel komutları EMS hattına tanımlayın',
COMMAND_EXECUTED: 'Komut başarıyla çalıştırıldı',
RUN: 'Komutu çalıştır',
- INTERNET_CONNECTION_CHECK: 'Online bağlantısı kontrol ediliyor'
+ INTERNET_CONNECTION_CHECK: 'Online bağlantısı kontrol ediliyor',
+ UPLOAD_BACKUP_TEXT: 'Yeni bir firmware dosyası (.bin) veya yedek dosyası (.json) yükle',
+ UPLOAD_FIRMWARE_TEXT: 'Bir firmware .bin dosyası veya buraya tıklayın',
+ UPLOAD_MD5_RECEIVED: 'Özet alındı, şimdi firmware .bin dosyasını yükleyin',
+ UPLOAD_MD5_MATCHED: 'MD5 eşleşti, firmware yükleniyor...'
};
export default tr;
diff --git a/interface/vite.config.ts b/interface/vite.config.ts
index 65ff0d722..c87ab4e41 100644
--- a/interface/vite.config.ts
+++ b/interface/vite.config.ts
@@ -207,9 +207,6 @@ export default defineConfig(
async ({ command, mode }: { command: string; mode: string }) => {
if (command === 'serve') {
console.log(`Preparing for standalone build with server, mode=${mode}`);
- // Imported through a computed URL so the config bundler leaves it as a real
- // runtime import: mock-api is a separate package with its own node_modules,
- // and inlining it here would drag its dependencies into every build.
const mockServerUrl = pathToFileURL(
path.resolve(import.meta.dirname, '../mock-api/mockServer.js')
).href;
diff --git a/mock-api/mockSSEServer.js b/mock-api/mockServer.js
similarity index 55%
rename from mock-api/mockSSEServer.js
rename to mock-api/mockServer.js
index 914164d8d..7fba27344 100644
--- a/mock-api/mockSSEServer.js
+++ b/mock-api/mockServer.js
@@ -1,5 +1,6 @@
-// Simulate EventSource for log messages in EMS-ESP standalone mode
-// Server-Sent Events (SSE)
+// EMS-ESP standalone mode to simulate
+// a REST server for file uploads
+// an EventSource (Server-Sent Events) for log messages in EMS-ESP standalone mode
const ONE_SECOND_MS = 1000;
// padding function
@@ -21,11 +22,113 @@ const formatDate = (date) => {
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`;
};
+const MOCK_REST_ORIGIN = 'http://localhost:3080';
+const UPLOAD_SIMULATED_KB_PER_SEC = 256;
+const UPLOAD_SLICE_BYTES = 16 * 1024;
+
+const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
+
+const readRequestThrottled = (req) =>
+ new Promise((resolve, reject) => {
+ const chunks = [];
+ let ended = false;
+ let settled = false;
+
+ const settle = (settler, value) => {
+ if (settled) {
+ return;
+ }
+ settled = true;
+ settler(value);
+ };
+
+ req.on('error', (error) => settle(reject, error));
+ req.on('end', () => {
+ ended = true;
+ void step();
+ });
+
+ const step = async () => {
+ if (settled) {
+ return;
+ }
+ try {
+ const chunk = req.read(UPLOAD_SLICE_BYTES);
+ if (chunk) {
+ chunks.push(chunk);
+ await sleep((chunk.length / (UPLOAD_SIMULATED_KB_PER_SEC * 1024)) * 1000);
+ void step();
+ return;
+ }
+ if (ended || req.readableEnded) {
+ settle(resolve, Buffer.concat(chunks));
+ return;
+ }
+ req.once('readable', () => {
+ void step();
+ });
+ } catch (error) {
+ settle(reject, error);
+ }
+ };
+
+ void step();
+ });
+
+const forwardThrottledUpload = async (req, res) => {
+ const startedAt = Date.now();
+ try {
+ const body = await readRequestThrottled(req);
+ console.log(
+ `Upload received: ${body.length} bytes in ${((Date.now() - startedAt) / 1000).toFixed(1)}s`
+ );
+ const headers = {};
+ if (req.headers['content-type']) {
+ headers['content-type'] = req.headers['content-type'];
+ }
+ if (req.headers.authorization) {
+ headers.authorization = req.headers.authorization;
+ }
+ headers['content-length'] = String(body.length);
+
+ const bunRes = await fetch(`${MOCK_REST_ORIGIN}${req.url}`, {
+ method: 'POST',
+ headers,
+ body
+ });
+ const buf = Buffer.from(await bunRes.arrayBuffer());
+ res.statusCode = bunRes.status;
+ bunRes.headers.forEach((value, key) => {
+ if (key !== 'transfer-encoding' && key !== 'content-encoding') {
+ res.setHeader(key, value);
+ }
+ });
+ res.end(buf);
+ } catch (error) {
+ if (error?.code === 'ECONNRESET' || req.destroyed) {
+ console.log('Upload cancelled by the client');
+ } else {
+ console.error('Throttled upload proxy failed', error);
+ }
+ if (!res.headersSent) {
+ res.statusCode = 502;
+ }
+ if (!res.writableEnded) {
+ res.end();
+ }
+ }
+};
+
export default () => {
return {
- name: 'vite:mockserver',
+ name: 'vite:mockServer',
configureServer: async (server) => {
server.middlewares.use(async (req, res, next) => {
+ if (req.url.startsWith('/rest/uploadFile') && req.method === 'POST') {
+ await forwardThrottledUpload(req, res);
+ return;
+ }
+
// Handle Server-Sent Events (SSE) for log streaming
if (req.url.startsWith('/es/log')) {
// Set SSE headers
diff --git a/mock-api/restServer.ts b/mock-api/restServer.ts
index a75f81127..ea02c45e3 100644
--- a/mock-api/restServer.ts
+++ b/mock-api/restServer.ts
@@ -242,15 +242,6 @@ let countHardwarePoll = 0; // for during an upload
let pendingFirmwareMd5 = false; // set by a .md5 upload, cleared by the next .bin
const VALID_UPLOAD_EXTENSIONS = new Set(['bin', 'json', 'md5']);
-const UPLOAD_PROGRESS_LOG_STEP = 10; // log every 10%
-
-// A real device takes a while to accept a firmware image, so uploads are read at
-// this rate instead of completing instantly. That keeps the WebUI progress bar on
-// screen long enough to see. Lower it to watch the progress bar for longer.
-const UPLOAD_SIMULATED_KB_PER_SEC = 2048;
-const UPLOAD_SLICE_BYTES = 64 * 1024; // granularity of the simulated transfer
-
-const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
function parseMd5Digest(text: string): string | null {
const token = text.trim().split(/\s+/)[0];
@@ -260,45 +251,6 @@ function parseMd5Digest(text: string): string | null {
return null;
}
-// Read the multipart body in slices at UPLOAD_SIMULATED_KB_PER_SEC, logging progress
-// as it goes, then hand the buffered bytes back as FormData so they parse normally.
-async function readUploadSlowly(request: Request): Promise {
- const contentType = request.headers.get('content-type') || '';
- const expected = Number(request.headers.get('content-length') || '0');
- const reader = request.body?.getReader();
- const chunks: Uint8Array[] = [];
- let received = 0;
- let loggedPercentage = 0;
-
- while (reader) {
- const { done, value } = await reader.read();
- if (done) {
- break;
- }
- chunks.push(value);
-
- // A fast local client arrives in very few chunks, so pace each one slice by
- // slice to keep the reported progress gradual instead of jumping to 100%
- for (let offset = 0; offset < value.length; offset += UPLOAD_SLICE_BYTES) {
- const sliceLength = Math.min(UPLOAD_SLICE_BYTES, value.length - offset);
- await sleep((sliceLength / (UPLOAD_SIMULATED_KB_PER_SEC * 1024)) * 1000);
- received += sliceLength;
-
- if (expected > 0) {
- const percentage = Math.round((received / expected) * 100);
- if (percentage >= loggedPercentage + UPLOAD_PROGRESS_LOG_STEP) {
- loggedPercentage = percentage;
- console.log(`Upload progress: ${percentage}%`);
- }
- }
- }
- }
-
- return new Response(new Blob(chunks as BlobPart[]), {
- headers: { 'content-type': contentType }
- }).formData();
-}
-
// DeviceTypes
const enum ScheduleFlag {
SCHEDULE_SUN = 1,
@@ -4702,7 +4654,7 @@ router
// SYSTEM and SETTINGS
router
.post(EMSESP_UPLOAD_FILE_ENDPOINT, async (request: Request) => {
- const formData = await readUploadSlowly(request);
+ const formData = await request.formData();
const uploaded = formData.get('file');
if (!uploaded || typeof uploaded === 'string') {
return status(400);
diff --git a/project-words.txt b/project-words.txt
index 3204475a4..ae59838d4 100644
--- a/project-words.txt
+++ b/project-words.txt
@@ -744,7 +744,7 @@ mlongcalls
mmio
mmode
mmplus
-mockSSEServer
+mockServer
modbus
modee
modetype