Files
MicrOBU/app/src/main/res/values/strings.xml
T
Ashin Walpola 01204a2c22 Give the V2X live map its own screen, and a traffic light per SPATEM
The map was a third view mode inside the V2X Monitor's topic pane, below
the use case alert panel and the DENM/CAM TX cards. On a phone that left
it about a third of the display tall, which is not enough to see where
anything is relative to anything else - the one thing a map is for. It
is now its own destination, V2xMapScreen on route v2x_map, reached from
a map button in that screen's header. The button sits in the header
rather than the view-mode row so it is also reachable from the message
detail pane and does not move as the available modes change with the
selected hardware. The status bar and bottom nav are hidden on this
route; the screen carries its own floating back button, and system back
still works. Both hardware paths get the same screen: everything drawn
comes from CamUseCaseRepository, which already merges the CiT One's MQTT
feed and the ESP32-C5's serial feed into one set of flows.

With the map gone from the toggle row, the row offers a single choice on
the ESP32-C5 path - there is no broker there and `topics` is always
empty - so it is hidden entirely in that mode.

SPATEM markers. Hazards already drew as a warning triangle; signalised
intersections did not draw at all. They now draw as a traffic light with
one lamp lit. Two things are worth knowing, because neither is forced by
the data:

- SPATEM carries signal state but no geometry, which is MAPEM's job and
  MAPEM is not decoded. The only position available is the sending RSU's
  own CAM, so the light is drawn there, and that RSU is drawn once - as
  the light, not as a CAM pin with a light on top of it. An intersection
  whose sender has not been heard over CAM cannot be placed; the map
  says how many rather than dropping them silently.
- Which lamp lights follows the rule DashboardScreen's SignalCard
  already uses, the signal group changing soonest speaking for the
  intersection, so the same intersection reads the same way in both
  places instead of inventing a second convention.

Four drawables rather than one tinted at runtime: setTint recolours
every path in a vector, so a single shared asset would turn the whole
light one flat colour and stop it reading as a traffic light.

Marker reuse. Every incoming message recomposes the map, and the update
block cleared the overlay list and rebuilt every Marker, decoding and
mutating a fresh Drawable per marker - at up to 10 Hz per station. It
also called animateTo(own) on every update, restarting the pan animation
before it could finish. Drawables are now loaded once per alert level
and phase and shared (osmdroid sets the icon's bounds on each draw, so
one instance across markers is safe), Markers are cached by key, and the
overlay list is only reordered, which moves references without
allocating. Following uses setCenter, keeping animateTo for the one move
worth seeing: the rider asking for follow back.

Follow-own now hands over to the rider on the first touch and returns
via the location button, which lights up while following. Before this
the map could not be panned at all while traffic was flowing, since the
next CAM dragged the viewport back.

Also on the map view: tiles scaled to DPI, the floating +/- buttons off
(they sit where the thumb lands and duplicate pinch), a zoom range, and
more tile threads so a pan that exposes a screenful of new tiles is not
served two at a time.

Compiles and the unit tests pass. None of it has been seen with live
traffic; TODO.md lists the on-device checks under "Waiting on hardware",
including which of the HAW RSUs send CAM alongside SPATEM.
2026-09-15 17:23:01 +02:00

329 lines
20 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- App -->
<string name="app_name">MicrOBU</string>
<string name="app_subtitle">V2X Companion - Phase 02</string>
<!-- Language names (always shown in their own language) -->
<string name="lang_english">English</string>
<string name="lang_german">Deutsch</string>
<!-- Navigation -->
<string name="nav_dashboard">Dashboard</string>
<string name="nav_sensors">Sensors</string>
<string name="nav_record">Record</string>
<string name="nav_log">Log</string>
<string name="nav_v2x">V2X</string>
<string name="nav_settings">Settings</string>
<string name="nav_connection">Connection</string>
<!-- Dashboard -->
<string name="dash_gnss">GNSS</string>
<string name="dash_imu">IMU</string>
<string name="dash_obu_connection">OBU Connection</string>
<string name="dash_acquiring_fix">Acquiring fix…</string>
<string name="dash_permission_required">Permission required</string>
<string name="dash_tap_to_connect">Tap V2X to connect</string>
<string name="dash_connected">Connected</string>
<string name="dash_mqtt_connected">MQTT connected</string>
<string name="dash_mqtt_connecting">Connecting to broker…</string>
<string name="dash_mqtt_error">Broker unreachable - check V2X settings</string>
<string name="dash_recording">Recording</string>
<string name="dash_samples">samples</string>
<string name="dash_start_driving_session">Start Driving Session</string>
<string name="dash_initialising">Initialising…</string>
<!-- Dashboard live V2X panel: nearest hazard and nearest signalised intersection -->
<string name="dash_hazard_warning">Hazard warning</string>
<string name="dash_hazard_station">station %1$d</string>
<string name="dash_more_count">+%1$d more</string>
<string name="dash_signal_title">Traffic light %1$s</string>
<string name="dash_signal_more">+%1$d more intersection(s)</string>
<string name="dash_signal_phase_go">Green</string>
<string name="dash_signal_phase_stop">Red</string>
<string name="dash_signal_phase_changing">Changing</string>
<string name="dash_signal_phase_dark">Dark</string>
<string name="dash_signal_phase_unknown">Unknown</string>
<string name="dash_signal_countdown">%1$s · %2$.0f s</string>
<string name="stat_pressure">Pressure</string>
<string name="stat_altitude">Altitude</string>
<string name="stat_heading">Heading</string>
<string name="stat_accuracy">Accuracy</string>
<!-- Sensor Screen -->
<string name="sensor_monitor_title">Sensor Monitor</string>
<string name="sensor_gnss">Phone GNSS</string>
<string name="sensor_accel">Accelerometer</string>
<string name="sensor_gyro">Gyroscope</string>
<string name="sensor_magnet">Magnetometer</string>
<string name="sensor_baro">Barometer</string>
<string name="sensor_latitude">Latitude</string>
<string name="sensor_longitude">Longitude</string>
<string name="sensor_altitude">Altitude</string>
<string name="sensor_speed">Speed</string>
<string name="sensor_heading">Heading</string>
<string name="sensor_accuracy">Accuracy</string>
<string name="sensor_pressure">Pressure</string>
<string name="sensor_est_altitude">Est. altitude</string>
<string name="sensor_waiting">Waiting for location fix…</string>
<string name="sensor_initialising">Initialising…</string>
<string name="sensor_not_present">Sensor not present on this device</string>
<!-- Connection Setup -->
<string name="conn_title">Connection Setup</string>
<string name="conn_desc">Connect to the micrOBU hardware via Bluetooth (primary) or USB-C (fallback).</string>
<string name="conn_phase2_desc">USB-C tethering is the primary transport in Phase 02. Plug the OBU in and tap Connect.</string>
<string name="conn_bluetooth">Bluetooth</string>
<string name="conn_bluetooth_phase3">Bluetooth</string>
<string name="conn_bluetooth_phase3_desc">Bluetooth connection is planned for Phase 03 and is not yet implemented.</string>
<string name="conn_esp32_title">ESP32-C5 (USB Serial)</string>
<string name="conn_esp32_phase3_desc">USB-serial connection to the ESP32-C5 is scaffolded for Phase 03 but not yet functional - it needs the ESP32 firmware protocol translated to Kotlin first.</string>
<string name="conn_esp32_state_disconnected">Not connected - plug the ESP32-C5 into the native USB-C port and tap Connect.</string>
<string name="conn_esp32_state_device_attached">Device detected, opening…</string>
<string name="conn_esp32_state_permission_requested">Waiting for USB permission…</string>
<string name="conn_esp32_state_connected">Connected</string>
<string name="conn_esp32_state_error">Connection error - check the cable and native USB-C port, then try again.</string>
<string name="conn_esp32_connect">Connect to ESP32-C5</string>
<string name="conn_scan">Scan for Devices</string>
<string name="conn_scanning">Scanning…</string>
<string name="conn_usb_title">USB-C (Primary)</string>
<string name="conn_usb_stub">Connect via USB-C (not yet implemented)</string>
<string name="conn_usb_cable_ok">Cable detected</string>
<string name="conn_usb_cable_missing">No cable</string>
<string name="conn_usb_obu_ip">OBU IP</string>
<string name="conn_usb_detecting">Detecting…</string>
<string name="conn_usb_mode">IP source</string>
<string name="conn_usb_auto">Auto-detected</string>
<string name="conn_usb_manual">Manual override</string>
<string name="conn_usb_no_cable_hint">⚠ Connect the USB-C cable to detect the OBU, or disable auto-detect in Settings → Connection to use a manual IP.</string>
<string name="conn_connect">Connect</string>
<string name="conn_connect_mqtt">Connect to OBU</string>
<string name="conn_disconnect">Disconnect</string>
<string name="conn_selected">Selected</string>
<string name="conn_connected_stub">Connected (stub)</string>
<string name="conn_stub_warning">⚠ Bluetooth stack not yet implemented. This screen shows the target UI layout.</string>
<!-- Recording -->
<string name="rec_title">Recording Session</string>
<string name="rec_ready">Ready to record</string>
<string name="rec_samples_captured">%1$d samples captured</string>
<string name="rec_active_streams">Active Streams</string>
<string name="rec_button_stop">STOP</string>
<string name="rec_button_rec">REC</string>
<string name="stream_gnss">Phone GNSS</string>
<string name="stream_accel">Accelerometer</string>
<string name="stream_gyro">Gyroscope</string>
<string name="stream_magnet">Magnetometer</string>
<string name="stream_baro">Barometer</string>
<string name="stream_obu">OBU / MQTT</string>
<!-- Session Log -->
<string name="log_title">Session Log</string>
<string name="log_stored_one">%1$d session stored on device</string>
<string name="log_stored_other">%1$d sessions stored on device</string>
<string name="log_session_number">Session #%1$d</string>
<string name="log_share_cd">Share CSV</string>
<string name="log_save_cd">Save to device</string>
<string name="trip_export_cd">Export trip CSV</string>
<string name="log_delete_cd">Delete session</string>
<string name="log_empty_title">No sessions yet</string>
<string name="log_empty_desc">Go to Record and start a session</string>
<string name="log_delete_dialog_title">Delete session?</string>
<string name="log_delete_dialog_text">This will permanently remove the session recorded on %1$s from the device.</string>
<string name="log_delete_confirm">Delete</string>
<string name="log_cancel">Cancel</string>
<string name="log_export_chooser">Export session</string>
<!-- GNSS bottom sheet & map -->
<string name="gnss_sheet_title">GNSS Location</string>
<string name="gnss_open_maps">Open in Maps App</string>
<string name="gnss_open_maps_sub">Opens in your preferred maps application</string>
<string name="gnss_view_inapp">View in App</string>
<string name="gnss_view_inapp_sub">Show current location on an in-app map</string>
<string name="gnss_no_fix">No GPS fix yet - move to an open area</string>
<string name="map_title">Location Map</string>
<string name="map_location_label">Current Location</string>
<string name="v2x_map_own_label">Own (ego)</string>
<string name="v2x_map_remote_plain">Remote #%1$d</string>
<string name="v2x_map_remote_info">Remote #%1$d · Info</string>
<string name="v2x_map_remote_awareness">Remote #%1$d · Awareness</string>
<string name="v2x_map_remote_warning">Remote #%1$d · Warning</string>
<string name="v2x_map_title">V2X Live Map</string>
<string name="v2x_map_back">Back</string>
<string name="v2x_map_follow">Centre on own position</string>
<string name="v2x_map_legend_cam">Road users (CAM)</string>
<string name="v2x_map_legend_denm">Hazards (DENM)</string>
<string name="v2x_map_legend_spat">Signals (SPATEM)</string>
<string name="v2x_map_spat_unlocated">%1$d signal(s) not shown - sender position unknown</string>
<!-- Settings -->
<string name="settings_title">Settings</string>
<string name="settings_language">Language</string>
<string name="settings_appearance">Appearance</string>
<string name="settings_dark_theme">Dark theme</string>
<string name="settings_sensors">Sensor Streams</string>
<string name="settings_gnss">Phone GNSS</string>
<string name="settings_accel">Accelerometer</string>
<string name="settings_gyro">Gyroscope</string>
<string name="settings_magnet">Magnetometer</string>
<string name="settings_baro">Barometer</string>
<string name="settings_units">Units</string>
<string name="settings_metric">Metric (m, km/h, hPa)</string>
<string name="settings_mqtt_section">MQTT Broker</string>
<string name="settings_broker_ip">Broker IP</string>
<string name="settings_port">Port</string>
<string name="settings_username">Username</string>
<string name="settings_password">Password</string>
<string name="settings_optional">optional</string>
<string name="settings_show">Show</string>
<string name="settings_hide">Hide</string>
<string name="settings_developer">Developer</string>
<string name="settings_dev_mode">Developer mode</string>
<string name="settings_wifi">Wi-Fi OBU connection</string>
<string name="settings_wifi_val">Dev mode only - not implemented</string>
<string name="settings_about">About</string>
<string name="settings_app_version">App version</string>
<string name="settings_app_version_val">0.5.0 (Phase 03 - ESP32-C5 serial link + phone-built CAM)</string>
<string name="settings_connection">Connection</string>
<string name="settings_usb_auto_detect">Auto-detect OBU via USB-C</string>
<string name="settings_usb_manual_ip">Manual OBU IP</string>
<string name="settings_obu_hardware">OBU Hardware</string>
<string name="settings_obu_hardware_cit_one">CiT One</string>
<string name="settings_obu_hardware_esp32">ESP32-C5</string>
<string name="settings_obu_hardware_esp32_note">ESP32-C5 acts as a "dumb" transceiver: CAM is built and encoded on the phone, sent to the ESP32 over USB serial, and broadcast over ITS-G5. No MQTT broker or DENM use-case engine on this path - see the V2X Monitor screen\'s CAM Pinger for a manual test tool.</string>
<string name="settings_usb_transport">Active transport</string>
<string name="settings_transport_usbc">USB-C</string>
<string name="settings_transport_wifi">Wi-Fi</string>
<string name="settings_save_broker">Save Broker Settings</string>
<!-- MQTT Topic Viewer -->
<string name="mqtt_viewer_title">V2X Monitor</string>
<string name="mqtt_connect">Connect</string>
<string name="mqtt_disconnect">Disconnect</string>
<string name="mqtt_auto_scroll">Auto-scroll to latest</string>
<string name="mqtt_no_topics">No messages yet</string>
<string name="mqtt_view_list">List</string>
<string name="mqtt_view_topics">Topics</string>
<string name="mqtt_no_topics_hint">Connect to the OBU and wait for V2X traffic</string>
<string name="mqtt_no_messages">No messages on this topic yet</string>
<!-- DENM TX - manual antenna/RSU-range test tool only, not use-case-driven -->
<string name="mqtt_last_tx">Last transmitted payload:</string>
<string name="mqtt_denm_tx_title">DENM Transmission (Manual Test)</string>
<string name="mqtt_send_denm">Send Test DENM</string>
<string name="mqtt_stop_denm">Stop DENM</string>
<string name="mqtt_denm_use_case_desc">Aftermarket Stationary Vehicle (causeCode 94)</string>
<string name="mqtt_denm_not_connected">Connect to the OBU to enable DENM triggering</string>
<string name="mqtt_denm_active">DENM active - OBU broadcasting via ITS-G5</string>
<string name="mqtt_denm_hint">Manual antenna/RSU range test - publishes uca-denmctrl (retained) to v2x-uca/input/denmtrg. Not triggered by detected events or use case alerts.</string>
<string name="mqtt_denm_show">Show last TX</string>
<string name="mqtt_denm_hide">Hide</string>
<!-- CAM Pinger - ESP32-C5-only manual bench test, equivalent to the DENM TX card above -->
<string name="mqtt_cam_pinger_title">CAM Pinger (Manual Test)</string>
<string name="mqtt_cam_pinger_desc">1 Hz CAM ping built from live GNSS and IMU data - verifies the serial link and ESP32 radio path without needing a trip recording.</string>
<string name="mqtt_cam_pinger_no_fix">Waiting for GNSS fix - nothing transmitted yet</string>
<!-- Received-CAM list (ESP32-C5 path) -->
<string name="v2x_cam_rx_count">%1$d station(s) in range - latest CAM per station</string>
<string name="v2x_cam_rx_none">No CAMs received</string>
<string name="v2x_cam_rx_none_hint">Decoded CAMs from nearby stations appear here as they arrive.</string>
<string name="v2x_cam_rx_station">Station %1$d · %2$s</string>
<string name="v2x_cam_rx_kinematics">%1$.1f km/h · heading %2$.0f°</string>
<string name="v2x_cam_rx_distance">%1$.0f m</string>
<string name="v2x_cam_rx_distance_unknown">- m</string>
<string name="v2x_cam_rx_rssi">%1$d dBm</string>
<string name="v2x_cam_rx_none_stations">No CAMs received</string>
<string name="v2x_cam_rx_no_kinematics">roadside unit - no kinematics reported</string>
<!-- Received-DENM list (ESP32-C5 path) -->
<string name="v2x_denm_rx_count">%1$d active hazard(s) - latest DENM per event</string>
<string name="v2x_denm_rx_hazard">%1$s · station %2$d</string>
<string name="v2x_denm_rx_cause_code">cause %1$d/%2$d</string>
<string name="v2x_denm_rx_radius">%1$d m radius</string>
<!-- Received-SPATEM list (ESP32-C5 path) -->
<string name="v2x_spat_rx_count">%1$d signalised intersection(s) - live SPAT</string>
<string name="v2x_spat_rx_title">Intersection %1$s · station %2$d</string>
<string name="v2x_spat_group">SG%1$d</string>
<string name="v2x_spat_countdown">%1$.0f s</string>
<!-- DENM map pins -->
<string name="v2x_map_denm_labeled">Hazard: cause %1$d/%2$d (station %3$d)</string>
<string name="v2x_map_denm_plain">Hazard from station %1$d</string>
<!-- ETSI station types -->
<string name="station_type_pedestrian">Pedestrian</string>
<string name="station_type_cyclist">Cyclist</string>
<string name="station_type_car">Car</string>
<string name="station_type_bus">Bus</string>
<string name="station_type_truck">Truck</string>
<string name="station_type_rsu">Roadside unit</string>
<string name="station_type_other">Type %1$d</string>
<string name="mqtt_cam_pinger_not_connected">Connect the ESP32-C5 to enable the CAM pinger</string>
<string name="mqtt_cam_pinger_active">Pinging - 1 CAM/s over the serial link</string>
<string name="mqtt_cam_pinger_sent_count">Sent: %1$d</string>
<string name="mqtt_cam_pinger_send_failures">Write failures: %1$d consecutive - CAMs are not reaching the ESP32</string>
<string name="mqtt_cam_pinger_fw_counters">ESP32: tx fail %1$d · oversize %2$d · crc err %3$d</string>
<string name="mqtt_cam_pinger_loopback">Own TX heard back: %1$d frames · %2$d dBm</string>
<string name="mqtt_cam_pinger_loopback_no_rssi">Own TX heard back: %1$d frames</string>
<string name="mqtt_start_pinger">Start Pinger</string>
<string name="mqtt_stop_pinger">Stop Pinger</string>
<!-- CAM-based Use Case Alert panel -->
<string name="mqtt_usecase_panel_title">CAM Use Case Alerts</string>
<string name="mqtt_usecase_not_connected">Connect to the OBU to evaluate CAM-based use cases</string>
<string name="mqtt_usecase_none_active">No active use case alerts</string>
<string name="mqtt_usecase_detail">Station %1$d · %2$.0f m · closing %3$.1f m/s · TTC %4$.1f s · %5$s</string>
<!-- Human-readable use-case narratives (Section 10.4 - not just raw JSON) -->
<string name="usecase_narrative_ima_b">Crossing vehicle ahead - %1$.0f s to conflict</string>
<string name="usecase_narrative_ima_s">Stopped vehicle may pull out - %1$.0f s</string>
<string name="usecase_narrative_rtw_b">Car turning right toward you - %1$.0f s</string>
<string name="usecase_narrative_ltw_b">Car turning left toward you - %1$.0f s</string>
<string name="usecase_narrative_smva_bcw_b">Fast-closing vehicle nearby - %1$.0f s</string>
<!-- Settings > Use Case Alerts -->
<string name="settings_usecase_alerts">Use Case Alerts</string>
<string name="settings_usecase_alerts_desc">Per-use-case enable/disable for the CAM-based Use Case Alert panel on the V2X Monitor screen. All use cases are CAM-only - none of them trigger a DENM.</string>
<string name="settings_usecase_alert_levels_title">Alert level thresholds (read-only)</string>
<string name="settings_usecase_level_warning">Warning</string>
<string name="settings_usecase_level_awareness">Awareness</string>
<string name="settings_usecase_level_info">Info</string>
<string name="settings_usecase_ttc_le">≤ %1$.0f s to conflict</string>
<!-- Dashboard transport -->
<string name="dash_transport_usbc">USB-C</string>
<string name="dash_transport_usb_serial">USB Serial</string>
<string name="dash_transport_wifi">Wi-Fi</string>
<string name="dash_transport_bt">BT</string>
<!-- OBU stationType warning -->
<string name="dash_station_type_warning">⚠ OBU stationType ≠ 2 (cyclist) - VRU detection may be impaired at equipped intersections</string>
<string name="settings_platform">Platform</string>
<string name="settings_platform_val">Android / Kotlin / Jetpack Compose</string>
<string name="settings_project">Project</string>
<string name="settings_project_val">MicrOBU - HAW Hamburg &amp; consider it GmbH</string>
<!-- Phase A: Trip Recording (bottom nav) -->
<string name="nav_trips">Trips</string>
<!-- Phase A: Recording screen event counters -->
<string name="rec_stream_event_detection">Event Detection</string>
<string name="rec_open_session_log">CSV Session Log</string>
<!-- Phase A: Trip History screen -->
<string name="trip_history_title">Trip History</string>
<string name="trip_history_count_one">%1$d trip stored on device</string>
<string name="trip_history_count_other">%1$d trips stored on device</string>
<string name="trip_number">Trip #%1$d</string>
<string name="trip_delete_title">Delete trip?</string>
<string name="trip_delete_text">This will permanently remove the trip recorded on %1$s.</string>
<string name="trip_empty_title">No trips yet</string>
<string name="trip_empty_desc">Go to Record and start a session</string>
<!-- Phase A: Trip Review screen -->
<string name="trip_review_title">Trip Review</string>
</resources>