Coder Social home page Coder Social logo

whirlpool-sixth-sense's People

Contributors

abmantis avatar austinmroczek avatar eskibars avatar iciubotarasu avatar mizterb avatar mkmer avatar onkelbeh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

whirlpool-sixth-sense's Issues

Updated Deployment Instructions

I am trying to deploy this with HA and have looked through the initial supported Whirlpool Appliances but am unable to. How do I deploy this? I can't pull this through HACS so I think I'm missing something to connect the dots.

Can the readme be updated with better documentation or can someone help me and I can pull to update the readme after I have it deployed.

Feature request: wet laundry status

Thanks for building this library. I have a feature request. I could code it and submit a PR with a little guidance.

My request is for a Washer "wet laundry" sensor in Home Assistant. This is when the washer cycle is complete, but the washer door has not been opened. This can tell or remind me that someone needs to move the wet clothes into the dryer.

I assume I'd create a function WasherDryer.is_laundry_wet() that returns a boolean.

Should I add a self._last_status and set it in get_machine_state, and then

def is_laundry_wet():
    return (self._last_status == MachineState.Complete and self._door_status == Closed)

Or do you have a better suggestion ?

EU/US vs brands

Hey there!

As I started writing an integration for the oven (#6), I noticed that -- at least for me, it appears that logins are dependent on region, not on brand. Here in the US, we get both Maytag and Whirlpool brand appliances (my oven is Whirlpool) but it appears auth is not brand (only?) dependent, but region dependent. Trying auth to https://api.whrcloud.eu gives a 400 error even with otherwise correct credentials for a Whirlpool-brand (oven) appliance for a US based account. Using the Maytag brand (-b maytag) does auth the US based account, but the brand/url base are then wrong. I don't have any other devices to test whether the brand matters or just the region, but the region definitely does.

I think we at least need to introduce a region parameter. WDYT?

Eventsocket dies with no log as to why

Current eventsocket code does not restart after 3 connection attempts and does not log the condition - results in a dead eventsocket task.

For a long lived eventsocket, it should continue to retry forever. At a minimum it should reset the retry count after a successful connection, and log when it stops trying.

#13 has retry counter removed.

SSL Cert Verification fails

Running the client in the US - all aiohttp calls fail the cert verification.

I have temporarily added verify_ssl = False to all .get and .post just to verify other functions are working - so far events are now connected an working. Not exactly sure how else to get around this issue.

websocket missing backend selection

After some testing, no event based messages were appearing in the cli.py test (as well as HomeAssistant). Looks like eventsocket.py didn't get the additions for backend selection and only connects to: websocketservice.wcloud-emea.eu-gb.containers.appdomain.cloud
There probably is a US version?

Include Maytag in United States

It would be great if Maytag washers and dryers located in the United States could be accessed using this. I can access the machines using the Maytag phone app, but not via whirlpool-sixth-sense (I get an "Invalid authentication" error when using the credentials that work for the phone app). I'm not a programmer and can't help programming, but can help as a user for testing.

Eventsocket restart does not update fetch_data

When the eventsocket is disconnected then reconnects, there is no mechanism to update the data for missed events.

Whenever the eventsocket reconnects, it should call fetch_data (or something like it) to get a fresh _data_dict and trigger a callback to HA to cover any missed events while the socket was "away".

Tests fail on 0.17.1

There is something wrong with the MockResponse and it's async context handler..

❯ pytest
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /tmp/whirlpool-sixth-sense
plugins: asyncio-0.19.0, mock-3.8.2
asyncio: mode=strict
collected 6 items                                                                                                                                                                           

tests/test_aircon.py FF                                                                                                                                                               [ 33%]
tests/test_auth.py ..                                                                                                                                                                 [ 66%]
tests/test_oven.py FF                                                                                                                                                                 [100%]

========================================================================================= FAILURES ==========================================================================================
______________________________________________________________________________________ test_attributes ______________________________________________________________________________________

caplog = <_pytest.logging.LogCaptureFixture object at 0x7efc915db0d0>, aio_httpclient = <MagicMock name='ClientSession()' id='139623235687744'>

    async def test_attributes(caplog, aio_httpclient):
        caplog.set_level(logging.DEBUG)
        auth = MagicMock()
    
        aio_httpclient.get.return_value = MockResponse(json.dumps(DATA1), 200)
    
        aircon = Aircon(BackendSelectorMock(), auth, SAID, None)
>       await aircon.connect()

tests/test_aircon.py:100: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
whirlpool/appliance.py:142: in connect
    await self.start_event_listener()
whirlpool/appliance.py:161: in start_event_listener
    await self._getWebsocketUrl(),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <whirlpool.aircon.Aircon object at 0x7efc90d7da20>

    async def _getWebsocketUrl(self):
        async with aiohttp.ClientSession(headers=self._create_headers()) as session:
            DEFAULT_WS_URL = "wss://ws.emeaprod.aws.whrcloud.com/appliance/websocket"
>           async with session.get(
                f"{self._backend_selector.base_url}/api/v1/client_auth/webSocketUrl"
            ) as r:
E           AttributeError: __aenter__

whirlpool/appliance.py:67: AttributeError
_______________________________________________________________________________________ test_setters ________________________________________________________________________________________

caplog = <_pytest.logging.LogCaptureFixture object at 0x7efc90c8fb20>, aio_httpclient = <MagicMock name='ClientSession()' id='139623225939504'>

    async def test_setters(caplog, aio_httpclient):
        caplog.set_level(logging.DEBUG)
        auth = MagicMock()
    
        aio_httpclient.get.return_value = MockResponse(json.dumps(DATA1), 200)
        aio_httpclient.post.return_value = MockResponse("", 200)
    
        cmd_data = {
            "header": {"said": SAID, "command": "setAttributes"},
        }
    
        aircon = Aircon(BackendSelectorMock(), auth, SAID, None)
>       await aircon.connect()

tests/test_aircon.py:150: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
whirlpool/appliance.py:142: in connect
    await self.start_event_listener()
whirlpool/appliance.py:161: in start_event_listener
    await self._getWebsocketUrl(),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <whirlpool.aircon.Aircon object at 0x7efc90c04580>

    async def _getWebsocketUrl(self):
        async with aiohttp.ClientSession(headers=self._create_headers()) as session:
            DEFAULT_WS_URL = "wss://ws.emeaprod.aws.whrcloud.com/appliance/websocket"
>           async with session.get(
                f"{self._backend_selector.base_url}/api/v1/client_auth/webSocketUrl"
            ) as r:
E           AttributeError: __aenter__

whirlpool/appliance.py:67: AttributeError
______________________________________________________________________________________ test_attributes ______________________________________________________________________________________

caplog = <_pytest.logging.LogCaptureFixture object at 0x7efc90ca97e0>, aio_httpclient = <MagicMock name='ClientSession()' id='139623225719248'>

    async def test_attributes(caplog, aio_httpclient):
        caplog.set_level(logging.DEBUG)
        auth = MagicMock()
    
        aio_httpclient.get.return_value = MockResponse(json.dumps(DATA1), 200)
    
        oven = Oven(BackendSelectorMock(), auth, SAID, None)
>       await oven.connect()

tests/test_oven.py:771: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
whirlpool/appliance.py:142: in connect
    await self.start_event_listener()
whirlpool/appliance.py:161: in start_event_listener
    await self._getWebsocketUrl(),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <whirlpool.oven.Oven object at 0x7efc90c7a8f0>

    async def _getWebsocketUrl(self):
        async with aiohttp.ClientSession(headers=self._create_headers()) as session:
            DEFAULT_WS_URL = "wss://ws.emeaprod.aws.whrcloud.com/appliance/websocket"
>           async with session.get(
                f"{self._backend_selector.base_url}/api/v1/client_auth/webSocketUrl"
            ) as r:
E           AttributeError: __aenter__

whirlpool/appliance.py:67: AttributeError
_______________________________________________________________________________________ test_setters ________________________________________________________________________________________

caplog = <_pytest.logging.LogCaptureFixture object at 0x7efc90d07c70>, aio_httpclient = <MagicMock name='ClientSession()' id='139623226441104'>

    async def test_setters(caplog, aio_httpclient):
        caplog.set_level(logging.DEBUG)
        auth = MagicMock()
    
        aio_httpclient.get.return_value = MockResponse(json.dumps(DATA2), 200)
        aio_httpclient.post.return_value = MockResponse("", 200)
    
        cmd_data = {
            "header": {"said": SAID, "command": "setAttributes"},
        }
    
        oven = Oven(BackendSelectorMock(), auth, SAID, None)
>       await oven.connect()

tests/test_oven.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
whirlpool/appliance.py:142: in connect
    await self.start_event_listener()
whirlpool/appliance.py:161: in start_event_listener
    await self._getWebsocketUrl(),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <whirlpool.oven.Oven object at 0x7efc90c94670>

    async def _getWebsocketUrl(self):
        async with aiohttp.ClientSession(headers=self._create_headers()) as session:
            DEFAULT_WS_URL = "wss://ws.emeaprod.aws.whrcloud.com/appliance/websocket"
>           async with session.get(
                f"{self._backend_selector.base_url}/api/v1/client_auth/webSocketUrl"
            ) as r:
E           AttributeError: __aenter__

whirlpool/appliance.py:67: AttributeError
===================================================================================== warnings summary ======================================================================================
tests/test_aircon.py::test_attributes
tests/test_aircon.py::test_setters
tests/test_oven.py::test_attributes
tests/test_oven.py::test_setters
  /tmp/whirlpool-sixth-sense/whirlpool/appliance.py:67: RuntimeWarning: coroutine 'AsyncMockMixin._execute_mock_call' was never awaited
    async with session.get(
  Enable tracemalloc to get traceback where the object was allocated.
  See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info.

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================================================================== short test summary info ==================================================================================
FAILED tests/test_aircon.py::test_attributes - AttributeError: __aenter__
FAILED tests/test_aircon.py::test_setters - AttributeError: __aenter__
FAILED tests/test_oven.py::test_attributes - AttributeError: __aenter__
FAILED tests/test_oven.py::test_setters - AttributeError: __aenter__
========================================================================== 4 failed, 2 passed, 4 warnings in 0.25s ==========================================================================

Adding integration

First of all congrats for this project @abmantis. I need your help please. The official whirlpool 6 sense integration doesn't work properly, how do I install this library in Homeassistant?

Eventsocket does not renew auth key

After some "time" the auth key expires. Once the eventsocket becomes disconnected and can never connect again as the auth key is statically passed to the event socket.

#13 includes one possible solution.

Oven integration

Thanks for creating this project! I was in the middle of creating a similar one when I saw yours. I have a Whirlpool smart oven that uses the same auth flow/APIs. Would you accept a pull request that adds smart oven support?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.