Move all user-facing strings to strings.xml, add user-facing-text.md reference

This commit is contained in:
eddy 2026-07-29 20:48:20 +02:00
commit c46db32cc7
6 changed files with 195 additions and 55 deletions

View file

@ -39,7 +39,7 @@ class EspFlasher(private val context: Context) {
} }
private class FlashStep( private class FlashStep(
val name: String, val nameResId: Int,
val address: Int, val address: Int,
val data: ByteArray, val data: ByteArray,
val baseProgress: Int, val baseProgress: Int,
@ -52,22 +52,22 @@ class EspFlasher(private val context: Context) {
coroutineContext.ensureActive() coroutineContext.ensureActive()
val connection = usbManager.openDevice(device) val connection = usbManager.openDevice(device)
?: throw IOException("Kan USB-apparaat niet openen") ?: throw IOException(context.getString(R.string.err_usb_open))
try { try {
val intf = UsbUtils.findCdcDataInterface(device) val intf = UsbUtils.findCdcDataInterface(device)
?: throw IOException("Geen CDC data interface gevonden") ?: throw IOException(context.getString(R.string.err_no_cdc))
if (!connection.claimInterface(intf, true)) { if (!connection.claimInterface(intf, true)) {
throw IOException("Kan USB interface niet claimen") throw IOException(context.getString(R.string.err_usb_claim))
} }
val epOut = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_OUT) val epOut = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_OUT)
?: throw IOException("Geen USB OUT endpoint gevonden") ?: throw IOException(context.getString(R.string.err_no_out))
val epIn = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_IN) val epIn = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_IN)
?: throw IOException("Geen USB IN endpoint gevonden") ?: throw IOException(context.getString(R.string.err_no_in))
callback.onProgress(0, "Verbinden met ESP bootloader...") callback.onProgress(0, context.getString(R.string.flash_connecting))
val transport = UsbSerialTransport(connection, epOut, epIn) val transport = UsbSerialTransport(connection, epOut, epIn)
coroutineContext.ensureActive() coroutineContext.ensureActive()
@ -78,20 +78,14 @@ class EspFlasher(private val context: Context) {
val bootApp0 = assets.open("firmware/boot_app0.bin").readBytes() val bootApp0 = assets.open("firmware/boot_app0.bin").readBytes()
val firmware = assets.open("firmware/firmware.bin").readBytes() val firmware = assets.open("firmware/firmware.bin").readBytes()
// Flash sectie layout (partition table check):
// NVS 0x9000-0xDFFF — NIET overschreven (key/UUID blijft behouden)
// otadata 0xE000-0xFFFF — overschreven door boot_app0
// app0 0x10000-... — firmware overschrijft
// Alleen schrijven naar benodigde adressen, geen full erase
val steps = listOf( val steps = listOf(
FlashStep("Bootloader", 0x0, bootloader, 30, 10, false), FlashStep(R.string.flash_step_bootloader, 0x0, bootloader, 30, 10, false),
FlashStep("Partitie tabel", 0x8000, partitions, 40, 10, false), FlashStep(R.string.flash_step_partitions, 0x8000, partitions, 40, 10, false),
FlashStep("Boot app0", 0xe000, bootApp0, 50, 10, false), FlashStep(R.string.flash_step_boot_app0, 0xe000, bootApp0, 50, 10, false),
FlashStep("Firmware", 0x10000, firmware, 60, 35, true) FlashStep(R.string.flash_step_firmware, 0x10000, firmware, 60, 35, true)
) )
callback.onProgress(5, "Sync met bootloader...") callback.onProgress(5, context.getString(R.string.flash_sync))
val api = EspFlasherApi.connect(transport) val api = EspFlasherApi.connect(transport)
.withCallBack(object : ProgressCallback { .withCallBack(object : ProgressCallback {
override fun onProgress(pct: Float) { override fun onProgress(pct: Float) {
@ -102,31 +96,32 @@ class EspFlasher(private val context: Context) {
} }
}) })
callback.onProgress(10, "Chip detecteren...") callback.onProgress(10, context.getString(R.string.flash_detect))
val detected = api.chipDetect() val detected = api.chipDetect()
val chipId = detected.getChipId() val chipId = detected.getChipId()
Log.i(TAG, "Detected chip: $chipId") Log.i(TAG, "Detected chip: $chipId")
callback.onProgress(15, "Chip: ${chipId.readableName}") callback.onProgress(15, context.getString(R.string.flash_chip, chipId.readableName))
callback.onProgress(20, "Stub laden...") callback.onProgress(20, context.getString(R.string.flash_stub))
val stub = detected.loadStub() val stub = detected.loadStub()
for (step in steps) { for (step in steps) {
coroutineContext.ensureActive() coroutineContext.ensureActive()
val stepName = context.getString(step.nameResId)
val sizeStr = if (step.data.size > 1024) "${step.data.size / 1024}KB" else "${step.data.size} bytes" val sizeStr = if (step.data.size > 1024) "${step.data.size / 1024}KB" else "${step.data.size} bytes"
callback.onProgress(step.baseProgress, "${step.name} schrijven ($sizeStr)...") callback.onProgress(step.baseProgress, "$stepName schrijven ($sizeStr)...")
val writeStub = if (step.compress) stub.withCompression(true) else stub.withCompression(false) val writeStub = if (step.compress) stub.withCompression(true) else stub.withCompression(false)
writeStub.writeFlash(step.address, step.data) writeStub.writeFlash(step.address, step.data)
val endProgress = step.baseProgress + step.range val endProgress = step.baseProgress + step.range
callback.onProgress(endProgress.coerceAtMost(95), "${step.name} geschreven") callback.onProgress(endProgress.coerceAtMost(95), "$stepName geschreven")
} }
callback.onProgress(95, "ESP resetten...") callback.onProgress(95, "ESP resetten...")
stub.reset() stub.reset()
callback.onProgress(100, "Firmware geflashed!") callback.onProgress(100, context.getString(R.string.flash_done))
} finally { } finally {
connection.close() connection.close()
} }

View file

@ -278,7 +278,8 @@ class SettingsActivity : AppCompatActivity() {
showConflictDialog(usbManager, device, result.espUuid, result.espKey, appKey ?: "") showConflictDialog(usbManager, device, result.espUuid, result.espKey, appKey ?: "")
} }
is KeyResult.Error -> { is KeyResult.Error -> {
Toast.makeText(this@SettingsActivity, getString(R.string.key_exchange_failed), Toast.LENGTH_LONG).show() val msg = if (result.arg != null) getString(result.resId, result.arg!!) else getString(result.resId)
Toast.makeText(this@SettingsActivity, msg, Toast.LENGTH_LONG).show()
cleanupAction() cleanupAction()
} }
null -> { null -> {
@ -431,25 +432,25 @@ class SettingsActivity : AppCompatActivity() {
sealed class KeyResult { sealed class KeyResult {
data class Success(val deviceUuid: String, val hexKey: String) : KeyResult() data class Success(val deviceUuid: String, val hexKey: String) : KeyResult()
data class Conflict(val espUuid: String, val espKey: String) : KeyResult() data class Conflict(val espUuid: String, val espKey: String) : KeyResult()
data class Error(val message: String) : KeyResult() data class Error(val resId: Int, val arg: String? = null) : KeyResult()
} }
private fun readKeyFromEsp(usbManager: UsbManager, device: UsbDevice, appUuid: String?, appKey: String?): KeyResult? { private fun readKeyFromEsp(usbManager: UsbManager, device: UsbDevice, appUuid: String?, appKey: String?): KeyResult? {
val intf = UsbUtils.findCdcDataInterface(device) val intf = UsbUtils.findCdcDataInterface(device)
?: return KeyResult.Error("Geen CDC interface gevonden") ?: return KeyResult.Error(R.string.err_no_cdc)
val connection = usbManager.openDevice(device) val connection = usbManager.openDevice(device)
?: return KeyResult.Error("Kan USB apparaat niet openen") ?: return KeyResult.Error(R.string.err_usb_open)
if (!connection.claimInterface(intf, true)) { if (!connection.claimInterface(intf, true)) {
connection.close() connection.close()
return KeyResult.Error("Kan USB interface niet claimen") return KeyResult.Error(R.string.err_usb_claim)
} }
val epOut = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_OUT) val epOut = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_OUT)
?: run { connection.close(); return KeyResult.Error("Geen USB OUT endpoint gevonden") } ?: run { connection.close(); return KeyResult.Error(R.string.err_no_out) }
val epIn = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_IN) val epIn = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_IN)
?: run { connection.close(); return KeyResult.Error("Geen USB IN endpoint gevonden") } ?: run { connection.close(); return KeyResult.Error(R.string.err_no_in) }
try { try {
setupCdcControl(connection, device) setupCdcControl(connection, device)
@ -489,7 +490,7 @@ class SettingsActivity : AppCompatActivity() {
} }
return KeyResult.Success(espUuidUpper, espKeyUpper) return KeyResult.Success(espUuidUpper, espKeyUpper)
} else { } else {
return KeyResult.Error("Ongeldig sleutel/UUID formaat") return KeyResult.Error(R.string.err_invalid_key)
} }
} else if (noKey) { } else if (noKey) {
val newKey: String val newKey: String
@ -508,7 +509,7 @@ class SettingsActivity : AppCompatActivity() {
val w = connection.bulkTransfer(epOut, setKeyCmd, setKeyCmd.size, USB_BULK_TIMEOUT_MS) val w = connection.bulkTransfer(epOut, setKeyCmd, setKeyCmd.size, USB_BULK_TIMEOUT_MS)
Log.d(TAG, "Sent SET_KEY ($w bytes)") Log.d(TAG, "Sent SET_KEY ($w bytes)")
if (w < 0) { if (w < 0) {
return KeyResult.Error("SET_KEY schrijven mislukt") return KeyResult.Error(R.string.err_set_key_write)
} }
Thread.sleep(RESPONSE_WAIT_MS) Thread.sleep(RESPONSE_WAIT_MS)
@ -516,14 +517,14 @@ class SettingsActivity : AppCompatActivity() {
Log.d(TAG, "SET_KEY response: ${okKeyResponse.take(200)}") Log.d(TAG, "SET_KEY response: ${okKeyResponse.take(200)}")
if (!okKeyResponse.contains("OK")) { if (!okKeyResponse.contains("OK")) {
return KeyResult.Error("ESP bevestigde sleutel niet") return KeyResult.Error(R.string.err_key_not_ack)
} }
val setIdCmd = "SET_ID:$newUuid\n".toByteArray(StandardCharsets.US_ASCII) val setIdCmd = "SET_ID:$newUuid\n".toByteArray(StandardCharsets.US_ASCII)
val w2 = connection.bulkTransfer(epOut, setIdCmd, setIdCmd.size, USB_BULK_TIMEOUT_MS) val w2 = connection.bulkTransfer(epOut, setIdCmd, setIdCmd.size, USB_BULK_TIMEOUT_MS)
Log.d(TAG, "Sent SET_ID ($w2 bytes)") Log.d(TAG, "Sent SET_ID ($w2 bytes)")
if (w2 < 0) { if (w2 < 0) {
return KeyResult.Error("SET_ID schrijven mislukt") return KeyResult.Error(R.string.err_set_id_write)
} }
Thread.sleep(RESPONSE_WAIT_MS) Thread.sleep(RESPONSE_WAIT_MS)
@ -533,17 +534,17 @@ class SettingsActivity : AppCompatActivity() {
if (okUuidResponse.contains("OK")) { if (okUuidResponse.contains("OK")) {
return KeyResult.Success(newUuid, newKey) return KeyResult.Success(newUuid, newKey)
} else { } else {
return KeyResult.Error("ESP bevestigde UUID niet") return KeyResult.Error(R.string.err_uuid_not_ack)
} }
} }
Log.w(TAG, "Attempt $attempt: no KEY response, retrying") Log.w(TAG, "Attempt $attempt: no KEY response, retrying")
} }
return KeyResult.Error("Geen sleutel gevonden na 5 pogingen") return KeyResult.Error(R.string.err_key_retries)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Key exchange error", e) Log.e(TAG, "Key exchange error", e)
return KeyResult.Error("Fout: ${e.message}") return KeyResult.Error(R.string.err_generic, e.message)
} finally { } finally {
try { connection.close() } catch (_: Exception) {} try { connection.close() } catch (_: Exception) {}
} }
@ -692,7 +693,8 @@ class SettingsActivity : AppCompatActivity() {
finish() finish()
} }
is KeyResult.Error -> { is KeyResult.Error -> {
Toast.makeText(this@SettingsActivity, result.message, Toast.LENGTH_LONG).show() val msg = if (result.arg != null) getString(result.resId, result.arg!!) else getString(result.resId)
Toast.makeText(this@SettingsActivity, msg, Toast.LENGTH_LONG).show()
cleanupAction() cleanupAction()
} }
else -> { else -> {
@ -707,20 +709,20 @@ class SettingsActivity : AppCompatActivity() {
private fun writeKeysToEsp(usbManager: UsbManager, device: UsbDevice, private fun writeKeysToEsp(usbManager: UsbManager, device: UsbDevice,
appKey: String, appUuid: String): KeyResult? { appKey: String, appUuid: String): KeyResult? {
val intf = UsbUtils.findCdcDataInterface(device) val intf = UsbUtils.findCdcDataInterface(device)
?: return KeyResult.Error("Geen CDC interface gevonden") ?: return KeyResult.Error(R.string.err_no_cdc)
val connection = usbManager.openDevice(device) val connection = usbManager.openDevice(device)
?: return KeyResult.Error("Kan USB apparaat niet openen") ?: return KeyResult.Error(R.string.err_usb_open)
if (!connection.claimInterface(intf, true)) { if (!connection.claimInterface(intf, true)) {
connection.close() connection.close()
return KeyResult.Error("Kan USB interface niet claimen") return KeyResult.Error(R.string.err_usb_claim)
} }
val epOut = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_OUT) val epOut = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_OUT)
?: run { connection.close(); return KeyResult.Error("Geen USB OUT endpoint gevonden") } ?: run { connection.close(); return KeyResult.Error(R.string.err_no_out) }
val epIn = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_IN) val epIn = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_IN)
?: run { connection.close(); return KeyResult.Error("Geen USB IN endpoint gevonden") } ?: run { connection.close(); return KeyResult.Error(R.string.err_no_in) }
try { try {
setupCdcControl(connection, device) setupCdcControl(connection, device)
@ -729,20 +731,20 @@ class SettingsActivity : AppCompatActivity() {
val setKeyCmd = "SET_KEY:$appKey\n".toByteArray(StandardCharsets.US_ASCII) val setKeyCmd = "SET_KEY:$appKey\n".toByteArray(StandardCharsets.US_ASCII)
val w = connection.bulkTransfer(epOut, setKeyCmd, setKeyCmd.size, USB_BULK_TIMEOUT_MS) val w = connection.bulkTransfer(epOut, setKeyCmd, setKeyCmd.size, USB_BULK_TIMEOUT_MS)
if (w < 0) return KeyResult.Error("SET_KEY schrijven mislukt") if (w < 0) return KeyResult.Error(R.string.err_set_key_write)
Log.d(TAG, "Sent SET_KEY ($w bytes)") Log.d(TAG, "Sent SET_KEY ($w bytes)")
Thread.sleep(RESPONSE_WAIT_MS) Thread.sleep(RESPONSE_WAIT_MS)
val okKeyResponse = readResponse(connection, epIn, SET_KEY_TIMEOUT_MS) val okKeyResponse = readResponse(connection, epIn, SET_KEY_TIMEOUT_MS)
if (!okKeyResponse.contains("OK")) return KeyResult.Error("ESP bevestigde sleutel niet") if (!okKeyResponse.contains("OK")) return KeyResult.Error(R.string.err_key_not_ack)
val setIdCmd = "SET_ID:$appUuid\n".toByteArray(StandardCharsets.US_ASCII) val setIdCmd = "SET_ID:$appUuid\n".toByteArray(StandardCharsets.US_ASCII)
val w2 = connection.bulkTransfer(epOut, setIdCmd, setIdCmd.size, USB_BULK_TIMEOUT_MS) val w2 = connection.bulkTransfer(epOut, setIdCmd, setIdCmd.size, USB_BULK_TIMEOUT_MS)
if (w2 < 0) return KeyResult.Error("SET_ID schrijven mislukt") if (w2 < 0) return KeyResult.Error(R.string.err_set_id_write)
Thread.sleep(RESPONSE_WAIT_MS) Thread.sleep(RESPONSE_WAIT_MS)
val okUuidResponse = readResponse(connection, epIn, SET_KEY_TIMEOUT_MS) val okUuidResponse = readResponse(connection, epIn, SET_KEY_TIMEOUT_MS)
if (!okUuidResponse.contains("OK")) return KeyResult.Error("ESP bevestigde UUID niet") if (!okUuidResponse.contains("OK")) return KeyResult.Error(R.string.err_uuid_not_ack)
val prefs = PrefsHelper.getPrefs(this) val prefs = PrefsHelper.getPrefs(this)
prefs.edit() prefs.edit()
@ -752,7 +754,7 @@ class SettingsActivity : AppCompatActivity() {
return KeyResult.Success(appUuid, appKey) return KeyResult.Success(appUuid, appKey)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Write keys error", e) Log.e(TAG, "Write keys error", e)
return KeyResult.Error("Fout: ${e.message}") return KeyResult.Error(R.string.err_generic, e.message)
} finally { } finally {
try { connection.close() } catch (_: Exception) {} try { connection.close() } catch (_: Exception) {}
} }

View file

@ -11,7 +11,7 @@
android:layout_gravity="end|top" android:layout_gravity="end|top"
android:src="@drawable/ic_settings" android:src="@drawable/ic_settings"
android:background="?android:attr/selectableItemBackgroundBorderless" android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="Instellingen" /> android:contentDescription="@string/cd_settings" />
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -46,7 +46,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|start" android:layout_gravity="bottom|start"
android:text="Disconnected" android:text="@string/status_default"
android:textSize="14sp" /> android:textSize="14sp" />
</FrameLayout> </FrameLayout>

View file

@ -8,7 +8,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Sluit de ESP aan op USB en kies een actie." android:text="@string/msg_settings_intro"
android:textSize="16sp" android:textSize="16sp"
android:layout_marginBottom="24dp" /> android:layout_marginBottom="24dp" />
@ -16,7 +16,7 @@
android:id="@+id/exchangeKeyButton" android:id="@+id/exchangeKeyButton"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Sleutel Uitwisselen" /> android:text="@string/button_key_exchange" />
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
@ -28,7 +28,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Zet de ESP in download-modus (houd reset 2s in tot de groene LED aangaat) en tik op 'Firmware Flashen'." android:text="@string/msg_flash_mode_help"
android:textSize="14sp" android:textSize="14sp"
android:layout_marginBottom="16dp" /> android:layout_marginBottom="16dp" />
@ -36,7 +36,7 @@
android:id="@+id/flashFirmwareButton" android:id="@+id/flashFirmwareButton"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Firmware Flashen" /> android:text="@string/button_firmware_flash" />
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -4,6 +4,7 @@
<string name="settings">Instellingen</string> <string name="settings">Instellingen</string>
<!-- MainActivity status --> <!-- MainActivity status -->
<string name="status_default">Disconnected</string>
<string name="status_discovering_services">Verbonden, services zoeken…</string> <string name="status_discovering_services">Verbonden, services zoeken…</string>
<string name="status_connecting">Verbinden…</string> <string name="status_connecting">Verbinden…</string>
<string name="status_connected">Connected</string> <string name="status_connected">Connected</string>
@ -19,11 +20,16 @@
<string name="button_retry_scan">Opnieuw scannen</string> <string name="button_retry_scan">Opnieuw scannen</string>
<!-- MainActivity UI --> <!-- MainActivity UI -->
<string name="cd_settings">Instellingen</string>
<string name="button_on">ON</string> <string name="button_on">ON</string>
<string name="button_hold">HOLD</string> <string name="button_hold">HOLD</string>
<!-- SettingsActivity --> <!-- SettingsActivity -->
<string name="title_settings">Instellingen</string> <string name="title_settings">Instellingen</string>
<string name="msg_settings_intro">Sluit de ESP aan op USB en kies een actie.</string>
<string name="button_key_exchange">Sleutel Uitwisselen</string>
<string name="msg_flash_mode_help">Zet de ESP in download-modus (houd reset 2s in tot de groene LED aangaat) en tik op Firmware Flashen.</string>
<string name="button_firmware_flash">Firmware Flashen</string>
<string name="build_number">Buildnummer: %s</string> <string name="build_number">Buildnummer: %s</string>
<string name="usb_access_denied">USB-toegang geweigerd</string> <string name="usb_access_denied">USB-toegang geweigerd</string>
<string name="key_read_success">Beveiligingssleutel gelezen</string> <string name="key_read_success">Beveiligingssleutel gelezen</string>
@ -55,6 +61,32 @@
<string name="button_close">Sluiten</string> <string name="button_close">Sluiten</string>
<string name="button_cancel">Annuleren</string> <string name="button_cancel">Annuleren</string>
<!-- SettingsActivity error messages -->
<string name="err_no_cdc">Geen CDC interface gevonden</string>
<string name="err_usb_open">Kan USB apparaat niet openen</string>
<string name="err_usb_claim">Kan USB interface niet claimen</string>
<string name="err_no_out">Geen USB OUT endpoint gevonden</string>
<string name="err_no_in">Geen USB IN endpoint gevonden</string>
<string name="err_invalid_key">Ongeldig sleutel/UUID formaat</string>
<string name="err_key_retries">Geen sleutel gevonden na 5 pogingen</string>
<string name="err_generic">Fout: %s</string>
<string name="err_set_key_write">SET_KEY schrijven mislukt</string>
<string name="err_set_id_write">SET_ID schrijven mislukt</string>
<string name="err_key_not_ack">ESP bevestigde sleutel niet</string>
<string name="err_uuid_not_ack">ESP bevestigde UUID niet</string>
<!-- EspFlasher -->
<string name="flash_connecting">Verbinden met ESP bootloader…</string>
<string name="flash_step_bootloader">Bootloader</string>
<string name="flash_step_partitions">Partitie tabel</string>
<string name="flash_step_boot_app0">Boot app0</string>
<string name="flash_step_firmware">Firmware</string>
<string name="flash_sync">Sync met bootloader…</string>
<string name="flash_detect">Chip detecteren…</string>
<string name="flash_chip">Chip: %s</string>
<string name="flash_stub">Stub laden…</string>
<string name="flash_done">Firmware geflashed!</string>
<!-- Label customization --> <!-- Label customization -->
<string name="section_labels">Knoptekst</string> <string name="section_labels">Knoptekst</string>
<string name="hint_label_relay1">Relay 1</string> <string name="hint_label_relay1">Relay 1</string>

111
docs/user-facing-text.md Normal file
View file

@ -0,0 +1,111 @@
# User-facing text — Atom Relay
## MainActivity — statusbalk
| Huidige tekst | strings.xml key |
|---|---|
| Connected | `status_connected` |
| Verbinden… | `status_connecting` |
| Servicefout | `status_service_error` |
| Service not found | `status_service_not_found` |
| Communicatiefout | `status_comm_error` |
| Geen HMAC sleutel - open Instellingen | `status_no_key` |
| Permissies geweigerd — open Instellingen | `status_permissions_denied` |
| Bluetooth not enabled | `status_bluetooth_disabled` |
| Scanning… | `status_scanning` |
| Device not found | `status_device_not_found` |
| Verkeerd apparaat — opnieuw scannen… | `status_wrong_device` |
| Verbonden, services zoeken… | `status_discovering_services` |
## MainActivity — knoppen
| Huidige tekst | strings.xml key |
|---|---|
| Instellingen (contentDescription) | `cd_settings` |
| Disconnected (placeholder) | `status_default` |
| HOLD (fallback knoplabel) | `button_hold` |
| Opnieuw scannen (fallback) | `button_retry_scan` |
| User-defined labels 1 & 2 | PrefsHelper (user input) |
## SettingsActivity — UI
| Huidige tekst | strings.xml key |
|---|---|
| Sluit de ESP aan op USB en kies een actie. | `msg_settings_intro` |
| Sleutel Uitwisselen | `button_key_exchange` |
| Zet de ESP in download-modus (houd reset 2s in tot de groene LED aangaat) en tik op Firmware Flashen. | `msg_flash_mode_help` |
| Firmware Flashen | `button_firmware_flash` |
| Knoptekst | `section_labels` |
| Relay 1 | `hint_label_relay1` |
| Relay 2 | `hint_label_relay2` |
| Weergave | `section_theme` |
| Systeem | `theme_system` |
| Licht | `theme_light` |
| Donker | `theme_dark` |
| Thema: %s | `theme_applied` |
| Buildnummer: %s | `build_number` |
## SettingsActivity — dialogs / toasts
| Huidige tekst | strings.xml key |
|---|---|
| Sleutel Uitwisselen | `title_key_exchange` |
| Sluit de ESP aan via USB. | `msg_connect_usb` |
| Sleutel uitlezen… | `msg_reading_key` |
| Beveiligingssleutel gelezen | `key_read_success` |
| Sleutel uitwisselen mislukt - probeer opnieuw | `key_exchange_failed` |
| USB-toegang geweigerd | `usb_access_denied` |
| Annuleren | `button_cancel` |
| Sluiten | `button_close` |
| Firmware Flashen | `title_firmware_flash` |
| Zet de ESP in download-modus (houd reset 2s in tot groene LED) en sluit aan via USB. | `msg_flash_download_mode` |
| Initialiseren… | `msg_initializing` |
| Firmware geflashed!\\n\\nOntkoppel de ESP en sluit opnieuw aan om de sleutel in te stellen. | `msg_flash_complete` |
| Flashen mislukt: %s | `flash_failed` |
| Sleutels komen niet overeen | `title_key_conflict` |
| De ESP (SylDa_Server) heeft andere sleutels dan deze app. Wat wil je doen? | `msg_key_conflict` |
| ESP sleutels overnemen | `button_keep_esp_keys` |
| App sleutels overzetten | `button_overwrite_esp` |
| ESP sleutels overschrijven? | `title_overwrite_confirm` |
| Dit vervangt de sleutels van de ESP. De ESP kan daarna niet meer met de oorspronkelijke app communiceren. | `msg_overwrite_warning` |
| Ik weet het zeker | `checkbox_confirm_overwrite` |
| Bevestigen | `button_confirm` |
| Sleutels overschrijven | `title_overwriting_keys` |
| Sleutels schrijven naar ESP… | `msg_writing_keys` |
## SettingsActivity — foutmeldingen (hardcoded in .kt)
| Huidige tekst | strings.xml key |
|---|---|
| Geen CDC interface gevonden | `err_no_cdc` |
| Kan USB apparaat niet openen | `err_usb_open` |
| Kan USB interface niet claimen | `err_usb_claim` |
| Geen USB OUT endpoint gevonden | `err_no_out` |
| Geen USB IN endpoint gevonden | `err_no_in` |
| Ongeldig sleutel/UUID formaat | `err_invalid_key` |
| Geen sleutel gevonden na 5 pogingen | `err_key_retries` |
| Fout: %s | `err_generic` |
| SET_KEY schrijven mislukt | `err_set_key_write` |
| SET_ID schrijven mislukt | `err_set_id_write` |
| ESP bevestigde sleutel niet | `err_key_not_ack` |
| ESP bevestigde UUID niet | `err_uuid_not_ack` |
## EspFlasher — hardcoded in .kt
| Huidige tekst | strings.xml key |
|---|---|
| Kan USB-apparaat niet openen | `err_usb_open` (reuse) |
| Geen CDC data interface gevonden | `err_no_cdc` (reuse) |
| Kan USB interface niet claimen | `err_usb_claim` (reuse) |
| Geen USB OUT endpoint gevonden | `err_no_out` (reuse) |
| Geen USB IN endpoint gevonden | `err_no_in` (reuse) |
| Verbinden met ESP bootloader... | `flash_connecting` |
| Bootloader | `flash_step_bootloader` |
| Partitie tabel | `flash_step_partitions` |
| Boot app0 | `flash_step_boot_app0` |
| Firmware | `flash_step_firmware` |
| Sync met bootloader... | `flash_sync` |
| Chip detecteren... | `flash_detect` |
| Chip: %s | `flash_chip` |
| Stub laden... | `flash_stub` |
| Firmware geflashed! | `flash_done` |
## AndroidManifest
| Huidige tekst | strings.xml key |
|---|---|
| Atom Relay | `app_name` |
| Instellingen | `settings` |