Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions carwatch/webchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def _switch_later(name: str) -> None:
It reads Home Assistant at home. You never type a Mercedes password here.
</div>
<ol style="color:#bbb;margin:0 0 14px 1.2em;padding:0;max-width:36em">
<li>On home wifi open Home Assistant (http://192.168.50.241:8123)</li>
<li>On home wifi open Home Assistant (__HA_URL__)</li>
<li>Tap your name, then Security, then Create long-lived access token</li>
<li>Copy the token and paste it below, then tap Connect</li>
</ol>
Expand Down Expand Up @@ -2965,7 +2965,10 @@ def run(cmd):
# Minimal setup + status page for the cloud provider: email ->
# vendor emails a one-time code -> code -> tokens on the Pi.
# The owner's PASSWORD is never asked anywhere on this page.
return self._send(200, CLOUDCAR_PAGE)
# The HA address comes from config (ha.url), not from source.
from html import escape
from carwatch import mercedesme as _mm
return self._send(200, CLOUDCAR_PAGE.replace("__HA_URL__", escape(_mm._ha_url())))
Comment on lines +2970 to +2971

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the cloud setup page when the provider fails

If the optional Mercedes provider failed to import during startup, main() deliberately catches that failure so the dashboard remains available and the cloud UI can report no_provider; this unguarded retry instead raises while handling /cloudcar, leaving that setup page without an HTTP response. Obtain the URL without importing the failed provider, or catch the import/config error and serve the page with an unavailable-state placeholder.

Useful? React with 👍 / 👎.

elif self.path.startswith("/streams"):
return self._send(200, STREAMS_PAGE)
elif self.path.startswith("/nerd"):
Expand Down
6 changes: 3 additions & 3 deletions tests/test_preflight.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ def setUp(self):
("tailscale", "ip", "-4"): "100.65.0.9",
("bluetoothctl", "info", "AA:BB:CC:DD:EE:FF"): "Device AA:BB:CC:DD:EE:FF\n\tPaired: yes\n\tTrusted: yes",
}
self.http = {pf.INTERNET_PROBE: 204, "http://100.97.140.13:8123/api/": 401}
self.http = {pf.INTERNET_PROBE: 204, "http://100.64.0.10:8123/api/": 401}
self._patches = [
mock.patch.object(pf, "_run", lambda cmd, timeout=5.0, any_rc=False: self.runs.get(tuple(cmd))),
mock.patch.object(pf, "_http_status", lambda url, timeout=4.0: self.http.get(url)),
mock.patch("carwatch.trips.current_ssid", lambda: "Petrus's S26 Ultra"),
mock.patch("carwatch.brain.model_url", lambda now=None: "http://127.0.0.1:8080/v1/chat/completions"),
mock.patch("carwatch.brain._healthy", lambda url, timeout=2.0: True),
mock.patch.object(pf, "_local_state", lambda: "down"),
mock.patch("carwatch.mercedesme._ha_url", lambda: "http://100.97.140.13:8123"),
mock.patch("carwatch.mercedesme._ha_url", lambda: "http://100.64.0.10:8123"),
mock.patch("carwatch.mercedesme._TOKEN_FILE", os.path.join(self.tmp, "ha-token")),
mock.patch.object(pf, "_adapter_present", lambda: None),
mock.patch.object(pf, "_obd_mac", lambda: "AA:BB:CC:DD:EE:FF"),
Expand Down Expand Up @@ -86,7 +86,7 @@ def test_all_ready(self):

def test_mercedes_names_missing_token_and_unreachable_ha(self):
os.remove(os.path.join(self.tmp, "ha-token"))
self.http.pop("http://100.97.140.13:8123/api/")
self.http.pop("http://100.64.0.10:8123/api/")
self.runs.pop(("tailscale", "ip", "-4"))
res = pf.run()
t = self._tile(res, "mercedes")
Expand Down
Loading