Add Mitsubishi WF-RAC integration - #181403
Conversation
There was a problem hiding this comment.
Hello @blues-sechseck,
When attempting to inspect the commits of your pull request for CLA signature status among all authors we encountered commit(s) which were not linked to a GitHub account, thus not allowing us to determine their status(es).
The commits that are missing a linked GitHub account are the following:
89e301afc9452d3a844138855be794be7b5524d4- This commit has something that looks like an email address (daniel@anders-osthofen.de). Maybe try linking that to GitHub?.
Unfortunately, we are unable to accept this pull request until this situation is corrected.
Here are your options:
-
If you had an email address set for the commit that simply wasn't linked to your GitHub account you can link that email now and it will retroactively apply to your commits. The simplest way to do this is to click the link to one of the above commits and look for a blue question mark in a blue circle in the top left. Hovering over that bubble will show you what email address you used. Clicking on that button will take you to your email address settings on GitHub. Just add the email address on that page and you're all set. GitHub has more information about this option in their help center.
-
If you didn't use an email address at all, it was an invalid email, or it's one you can't link to your GitHub, you will need to change the authorship information of the commit and your global Git settings so this doesn't happen again going forward. GitHub provides some great instructions on how to change your authorship information in their help center.
- If you only made a single commit you should be able to run
(substituting "Author Name" and "
git commit --amend --author="Author Name <email@address.com>"email@address.com" for your actual information) to set the authorship information. - If you made more than one commit and the commit with the missing authorship information is not the most recent one you have two options:
- You can re-create all commits missing authorship information. This is going to be the easiest solution for developers that aren't extremely confident in their Git and command line skills.
- You can use this script that GitHub provides to rewrite history. Please note: this should be used only if you are very confident in your abilities and understand its impacts.
- Whichever method you choose, I will come by to re-check the pull request once you push the fixes to this branch.
- If you only made a single commit you should be able to run
We apologize for this inconvenience, especially since it usually bites new contributors to Home Assistant. We hope you understand the need for us to protect ourselves and the great community we all have built legally. The best thing to come out of this is that you only need to fix this once and it benefits the entire Home Assistant and GitHub community.
Thanks, I look forward to checking this PR again soon! ❤️
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
There was a problem hiding this comment.
When adding new integrations, limit included platforms to a single platform. While we appreciate the effort, reviewing larger than necessary PRs slows down the review process. Please reduce this PR to a single platform. See the review process for more details.
There was a problem hiding this comment.
🟡 Changes recommended
Config identity, command error handling, climate behavior, and quality-scale compliance contain unresolved issues.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds local polling support for Mitsubishi Heavy Industries air conditioners using WF-RAC modules.
Changes:
- Adds configuration, discovery, migration, diagnostics, and climate support.
- Introduces the
pywfracdependency and integration metadata. - Adds comprehensive fixtures, snapshots, and integration tests.
File summaries
| File | Description |
|---|---|
.strict-typing |
Enables strict typing. |
CODEOWNERS |
Adds integration owners. |
mypy.ini |
Enables strict mypy checks. |
requirements_all.txt |
Adds pywfrac. |
homeassistant/generated/config_flows.py |
Registers the config flow. |
homeassistant/generated/integrations.json |
Registers integration metadata. |
homeassistant/generated/zeroconf.py |
Registers zeroconf discovery. |
homeassistant/components/mitsubishi_wf_rac/__init__.py |
Implements lifecycle and migrations. |
homeassistant/components/mitsubishi_wf_rac/climate.py |
Implements climate controls. |
homeassistant/components/mitsubishi_wf_rac/config_flow.py |
Implements setup and options flows. |
homeassistant/components/mitsubishi_wf_rac/const.py |
Defines protocol and entity constants. |
homeassistant/components/mitsubishi_wf_rac/coordinator.py |
Implements polling and commands. |
homeassistant/components/mitsubishi_wf_rac/diagnostics.py |
Provides redacted diagnostics. |
homeassistant/components/mitsubishi_wf_rac/entity.py |
Adds the shared entity base. |
homeassistant/components/mitsubishi_wf_rac/icons.json |
Defines entity-state icons. |
homeassistant/components/mitsubishi_wf_rac/manifest.json |
Declares integration metadata. |
homeassistant/components/mitsubishi_wf_rac/py.typed |
Marks the integration typed. |
homeassistant/components/mitsubishi_wf_rac/quality_scale.yaml |
Declares quality-scale compliance. |
homeassistant/components/mitsubishi_wf_rac/strings.json |
Adds user-facing translations. |
tests/components/mitsubishi_wf_rac/__init__.py |
Defines shared test data. |
tests/components/mitsubishi_wf_rac/conftest.py |
Provides integration fixtures. |
tests/components/mitsubishi_wf_rac/fixtures/aircon_stat.json |
Adds a protocol response fixture. |
tests/components/mitsubishi_wf_rac/snapshots/test_climate.ambr |
Captures climate entity state. |
tests/components/mitsubishi_wf_rac/snapshots/test_diagnostics.ambr |
Captures diagnostics output. |
tests/components/mitsubishi_wf_rac/test_climate.py |
Tests climate behavior. |
tests/components/mitsubishi_wf_rac/test_config_flow.py |
Tests configuration flows. |
tests/components/mitsubishi_wf_rac/test_coordinator.py |
Tests polling and recovery. |
tests/components/mitsubishi_wf_rac/test_diagnostics.py |
Tests diagnostics redaction. |
tests/components/mitsubishi_wf_rac/test_init.py |
Tests setup, removal, and migrations. |
Review details
Suppressed comments (3)
homeassistant/components/mitsubishi_wf_rac/config_flow.py:314
- Remove the name field from manual setup and generate the config-entry title from device information. Home Assistant integrations must not ask users to choose config-entry names during onboarding because entries and devices can be renamed afterward.
field(CONF_NAME, vol.Required, "Airco unknown"): cv.string,
homeassistant/components/mitsubishi_wf_rac/config_flow.py:339
- Remove name editing from reconfiguration. Reconfigure should update connection details only; changing the user-visible name belongs to Home Assistant's standard rename UI.
field(CONF_NAME, vol.Required): cv.string,
homeassistant/components/mitsubishi_wf_rac/quality_scale.yaml:57
- Mark
docs-use-casesincomplete until the linked documentation explains a concrete user scenario or benefit. The page describes installation and supported controls, but it does not include the use-case illustration required by this no-exceptions rule.
docs-use-cases: done
- Files reviewed: 25/29 changed files
- Comments generated: 16
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| # AUTO mode - use CoolHotJudge directly (unit tells us what it's doing) | ||
| if _mode == 0: | ||
| return HVACAction.HEATING if airco.CoolHotJudge else HVACAction.COOLING |
| # An entry whose setup never got as far as storing its runtime data can | ||
| # still be unloaded - there is simply no coordinator to shut down then. | ||
| if (data := getattr(entry, "runtime_data", None)) is not None: | ||
| await data.device.async_shutdown() | ||
|
|
||
| if unload_ok: |
| class AircoClimate(WfRacEntity, ClimateEntity): | ||
| """Representation of a climate entity.""" | ||
|
|
||
| _attr_supported_features: ClimateEntityFeature = SUPPORT_FLAGS |
| target_offset = self._resolve_target_offset(target_hvac_mode) | ||
| target_temp = set_temp - target_offset | ||
| target_temp = max(min_temp, min(max_temp, target_temp)) |
| info = await self._async_register_airco( | ||
| self.hass, user_input, allow_port_fallback=allow_port_fallback | ||
| ) |
| super().__init__(device) | ||
| self._attr_name = device.device_name | ||
| self._attr_unique_id = f"{DOMAIN}-{self._device.airco_id}-climate" |
| # Intentionally broad: this is the outermost boundary of the config | ||
| # flow step, so any bug here should show the user a graceful | ||
| # "unexpected_error" instead of crashing the flow. | ||
| _LOGGER.error("Unexpected exception") |
| field( | ||
| CONF_NAME, vol.Required, f"Airco {self._discovery_info[CONF_NAME]}" | ||
| ): str, |
| comment: >- | ||
| No credentials to renew - the operatorId registration is a device-side | ||
| account slot, not a login. | ||
| test-coverage: done |
| discovery: done | ||
| discovery-update-info: done | ||
| docs-data-update: done | ||
| docs-examples: done |
89e301a to
0e8534d
Compare
There was a problem hiding this comment.
It seems you haven't yet signed a CLA. Please do so here.
Once you do that we will be able to review and accept this pull request.
Thanks!
Local control of Mitsubishi Heavy Industries air conditioners fitted with the WF-RAC wireless module, over the module's own HTTP API on the local network. No cloud account and no outbound internet connection. This first PR is deliberately minimal: config flow plus the climate platform. The protocol lives in pywfrac on PyPI; the remaining seven platforms follow as separate PRs once this one is in.
0e8534d to
a79b714
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The config flow contains security- and correctness-adjacent issues (sensitive identifier logging, error logging behavior, and entry/ID handling) that should be addressed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
homeassistant/components/mitsubishi_wf_rac/config_flow.py:236
- Log unexpected exceptions with stack context so failures are diagnosable while still surfacing the form error to the user.
except Exception: # noqa: BLE001 # pylint: disable=broad-except
# Intentionally broad: this is the outermost boundary of the config
# flow step, so any bug here should show the user a graceful
# "unexpected_error" instead of crashing the flow.
_LOGGER.error("Unexpected exception")
errors[CONF_BASE] = "unexpected_error"
homeassistant/components/mitsubishi_wf_rac/config_flow.py:210
- Set the config entry unique_id to the discovered airco_id before creating the entry so the same device can’t be added twice (e.g., when its IP changes).
info = await self._async_register_airco(
self.hass, user_input, allow_port_fallback=allow_port_fallback
)
data_input = user_input.copy()
- Files reviewed: 25/29 changed files
- Comments generated: 6
- Review effort level: Lite
| _LOGGER.info( | ||
| "Trying to register OperatorId[%s] on Airco[%s]", | ||
| data[CONF_OPERATOR_ID], | ||
| data[CONF_AIRCO_ID], | ||
| ) |
| @@ -0,0 +1,224 @@ | |||
| """The WF-RAC sensor integration.""" # pylint: disable=invalid-name | |||
| async def _async_fetch_operator_id(self) -> str: | ||
| """Fetch UUID operator id if exists otherwise create it.""" | ||
| entry = self._find_entry_matching(CONF_OPERATOR_ID, bool) | ||
| if entry: | ||
| return str(entry.data[CONF_OPERATOR_ID]) | ||
| return f"hassio-{str(uuid4())[7:]}" | ||
|
|
| async def _async_fetch_device_id(self) -> str: | ||
| """Fetch unique device id if exists otherwise create it.""" | ||
| entry = self._find_entry_matching(CONF_DEVICE_ID, bool) | ||
| if entry: | ||
| return str(entry.data[CONF_DEVICE_ID]) | ||
| return f"homeassistant-device-{uuid4().hex[21:]}" |
| data_input.pop(CONF_HOST) | ||
|
|
| except KnownError as error: | ||
| _LOGGER.exception("create failed") | ||
| errors, placeholders = error.get_errors_and_placeholders( | ||
| data_schema.schema | ||
| ) | ||
| errors.update(errors) |
Host moves from entry.options back into entry.data (migration v5 -> v6). It lived in options so it could be edited there, which the reconfigure flow does now - and options was the wrong home for a second reason: the discovery helper that refreshes a changed address only merges into entry.data, so the refresh wrote a key setup never read and the address stayed stale. Commands are awaited to their result. async_queue_command() now waits on the flush its parameters ended up in, set_airco() raises a translated HomeAssistantError instead of a library error, and async_shutdown() cancels a command still in flight. The cost is that two blocking calls on the same entity no longer coalesce - climate runs with PARALLEL_UPDATES = 1, so the window is over before the second call starts. Reporting a refusal back to the action that caused it is worth more than saving that frame. The manual step had no unique id to abort on, so a unit reached at a second address became a second entry whose entities collide with the first one's; it now matches on the airco id the registration returns. KnownError is a plain Exception: none of them leaves the config flow, they are caught and turned into entries in the errors dict that async_show_form renders, so they carry an error_name rather than a translation key. quality_scale drops to bronze until two rules are honestly met: coverage is at 90% where test-coverage asks for 95%, and the documentation carries no blueprint example. Also: has_entity_name on the climate entity, the coordinator is only shut down once unloading the platforms succeeded, AddConfigEntryEntitiesCallback, climate imports through the component root, the swing parameter name, logger levels in the config flow, force_update no longer stored on the entry, and a CoolHotJudge comment that read as the opposite of what the parser does. The unique id keeps its domain and platform segments deliberately: ~1900 installations of the custom component share this domain and shortening it would orphan every entity they have named or wired into an automation.
There was a problem hiding this comment.
🟡 Changes recommended
The config flow’s zeroconf unique-id derivation and registration error handling can lead to unstable unique IDs and “unexpected_error” instead of a proper “cannot_connect” outcome.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (3)
Previously missed (3) — in code that hasn't changed since the last review.
homeassistant/components/mitsubishi_wf_rac/config_flow.py:392
- Derive node_name with removesuffix() instead of blind slicing so non-.local hostnames don't get truncated incorrectly (which would break unique_id stability).
homeassistant/components/mitsubishi_wf_rac/climate.py:239 - Update the comment to describe applying target_offset (not CONF_INDOOR_OFFSET) and remove the reference to sensor.py, which is not part of this integration yet.
homeassistant/components/mitsubishi_wf_rac/entity.py:95 - Log the caught exception details when _update_state() fails so parsing/index errors are actionable during debugging.
- Files reviewed: 25/29 changed files
- Comments generated: 1
- Review effort level: Lite
| result = await repository.update_account_info(airco_id, hass.config.time_zone) | ||
| if not result: | ||
| raise CannotConnect(reason="no answer to the registration request") | ||
| if int(result["result"]) == 2: | ||
| raise TooManyDevicesRegistered |
Awaiting every command cost the consolidation window: with PARALLEL_UPDATES = 1 the second action does not start until the first has been sent, so a scene that sets mode, temperature and fan speed left as three frames where it used to leave as one. The semaphore was never what protected the module. The coordinator holds a send lock around the request and spaces requests by MIN_TIME_BETWEEN_REQUESTS; the platform limit only kept actions issued together from reaching the consolidation window together - which is precisely the case worth merging. Zero restores that without giving up the error the caller now gets. Actions issued one after another still leave as separate frames. There is no window left to join once the first has been sent and answered, and that is the honest cost of reporting a refusal to the action that caused it.
There was a problem hiding this comment.
🔵 Needs a closer look
The write-lock retry delay calculation uses a local-time naive timestamp, which can produce incorrect retry timing on non-UTC systems.
Review details
Suppressed comments (4)
Previously missed (3) — in code that hasn't changed since the last review.
homeassistant/components/mitsubishi_wf_rac/coordinator.py:299
- Compute the remaining write-lock time using an explicit UTC timestamp to avoid local-timezone skew affecting the retry delay.
homeassistant/components/mitsubishi_wf_rac/config_flow.py:547 - Fix the KnownError docstring to refer to the "error" translation section (not "errors") so future changes don’t follow the wrong contract.
This issue also appears on line 593 of the same file.
homeassistant/components/mitsubishi_wf_rac/strings.json:13
- Update the invalid-name error text to match the current validation (minimum length) or add a name uniqueness check if that’s intended.
homeassistant/components/mitsubishi_wf_rac/config_flow.py:595
- Correct the InvalidName docstring to describe a name validation error (not a hostname validation error).
class InvalidName(KnownError):
"""Error to indicate there is an invalid hostname."""
- Files reviewed: 25/29 changed files
- Comments generated: 0 new
- Review effort level: Lite
Imports of climate constants go through the component root, the offset helper stops shadowing typing.override with a local name, and the write-lock delay reads the clock through homeassistant.util.dt.
There was a problem hiding this comment.
🔵 Needs a closer look
A few correctness issues were found (notably time calculations for write-lock retry and robustness around registration responses) that should be addressed before approval.
Review details
Suppressed comments (5)
Previously missed (2) — in code that hasn't changed since the last review.
homeassistant/components/mitsubishi_wf_rac/coordinator.py:301
- Compute the remaining write-lock time using a UTC/epoch-based clock (not dt_util.naive_now().timestamp()) to avoid timezone-dependent delays.
homeassistant/components/mitsubishi_wf_rac/strings.json:12 - Align the "name_invalid" error text with the actual validation (currently only enforces a minimum length, not uniqueness).
homeassistant/components/mitsubishi_wf_rac/config_flow.py:166
- Generate operator IDs using the full UUID so the stored operator_id is a valid UUID string and avoids surprising truncation.
return f"hassio-{str(uuid4())[7:]}"
homeassistant/components/mitsubishi_wf_rac/config_flow.py:157
- Handle unexpected updateAccountInfo responses defensively so a missing "result" key does not crash the config flow.
result = await repository.update_account_info(airco_id, hass.config.time_zone)
if not result:
raise CannotConnect(reason="no answer to the registration request")
if int(result["result"]) == 2:
raise TooManyDevicesRegistered
homeassistant/components/mitsubishi_wf_rac/config_flow.py:173
- Generate device IDs using the full UUID hex to reduce collision risk compared to taking only the last 11 hex digits.
return f"homeassistant-device-{uuid4().hex[21:]}"
- Files reviewed: 25/29 changed files
- Comments generated: 0 new
- Review effort level: Lite
Coverage was 90 % against the 95 % test-coverage asks for, so the rule was marked todo and the manifest dropped to bronze. The gaps were the branches that only show up on real hardware: every operation mode and the HVAC action it maps to, the wider heating range PresetTempRange2 models report, the cooling ceiling, a setpoint below the mode's floor, setting temperature and mode in one call, 3D auto on both louvers, the write lock being waited out, an evicted account re-registering mid-command, the repair issue for a full account table appearing and clearing, a frame that answers but does not parse, and a poll that never answers at all. 97 % overall now, no module below 95 %, so test-coverage and the platinum declaration are back.
There was a problem hiding this comment.
🟡 Changes recommended
The PR description’s stated quality scale/versioning intent does not match the actual manifest.json/quality_scale.yaml/VERSION values in the code.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (4)
Previously missed (2) — in code that hasn't changed since the last review.
homeassistant/components/mitsubishi_wf_rac/config_flow.py:55
- Update the PR description to match the actual config entry VERSION here (the description mentions VERSION=5 but the code ships VERSION=6 with a v5→v6 migration).
homeassistant/components/mitsubishi_wf_rac/entity.py:95 - Include exception details in this warning so unexpected parsing/indexing errors can be diagnosed from logs.
homeassistant/components/mitsubishi_wf_rac/quality_scale.yaml:53
- Mark docs-examples accurately (the PR description says the documentation lacks an example/blueprint, but quality_scale.yaml currently marks docs-examples done).
discovery-update-info: done
docs-data-update: done
docs-examples: done
docs-known-limitations: done
docs-supported-devices: done
homeassistant/components/mitsubishi_wf_rac/quality_scale.yaml:44
- Mark the test-coverage rule accurately (the PR description states overall coverage is ~90% and below the rule threshold, but quality_scale.yaml currently marks it done).
test-coverage: done
- Files reviewed: 25/29 changed files
- Comments generated: 1
- Review effort level: Lite
| "iot_class": "local_polling", | ||
| "loggers": ["pywfrac"], | ||
| "quality_scale": "platinum", | ||
| "requirements": ["pywfrac==0.1.0"], | ||
| "zeroconf": ["_beaver._tcp.local."] |
| ) -> bool: | ||
| """Migrate old config entry.""" | ||
|
|
||
| if entry.version == 1: |
There was a problem hiding this comment.
Shouldn't there be no versions, since this is a new integration?
There was a problem hiding this comment.
Fair question, and it would be right for a genuinely new integration.
The catch is the domain. mitsubishi_wf_rac is not new to the installations
this lands on: it has existed as a custom component for a while, with roughly
1,900 installations, and it uses this exact domain. When one of them removes
the custom component and picks up the core integration, Home Assistant loads
the config entries that are already there — and those carry versions 1 through
5 from the custom component's own history.
Without the migration each of those entries fails to load with a "config entry
version is newer/older" error, and the user is left deleting and re-adding
every unit by hand. With it, they carry over.
The versions themselves are the custom component's, not invented for this PR.
The last step is the one this branch added: v5 → v6 moves the host from
options back into data, so the discovery helper that refreshes a changed
address writes it where setup reads it.
The write-lock retry read `expires`, an epoch stamp, back through a naive local datetime; time.time() is what the helper's own docstring points at for a relative time, and it takes the DST fold out of the arithmetic. The delay itself had no test of its own - the retry count is the same either way, so getting it wrong only showed up as a retry into a lock that had not lapsed. A registration answer without a "result" key ended the flow as an unexpected error rather than as the connection problem it is. Plus what the review found in passing: the entity update warning now carries its traceback, InvalidName no longer describes a hostname, the KnownError docstring points at the "error" section it actually uses, and the name_invalid message no longer promises a uniqueness check that was never made. The config entry fixture moves to version 6, which is what "current version" has meant since the migration landed.
There was a problem hiding this comment.
🔵 Needs a closer look
Correctness, security, identity handling, documentation, and quality-scale issues remain unresolved.
Review details
Suppressed comments (6)
Previously missed (6) — in code that hasn't changed since the last review.
tests/components/mitsubishi_wf_rac/test_climate.py:95
- Verify the encoded command values rather than only checking that a write occurred. These cases all pass if a setter sends the wrong mode, fan, temperature, or swing value, leaving the protocol mappings effectively untested.
homeassistant/components/mitsubishi_wf_rac/climate.py:247 - Correct this explanation to refer to the target offset, not
CONF_INDOOR_OFFSET. The implementation intentionally keeps the indoor sensor offset display-only and subtracts the separately configured target offset here, so the current comment contradicts both the code and the option description.
homeassistant/components/mitsubishi_wf_rac/config_flow.py:55 - Update the PR description to state
VERSION = 6and migrations through version 5. It currently promises version 5 and only versions 1–4, while this flow andasync_migrate_entryinclude an additional v5-to-v6 migration.
homeassistant/components/mitsubishi_wf_rac/coordinator.py:540 - Use the full manufacturer name to avoid identifying these Mitsubishi Heavy Industries units as the unrelated Mitsubishi Electric brand.
homeassistant/components/mitsubishi_wf_rac/strings.json:52 - Describe address updates accurately for discovered devices. Zeroconf calls
_abort_if_unique_id_configured(updates=info), so those entries do follow changed IP addresses; this blanket static-address warning, repeated in the linked documentation, contradicts the implemented discovery behavior.
tests/components/mitsubishi_wf_rac/test_climate.py:479 - Rename this test and correct its docstring to match what it actually verifies. With the fixture's
preset_temp_range_2=False, the implementation returns 30 for heating and auto too; the 33 °C branch applies to cooling/dry only when that capability is enabled.
- Files reviewed: 25/29 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Proposed change
New integration for Mitsubishi Heavy Industries air conditioners fitted with the WF-RAC wireless LAN module (sold under that part number, marketed together with the Smart M-Air app). It talks to the module over the local network using the same HTTP API the app uses — no manufacturer account, no outbound connection,
local_polling.This first PR is deliberately minimal: a config flow with zeroconf discovery, and the
climateplatform. The integration has existed as a custom component for a while and covers eight platforms there; the remaining seven will follow as separate PRs once this one is in, the way the component checklist asks for.Four things worth flagging before review:
pywfracholds everything that builds and parses the module'sairconStatframes. It takes an injectedaiohttpsession and an explicit certificate path rather than reaching intohass, is fully typed, and has its own test suite.mitsubishi_wf_rac, next to the existingmelcloud. Those are two different manufacturers:melcloudis Mitsubishi Electric, this is Mitsubishi Heavy Industries, with an unrelated protocol and no shared hardware.async_migrate_entryandVERSION = 6are included even though core has no old entries of its own. The domain matches the custom component's, so an installation that switches over carries config entries of versions 1–5 with it, and those would fail to load without the migration. The last step, v5 → v6, moves the host fromoptionsback intodata, where the discovery helper that refreshes a changed address actually writes it.ac_cert.pemis present in the configuration directory the integration pins it; without it the connection falls back to a permissive SSL context.const.pycarries the filename and theopensslrecipe that produces it.quality_scaleis declared as platinum. The two rules that were open when this PR was filed are met now: coverage is above 95 % in every module of the integration, and the documentation has gained an Examples section.Verified locally:
python3 -m script.hassfest(all 1,515 integrations, 0 invalid),python3 -m script.gen_requirements_all(no diff),ruff checkandruff format,mypy,pylint, andpytest tests/components/mitsubishi_wf_rac— 79 tests, 98 % overall with no module below 95 %.Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: