Skip to content

Commit

Permalink
Some fixes for None types, cleanup and extra checks (#198)
Browse files Browse the repository at this point in the history
* Update climate.py

* Fixes, checks & removal of old stuff
  • Loading branch information
RobHofmann authored Jul 23, 2024
1 parent 9bbfe64 commit 55b914a
Showing 1 changed file with 85 additions and 48 deletions.
133 changes: 85 additions & 48 deletions custom_components/gree/climate.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
#!/usr/bin/python
# Do basic imports
import importlib.util
import socket
import base64
import re
import sys

import asyncio
import logging
import binascii
import os.path
import voluptuous as vol
import homeassistant.helpers.config_validation as cv

Expand All @@ -23,24 +17,18 @@
from homeassistant.const import (
ATTR_TEMPERATURE,
ATTR_UNIT_OF_MEASUREMENT,
CONF_CUSTOMIZE,
CONF_HOST,
CONF_MAC,
CONF_NAME,
CONF_PORT,
CONF_TIMEOUT,
PRECISION_TENTHS,
PRECISION_WHOLE,
STATE_OFF,
STATE_ON,
STATE_UNKNOWN,
UnitOfTemperature
STATE_UNKNOWN
)

from homeassistant.core import Event, EventStateChangedData, callback
from homeassistant.helpers.event import async_track_state_change_event
from homeassistant.helpers.restore_state import RestoreEntity
from configparser import ConfigParser
from Crypto.Cipher import AES
try: import simplejson
except ImportError: import json as simplejson
Expand Down Expand Up @@ -186,7 +174,7 @@ def __init__(self, hass, name, ip_addr, port, mac_addr, timeout, target_temp_ste
self._unit_of_measurement = '°C'

self._hvac_modes = hvac_modes
self._hvac_mode = None
self._hvac_mode = HVACMode.OFF
self._fan_modes = fan_modes
self._fan_mode = None
self._swing_modes = swing_modes
Expand Down Expand Up @@ -292,33 +280,33 @@ def __init__(self, hass, name, ip_addr, port, mac_addr, timeout, target_temp_ste

if light_sensor_entity_id:
_LOGGER.info('Setting up light sensor entity: ' + str(light_sensor_entity_id))
if self.hass.states.get(light_sensor_entity_id).state is STATE_ON:
if self.hass.states.get(light_sensor_entity_id) is not None and self.hass.states.get(light_sensor_entity_id).state is STATE_ON:
self._enable_light_sensor = True
elif self.hass.states.get(light_sensor_entity_id).state is STATE_OFF:
else:
self._enable_light_sensor = False
async_track_state_change_event(hass, light_sensor_entity_id, self._async_light_sensor_entity_state_changed)
else:
self._enable_light_sensor = None
self._enable_light_sensor = False

if auto_light_entity_id:
_LOGGER.info('Setting up auto light entity: ' + str(auto_light_entity_id))
if self.hass.states.get(auto_light_entity_id).state is STATE_ON:
if self.hass.states.get(auto_light_entity_id) is not None and self.hass.states.get(auto_light_entity_id).state is STATE_ON:
self._auto_light = True
elif self.hass.states.get(auto_light_entity_id).state is STATE_OFF:
else:
self._auto_light = False
async_track_state_change_event(hass, auto_light_entity_id, self._async_auto_light_entity_state_changed)
else:
self._auto_light = None
self._auto_light = False

if auto_xfan_entity_id:
_LOGGER.info('Setting up auto xfan entity: ' + str(auto_xfan_entity_id))
if self.hass.states.get(auto_xfan_entity_id).state is STATE_ON:
if self.hass.states.get(auto_xfan_entity_id) is not None and self.hass.states.get(auto_xfan_entity_id).state is STATE_ON:
self._auto_xfan = True
elif self.hass.states.get(auto_xfan_entity_id).state is STATE_OFF:
else:
self._auto_xfan = False
async_track_state_change_event(hass, auto_xfan_entity_id, self._async_auto_xfan_entity_state_changed)
else:
self._auto_xfan = None
self._auto_xfan = False

# Pad helper method to help us get the right string for encrypting
def Pad(self, s):
Expand All @@ -330,6 +318,7 @@ def FetchResult(self, cipher, ip_addr, port, timeout, json):
clientSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
clientSock.settimeout(timeout)
clientSock.sendto(bytes(json, "utf-8"), (ip_addr, port))
_LOGGER.info('3')
data, addr = clientSock.recvfrom(64000)
receivedJson = simplejson.loads(data)
clientSock.close()
Expand Down Expand Up @@ -754,9 +743,12 @@ async def _async_lights_entity_state_changed(self, event: Event[EventStateChange
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('lights_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('lights_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('lights_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._current_lights:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -778,9 +770,12 @@ async def _async_xfan_entity_state_changed(self, event: Event[EventStateChangedD
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('xfan_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('xfan_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('xfan_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._current_xfan:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -806,9 +801,12 @@ async def _async_health_entity_state_changed(self, event: Event[EventStateChange
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('health_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('health_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('health_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._current_health:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -830,12 +828,21 @@ async def _async_powersave_entity_state_changed(self, event: Event[EventStateCha
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('powersave_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('powersave_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('powersave_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._current_powersave:
# do nothing if state change is triggered due to Sync with HVAC
return
if not hasattr(self, "_hvac_mode"):
_LOGGER.info('Cant set powersave in unknown mode')
return
if self._hvac_mode is None:
_LOGGER.info('Cant set powersave in unknown HVAC mode (self._hvac_mode is None)')
return
if not self._hvac_mode in (HVACMode.COOL):
# do nothing if not in cool mode
_LOGGER.info('Cant set powersave in %s mode' % str(self._hvac_mode))
Expand All @@ -859,9 +866,12 @@ async def _async_sleep_entity_state_changed(self, event: Event[EventStateChanged
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('sleep_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('sleep_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('sleep_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._current_sleep:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -887,9 +897,12 @@ async def _async_eightdegheat_entity_state_changed(self, event: Event[EventState
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('eightdegheat_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('eightdegheat_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('eightdegheat_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._current_eightdegheat:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -915,9 +928,12 @@ def _async_air_entity_state_changed(self, event: Event[EventStateChangedData]) -
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('air_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('air_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('air_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._current_air:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -940,9 +956,12 @@ def _async_anti_direct_blow_entity_state_changed(self, event: Event[EventStateCh
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('anti_direct_blow_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('anti_direct_blow_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('anti_direct_blow_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._current_anti_direct_blow:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -964,9 +983,12 @@ def _async_light_sensor_entity_state_changed(self, event: Event[EventStateChange
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('light_sensor_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('light_sensor_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('light_sensor_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if new_state.state is self._enable_light_sensor:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -990,9 +1012,15 @@ def _async_auto_light_entity_state_changed(self, event: Event[EventStateChangedD
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('auto_light_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('auto_light_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('auto_light_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if not hasattr(self, "_auto_light"):
_LOGGER.info('auto_light_entity state changed | auto_light not (yet) initialized. Skipping.')
return
if new_state.state is self._auto_light:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -1018,9 +1046,15 @@ def _async_auto_xfan_entity_state_changed(self, event: Event[EventStateChangedDa
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('auto_xfan_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('auto_xfan_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('auto_xfan_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if not hasattr(self, "_auto_xfan"):
_LOGGER.info('auto_xfan_entity state changed | auto_xfan not (yet) initialized. Skipping.')
return
if new_state.state is self._auto_xfan:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand All @@ -1043,9 +1077,12 @@ def _async_target_temp_entity_state_changed(self, event: Event[EventStateChanged
entity_id = event.data["entity_id"]
old_state = event.data["old_state"]
new_state = event.data["new_state"]
_LOGGER.info('target_temp_entity state changed | ' + str(entity_id) + ' from ' + str(old_state.state) + ' to ' + str(new_state.state))
_LOGGER.info('target_temp_entity state changed | ' + str(entity_id) + ' from ' + (str(old_state.state) if hasattr(old_state,'state') else "None") + ' to ' + str(new_state.state))
if new_state is None:
return
if new_state.state is "off" and (old_state is None or old_state.state is None):
_LOGGER.info('target_temp_entity state changed to off, but old state is None. Ignoring to avoid beeps.')
return
if int(float(new_state.state)) is self._target_temperature:
# do nothing if state change is triggered due to Sync with HVAC
return
Expand Down Expand Up @@ -1155,7 +1192,7 @@ def swing_modes(self):

@property
def preset_mode(self):
if self._horizontal_swing:
if hasattr(self, "_horizontal_swing") and self._horizontal_swing:
_LOGGER.info('preset_mode(): ' + str(self._preset_mode))
# get the current preset mode
return self._preset_mode
Expand Down Expand Up @@ -1188,8 +1225,8 @@ def fan_modes(self):

@property
def supported_features(self):
if self._horizontal_swing:
sf = SUPPORT_FLAGS | ClimateEntityFeature.PRESET_MODE
if hasattr(self, "_horizontal_swing") and self._horizontal_swing:
sf = SUPPORT_FLAGS | ClimateEntityFeature.PRESET_MODE
else:
sf = SUPPORT_FLAGS
_LOGGER.info('supported_features(): ' + str(sf))
Expand Down Expand Up @@ -1249,17 +1286,17 @@ def set_hvac_mode(self, hvac_mode):
c = {}
if (hvac_mode == HVACMode.OFF):
c.update({'Pow': 0})
if self._auto_light:
if hasattr(self, "_auto_light") and self._auto_light:
c.update({'Lig': 0})
if self._has_light_sensor and self._enable_light_sensor:
if hasattr(self, "_has_light_sensor") and self._has_light_sensor and hasattr(self, "_enable_light_sensor") and self._enable_light_sensor:
c.update({'LigSen': 1})
else:
c.update({'Pow': 1, 'Mod': self.hvac_modes.index(hvac_mode)})
if self._auto_light:
if hasattr(self, "_auto_light") and self._auto_light:
c.update({'Lig': 1})
if self._has_light_sensor and self._enable_light_sensor:
if hasattr(self, "_has_light_sensor") and self._has_light_sensor and hasattr(self, "_enable_light_sensor") and self._enable_light_sensor:
c.update({'LigSen': 0})
if self._auto_xfan:
if hasattr(self, "_auto_xfan") and self._auto_xfan:
if (hvac_mode == HVACMode.COOL) or (hvac_mode == HVACMode.DRY):
c.update({'Blo': 1})
self.SyncState(c)
Expand All @@ -1269,9 +1306,9 @@ def turn_on(self):
_LOGGER.info('turn_on(): ')
# Turn on.
c = {'Pow': 1}
if self._auto_light:
if hasattr(self, "_auto_light") and self._auto_light:
c.update({'Lig': 1})
if self._has_light_sensor and self._enable_light_sensor:
if hasattr(self, "_has_light_sensor") and self._has_light_sensor and hasattr(self, "_enable_light_sensor") and self._enable_light_sensor:
c.update({'LigSen': 0})
self.SyncState(c)
self.schedule_update_ha_state()
Expand All @@ -1280,10 +1317,10 @@ def turn_off(self):
_LOGGER.info('turn_off(): ')
# Turn off.
c = {'Pow': 0}
if self._auto_light:
if hasattr(self, "_auto_light") and self._auto_light:
c.update({'Lig': 0})
if self._has_light_sensor and self._enable_light_sensor:
c.update({'LigSen': 1})
if hasattr(self, "_has_light_sensor") and self._has_light_sensor and hasattr(self, "_enable_light_sensor") and self._enable_light_sensor:
c.update({'LigSen': 1})
self.SyncState(c)
self.schedule_update_ha_state()

Expand Down

0 comments on commit 55b914a

Please sign in to comment.