Skip to content
This repository has been archived by the owner on Sep 13, 2022. It is now read-only.

Commit

Permalink
Optimizition
Browse files Browse the repository at this point in the history
  • Loading branch information
georgezhao2010 authored Jun 25, 2021
1 parent 39e1fe6 commit c5be463
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 126 deletions.
52 changes: 29 additions & 23 deletions custom_components/climate_ewelink/ac_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,30 @@
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.DEBUG)

AC_SWITCHES = {
AC_ENTITIES = {
"climate": {
"type": "climate",
"icon": "mdi:air-conditioner"
},
"wind_swing_lr": {
"type": "switch",
"name": "Swing Horizontal",
"icon": "mdi:arrow-split-vertical",
"icon": "mdi:arrow-split-vertical"
},
"wind_swing_ud": {
"type": "switch",
"name": "Swing Vertical",
"icon": "mdi:arrow-split-horizontal",
"icon": "mdi:arrow-split-horizontal"
},
"eco": {
"type": "switch",
"name": "ECO Mode",
"icon": "mdi:alpha-e-circle",
"icon": "mdi:alpha-e-circle"
},
"comfort_power_save": {
"type": "switch",
"name": "Comfort Mode",
"icon": "mdi:alpha-c-circle",
"icon": "mdi:alpha-c-circle"
},
"prevent_straight_wind": {
"type": "switch",
Expand Down Expand Up @@ -67,28 +71,29 @@ def __init__(self, states_manager, deviceid, state_key, device_status):
self.entity_id = self._unique_id
self._state = None
self._is_online = True
manufacturer = "Unknown"
model = "Unknown"
if "extra" in device_status and "extra" in device_status["extra"] \
and "manufacturer" in device_status["extra"]["extra"]:
manufacturer = device_status["extra"]["extra"]["manufacturer"]
if "extra" in device_status and "extra" in device_status["extra"] \
and "model" in device_status["extra"]["extra"]:
model = device_status["extra"]["extra"]["model"]
if "params" in device_status:
self._update_state(device_status["params"])
manufacturer = "Unknow"
model = "Unknow"
self._device_name = f"Climate {self._device_id}"
if "brandName" in device_status:
manufacturer = device_status["brandName"]
if "productModel" in device_status:
model = device_status["productModel"]
if "name" in device_status:
self._device_name = device_status["name"]
self._device_info = {
"manufacturer": manufacturer,
"model": model,
"identifiers": {(DOMAIN, self._device_id)},
"name": f"Climate {self._device_id}",
"name": self._device_name
}
if "params" in device_status:
self._update_state(device_status["params"])

def _update_state(self, status):
if self._state_key in status:
if "value_exchange" in AC_SWITCHES[self._state_key] \
and str(status[self._state_key]) in AC_SWITCHES[self._state_key]["value_exchange"]["get"]:
value = AC_SWITCHES[self._state_key]["value_exchange"]["get"][str(status[self._state_key])]
if "value_exchange" in AC_ENTITIES[self._state_key] \
and str(status[self._state_key]) in AC_ENTITIES[self._state_key]["value_exchange"]["get"]:
value = AC_ENTITIES[self._state_key]["value_exchange"]["get"][str(status[self._state_key])]
else:
value = status[self._state_key]
if value != self._state:
Expand All @@ -114,19 +119,20 @@ def should_poll(self):

@property
def device_class(self):
return AC_SWITCHES[self._state_key]["device_class"] if "device_class" in AC_SWITCHES[self._state_key] else None
return AC_ENTITIES[self._state_key]["device_class"] if "device_class" in AC_ENTITIES[self._state_key] else None

@property
def name(self):
return f"Climate {self._device_id} {AC_SWITCHES[self._state_key]['name']}"
return f"{self._device_name} {AC_ENTITIES[self._state_key]['name']}" if "name" in AC_ENTITIES[self._state_key] \
else self._device_name

@property
def unit_of_measurement(self):
return AC_SWITCHES[self._state_key]["unit"] if "unit" in AC_SWITCHES[self._state_key] else None
return AC_ENTITIES[self._state_key]["unit"] if "unit" in AC_ENTITIES[self._state_key] else None

@property
def icon(self):
return AC_SWITCHES[self._state_key]["icon"] if "icon" in AC_SWITCHES[self._state_key] else None
return AC_ENTITIES[self._state_key]["icon"] if "icon" in AC_ENTITIES[self._state_key] else None

@property
def state(self):
Expand Down
136 changes: 49 additions & 87 deletions custom_components/climate_ewelink/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
CLIMATE_DEVICES,
MODE_OFFLINE
)
from .ac_entity import AirConditionerEntity


_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.DEBUG)
Expand All @@ -32,63 +34,26 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities(devices)


class EWeLinkClimate(ClimateEntity):
class EWeLinkClimate(AirConditionerEntity, ClimateEntity):
def __init__(self, states_manager, deviceid:str, device_status):
self._is_on = None
self._device_id = deviceid
self._unique_id = f"{DOMAIN}.{deviceid}"
self.entity_id = self._unique_id
self._states_manager = states_manager
self._states_manager.add_update(self._device_id, self.update)
AirConditionerEntity.__init__(self, states_manager, deviceid, "climate", device_status)
self._attr_precision = PRECISION_TENTHS
self._attr_fan_mode = None
self._attr_indoor_temperature = None
self._attr_target_temperature = None
self._attr_swing_mode = None
self._is_online = True

if "params" in device_status:
self.update_data(device_status["params"])
manufacturer = "Unknow"
model = "Unknow"
if "extra" in device_status and "extra" in device_status["extra"] and "manufacturer" in device_status["extra"]["extra"]:
manufacturer = device_status["extra"]["extra"]["manufacturer"]
if "extra" in device_status and "extra" in device_status["extra"] and "model" in device_status["extra"]["extra"]:
model = device_status["extra"]["extra"]["model"]
self._device_info = {
"manufacturer": manufacturer,
"model": model,
"identifiers": {(DOMAIN, self._device_id)},
"name": f"Climate {self._device_id}",
}

@property
def name(self):
return f"Climate {self._device_id}"

@property
def device_info(self):
return self._device_info

@property
def unique_id(self):
return self._unique_id

@property
def supported_features(self):
return SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE | SUPPORT_SWING_MODE

@property
def should_poll(self):
return False

@property
def hvac_mode(self) -> str:
return self._attr_hvac_mode if self._is_on else HVAC_MODE_OFF
return self.state

@property
def hvac_modes(self):
return [MODE_OFFLINE, HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_AUTO, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY]
return [HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_AUTO, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY]

@property
def temperature_unit(self):
Expand Down Expand Up @@ -139,51 +104,48 @@ def max_temp(self):
return TEMPERATURE_MAX

@property
def state(self) -> str:
if self._is_online is False:
return MODE_OFFLINE
elif self._is_on:
return self.hvac_mode
else:
return HVAC_MODE_OFF

def update_data(self, data: dict = None):
try:
if "online" in data:
self._is_online = data["online"]
if "power" in data: # 0 - off, 1 - onW
self._is_on = (data['power'] == "on")
if "mode" in data: # 0 - heat, 1 - cool, 15 - off
if data['mode'] == "fan":
self._attr_hvac_mode = HVAC_MODE_FAN_ONLY
else:
self._attr_hvac_mode = data['mode']
if 'wind_speed' in data: # 0 - low, 3 - auto, 15 - off
self._attr_fan_speed = data['wind_speed']
if self._attr_fan_speed > 100:
self._attr_fan_mode = FAN_AUTO
elif self._attr_fan_speed > 70:
self._attr_fan_mode = FAN_HIGH
elif self._attr_fan_speed > 30:
self._attr_fan_mode = FAN_MEDIUM
else:
self._attr_fan_mode = FAN_LOW
if "temperature" in data:
self._attr_target_temperature = data["temperature"]
if "indoor_temperature" in data:
self._attr_indoor_temperature = data["indoor_temperature"]

except:
pass

def update(self, data: dict = None):
self.update_data(data)
self.schedule_update_ha_state()
def is_on(self) -> bool:
return self._state != HVAC_MODE_OFF and self._state != MODE_OFFLINE

def _update_state(self, data: dict = None):
result = False
if "online" in data:
self._is_online = data["online"]
result = True
if "power" in data: # 0 - off, 1 - onW
state = HVAC_MODE_OFF
if data['power'] == "on":
if "mode" in data: # 0 - heat, 1 - cool, 15 - off
if data['mode'] == "fan":
state = HVAC_MODE_FAN_ONLY
result = True
else:
state = data['mode']
result = True
self._state = state
if 'wind_speed' in data: # 0 - low, 3 - auto, 15 - off
self._attr_fan_speed = data['wind_speed']
if self._attr_fan_speed > 100:
self._attr_fan_mode = FAN_AUTO
elif self._attr_fan_speed > 70:
self._attr_fan_mode = FAN_HIGH
elif self._attr_fan_speed > 30:
self._attr_fan_mode = FAN_MEDIUM
else:
self._attr_fan_mode = FAN_LOW
result = True
if "temperature" in data:
self._attr_target_temperature = data["temperature"]
result = True
if "indoor_temperature" in data:
self._attr_indoor_temperature = data["indoor_temperature"]
result = True
return result

def set_temperature(self, **kwargs) -> None:
if self.state != MODE_OFFLINE:
temperature = int(kwargs[ATTR_TEMPERATURE])
self._states_manager.send_payload(self._device_id, {"temperature": temperature})
self._state_manager.send_payload(self._device_id, {"temperature": temperature})

def set_fan_mode(self, fan_mode: str) -> None:
if self.state != MODE_OFFLINE:
Expand All @@ -194,7 +156,7 @@ def set_fan_mode(self, fan_mode: str) -> None:
wind_speed = 69
elif fan_mode == FAN_HIGH:
wind_speed = 99
self._states_manager.send_payload(self._device_id, {"power": "on","wind_speed": wind_speed})
self._state_manager.send_payload(self._device_id, {"power": "on","wind_speed": wind_speed})

def set_hvac_mode(self, hvac_mode: str) -> None:
if self.state != MODE_OFFLINE:
Expand All @@ -204,7 +166,7 @@ def set_hvac_mode(self, hvac_mode: str) -> None:
mode_key = "power"
elif hvac_mode == HVAC_MODE_FAN_ONLY:
mode = "fan"
self._states_manager.send_payload(self._device_id, {"power": "on", mode_key: mode})
self._state_manager.send_payload(self._device_id, {"power": "on", mode_key: mode})

def set_swing_mode(self, swing_mode: str) -> None:
if self.state != MODE_OFFLINE:
Expand All @@ -215,12 +177,12 @@ def set_swing_mode(self, swing_mode: str) -> None:
data = {"wind_swing_lr": "off", "wind_swing_ud": "on"}
elif swing_mode == SWING_HORIZONTAL:
data = {"wind_swing_lr": "on", "wind_swing_ud": "off"}
self._states_manager.send_payload(self._device_id, data)
self._state_manager.send_payload(self._device_id, data)

def turn_on(self):
if self.state != MODE_OFFLINE:
self._states_manager.send_payload(self._device_id, {"power": "on"})
self._state_manager.send_payload(self._device_id, {"power": "on"})

def turn_off(self):
if self.state != MODE_OFFLINE:
self._states_manager.send_payload(self._device_id, {"power": "off"})
self._state_manager.send_payload(self._device_id, {"power": "off"})
2 changes: 1 addition & 1 deletion custom_components/climate_ewelink/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"domain": "climate_ewelink",
"name": "Midea A/C via eWeLink",
"version": "v0.2.3",
"version": "v1.0.24",
"config_flow": true,
"documentation": "https://github.com/georgezhao2010/climate_ewelink",
"issue_tracker": "https://github.com/georgezhao2010/climate_ewelink/issues",
Expand Down
5 changes: 2 additions & 3 deletions custom_components/climate_ewelink/sensor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from .ac_entity import AirConditionerEntity, AC_SWITCHES

from .ac_entity import AirConditionerEntity, AC_ENTITIES
from .const import (
STATES_MANAGER,
CLIMATE_DEVICES
Expand All @@ -14,7 +13,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
devices = []
states_manager = hass.data[config_entry.entry_id][STATES_MANAGER]
for deviceid,device in hass.data[config_entry.entry_id][CLIMATE_DEVICES].items():
for state_key, config in AC_SWITCHES.items():
for state_key, config in AC_ENTITIES.items():
if config["type"] == "sensor":
dev = AirConditionerEntity(states_manager, deviceid, state_key, device.status)
devices.append(dev)
Expand Down
10 changes: 6 additions & 4 deletions custom_components/climate_ewelink/statemanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ def __init__(self, ewelink_cloud: EWeLinkCloud):
self._device_updates = {}

def update_device(self, deviceid, params):
updates = self._device_updates[deviceid]
if updates:
for update_state in updates:
update_state(params)
if deviceid in self._device_updates:
updates = self._device_updates[deviceid]
if updates:
for update_state in updates:
update_state(params)

def on_open(self):
ts = time.time()
Expand Down Expand Up @@ -117,6 +118,7 @@ def run(self):
on_open=self.on_open, on_message=self.on_message)
self._ws.keep_running = True
threading.Thread(target = self._ws.run_forever(ping_interval=145, ping_timeout=5))
_LOGGER.debug("websocket disconnected, retrying")
self._ws.close()
self._ws = None
self._url = None
Expand Down
16 changes: 8 additions & 8 deletions custom_components/climate_ewelink/switch.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .ac_entity import AirConditionerEntity, AC_SWITCHES
from .ac_entity import AirConditionerEntity, AC_ENTITIES
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.const import (
STATE_ON,
Expand All @@ -22,7 +22,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
devices = []
states_manager = hass.data[config_entry.entry_id][STATES_MANAGER]
for deviceid, device in hass.data[config_entry.entry_id][CLIMATE_DEVICES].items():
for state_key, config in AC_SWITCHES.items():
for state_key, config in AC_ENTITIES.items():
if config["type"] == "switch":
dev = ACSwitch(states_manager, deviceid, state_key, device.status)
devices.append(dev)
Expand All @@ -36,16 +36,16 @@ def is_on(self) -> bool:

def turn_on(self, **kwargs: Any):
value = STATE_ON
if "value_exchange" in AC_SWITCHES[self._state_key] and \
value in AC_SWITCHES[self._state_key]["value_exchange"]["set"]:
value = AC_SWITCHES[self._state_key]["value_exchange"]["set"][value]
if "value_exchange" in AC_ENTITIES[self._state_key] and \
value in AC_ENTITIES[self._state_key]["value_exchange"]["set"]:
value = AC_ENTITIES[self._state_key]["value_exchange"]["set"][value]
self._state_manager.send_payload(self._device_id, {"power": "on", self._state_key: value})

def turn_off(self, **kwargs: Any):
value = STATE_OFF
if "value_exchange" in AC_SWITCHES[self._state_key] and \
value in AC_SWITCHES[self._state_key]["value_exchange"]["set"]:
value = AC_SWITCHES[self._state_key]["value_exchange"]["set"][value]
if "value_exchange" in AC_ENTITIES[self._state_key] and \
value in AC_ENTITIES[self._state_key]["value_exchange"]["set"]:
value = AC_ENTITIES[self._state_key]["value_exchange"]["set"][value]
self._state_manager.send_payload(self._device_id, {self._state_key: value})

def _update_state(self, status):
Expand Down

0 comments on commit c5be463

Please sign in to comment.