Skip to content
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

[WIP]Add Xiaomi&Aqara air conditioner partner #10761

Closed
wants to merge 24 commits into from

Conversation

cxlwill
Copy link

@cxlwill cxlwill commented Nov 23, 2017

Description:

Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.io#4050

Example entry for configuration.yaml (if applicable):

climate:
  - platform: xiaomi_miio
    name: Xiaomi AC Partner
    host: YOUR_DEVICE_IP
    token: YOUR_TOKEN
    target_sensor: 
    customize:

Checklist:

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • New dependencies have been added to the REQUIREMENTS variable ([example][ex-requir]).
  • New dependencies are only imported inside functions that use them ([example][ex-import]).
  • New dependencies have been added to requirements_all.txt by running script/gen_requirements_all.py.
  • New files were added to .coveragerc.

self.climate.send('send_cmd', [mainCode])
else:
self.climate.send('send_ir_code', [mainCode])
_LOGGER.info('Send Customize Code: acmodel: %s, operation: %s , temperature: %s, fan: %s, swing: %s, sendCode: %s', model, self._current_operation, self._target_temperature, self._current_fan_mode, self._current_swing_mode, mainCode )

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (246 > 79 characters)
whitespace before ')'


try:
self.climate.send('send_cmd', [mainCode])
_LOGGER.info('Change Climate Successful: acmodel: %s, operation: %s , temperature: %s, fan: %s, swing: %s, sendCode: %s', model, self._current_operation, self._target_temperature, self._current_fan_mode, self._current_swing_mode, mainCode )

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (252 > 79 characters)
whitespace before ')'

index += 1


try:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too many blank lines (2)

temp = hex(temp)[2:].upper()
mainCode = mainCode.replace('t4wt', temp)
index += 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line contains whitespace

temp = hex(temp)[2:].upper()
mainCode = mainCode.replace('t6t', temp)
if tep == "t4wt":
temp = (int(codeConfig['t4wt']) + int(self._target_temperature) - 17) % 16

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (98 > 79 characters)

mainCode = mainCode
# mainCode = mainCode.replace('li', codeConfig['li']['on'])
index += 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line contains whitespace

if self._current_swing_mode == 'on':
mainCode = mainCode.replace('sw', codeConfig['sw']['on'])
else:
mainCode = mainCode.replace('sw', codeConfig['sw']['off'])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (82 > 79 characters)

if tep == "sw":
if self._current_swing_mode == 'on':
mainCode = mainCode.replace('sw', codeConfig['sw']['on'])
else:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing whitespace

mainCode = mainCode.replace('wi', wiCode);
if tep == "sw":
if self._current_swing_mode == 'on':
mainCode = mainCode.replace('sw', codeConfig['sw']['on'])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (81 > 79 characters)

wiCode = '2'
else:
wiCode = '3'
mainCode = mainCode.replace('wi', wiCode);

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

@cxlwill cxlwill changed the title Add Xiaomi&Aqara air conditioner partner [WIP]Add Xiaomi&Aqara air conditioner partner Nov 23, 2017
@cxlwill
Copy link
Author

cxlwill commented Nov 23, 2017

The main contributor is Mac_zhou. We will work together to make it to HA~

@Mylife4air
Copy link

用 pycharm 的话 只要把画灰色线的解决了,格式检查就没问题

@tinloaf tinloaf self-requested a review November 23, 2017 15:20
@homeassistant
Copy link
Contributor

Hi @mac-zhou,

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!

self._customize_swing_list = list(self._customize['swing'])
self._swing_list = self._customize_swing_list
self._current_swing_mode = 'idle'
else:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing whitespace

from homeassistant.const import (
TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_TEMPERATURE, ATTR_UNIT_OF_MEASUREMENT,
CONF_NAME, CONF_HOST, CONF_TOKEN, CONF_TIMEOUT)
from homeassistant.helpers import condition

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'homeassistant.helpers.condition' imported but unused

from homeassistant.components.climate import (
PLATFORM_SCHEMA,
ClimateDevice, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW)
from homeassistant.const import (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'homeassistant.const.TEMP_FAHRENHEIT' imported but unused

maincode = maincode
index += 1

if (model in __Presets__) and ('EXTRA_VALUE' in __Presets__[model]):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (80 > 79 characters)

CONF_SYNC = 'sync'
CONF_CUSTOMIZE = 'customize'

__Presets__ = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a lot like protocol-level magic strings. We try to keep protocol implementations out of home assistant as far as possible. Perhaps it would be better to include this low-level protocol stuff in the python-miio package?

vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
vol.Required(CONF_SENSOR, default=None): cv.entity_id,
vol.Optional(CONF_CUSTOMIZE, default=None): dict,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to use the _customize member to set fan and swing modes. Why don't you just let the user configure a list of possible fan and swing modes, as for example the mqtt climate platform does?

customize = config.get(CONF_CUSTOMIZE)

add_devices_callback([MiAcPartner(
hass, name, None, None, None, 'auto', None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the class constructor have all these arguments if you just statically pass None for them?

token, sensor_entity_id, sync, customize)])


class ClimateStatus(ClimateDevice):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the idea behind this? Is that just for decoding the response from the device? If so, (a) it might also belong into python-miio, and (b) it should not derive from ClimateDevice. Otherwise: What kind of entity is this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class should belong to the upstream lib.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"""get states from climate"""
getstate = self.climate.send("get_model_and_state", [])
_LOGGER.info(getstate)
self._state = ClimateStatus(getstate)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you set the state of an entity do another entity (remember that ClimateStatus derives from ClimateDevice). That is… weird. self._state should be a simple (string) representation of the device's current state.

self.schedule_update_ha_state()

def set_swing_mode(self, swing_mode):
"""Set new target temperature."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is also wrong.

self.schedule_update_ha_state()

def set_fan_mode(self, fan):
"""Set new target temperature."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment wrong

self.schedule_update_ha_state()

def set_operation_mode(self, operation_mode):
"""Set new target temperature."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment wrong.

"""Return the list of available fan modes."""
return self._fan_list

def set_temperature(self, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set_temperature can also be called with a new operation mode, to set both in one go. That must be handled here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

self._state = ClimateStatus(getstate)
return self._state

def sendcmd(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also very much protocol-level and should be factored out into a library.

@rytilahti
Copy link
Member

rytilahti commented Nov 26, 2017

Just FYI, some of the upstream parts of this are being worked in rytilahti/python-miio#129 . It probably makes sense to combine the effort, right?

from homeassistant.const import (
TEMP_CELSIUS, ATTR_TEMPERATURE, ATTR_UNIT_OF_MEASUREMENT,
CONF_NAME, CONF_HOST, CONF_TOKEN, CONF_TIMEOUT)
# from homeassistant.helpers import condition
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented out code lines should not be added.

token, sensor_entity_id, sync, customize)])


class ClimateStatus(ClimateDevice):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class should belong to the upstream lib.

token, sensor_entity_id, sync, customize)])


class ClimateStatus(ClimateDevice):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thundergreen
Copy link

Hi.was just wondering if this could also include the ir WiFi transmitter ... For people using the it transmitter from xiaomi

@Danielhiversen
Copy link
Member

@cxlwill do you plan to finish this?

@cxlwill
Copy link
Author

cxlwill commented Jan 19, 2018

@Danielhiversen Yeah, but I want to wait for Aqara to update the protocol in order to use Gateway function as well. If you want to close it for now or continue the work, very welcome.

@syssi
Copy link
Member

syssi commented Jan 28, 2018

@cxlwill @mac-zhou I've made a lot of code changes. The update interval (called "sync" in the past) can be controlled by the configuration key "scan_interval" (cp. https://home-assistant.io/docs/configuration/platform_options/).

I didn't change the customization handling yet. Could you test the updated codebase extensive? You will need the current master of python-miio.

@balloob
Copy link
Member

balloob commented Feb 18, 2018

What's the status of this PR? This PR has been WIP since last year.

@syssi
Copy link
Member

syssi commented Feb 18, 2018

I've refactored the code and looking for somebody willing to test. If nobody is able to test the component the PR can be close d.

@balloob
Copy link
Member

balloob commented Feb 18, 2018

I suggest we close it. It has been 3 weeks since your changes and asking to test it. Nothing happened. We can reconsider when testing happens

@balloob balloob closed this Feb 18, 2018
@syssi
Copy link
Member

syssi commented Feb 18, 2018

The component is available as custom_component now: https://github.com/syssi/xiaomi_airconditioningcompanion

@cxlwill
Copy link
Author

cxlwill commented Feb 18, 2018

Sorry for late response. It’s Chinese New Year now so I bet everyone is on vacation and leave HA stuffs behind. Thanks to Syssi for all your efforts. I didn’t notice about the PR Of custom_component before. And original author is quite busy since last year so he paused the update of this component. I will test it this evening. If everything works well, I will reopen this.

@balloob
Copy link
Member

balloob commented Feb 18, 2018

@cxlwill happy new year! 🎉🐕

I don't think you can reopen this PR, but just post here and we'll reopen.

@cxlwill
Copy link
Author

cxlwill commented Feb 20, 2018

@balloob Cheers~ @syssi No luck here. I test the custom component and issued an error:

xiaomi_miio: Error on device update!
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 197, in _async_add_entity
    yield from entity.async_device_update(warning=False)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 325, in async_device_update
    yield from self.async_update()
  File "/Users/cxlwill/.homeassistant/custom_components/climate/xiaomi_miio.py", line 208, in async_update
    ATTR_SWING_MODE: state.swing_mode.name,
AttributeError: 'bool' object has no attribute 'name'

@syssi
Copy link
Member

syssi commented Feb 20, 2018

@cxlwill Please report all issues here: https://github.com/syssi/xiaomi_airconditioningcompanion/issues

If the custom component is stable again I will move the code.

@syssi
Copy link
Member

syssi commented Feb 20, 2018

@cxlwill fixed.

@home-assistant home-assistant locked and limited conversation to collaborators May 29, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet