-
Notifications
You must be signed in to change notification settings - Fork 127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an improve_contrast switch #230
Add an improve_contrast switch #230
Conversation
I don't speak for the others, but personally I think spamming entities is bad, but this is certainly one that many would find useful. Also in general, entities can be disabled if not used so not a huge issue. We are also looking to add a generic |
Codecov Report
@@ Coverage Diff @@
## master #230 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 10 10
Lines 1318 1322 +4
=========================================
+ Hits 1318 1322 +4
Continue to review full report at Codecov.
|
Similar to @NickM-27 suggests: I would suggest we add this but have it disabled by default. Users who want it, can enable it and get the extra functionality. To do this, I'd add another variable to the FrigateSwitch constructor ( Please also add a test that verifies the disable-by-default works, you can follow the example @NickM-27 set in this test. |
Thanks for the feedback, it's a great idea. I have a lot of python experience but no experience with HA integrations - but I'll do what I can. I may need some questions answered! |
@dermotduffy @NickM-27 Updated the constructor and added some tests... Since I have little idea what I am doing, please help if it's way off :) |
@dermotduffy @NickM-27 I added the new |
Could maybe adjust it to be |
I think maybe break apart |
PS: Make sure to run the |
Appreciate the help and advice @dermotduffy. Let me know how this looks now. |
tests/test_switch.py
Outdated
@@ -154,3 +164,23 @@ async def test_switch_unique_id(hass: HomeAssistant) -> None: | |||
assert ( | |||
registry_entry.unique_id == f"{TEST_CONFIG_ENTRY_ID}:switch:front_door_detect" | |||
) | |||
|
|||
|
|||
async def test_switch_improve_contrast_can_be_enabled(hass: HomeAssistant) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even better would be to use @pytest.mark.parametrize
here so that this test gets run for all members of DISABLED_SWITCH_ENTITY_IDS
(so that when we add more switches there this test will "just work").
Take a look at the sensor test for inspiration: https://github.com/blakeblackshear/frigate-hass-integration/blob/master/tests/test_sensor.py#L92
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea. So, something like this? Not sure if I've got the syntax right.
@pytest.mark.parametrize("disabled_switch_name", DISABLED_SWITCH_ENTITY_IDS)
async def test_disabled_switch_can_be_enabled(
disabled_switch_name: Any, hass: HomeAssistant
) -> None:
"""Verify disabled switches can be enabled."""
await setup_mock_frigate_config_entry(hass)
entity_registry = er.async_get(hass)
# Test original entity is disabled as expected
entry = entity_registry.async_get(disabled_switch_name)
assert entry
assert entry.disabled
assert entry.disabled_by == er.DISABLED_INTEGRATION
entity_state = hass.states.get(disabled_switch_name)
assert not entity_state
# Update and test that entity is now enabled
updated_entry = entity_registry.async_update_entity(
disabled_switch_name, disabled_by=None
)
assert not updated_entry.disabled
Really appreciate your patience as I learn this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, exactly.
Minor:
- I'd call
disabled_switch_name
asdisabled_entity_id
instead (slightly clearer) - I think you should be able to type annotate it with
str
instead ofAny
Looking great @hawkeye217 ! One improvement suggestion added above that could make this even better I think. Also need to fix the tests/formatting (see failed CI build). Thanks! |
Sorry about all the failed tests. I've run |
(~/src/frigate-hass-integration) $ pre-commit run -a
pyupgrade................................................................Passed
black....................................................................Passed
codespell................................................................Passed
flake8...................................................................Passed
isort....................................................................Passed
Check JSON...............................................................Passed
yamllint.................................................................Passed
pylint...................................................................Passed
mypy.....................................................................Passed (~/src/frigate-hass-integration) $ pytest
Test session starts (platform: linux, Python 3.8.10, pytest 6.2.5, pytest-sugar 0.9.4)
rootdir: /home/src/frigate-hass-integration, configfile: pyproject.toml, testpaths: tests
plugins: freezegun-0.4.2, homeassistant-custom-component-0.5.0, aiohttp-0.3.0, respx-0.19.0, cov-2.12.1, test-groups-1.0.3, forked-1.4.0, sugar-0.9.4, requests-mock-1.9.2, socket-0.4.1, xdist-2.4.0, anyio-3.5.0, timeout-2.0.1
timeout: 10.0s
timeout method: signal
timeout func_only: False
collecting ...
tests/test_api.py ✓✓✓✓✓✓✓✓ 7% ▊
tests/test_binary_sensor.py ✓✓✓✓✓✓✓ 14% █▍
tests/test_camera.py ✓✓✓✓✓✓✓✓ 21% ██▎
tests/test_config_flow.py ✓✓✓✓✓✓✓ 28% ██▊
tests/test_init.py ✓✓✓✓✓✓✓✓✓ 36% ███▋
tests/test_media_source.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 53% █████▍
tests/test_sensor.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 72% ███████▎
tests/test_switch.py ✓✓✓✓✓✓ 77% ███████▊
tests/test_views.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 100% ██████████
---------- coverage: platform linux, python 3.8.10-final-0 -----------
Name Stmts Miss Cover Missing
--------------------------------------------------------------------------
custom_components/frigate/__init__.py 178 0 100%
custom_components/frigate/api.py 57 0 100%
custom_components/frigate/binary_sensor.py 46 0 100%
custom_components/frigate/camera.py 84 0 100%
custom_components/frigate/config_flow.py 54 0 100%
custom_components/frigate/const.py 33 0 100%
custom_components/frigate/media_source.py 441 0 100%
custom_components/frigate/sensor.py 165 0 100%
custom_components/frigate/switch.py 55 0 100%
custom_components/frigate/views.py 205 0 100%
--------------------------------------------------------------------------
TOTAL 1318 0 100%
Coverage XML written to file coverage.xml
Required test coverage of 100% reached. Total coverage: 100.00%
Results (15.50s):
109 passed |
Great, thanks! I must be missing some dependencies because I'm getting errors on files I didn't modify. Let me push what I have and I'll work through that issue separately. |
Yeah, that may be a sign your development environment isn't quite right. I'd recommend using a dedicated or throwaway Python virtual environment, and making sure you have all the dependencies installed: (~/src/frigate-hass-integration) $ pip install -r requirements_dev.txt Getting it to pass cleanly prior to your changes is a good sign you have everything setup right. |
@dermotduffy Got the dev environment set up right and I can finally see what test was failing. Thanks for the help. The |
@hawkeye217 Yes, I think so, the point of that test is to verify switch icons -- so whether enabled/disable we should probably do that test. For disabled switches, enable them first ... then check the icon? If you want to test the icons as part of some other test (and remove the dedicated test for it) that'd be fine also, whatever works out cleanest in the test code. |
A separate test to check disabled switch icons is probably the simplest/cleanest since the default-enabled ones are already hard coded in the test. But that does mean that the enabling test code is redundant. And here's where my unfamiliarity with HA integrations comes in - is there something else I need to call to enable an entity? The last assertion is failing:
Would you do this differently? |
No, that's roughly what I would have done. How is it failing? If I had to guess, I'd say the state machine may not yet have processed the re-enable, so maybe something like this is necessary between calling # async_update_entity
await hass.async_block_till_done()
# Now check hass.states |
Makes sense, I figured it could have been that. Unfortunately putting an |
After the re-enable & |
It's I do see this from HA, however:
|
I knew this problem seemed familiar, I ran into this with the Hyperion integration, this was my fix. |
Legend. That's awesome. I see
|
Yeah, this is a weird one. The HA Core tests functionality is bundled separately for use in custom integrations like this, it's bundled into this package. We already use this package in these tests. Try: from pytest_homeassistant_custom_component.common import async_fire_time_changed The |
Hmm. Still no-go with the icon, the final assertion fails. Any other ideas?
|
As in the Hyperion example, you specifically need to "fast-forward" time by async_fire_time_changed(
hass,
dt.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1),
)
|
Yeah, I tried that first but got this:
So I looked at the similar calls in |
As a silver lining, aren't you getting a nice tour of HA integration testing? ;-) Somehow your test is trying to talk to the outside world. Would you be able to commit whatever code you have, and I'll take a look? |
Haha, yes! This is actually really helpful (and fun) and you've been super patient with a HA integration newbie. Thank you! I'll commit what I have so you can take a look. |
The data coordinator (the code that runs every X seconds to poll Frigate stats) was trying to reload its data during the time you were 'fast-forwarding time'. Since the API patch wasn't in place during this fetch, it was trying to talk to the Frigate server at This test passes for me: async def test_disabled_switch_icon(hass: HomeAssistant) -> None:
"""Verify icons for disabled switches by enabling them."""
client = create_mock_frigate_client()
await setup_mock_frigate_config_entry(hass, client=client)
entity_registry = er.async_get(hass)
expected_results = {
TEST_SWITCH_FRONT_DOOR_IMPROVE_CONTRAST_ENTITY_ID: "mdi:contrast-circle",
}
# Keep the patch in place to ensure that coordinator updates that are
# scheduled during the reload period will use the mocked API.
with patch(
"custom_components.frigate.FrigateApiClient",
return_value=client,
):
for disabled_entity_id, icon in expected_results.items():
updated_entry = entity_registry.async_update_entity(
disabled_entity_id, disabled_by=None
)
assert not updated_entry.disabled
await hass.async_block_till_done()
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1))
# async_fire_time_changed(hass, dt_util.utcnow() + SCAN INTERVAL)
await hass.async_block_till_done()
entity_state = hass.states.get(disabled_entity_id)
assert entity_state
assert entity_state.attributes["icon"] == icon |
Awesome! It passes now for me as well, and what you said makes sense. Thank you! |
Great! Think we're good to go here. I'll merge it in after the parent PR has been merged (blakeblackshear/frigate#3011). PS: Thank you for the contribution, using your new experience and finding more opportunities to contribute would be really appreciated. Bugs that need help. |
I'll certainly look for more opportunities. I've learned a lot from you here and it's made the contribution process seem much less intimidating. Frigate is an amazing piece of software (and so is HA!) and I'd love help to improve it wherever I can. Thanks again! |
@dermotduffy also just a heads up the related frigate PR was merged so this can be merged as well 👍 |
To be paired with the PR I submitted for frigate for toggling improve_contrast via mqtt.
I'm not sure if adding even more entities is something you want for the HA integration, but it was an easy addition so I figured I'd submit this PR for your consideration. I'm happy to keep some manually added mqtt switch entities in HA if you don't want to add this to the official integration.
Thanks again for all the amazing work on Frigate!