Skip to content

Commit 144cd59

Browse files
committed
feat(UI): add a upload config to duet button to settings
1 parent b3f3b53 commit 144cd59

File tree

14 files changed

+64
-19
lines changed

14 files changed

+64
-19
lines changed

assets/i18n/de-DE.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
"notifications": "Duet-Benachrichtigungen",
226226
"screen_networking": "Bildschirm-Netzwerk"
227227
},
228+
"send_config_to_duet": "Konfiguration zu Duet hochladen",
228229
"network": {
229230
"available_wifi": "Verfügbare WLAN-Netzwerke",
230231
"connect": "Verbinden",

assets/i18n/en-GB.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@
289289
"screen": "Screen",
290290
"screen_header": "Screen Settings",
291291
"screensaver_timeout": "Screensaver Timeout (s):",
292+
"send_config_to_duet": "Upload config to Duet",
292293
"show_confirmation_dialogs": "Show Confirmation Dialogs:",
293294
"storage_info": "Used Storage: ",
294295
"storage_info_format": "{:s} / {:s} ({:d}%)",

assets/i18n/es-ES.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
"notifications": "Notificaciones Duet",
226226
"screen_networking": "Red de pantalla"
227227
},
228+
"send_config_to_duet": "Subir configuración a Duet",
228229
"network": {
229230
"available_wifi": "Redes WiFi disponibles",
230231
"connect": "Conectar",

assets/i18n/fr-FR.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
"notifications": "Notifications Duet",
226226
"screen_networking": "Réseau de l'écran"
227227
},
228+
"send_config_to_duet": "Téléverser la configuration sur Duet",
228229
"network": {
229230
"available_wifi": "Réseaux WiFi disponibles",
230231
"connect": "Connecter",

assets/i18n/it-IT.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
"notifications": "Notifiche Duet",
226226
"screen_networking": "Rete dello schermo"
227227
},
228+
"send_config_to_duet": "Carica configurazione su Duet",
228229
"network": {
229230
"available_wifi": "Reti WiFi disponibili",
230231
"connect": "Connetti",

assets/i18n/nl-NL.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
"notifications": "Duet-meldingen",
226226
"screen_networking": "Schermnetwerk"
227227
},
228+
"send_config_to_duet": "Configuratie naar Duet uploaden",
228229
"network": {
229230
"available_wifi": "Beschikbare WiFi-netwerken",
230231
"connect": "Verbinden",

assets/i18n/pt-PT.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@
226226
"notifications": "Notificações Duet",
227227
"screen_networking": "Rede do ecrã"
228228
},
229+
"send_config_to_duet": "Carregar configuração para o Duet",
229230
"network": {
230231
"available_wifi": "Redes WiFi disponíveis",
231232
"connect": "Conectar",

scripts/manage_translations.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ def load_jsonc(path: Path) -> dict:
7676
"""Load a JSONC file, stripping comments before parsing."""
7777
raw = path.read_text(encoding="utf-8")
7878
cleaned = strip_jsonc_comments(raw)
79-
return json.loads(cleaned)
79+
try:
80+
return json.loads(cleaned)
81+
except json.decoder.JSONDecodeError as e:
82+
print(f"\n[ERROR] Failed to parse JSON in '{path}': {e}\n", file=sys.stderr)
83+
return None
8084

8185

8286
def save_json(path: Path, data: dict) -> None:
@@ -163,14 +167,18 @@ def process_file(
163167
dry_run: bool,
164168
) -> bool:
165169
"""Process a single translation file. Returns True if any issues found."""
170+
166171
lang_data = load_jsonc(lang_path)
172+
if lang_data is None:
173+
print(f"[SKIP] Skipping file due to JSON error: {lang_path}")
174+
return True
167175
translations = lang_data.get("translations", {})
168176
lang_flat = flatten_keys(translations)
169177
ref_keys = set(ref_flat.keys())
170178
lang_keys = set(lang_flat.keys())
171179

172180
extra_keys = sorted(lang_keys - ref_keys)
173-
missing_keys = sorted(ref_keys - lang_keys)
181+
missing_keys = sorted(ref_flat.keys() - lang_flat.keys())
174182

175183
# --- Format-brace validation ---
176184
brace_mismatches: list[tuple[str, int, int]] = []

src/Hardware/Duet.cpp

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -282,33 +282,44 @@ namespace Comm
282282
bool Duet::Post(std::string_view subUrl, HttpResponse& r, hv::QueryParams& queryParameters, std::string_view data)
283283
{
284284
ZoneScoped;
285-
#if 0
286-
if ((!m_sbcMode && m_sessionKey == sm_noSessionKey) ||
287-
(TimeHelper::getCurrentTime() - m_lastRequestTime > m_sessionTimeout))
285+
if (!IsConnected())
288286
{
289287
if (!Connect())
290288
{
291289
LOG_WARN("Failed to connect to Duet, cannot send post request {:s}", subUrl);
292290
return false;
293291
}
294292
}
295-
if (!Comm::Post(GetBaseUrl(), subUrl, r, queryParameters, data, m_sessionKey))
293+
294+
HttpRequest req;
295+
req.method = HTTP_POST;
296+
req.host = GetBaseUrl();
297+
req.path = subUrl;
298+
req.headers["Connection"] = "keep-alive";
299+
req.headers["Accept"] = "application/json";
300+
req.headers["Content-Type"] = "application/json";
301+
if (m_sessionKey != sm_noSessionKey)
296302
{
297-
if (r.code == 401 || r.code == 403)
298-
{
299-
LOG_ERROR("HTTP error {:d}: Likely invalid sessionKey {:d}. Running rr_connect", (int)r.code, m_sessionKey);
300-
Connect();
301-
return Comm::Post(GetBaseUrl(), subUrl, r, queryParameters, data, m_sessionKey);
302-
}
303+
// req.headers["X-Session-Key"] = fmt::format("{:d}", m_sessionKey).c_str();
304+
}
305+
req.query_params = queryParameters;
306+
req.timeout = HTTP_TIMEOUT;
307+
req.body = data;
308+
309+
req.DumpUrl();
310+
311+
hv::HttpClient cli;
312+
cli.send(&req, &r); // `send()` is not thread safe if using the same client so client is created on stack
313+
314+
LOG_DBG("Response (post): {:s} {:s}", req.url.c_str(), r.status_message());
315+
316+
if (r.status_code != HTTP_STATUS_OK)
317+
{
318+
LOG_ERROR("HTTP error {:d}: Likely invalid sessionKey {:d}.", (int)r.status_code, m_sessionKey);
303319
return false;
304320
}
305-
m_lastRequestTime = TimeHelper::getCurrentTime();
306-
#else
307-
UNUSED(subUrl);
308-
UNUSED(r);
309-
UNUSED(queryParameters);
310-
UNUSED(data);
311-
#endif
321+
LOG_VERBOSE("{:s}", r.body.c_str());
322+
m_lastRequestTime = TimeHelper::getRunningTime();
312323
return true;
313324
}
314325

src/UI/Screens/Settings/SettingsView.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ namespace UI
766766
#if DEVELOPER_MODE
767767
&m_runBuildrootSetup,
768768
#endif
769+
&m_sendConfigJson,
769770
&m_clearCache,
770771
})
771772
{
@@ -776,6 +777,14 @@ namespace UI
776777
m_eraseAndRestart.setText(_("settings.erase_and_restart"));
777778
m_reboot.setText(_("settings.reboot"));
778779
m_startHardwareTest.setText(_("settings.start_hardware_test"));
780+
m_sendConfigJson.setText(_("settings.send_config_to_duet"));
781+
m_sendConfigJson.addClickedCallback(
782+
[this](lv_event_t*)
783+
{
784+
std::string config = StorageHelper::dump();
785+
Comm::DUET.UploadFile(fmt::format("{:s}/duetscreen.json", OM::Directories::GetSystemDirectory()),
786+
config);
787+
});
779788

780789
m_restart.addClickedCallback([](lv_event_t*) { Restart(); });
781790
m_eraseAndRestart.addClickedCallback([](lv_event_t*) { EraseAndRestart(); });

0 commit comments

Comments
 (0)