-
-
Notifications
You must be signed in to change notification settings - Fork 31.2k
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
Daikin Climate - Better integration with Climate base component #16913
Conversation
Made some modification in order to better integrate the Daikin AC Component with the base Climate Component. Benefits are: Support localization for Operation Mode Support for Homekit Integration (if the AC is turned On, now the status is updated in Homekit)
Hi @MatteGary, 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! |
@@ -262,4 +277,4 @@ def swing_list(self): | |||
def update(self): | |||
"""Retrieve latest state.""" | |||
self._api.update(no_throttle=self._force_refresh) | |||
self._force_refresh = False | |||
self._force_refresh = False |
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.
no newline at end of file
if daikin_op_mode is not None: | ||
value = DAIKIN_TO_HA_STATE.get(daikin_op_mode) | ||
else: | ||
value = tmp_value |
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.
trailing whitespace
'[^a-z]', | ||
'', | ||
self._api.device.represent(daikin_attr)[1] | ||
).title() | ||
) | ||
|
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.
blank line contains whitespace
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Fixed to .title() functionality in matching the Operation_Mode
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
||
daikin_op_mode = DAIKIN_TO_HA_STATE[tmp_value] | ||
if daikin_op_mode is not None: | ||
value = DAIKIN_TO_HA_STATE.get(daikin_op_mode) |
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.
How can this work? We already have the value from the dict in daikin_op_mode
. We shouldn't need to get it again.
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.
I think that I can make this part a little bit better, as soon as I can I will do that. The if statement is definetly too much. But the dictionary DAIKIN_TO_HA_STATE is necessary to map the operation_mode from the AC into the accepted one in HA climate component (there are some mismatch, like ‘heat’ vs ‘hot’). That’s way in the previous version the localization wasn’t working.
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.
Yes, but you're using the same dictionary twice. That looks like a bug. We should only need to do one lookup.
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.
I’m not an expert in Python (I work more with .NET tools), how can I use a key-value dictionary in “both direction”? (I mean, one time I’m using the key to get the value, and the next time I should use the value to get the key)
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.
Dictionaries in Python are "one way" only. Keys are unique, but values don't have to be unique. It's possible to iterate over a dictionary, check for a value and then save the key(s) that match the value. What is the goal with this part of the code? If you explain that we can try to figure out the best way.
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.
I’ll try to explain: in the original component’s code, there was no mapping between the operation mode formthe daikin AC unit and the one for the base HA climate component. The list of available operation mode and the actual operation mode was just the ones available for the Daikin AC with a starting Uppercase. This was ok for most of the functionality, but what wasn’t working was:
- Localization: the operation mode was indeed something like ‘Off’, ‘Hot’, ‘Auto’, but it was just hardcoded from the component. It was ok for english user, but that didn’t match the lsbel in the climate translation file, which are ‘off’, ‘heat’, ‘auto’ (as you can see there is also a mismatch between Hot and Heat).
- Homekit integration (and possibly other platform): this part wasn’t working at all. Since Homekit interact with the base HA climate component, and due to the mismatch I describe before, I wasn't able to use Homekit to get or set the status of the AC.
I managed to make it eork using a dictionary to translate Daikin Operation Mode to HA Operation Mode (DAIKIN_TO_HA_STATE) and the other way around (HA_STATE_TO_DAIKIN).
Since, as you point it out, the mapping is the same in the two direction, I can change the behavior removing the dictionary and using something like a Tuple (or at least that is what I would use in C#). Do you have any suggestion? Otherwhise tomorrow I’ll try to find sometime to fix this.
Tks
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.
Dictionary is what we always use for translating modes between home assistant and device. You still didn't explain what you want to do with this part of the code. Do we want to end up with Daikin mode or home assistant mode, after the translation?
If it's home assistant mode, we should only use DAIKIN_TO_HA_STATE
dictionary one time, not twice in a row.
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.
This is how I would expect us to do it:
daikin_mode = re.sub(
'[^a-z]', '', self._api.device.represent(daikin_attr)[1])
ha_mode = DAIKIN_TO_HA_STATE.get(daikin_mode)
value = ha_mode
@@ -76,7 +85,7 @@ def __init__(self, api): | |||
self._force_refresh = False | |||
self._list = { | |||
ATTR_OPERATION_MODE: list( | |||
map(str.title, set(HA_STATE_TO_DAIKIN.values())) | |||
map(str, set(DAIKIN_TO_HA_STATE.values())) |
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.
Why do we need the str
copy?
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.
Making it a set doesn't seem necessary either. We know what the values are and they are unique. The dictionary is a constant so it won't change unless we change it.
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.
For this part I made just little modification to make it work properly, but the logics is the one from the original commit for the daikin component.
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.
Since we're here, please clean it up.
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.
Change this to:
self._list = {
ATTR_OPERATION_MODE: list(HA_STATE_TO_DAIKIN),
...
}
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
if value.title() in self._list[attr]: | ||
values[daikin_attr] = value.lower() | ||
if value in self._list[attr]: | ||
values[daikin_attr] = HA_STATE_TO_DAIKIN[value]; |
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.
statement ends with a semicolon
self._api.device.represent(daikin_attr)[1] | ||
).title() | ||
daikin_mode = re.sub( | ||
'[^a-z]','',self._api.device.represent(daikin_attr)[1]) |
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.
missing whitespace after ','
ATTR_OPERATION_MODE: list( | ||
map(str.title, set(HA_STATE_TO_DAIKIN.values())) | ||
), | ||
ATTR_OPERATION_MODE: list(DAIKIN_TO_HA_STATE), |
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.
This should be:
ATTR_OPERATION_MODE: list(HA_STATE_TO_DAIKIN),
We want to use the ha states so we use the keys of the HA_STATE_TO_DAIKIN
dictionary.
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.
Can you check my lasts commit? I’m quite sure that I should use the other dictionary in that point. Today I’m not able to test since I’m travelling.
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.
We should use the same dictionary as we do here:
https://github.com/home-assistant/home-assistant/pull/16913/files#diff-f35f4028d7ed0027465e5dea53ef4acdR178
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.
I made the modification you suggested, but I'm not able to test it right now. I'm hoping that @mynameisdaniel32 can test it sooner than I can 😃
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.
I managed to run a quick test, and it seems to work good. As soon as I can I will run some further tests.
Just did another test of this (latest version), most modes work fine, but I'm seeing problems with some. When selecting 'hot' or 'fan' from the HA UI I get the task exceptions errors below (and nothing happens on the AC). When selecting 'heat' from HomeKit, the bottom (invalid value) error shows. All other operation modes seem to work fine.
|
@mynameisdaniel32 thanks for your precise testing. This week I don’t have much time to do testing, but I will try to find some. Thanks a lot. |
Change in list of Operation Mode
'', | ||
self._api.device.represent(daikin_attr)[1] | ||
).title() | ||
daikin_mode = re.sub('[^a-z]', '', self._api.device.represent(daikin_attr)[1]) |
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.
line too long (90 > 79 characters)
self._api.device.represent(daikin_attr)[1] | ||
).title() | ||
daikin_mode = re.sub('[^a-z]', '', | ||
self._api.device.represent(daikin_attr)[1]) |
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.
continuation line under-indented for visual indent
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.
Looks good! Let me know when you're happy with testing and we can merge.
Please update the PR description with a paragraph about the breaking change for the release notes. This is a breaking change since we change the names of the available operating modes of this platform. |
@MartinHjelmare I'm OK with testing, I think we can merge this PR so that everyone else can play with it. |
Great! |
This looks like a good fix. How can I test it or when might I expect it in the main release, so my Hass.io would get updated? I am running the latest (0.80) but still see "hot" so don't think this has made it yet? |
@charlietomo If you want to test it now you can copy the PR code into a custom component. Regarding the merge in the main release, it's all up to the usual process of PR of getting into stable release, I don't know how long will it take to see this PR in the main release. |
Thanks. I downloaded the raw file as daikin.py and moved it into |
Just an update and thankyou message. I see that in 0.81 which I just upgraded to on Hass.io this has made it into the main release. I removed my |
@charlietomo you're welcome! As soon as I have time I'll have a look at the 22°C issue. |
@MatteGary there has been some work (solved?) done on the 22°C issue over here. I haven't got it to work yet but I think that is "user error" trying to merge these new changes with other code changes to handle the 22°C issue. Ideally both changes could be merged and end up in the main release! |
Description:
I made some modification do the Daikin Climate Component in order to better integrate the Daikin AC interface with the base Climate Component.
Improved functionality are:
Support for localization for Operation Mode
Support for Homekit Integration (if the AC is turned On, now the status is updated in Homekit)
Breaking Changes
In order to support localization for Operation Mode, now the available options for this field are changed according to:
old version / new version (english only)
For other languages, the new version is used according to the translated version.