Skip to content

[PATCH] feat: add Force IPv4 option to config and options flow#131

Open
baylanger wants to merge 1 commit into
hydroqc:mainfrom
baylanger:feat/force-ipv4
Open

[PATCH] feat: add Force IPv4 option to config and options flow#131
baylanger wants to merge 1 commit into
hydroqc:mainfrom
baylanger:feat/force-ipv4

Conversation

@baylanger
Copy link
Copy Markdown

Context: Hydro-Québec servers geo-block traffic originating from outside
Quebec/Canada, returning a timeout. On dual-stack hosts, IPv6 traffic may
route through a non-Canadian path (e.g. via a tunnel broker). Forcing IPv4
ensures all connections use the Canadian IPv4 address.

Adds a 'Force IPv4' toggle to the first setup step (Choose Connection
Mode), visible in both the initial setup wizard and the options flow.

When enabled, all aiohttp sessions are created with a TCPConnector
restricted to socket.AF_INET (IPv4 only):

  • Config flow login: temp WebUser session uses IPv4 + correct CookieJar
  • Coordinator portal mode: WebUser session uses IPv4 + correct CookieJar
  • OpenData mode: PublicDataClient creates its own IPv4-only session

The correct CookieJar settings (quote_cookie=False, unsafe=True,
requote_redirect_url=False) are applied to match what HydroClient uses
internally, which is required for Azure B2C authentication to succeed.

Improves exception logging during login (HTTP status code logged on
HydroQcHTTPError, warning logged on RuntimeError portal unavailable).

FIX a pre-existing naming mismatch: Home Assistant resolves UI labels for
a config flow step by matching the step's step_id against the keys in
strings.json and the translation files. The function
async_step_opendata_rate was registered with step_id="opendata_rate" in
config_flow/base.py, but all translation files defined the labels under
the key "opendata_offer". This mismatch meant translated labels for
contract name, rate selection, and the new Force IPv4 option were never
shown to the user. Fixed by renaming the function and step_id in
config_flow/base.py to "opendata_offer" to match the existing translation
keys. No changes were needed in strings.json or the translation files.

Depends on: PR to hydroqc (Hydro-Quebec-API-Wrapper) adding the session
parameter passthrough in WebUser.init().

Changes:

  • const.py: add CONF_FORCE_IPV4
  • config_flow/base.py: Force IPv4 checkbox in async_step_user; inject
    IPv4 session with correct CookieJar for temp WebUser during login;
    write CONF_FORCE_IPV4 into all entry_data paths; improve exception
    logging; rename async_step_opendata_rate -> async_step_opendata_offer
    to match existing translation keys
  • config_flow/options.py: Force IPv4 toggle in options init step;
    reads from both options and data for backward compatibility with
    existing entries
  • coordinator/base.py: read CONF_FORCE_IPV4; inject IPv4 session with
    correct CookieJar into WebUser; pass force_ipv4 to PublicDataClient
  • public_data/client.py: accept force_ipv4 param; use AF_INET connector
    in _get_session()
  • strings.json + translations/en|fr|es.json: labels and geo-blocking
    explanation note in user step and options step

@baylanger
Copy link
Copy Markdown
Author

baylanger commented May 14, 2026

I believe the PR is good but later today when I have time I'll test again both PRs and post an update.

preheat_duration: Pre-heat duration in minutes (default 120)
force_ipv4: When True, restricts the aiohttp session to IPv4
only (family=socket.AF_INET). Useful on dual-stack hosts
where Hydro-Québec servers are not reachable over IPv6.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Oops ... comment needs to mention traffic not from Quebec/Canada.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant