GeorgeSG / philips_airpurifier_http

Home Assistant integration for Philips Air Purifiers
33 stars 12 forks source link

Add per-device configuration #3

Open GeorgeSG opened 3 years ago

GeorgeSG commented 3 years ago

Background

Philips devices have slight (or major) differences in their APIs and how they set modes, speeds, etc.

They have differences in the used communication protocol as well - some devices use HTTP, some use CoAP, and some use Encrypted CoAP.

Overview

  1. Implement a way to change the behavior of the component based on the device model. For example, AC2729_10 has no "bacteria" or "night" mode. AC2889 has a "Sleep Speed", etc, etc.
  2. Add a configuration option for device models. Users should be able to set their device model manually in the config.
  3. If a device model is not recognized or set, revert to some reasonable defaults (probably the current behavior)

Optional, or future

  1. Attempt to auto-detect device model using py-air-control.
  2. Decide on communication protocol based on device model.

Request for info

If you can, please share your device's:

It will be especially useful if you can test with py-air-control before that to validate that the values work.

Additional context

ronaldt80 commented 3 years ago

I own the "3259 - http" as well as the "2889 - coap". Bacteria and Sleep mode both do not work in this version for my 3259. I will adjust in my local file. Both share the same (in consistent) settings for the various modes, eg some options with "mode" added some without "mode" added:

MODE_AUTO = 'Auto Mode'
MODE_ALLERGEN = 'Allergen Mode'
MODE_SLEEP = 'Sleep Mode'
MODE_MANUAL = 'Manual'
MODE_BACTERIA = 'Bacteria'

Betaboon solved this by creating classes for the various models and sticking to API codes:

class PhilipsAC2889(PhilipsGenericCoAPFan):
    AVAILABLE_PRESET_MODES = {
        PRESET_MODE_SPEED_1: {PHILIPS_POWER: "1", PHILIPS_MODE: "M", PHILIPS_SPEED: "1"},
        PRESET_MODE_SPEED_2: {PHILIPS_POWER: "1", PHILIPS_MODE: "M", PHILIPS_SPEED: "2"},
        PRESET_MODE_SPEED_3: {PHILIPS_POWER: "1", PHILIPS_MODE: "M", PHILIPS_SPEED: "3"},
        PRESET_MODE_ALLERGEN: {PHILIPS_POWER: "1", PHILIPS_MODE: "A"},
        PRESET_MODE_AUTO: {PHILIPS_POWER: "1", PHILIPS_MODE: "P"},
        PRESET_MODE_BACTERIA: {PHILIPS_POWER: "1", PHILIPS_MODE: "B"},
        PRESET_MODE_SLEEP: {PHILIPS_POWER: "1", PHILIPS_MODE: "M", PHILIPS_SPEED: "s"},
        PRESET_MODE_TURBO: {PHILIPS_POWER: "1", PHILIPS_MODE: "M", PHILIPS_SPEED: "t"},
Plevuus commented 3 years ago

Today I experimented once again with airctrl and my 2889_http airctrl 192.168.xxx.xx --om 1 doesn't do anything (neither does --om s, --om 2, --om 3 or --om t) airctrl 192.168.xxx.xx --mode M doesn't do anything either. Sending --om x after --mode M, does do anything either. To manually set the speed, I really need to do airctrl 192.168.xxx.xx --mode M --om 1. --om 1 is speed 1 --om 2 is speed 2 --om 3 is speed 3 --om s is speed Sleep --om t is speed Turbo

ronaldt80 commented 3 years ago

It is the same for me and that is also what the preset_mode setting above shows:

Sleep requires airctrl 192.168.xxx.xx --mode M --om s for me.

Oddly enough on some models Philips implemented Sleep/Night/Turbo as a mode (which makes sense!) and on some as a speed (which can only be invoked by setting mode to manual).

ronaldt80 commented 3 years ago

Today I experimented once again with airctrl and my 2889_http airctrl 192.168.xxx.xx --om 1 doesn't do anything (neither does --om s, --om 2, --om 3 or --om t) airctrl 192.168.xxx.xx --mode M doesn't do anything either. Sending --om x after --mode M, does do anything either. To manually set the speed, I really need to do airctrl 192.168.xxx.xx --mode M --om 1. --om 1 is speed 1 --om 2 is speed 2 --om 3 is speed 3 --om s is speed Sleep --om t is speed Turbo

I managed a quick fix by adding a bit of code to the async_set_preset_mode as follows:

    async def async_set_preset_mode(self, preset_mode: str) -> None:
        """Set a preset mode on the fan."""
        if preset_mode in MODE_MAP.values():
            philips_mode = self._find_key(MODE_MAP, preset_mode)
            if philips_mode == "S":
                await self._async_set_values({PHILIPS_MODE: "M", PHILIPS_SPEED: "s"})
            else:
                await self._async_set_values({PHILIPS_MODE: philips_mode})
        else:
            _LOGGER.warning('Unsupported preset mode "%s"', preset_mode)

not a permanent fix as it does not work on all models but at least it allows to trigger a sleep mode on my machine (AC3259) - problem is indeed that on these implementations Turbo and Sleep are speeds and not modes.

GeorgeSG commented 3 years ago

@ronaldt80, @Plevuus thanks for the info! Can you share what's the exact model name of your (http) devices that the integration sets?

You should be able to see it in the entity attributes:

image
ronaldt80 commented 3 years ago

Hi George,

Mine is AC3259_10

Ronald

On Thu, 15 Apr 2021, 18:18 Georgi Gardev, @.***> wrote:

@ronaldt80 https://github.com/ronaldt80, @Plevuus https://github.com/Plevuus thanks for the info! Can you share what's the exact model name of your (http) devices that the integration sets?

You should be able to see it in the entity attributes: [image: image] https://user-images.githubusercontent.com/2514425/114903209-3d9ff500-9e1f-11eb-8204-d885b4c4853d.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/GeorgeSG/philips_airpurifier_http/issues/3#issuecomment-820556975, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMXEM3E7TIRTXCJU3ITXK6TTI4GULANCNFSM42PNHFYQ .

Plevuus commented 3 years ago

Mine says AC2889_10

image

GeorgeSG commented 3 years ago

@ronaldt80, @Plevuus Thanks. I just released version 1.4.0 with some ability to do per-device configuration.

I added initial configurations for your devices, it may not be perfect, but should be a good start :). For both of your devices, "Manual" mode should be send when setting a custom speed.


@Plevuus, technically I added a "Silent" speed instead of "Sleep" speed, but to the Phillips API it shouldn't matter, it's always "s". And it doesn't really matter in HA either, because it's just set_percentage to 20%.

I'm not sure about the "General" and the "Bacteria & Virus" modes from your screenshots. We'll have to adjust those. I assume "general" is "auto"? If you can figure out what needs to be send to the Phillips API (e.g. is it "G" for General, "B" for Bacteria), we can tweak this.


@ronaldt80, unless we missed something, I think your device should just work now, and show only the supported modes. Let me know if there are issues :)

GeorgeSG commented 3 years ago

Per-model config is currently located in https://github.com/GeorgeSG/philips_airpurifier_http/blob/master/custom_components/philips_airpurifier_http/model_config.py

Plevuus commented 3 years ago

Thanks a lot @GeorgeSG!! I just upgraded to version 1.4.0. At first sight behavior seems to be identical to version 1.2.0. Read-out is still working, switching on and off and (some) preset modes are still working, Services still seem to be working, but setting speed still doesn't work. I'll dig into it in the weekend and will let you know the results.

Plevuus commented 3 years ago

I looked into it. It turned out that I was actually still using 1.2.0, because I didn't read the breaking change message well enough. But also with 1.4.0 I couldn't set the speed, only preset modes. I made a change and now it works for me on the AC2889. I did create a pull request for it. "general' is "auto" indeed.

ronaldt80 commented 3 years ago

hi, i have tested this a bit as well, not sure if I fully comprehend the desired behaviour. Set speed percentage to 20% puts the device in sleep mode but this was already the case for me in the previous version. Selecting sleep as preset mode does nothing, when I select manual though it does enter sleep mode. Screenshot 2021-04-25 163524 I was hoping for the possibility to send mode manual, speed sleep (eg. in line with my quick fix above) upon selection of "sleep mode":
await self._async_set_values({PHILIPS_MODE: "M", PHILIPS_SPEED: "s"})

What would be the best way to approach this?

GeorgeSG commented 3 years ago

@ronaldt80 hm, after 1.4.0/1.4.1, it's expected that for your device, manual mode will be send automatically. So changing the speed, should explicitly also change the mode to manual.

So if you set the percentage to 20% (which is sleep), that's exactly what you want - speed sleep, mode manual.

ronaldt80 commented 3 years ago

Hi George, that is correct, set speed percentage works. Silent/Sleep and Turbo are however in reality modes which have (in my view) erroneously been implemented as speeds by Philips.

For all newer models they have corrected this mistake and chosen a mode implementation. I intend to mirror this in HA, eg when I select sleep mode behind the scenes speed is set to sleep and mode to manual. That also allows for usage with the "scheduler" custom component.

My quick fix works but it is not so elegant. Any tips are most welcome:)

Ronald

On Fri, 30 Apr 2021, 17:49 Georgi Gardev, @.***> wrote:

@ronaldt80 https://github.com/ronaldt80 hm, after 1.4.0/1.4.1, it's expected that for your device, manual mode will be send automatically. So changing the speed, should explicitly also change the mode to manual.

So if you set the percentage to 20% (which is sleep), that's exactly what you want - speed sleep, mode manual.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/GeorgeSG/philips_airpurifier_http/issues/3#issuecomment-830187841, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMXEM3F6QHL43IWCDWGYK6LTLLGOTANCNFSM42PNHFYQ .

1toothy commented 3 years ago

Hello,

got the problem:

Error while setting up philips_airpurifier_http platform for fan Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 205, in _async_setup_platform await asyncio.shield(task) File "/config/custom_components/philips_airpurifier_http/fan.py", line 119, in async_setup_platform client = await hass.async_add_executor_job( File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "/config/custom_components/philips_airpurifier_http/fan.py", line 120, in lambda: HTTPAirClient(config[CONF_HOST], False) File "/usr/local/lib/python3.8/site-packages/pyairctrl/http_client.py", line 108, in init self.load_key() File "/usr/local/lib/python3.8/site-packages/pyairctrl/http_client.py", line 148, in load_key config.read(fpath) File "/usr/local/lib/python3.8/configparser.py", line 697, in read self._read(fp, filename) File "/usr/local/lib/python3.8/configparser.py", line 1093, in _read raise DuplicateOptionError(sectname, optname, configparser.DuplicateOptionError: While reading from '/root/.pyairctrl' [line 5]: option '192.168.1.21' in section 'keys' already exists

Any ideas?

Thank u Dave

ronaldt80 commented 3 years ago

Can you raise a different issue and include config details as well as model/make and year of purchase? Could be incompatible with http

1toothy commented 3 years ago

thx for your answer, I have two AC2729 bought 03'2019. Dont know why hass looking adrress 192.168.1.21. I used to have platform: philips_airpurifier and for some time worked ok.

In configuration.yaml

fan:

Below log file: 2021-05-01 17:51:07 WARNING (MainThread) [homeassistant.loader] You are using a custom integration nodered which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant 2021-05-01 17:51:07 WARNING (MainThread) [homeassistant.loader] You are using a custom integration xiaomi_gateway3 which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant 2021-05-01 17:51:07 WARNING (MainThread) [homeassistant.loader] You are using a custom integration hacs which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant 2021-05-01 17:51:08 WARNING (MainThread) [homeassistant.loader] You are using a custom integration momentary which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant 2021-05-01 17:51:09 WARNING (MainThread) [homeassistant.loader] You are using a custom integration philips_airpurifier_http which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant 2021-05-01 17:51:11 ERROR (MainThread) [homeassistant.components.fan] Error while setting up philips_airpurifier_http platform for fan Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 205, in _async_setup_platform await asyncio.shield(task) File "/config/custom_components/philips_airpurifier_http/fan.py", line 119, in async_setup_platform client = await hass.async_add_executor_job( File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, *self.kwargs) File "/config/custom_components/philips_airpurifier_http/fan.py", line 120, in lambda: HTTPAirClient(config[CONF_HOST], False) File "/usr/local/lib/python3.8/site-packages/pyairctrl/http_client.py", line 108, in init self.load_key() File "/usr/local/lib/python3.8/site-packages/pyairctrl/http_client.py", line 148, in load_key config.read(fpath) File "/usr/local/lib/python3.8/configparser.py", line 697, in read self._read(fp, filename) File "/usr/local/lib/python3.8/configparser.py", line 1093, in _read raise DuplicateOptionError(sectname, optname, configparser.DuplicateOptionError: While reading from '/root/.pyairctrl' [line 5]: option '192.168.1.21' in section 'keys' already exists 2021-05-01 17:51:11 ERROR (MainThread) [homeassistant.components.fan] Error while setting up philips_airpurifier_http platform for fan Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 205, in _async_setup_platform await asyncio.shield(task) File "/config/custom_components/philips_airpurifier_http/fan.py", line 119, in async_setup_platform client = await hass.async_add_executor_job( File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run result = self.fn(self.args, **self.kwargs) File "/config/custom_components/philips_airpurifier_http/fan.py", line 120, in lambda: HTTPAirClient(config[CONF_HOST], False) File "/usr/local/lib/python3.8/site-packages/pyairctrl/http_client.py", line 108, in init self.load_key() File "/usr/local/lib/python3.8/site-packages/pyairctrl/http_client.py", line 148, in load_key config.read(fpath) File "/usr/local/lib/python3.8/configparser.py", line 697, in read self._read(fp, filename) File "/usr/local/lib/python3.8/configparser.py", line 1093, in _read raise DuplicateOptionError(sectname, optname, configparser.DuplicateOptionError: While reading from '/root/.pyairctrl' [line 5]: option '192.168.1.21' in section 'keys' already exists 2021-05-01 17:51:31 WARNING (MainThread) [homeassistant.components.websocket_api.http.connection] [140401726226736] Disconnected: Did not receive auth message within 10 seconds 2021-05-01 17:51:56 WARNING (MainThread) [homeassistant.components.websocket_api.http.connection] [140401580562992] Disconnected: Did not receive auth message within 10 seconds 2021-05-01 17:52:21 WARNING (MainThread) [homeassistant.components.websocket_api.http.connection] [140401749903728] Disconnected: Did not receive auth message within 10 seconds 2021-05-01 17:52:46 WARNING (MainThread) [homeassistant.components.websocket_api.http.connection] [140401595685424] Disconnected: Did not receive auth message within 10 seconds