Created
March 26, 2020 04:37
-
-
Save boralyl/511a8d669c58331f29b04058214945f6 to your computer and use it in GitHub Desktop.
Home Assistant LG Washer/Dryer Custom Component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Support for LG Smartthinq device. | |
This is made for korean only. | |
If you want to apply other county devices, you should change the code little bit. | |
""" | |
import logging | |
import wideq | |
import voluptuous as vol | |
from homeassistant.const import ( | |
CONF_TOKEN, ) | |
import homeassistant.helpers.config_validation as cv | |
from homeassistant.helpers.entity import Entity | |
DOMAIN = 'smartthinq' | |
CONFIG_SCHEMA = vol.Schema({ | |
DOMAIN: vol.Schema({ | |
vol.Required(CONF_TOKEN): cv.string, | |
}) | |
}, extra=vol.ALLOW_EXTRA) | |
LGE_DEVICES = 'lge_devices' | |
_LOGGER = logging.getLogger(__name__) | |
def setup(hass, config): | |
import wideq | |
_LOGGER.info("Creating new LGE component") | |
if LGE_DEVICES not in hass.data: | |
hass.data[LGE_DEVICES] = [] | |
refresh_token = config[DOMAIN][CONF_TOKEN] | |
client = wideq.Client.from_token(refresh_token) | |
hass.data[CONF_TOKEN] = refresh_token | |
for device in client.devices: | |
device_id = device.id | |
hass.data[LGE_DEVICES].append(device_id) | |
return True | |
class LGEDevice(Entity): | |
def __init__(self, client, device): | |
self._client = client | |
self._device = device | |
@property | |
def name(self): | |
return self._device.name | |
@property | |
def available(self): | |
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import threading | |
import voluptuous as vol | |
import json | |
from homeassistant.components import climate | |
from homeassistant.components.climate import ( | |
ClimateDevice) | |
from custom_components.smartthinq import ( | |
DOMAIN, LGE_DEVICES, LGEDevice) | |
from homeassistant.helpers.temperature import display_temp as show_temp | |
from homeassistant.util.temperature import convert as convert_temperature | |
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa | |
import homeassistant.helpers.config_validation as cv | |
from homeassistant import const | |
from homeassistant.const import ( | |
ATTR_ENTITY_ID, ATTR_TEMPERATURE, TEMP_CELSIUS, CONF_NAME, CONF_TOKEN, CONF_ENTITY_ID,) | |
import time | |
import wideq | |
LGE_HVAC_DEVICES = 'lge_HVAC_devices' | |
LGE_REF_DEVICES = 'lge_REF_devices' | |
LGE_AIRPURIFIER_DEVICES = 'lge_AirPurifier_devices' | |
LGE_DEHUMIDIFIER_DEVICES = 'lge_dehumidifier_devices' | |
CONF_MAC = 'mac' | |
CONF_AREA = 'area_code' | |
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | |
vol.Required(CONF_NAME): cv.string, | |
vol.Required(CONF_MAC): cv.string, | |
vol.Optional(CONF_AREA): cv.string, | |
}) | |
# For HVAC | |
#----------------------------------------------------------- | |
SUPPORT_TARGET_TEMPERATURE = 1 | |
SUPPORT_FAN_MODE = 64 | |
SUPPORT_OPERATION_MODE = 128 | |
SUPPORT_SWING_MODE = 512 | |
SUPPORT_ON_OFF = 4096 | |
CONF_AIRCLEAN_MODE = 'airclean_mode' | |
CONF_COOLPOWER_MODE = 'coolpower_mode' | |
CONF_AUTODRY_MODE = 'autodry_mode' | |
CONF_SMARTCARE_MODE = 'smartcare_mode' | |
CONF_POWERSAVE_MODE = 'powersave_mode' | |
CONF_LONGPOWER_MODE = 'longpower_mode' | |
CONF_WDIRUPDOWN_MODE = 'up_down_mode' | |
CONF_SENSORMON_MODE = 'sensormon_mode' | |
CONF_JET_MODE = 'jet_mode' | |
CONF_WDIRVSTEP_MODE = 'wdirvstep_mode' | |
CONF_WDIRHSTEP_MODE = 'wdirhstep_mode' | |
CONF_SLEEP_TIME = 'sleep_time' | |
ATTR_CURRENT_TEMPERATURE = 'current_temperature' | |
ATTR_MAX_TEMP = 'max_temp' | |
ATTR_MIN_TEMP = 'min_temp' | |
ATTR_TARGET_TEMPERATURE = 'target_temperature' | |
ATTR_HUMIDITY = 'humidity' | |
ATTR_SENSORPM1 = 'PM1' | |
ATTR_SENSORPM2 = 'PM2' | |
ATTR_SENSORPM10 = 'PM10' | |
ATTR_TOTALAIRPOLUTION = 'total_air_polution' | |
ATTR_FILTER_STATE = 'filter_state' | |
ATTR_MFILTER_STATE = 'mfilter_state' | |
ATTR_AIRPOLUTION = 'air_polution' | |
ATTR_OPERATION_MODE = 'operation_mode' | |
ATTR_OPERATION_LIST = 'operation_list' | |
ATTR_FAN_MODE = 'fan_mode' | |
ATTR_FAN_LIST = 'fan_list' | |
ATTR_SWING_MODE = 'swing_mode' | |
ATTR_SWING_LIST = 'swing_list' | |
ATTR_STATUS = 'current_status' | |
ATTR_AIRCLEAN_MODE = 'airclean_mode' | |
ATTR_COOLPOWER_MODE = 'coolpower_mode' | |
ATTR_AUTODRY_MODE = 'autodry_mode' | |
ATTR_SMARTCARE_MODE = 'smartcare_mode' | |
ATTR_POWERSAVE_MODE = 'powersave_mode' | |
ATTR_LONGPOWER_MODE = 'longpower_mode' | |
ATTR_UP_DOWN_MODE = 'up_down_mode' | |
ATTR_SENSORMON_MODE = 'sensormon_mode' | |
ATTR_JET_MODE = 'jet_mode' | |
ATTR_WDIRVSTEP_MODE = 'wdirvstep_mode' | |
ATTR_WDIRHSTEP_MODE = 'wdirhstep_mode' | |
ATTR_DEVICE_TYPE = 'device_type' | |
ATTR_OUTDOOR_TEMPERATURE = 'outdoor_temperature' | |
ATTR_OUTDOOR_HUMIDITY = 'outdoor_humidity' | |
ATTR_OUTDOOR_NOW_PM25 = 'outdoor_now_pm2.5' | |
ATTR_OUTDOOR_TODAY_MORNING_PM25 = 'outdoor_today_morning_pm2.5' | |
ATTR_OUTDOOR_TODAY_AFTERNOON_PM25 = 'outdoor_today_afternoon_pm2.5' | |
ATTR_OUTDOOR_TOMORROW_MORNING_PM25 = 'outdoor_tomorrow_morning_pm2.5' | |
ATTR_OUTDOOR_TOMORROW_AFTERNOON_PM25 = 'outdoor_tomorrow_afternoon_pm2.5' | |
ATTR_OUTDOOR_TOTAL_INSTANTPOWER = 'outdoor_total_instant_power' | |
ATTR_INOUTDOOR_INSTANTPOWER = 'in_outdoor_instant_power' | |
ATTR_POWER_USAGE_DAY = 'power_usage_day' | |
ATTR_POWER_USAGE_WEEK = 'power_usage_week' | |
ATTR_POWER_USAGE_MONTH = 'power_usage_month' | |
ATTR_ELEC_FARE = 'electric_fare' | |
ATTR_SLEEP_TIME = 'sleep_time' | |
CONVERTIBLE_ATTRIBUTE = [ | |
ATTR_TEMPERATURE | |
] | |
SERVICE_SET_AIRCLEAN_MODE = 'lge_hvac_set_airclean_mode' | |
SERVICE_SET_COOLPOWER_MODE = 'lge_hvac_set_coolpower_mode' | |
SERVICE_SET_AUTODRY_MODE = 'lge_hvac_set_autodry_mode' | |
SERVICE_SET_SMARTCARE_MODE = 'lge_hvac_set_smartcare_mode' | |
SERVICE_SET_POWERSAVE_MODE = 'lge_hvac_set_powersave_mode' | |
SERVICE_SET_LONGPOWER_MODE = 'lge_hvac_set_longpower_mode' | |
SERVICE_SET_WDIRUPDOWN_MODE = 'lge_hvac_set_up_down_mode' | |
SERVICE_SET_SENSORMON_MODE = 'lge_hvac_set_sensormon_mode' | |
SERVICE_SET_JET_MODE = 'lge_hvac_set_jet_mode' | |
SERVICE_SET_WDIRVSTEP_MODE = 'lge_hvac_set_wdirvstep_mode' | |
SERVICE_SET_WDIRHSTEP_MODE = 'lge_hvac_set_wdirhstep_mode' | |
SERVICE_SET_SLEEP_TIMER = 'lge_hvac_set_sleep_timer' | |
MODES = { | |
'COOL': wideq.STATE_COOL, | |
'DRY': wideq.STATE_DRY, | |
'AIRCLEAN': wideq.STATE_AIRCLEAN, | |
} | |
WITHFANMODES = { | |
'COOL': wideq.STATE_COOL, | |
'DRY': wideq.STATE_DRY, | |
'FAN': wideq.STATE_FAN, | |
} | |
RAC_MODE_ONE = { | |
'COOL': wideq.STATE_COOL, | |
'DRY': wideq.STATE_DRY, | |
'FAN': wideq.STATE_FAN, | |
'AIRCLEAN': wideq.STATE_AIRCLEAN, | |
'AI': wideq.STATE_AI, | |
} | |
RAC_SACMODES = { | |
'COOL': wideq.STATE_COOL, | |
'DRY': wideq.STATE_DRY, | |
'HEAT': wideq.STATE_HEAT, | |
'AI': wideq.STATE_AI, | |
'FAN': wideq.STATE_FAN, | |
} | |
FANMODES = { | |
'LOW' : wideq.STATE_LOW, | |
'MID' : wideq.STATE_MID, | |
'HIGH' : wideq.STATE_HIGH, | |
'AUTO' : wideq.STATE_AUTO, | |
'COOLPOWER' : wideq.STATE_COOLPOWER, | |
'LONGPOWER': wideq.STATE_LONGPOWER, | |
'RIGHT_ONLY_LOW': wideq.STATE_RIGHT_ONLY_LOW, | |
'RIGHT_ONLY_MID': wideq.STATE_RIGHT_ONLY_MID, | |
'RIGHT_ONLY_HIGH': wideq.STATE_RIGHT_ONLY_HIGH, | |
'LEFT_ONLY_LOW': wideq.STATE_LEFT_ONLY_LOW, | |
'LEFT_ONLY_MID': wideq.STATE_LEFT_ONLY_MID, | |
'LEFT_ONLY_HIGH': wideq.STATE_LEFT_ONLY_HIGH, | |
'RIGHT_LOW_LEFT_MID': wideq.STATE_RIGHT_LOW_LEFT_MID, | |
'RIGHT_LOW_LEFT_HIGH': wideq.STATE_RIGHT_LOW_LEFT_HIGH, | |
'RIGHT_MID_LEFT_LOW': wideq.STATE_RIGHT_MID_LEFT_LOW, | |
'RIGHT_MID_LEFT_HIGH': wideq.STATE_RIGHT_MID_LEFT_HIGH, | |
'RIGHT_HIGH_LEFT_LOW': wideq.STATE_RIGHT_HIGH_LEFT_LOW, | |
'RIGHT_HIGH_LEFT_MID': wideq.STATE_RIGHT_HIGH_LEFT_MID, | |
} | |
SINGLE_FANMODES = { | |
'SYSTEM_LOW': wideq.STATE_LOW, | |
'SYSTEM_MID': wideq.STATE_MID, | |
'SYSTEM_HIGH': wideq.STATE_HIGH, | |
'SYSTEM_AUTO': wideq.STATE_AUTO, | |
} | |
RAC_SACFANMODES = { | |
'SYSTEM_LOW': wideq.STATE_LOW, | |
'SYSTEM_MID': wideq.STATE_MID, | |
'SYSTEM_HIGH': wideq.STATE_HIGH, | |
'SYSTEM_AUTO': wideq.STATE_AUTO, | |
'SYSTEM_POWER': wideq.STATE_POWER, | |
} | |
SWINGMODES = { | |
'LEFT_RIGHT': wideq.STATE_LEFT_RIGHT, | |
'RIGHTSIDE_LEFT_RIGHT': wideq.STATE_RIGHTSIDE_LEFT_RIGHT, | |
'LEFTSIDE_LEFT_RIGHT': wideq.STATE_LEFTSIDE_LEFT_RIGHT, | |
'LEFT_RIGHT_STOP': wideq.STATE_LEFT_RIGHT_STOP, | |
} | |
RAC_SACSWINGMODES = { | |
'LEFT_RIGTH_ON': wideq.STATE_LEFT_RIGHT_ON, | |
'LEFT_RIGHT_STOP': wideq.STATE_LEFT_RIGHT_STOP, | |
} | |
WDIRHSTEP = { | |
'OFF': wideq.STATE_WDIRHSTEP_OFF, | |
'FIRST': wideq.STATE_WDIRHSTEP_FIRST, | |
'SECOND': wideq.STATE_WDIRHSTEP_SECOND, | |
'THIRD': wideq.STATE_WDIRHSTEP_THIRD, | |
'FOURTH': wideq.STATE_WDIRHSTEP_FOURTH, | |
'FIFTH': wideq.STATE_WDIRHSTEP_FIFTH, | |
'THIRTEENTH': wideq.STATE_WDIRHSTEP_THIRTEENTH, | |
'THIRTYFIFTH': wideq.STATE_WDIRHSTEP_THIRTYFIFTH, | |
'AUTO': wideq.STATE_WDIRHSTEP_AUTO, | |
} | |
WDIRVSTEP = { | |
'OFF': wideq.STATE_WDIRVSTEP_OFF, | |
'FIRST': wideq.STATE_WDIRVSTEP_FIRST, | |
'SECOND': wideq.STATE_WDIRVSTEP_SECOND, | |
'THIRD': wideq.STATE_WDIRVSTEP_THIRD, | |
'FOURTH': wideq.STATE_WDIRVSTEP_FOURTH, | |
'FIFTH': wideq.STATE_WDIRVSTEP_FIFTH, | |
'SIXTH': wideq.STATE_WDIRVSTEP_SIXTH, | |
'AUTO': wideq.STATE_WDIRVSTEP_AUTO, | |
} | |
ACETCMODES = { | |
'ON': wideq.STATE_MODE_ON, | |
'OFF': wideq.STATE_MODE_OFF, | |
} | |
LGE_HVAC_SET_AIRCLEAN_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_AIRCLEAN_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_COOLPOWER_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_COOLPOWER_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_AUTODRY_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_AUTODRY_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_SMARTCARE_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_SMARTCARE_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_POWERSAVE_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_POWERSAVE_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_LONGPOWER_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_LONGPOWER_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_WDIRUPDOWN_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_WDIRUPDOWN_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_SENSORMON_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_SENSORMON_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_JET_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_JET_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_WDIRVSTEP_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_WDIRVSTEP_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_WDIRHSTEP_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_WDIRHSTEP_MODE): cv.string, | |
}) | |
LGE_HVAC_SET_SLEEP_TIMER_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_SLEEP_TIME): cv.string, | |
}) | |
TRANSIENT_EXP = 5.0 # Report set temperature for 5 seconds. | |
TEMP_MIN_C = 18 | |
TEMP_MIN_HEAT_C = 16 | |
TEMP_MAX_C = 26 | |
TEMP_MAX_HEAT_C = 30 | |
# For Refrigerator | |
#----------------------------------------------------------- | |
CONF_REFRIGERATOR_TEMPERATURE = 'refrigerator_temperature' | |
CONF_FREEZER_TEMPERATURE = 'freezer_temperature' | |
CONF_ICEPLUS_MODE = 'iceplus_mode' | |
CONF_FRESHAIRFILTER_MODE = 'freshairfilter_mode' | |
ATTR_REFRIGERATOR_TEMPERATURE = 'refrigerator_temperature' | |
ATTR_FREEZER_TEMPERATURE = 'freezer_temperature' | |
ATTR_ICEPLUS_STATE = 'iceplus_state' | |
ATTR_ICEPLUS_LIST = 'iceplus_list' | |
ATTR_FRESHAIRFILTER_STATE = 'freshairfilter_state' | |
ATTR_FRESHAIRFILTER_LIST = 'freshairfilter_list' | |
ATTR_SMARTSAVING_MODE = 'smartsaving_mode' | |
ATTR_WATERFILTER_STATE = 'waterfilter_state' | |
ATTR_DOOR_STATE = 'door_state' | |
ATTR_SMARTSAVING_STATE = 'smartsaving_state' | |
ATTR_LOCKING_STATE = 'locking_state' | |
ATTR_ACTIVESAVING_STATE = 'activesaving_state' | |
SERVICE_SET_REFRIGERATOR_TEMPERATURE = 'lge_ref_set_refrigerator_temperature' | |
SERVICE_SET_FREEZER_TEMPERATURE = 'lge_ref_set_freezer_temperature' | |
SERVICE_SET_ICEPLUS_MODE = 'lge_ref_set_iceplus_mode' | |
SERVICE_SET_FRESHAIRFILTER_MODE = 'lge_ref_set_freshairfilter_mode' | |
ICEPLUSMODES = { | |
'ON': wideq.STATE_ICE_PLUS_ON, | |
'OFF': wideq.STATE_ICE_PLUS_OFF, | |
'ICE_PLUS': wideq.STATE_ICE_PLUS, | |
'ICE_PLUS_FREEZE': wideq.STATE_ICE_PLUS_FREEZE, | |
'ICE_PLUS_OFF': wideq.STATE_REF_MODE_OFF | |
} | |
FRESHAIRFILTERMODES = { | |
'POWER' : wideq.STATE_FRESH_AIR_FILTER_POWER, | |
'AUTO' : wideq.STATE_FRESH_AIR_FILTER_AUTO, | |
'OFF' : wideq.STATE_FRESH_AIR_FILTER_OFF, | |
} | |
SMARTCAREMODES = { | |
'SMARTCARE_ON' : wideq.STATE_FRESH_AIR_FILTER_SMART_CARE_ON, | |
'SMARTCARE_OFF' : wideq.STATE_FRESH_AIR_FILTER_SMART_CARE_OFF, | |
'SMARTCARE_WAIT' : wideq.STATE_FRESH_AIR_FILTER_SMART_CARE_WAIT, | |
'REPLACE_FILTER' : wideq.STATE_FRESH_AIR_FILTER_REPLACE_FILTER, | |
} | |
SMARTSAVINGMODES = { | |
'NIGHT' : wideq.STATE_SMART_SAVING_NIGHT, | |
'CUSTOM' : wideq.STATE_SMART_SAVING_CUSTOM, | |
'OFF' : wideq.STATE_SMART_SAVING_OFF, | |
} | |
LGE_REF_SET_REFRIGERATOR_TEMPERATURE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_REFRIGERATOR_TEMPERATURE): cv.string, | |
}) | |
LGE_REF_SET_FREEZER_TEMPERATURE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_FREEZER_TEMPERATURE): cv.string, | |
}) | |
LGE_REF_SET_ICEPLUS_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_ICEPLUS_MODE): cv.string, | |
}) | |
LGE_REF_SET_FRESHAIRFILTER_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_FRESHAIRFILTER_MODE): cv.string, | |
}) | |
# For Air Purifier | |
#----------------------------------------------------------- | |
CONF_CIRCULATEDIR_MODE = 'circulatedir_mode' | |
CONF_AIRREMOVAL_MODE = 'airremoval_mode' | |
CONF_SIGNALLIGHTING_MODE = 'signallighting_mode' | |
CONF_AIRFAST_MODE = 'airfast_mode' | |
ATTR_AIRREMOVAL_MODE = 'airremoval_mode' | |
ATTR_SIGNALLIGHTING_MODE = 'signallighting_mode' | |
ATTR_CIRCULATEDIR_MODE = 'circulatedir_mode' | |
ATTR_AIRFAST_MODE = 'airfast_mode' | |
SERVICE_SET_AIRREMOVAL_MODE = 'lge_airpurifier_set_airremoval_mode' | |
SERVICE_SET_SIGNALLIGHTING_MODE = 'lge_airpurifier_set_signallighting_mode' | |
SERVICE_SET_CIRCULATEDIR_MODE = 'lge_airpurifier_set_circulatedir_mode' | |
SERVICE_SET_AIRFAST_MODE = 'lge_airpurifier_set_airfast_mode' | |
APMODES = { | |
'CLEANBOOSTER': wideq.STATE_AIRPURIFIER_CIRCULATOR_CLEAN, | |
'SINGLECLEAN': wideq.STATE_AIRPURIFIER_BABY_CARE, | |
'DUALCLEAN': wideq.STATE_AIRPURIFIER_DUAL_CLEAN, | |
'AUTO': wideq.STATE_AIRPURIFIER_AUTO_MODE, | |
} | |
SINGLECLEANMODES = { | |
'CLEAN': wideq. STATE_AIRPURIFIER_CLEAN, | |
} | |
APFANMODES = { | |
'LOW': wideq.STATE_AIRPURIFIER_LOW, | |
'MID': wideq.STATE_AIRPURIFIER_MID, | |
'HIGH': wideq.STATE_AIRPURIFIER_HIGH, | |
'POWER': wideq.STATE_AIRPURIFIER_POWER, | |
'AUTO': wideq.STATE_AIRPURIFIER_AUTO, | |
} | |
APSINGLECLEAN_FANMODES ={ | |
'LOW': wideq.STATE_AIRPURIFIER_LOW, | |
'MID': wideq.STATE_AIRPURIFIER_MID, | |
'HIGH': wideq.STATE_AIRPURIFIER_HIGH, | |
'AUTO': wideq.STATE_AIRPURIFIER_AUTO, | |
} | |
APCIRCULATEMODES = { | |
'LOW': wideq.STATE_AIRPURIFIER_CIR_LOW, | |
'MID': wideq.STATE_AIRPURIFIER_CIR_MID, | |
'HIGH': wideq.STATE_AIRPURIFIER_CIR_HIGH, | |
'POWER': wideq.STATE_AIRPURIFIER_CIR_POWER, | |
'AUTO': wideq.STATE_AIRPURIFIER_CIR_AUTO, | |
} | |
APETCMODES = { | |
'NOT_SUPPORTED': wideq.STATE_AIRPURIFIER_NOT_SUPPORTED, | |
'ON': wideq.STATE_AIRPURIFIER_ON, | |
'OFF': wideq.STATE_AIRPURIFIER_OFF, | |
} | |
APTOTALAIRPOLUTION = { | |
'NOT_SUPPORT': wideq.STATE_AIRPURIFIER_NOT_SUPPORTED, | |
'GOOD': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_GOOD, | |
'NORMAL': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_NORMAL, | |
'BAD': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_BAD, | |
'VERYBAD': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_VERYBAD | |
} | |
APSMELL = { | |
'NOT_SUPPORT': wideq.STATE_AIRPURIFIER_NOT_SUPPORTED, | |
'WEEK': wideq.STATE_AIRPURIFIER_SMELL_WEEK, | |
'NORMAL': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_NORMAL, | |
'STRONG': wideq.STATE_AIRPURIFIER_SMELL_STRONG, | |
'VERYSTRONG': wideq.STATE_AIRPURIFIER_SMELL_VERYSTRONG | |
} | |
LGE_AIRPURIFIER_SET_AIRREMOVAL_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_AIRREMOVAL_MODE): cv.string, | |
}) | |
LGE_AIRPURIFIER_SET_CIRCULATEDIR_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_CIRCULATEDIR_MODE): cv.string, | |
}) | |
LGE_AIRPURIFIER_SET_SIGNALLIGHTING_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_SIGNALLIGHTING_MODE): cv.string, | |
}) | |
LGE_AIRPURIFIER_SET_AIRFAST_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_AIRFAST_MODE): cv.string, | |
}) | |
# For Dehumidifier | |
#----------------------------------------------------------- | |
SUPPORT_TARGET_HUMIDITY = 8 | |
SUPPORT_TARGET_HUMIDITY_HIGH = 16 | |
SUPPORT_TARGET_HUMIDITY_LOW = 32 | |
ATTR_MAX_HUMIDITY = 'max_humidity' | |
ATTR_MIN_HUMIDITY = 'min_humidity' | |
ATTR_TARGET_HUMIDITY_STEP = 'humidity_step' | |
ATTR_CURRENT_HUMIDITY = 'current_humidity' | |
SERVICE_DEHUMIDIFIER_SET_AIRREMOVAL_MODE = 'lge_dehumidifier_set_airremoval_mode' | |
DEHUMMODES = { | |
'SMART_DEHUM': wideq.STATE_DEHUM_OPMODE_SMART_DEHUM, | |
'FAST_DEHUM': wideq.STATE_DEHUM_OPMODE_FAST_DEHUM, | |
'SILENT_DEHUM': wideq.STATE_DEHUM_OPMODE_SILENT_DEHUM, | |
'CONCENTRATION_DRY': wideq.STATE_DEHUM_OPMODE_CONCENTRATION_DRY, | |
'CLOTHING_DRY': wideq.STATE_DEHUM_OPMODE_CLOTHING_DRY, | |
'IONIZER' : wideq.STATE_DEHUM_OPMODE_IONIZER, | |
} | |
DEHUMFANMODES = { | |
'LOW' : wideq.STATE_DEHUM_WINDSTRENGTH_LOW, | |
'HIGH' : wideq.STATE_DEHUM_WIDESTRENGTH_HIGH, | |
} | |
DEHUMAIRREMOVALMODES = { | |
'ON': wideq.STATE_DEHUM_AIRREMOVAL_ON, | |
'OFF': wideq.STATE_DEHUM_AIRREMOVAL_OFF, | |
} | |
LGE_DEHUMIDIFIER_SET_AIRREMOVAL_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_AIRREMOVAL_MODE): cv.string, | |
}) | |
HUM_MIN = 30 | |
HUM_MAX = 70 | |
HUM_STEP = 5 | |
MAX_RETRIES = 5 | |
LOGGER = logging.getLogger(__name__) | |
def setup_platform(hass, config, add_entities, discovery_info=None): | |
import wideq | |
refresh_token = hass.data[CONF_TOKEN] | |
client = wideq.Client.from_token(refresh_token) | |
name = config[CONF_NAME] | |
conf_mac = config[CONF_MAC] | |
"""Set up the LGE entity.""" | |
for device_id in hass.data[LGE_DEVICES]: | |
device = client.get_device(device_id) | |
model = client.model_info(device) | |
model_type = model.model_type | |
mac = device.macaddress | |
if device.type == wideq.DeviceType.AC: | |
LGE_HVAC_DEVICES = [] | |
if mac == conf_mac.lower(): | |
LOGGER.debug("Creating new LGE HVAC") | |
hvac_entity = LGEHVACDEVICE(client, device, name, model_type, config) | |
LGE_HVAC_DEVICES.append(hvac_entity) | |
add_entities(LGE_HVAC_DEVICES) | |
LOGGER.debug("LGE HVAC is added") | |
elif device.type == wideq.DeviceType.REFRIGERATOR: | |
LGE_REF_DEVICES = [] | |
if mac == conf_mac.lower(): | |
LOGGER.debug("Creating new LGE Refrigerator") | |
ref_entity = LGEREFDEVICE(client, device, name, model_type) | |
LGE_REF_DEVICES.append(ref_entity) | |
add_entities(LGE_REF_DEVICES) | |
LOGGER.debug("LGE Refrigerator is added") | |
elif device.type == wideq.DeviceType.AIR_PURIFIER: | |
LGE_AIRPURIFIER_DEVICES = [] | |
if mac == conf_mac.lower(): | |
ap_entity = LGEAPDEVICE(client, device, name, model_type) | |
LGE_AIRPURIFIER_DEVICES.append(ap_entity) | |
add_entities(LGE_AIRPURIFIER_DEVICES) | |
LOGGER.debug("LGE AirPurifier is added") | |
elif device.type == wideq.DeviceType.DEHUMIDIFIER: | |
LGE_DEHUMIDIFIER_DEVICES = [] | |
if mac == conf_mac.lower(): | |
dehum_entity = LGEDEHUMDEVICE(client, device, name, model_type) | |
LGE_DEHUMIDIFIER_DEVICES.append(dehum_entity) | |
add_entities(LGE_DEHUMIDIFIER_DEVICES) | |
LOGGER.debug("LGE DEHUMIDIFIER is added") | |
def hvac_service_handle(service): | |
"""Handle the HVAC services.""" | |
entity_ids = service.data.get(ATTR_ENTITY_ID) | |
airclean_mode = service.data.get(CONF_AIRCLEAN_MODE) | |
coolpower_mode = service.data.get(CONF_COOLPOWER_MODE) | |
autodry_mode = service.data.get(CONF_AUTODRY_MODE) | |
smartcare_mode = service.data.get(CONF_SMARTCARE_MODE) | |
powersave_mode = service.data.get(CONF_POWERSAVE_MODE) | |
longpower_mode = service.data.get(CONF_LONGPOWER_MODE) | |
up_down_mode = service.data.get(CONF_WDIRUPDOWN_MODE) | |
sensormon_mode = service.data.get(CONF_SENSORMON_MODE) | |
jet_mode = service.data.get(CONF_JET_MODE) | |
wdirhstep_mode = service.data.get(CONF_WDIRHSTEP_MODE) | |
wdirvstep_mode = service.data.get(CONF_WDIRVSTEP_MODE) | |
sleep_timer = service.data.get(CONF_SLEEP_TIME) | |
if service.service == SERVICE_SET_AIRCLEAN_MODE: | |
hvac_entity.airclean_mode(airclean_mode) | |
elif service.service == SERVICE_SET_COOLPOWER_MODE: | |
hvac_entity.coolpower_mode(coolpower_mode) | |
elif service.service == SERVICE_SET_AUTODRY_MODE: | |
hvac_entity.autodry_mode(autodry_mode) | |
elif service.service == SERVICE_SET_SMARTCARE_MODE: | |
hvac_entity.smartcare_mode(smartcare_mode) | |
elif service.service == SERVICE_SET_POWERSAVE_MODE: | |
hvac_entity.powersave_mode(powersave_mode) | |
elif service.service == SERVICE_SET_LONGPOWER_MODE: | |
hvac_entity.longpower_mode(longpower_mode) | |
elif service.service == SERVICE_SET_WDIRUPDOWN_MODE: | |
hvac_entity.up_down_mode(up_down_mode) | |
elif service.service == SERVICE_SET_SENSORMON_MODE: | |
hvac_entity.sensormon_mode(sensormon_mode) | |
elif service.service == SERVICE_SET_JET_MODE: | |
hvac_entity.jet_mode(jet_mode) | |
elif service.service == SERVICE_SET_WDIRHSTEP_MODE: | |
hvac_entity.wdirhstep_mode(wdirhstep_mode) | |
elif service.service == SERVICE_SET_WDIRVSTEP_MODE: | |
hvac_entity.wdirvstep_mode(wdirvstep_mode) | |
elif service.service == SERVICE_SET_SLEEP_TIMER: | |
hvac_entity.sleep_timer(sleep_timer) | |
def ref_service_handle(service): | |
"""Handle the Refrigerator services.""" | |
entity_id = service.data.get(CONF_ENTITY_ID) | |
refrigerator_temperature = service.data.get(CONF_REFRIGERATOR_TEMPERATURE) | |
freezer_temperature = service.data.get(CONF_FREEZER_TEMPERATURE) | |
iceplus_mode = service.data.get(CONF_ICEPLUS_MODE) | |
freshairfilter_mode = service.data.get(CONF_FRESHAIRFILTER_MODE) | |
if service.service == SERVICE_SET_REFRIGERATOR_TEMPERATURE: | |
ref_entity.set_ref_temperature(refrigerator_temperature) | |
elif service.service == SERVICE_SET_FREEZER_TEMPERATURE: | |
ref_entity.set_freezer_temperature(freezer_temperature) | |
elif service.service == SERVICE_SET_ICEPLUS_MODE: | |
ref_entity.set_iceplus_mode(iceplus_mode) | |
elif service.service == SERVICE_SET_FRESHAIRFILTER_MODE: | |
ref_entity.set_fresh_air_filter_mode(freshairfilter_mode) | |
def airpurifier_service_handle(service): | |
"""Handle the AirPurifier services.""" | |
entity_ids = service.data.get(ATTR_ENTITY_ID) | |
airremoval_mode = service.data.get(CONF_AIRREMOVAL_MODE) | |
circulatedir_mode = service.data.get(CONF_CIRCULATEDIR_MODE) | |
signallighting_mode = service.data.get(CONF_SIGNALLIGHTING_MODE) | |
airfast_mode = service.data.get(CONF_AIRFAST_MODE) | |
if service.service == SERVICE_SET_AIRREMOVAL_MODE: | |
ap_entity.airremoval_mode(airremoval_mode) | |
elif service.service == SERVICE_SET_CIRCULATEDIR_MODE: | |
ap_entity.circulatedir_mode(circulatedir_mode) | |
elif service.service == SERVICE_SET_SIGNALLIGHTING_MODE: | |
ap_entity.signallighting_mode(signallighting_mode) | |
elif service.service == SERVICE_SET_AIRFAST_MODE: | |
ap_entity.airfast_mode(airfast_mode) | |
def dehum_service_handle(service): | |
"""Handle the DEHUMIDIFIER services.""" | |
entity_id = service.data.get(CONF_ENTITY_ID) | |
airremoval_mode = service.data.get(CONF_AIRREMOVAL_MODE) | |
if service.service == SERVICE_DEHUMIDIFIER_SET_AIRREMOVAL_MODE: | |
dehum_entity.airremoval_mode(airremoval_mode) | |
# Register hvac service(s) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_AIRCLEAN_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_AIRCLEAN_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_COOLPOWER_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_COOLPOWER_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_AUTODRY_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_AUTODRY_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_SMARTCARE_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_SMARTCARE_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_POWERSAVE_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_POWERSAVE_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_LONGPOWER_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_LONGPOWER_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_WDIRUPDOWN_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_WDIRUPDOWN_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_SENSORMON_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_SENSORMON_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_JET_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_JET_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_WDIRVSTEP_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_WDIRVSTEP_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_WDIRHSTEP_MODE, hvac_service_handle, | |
schema=LGE_HVAC_SET_WDIRHSTEP_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_SLEEP_TIMER, hvac_service_handle, | |
schema=LGE_HVAC_SET_SLEEP_TIMER_SCHEMA) | |
# Register refrigerator service(s) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_REFRIGERATOR_TEMPERATURE, ref_service_handle, | |
schema=LGE_REF_SET_REFRIGERATOR_TEMPERATURE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_FREEZER_TEMPERATURE, ref_service_handle, | |
schema=LGE_REF_SET_FREEZER_TEMPERATURE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_ICEPLUS_MODE, ref_service_handle, | |
schema=LGE_REF_SET_ICEPLUS_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_FRESHAIRFILTER_MODE, ref_service_handle, | |
schema=LGE_REF_SET_FRESHAIRFILTER_MODE_SCHEMA) | |
# Register air purifier service(s) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_AIRREMOVAL_MODE, airpurifier_service_handle, | |
schema=LGE_AIRPURIFIER_SET_AIRREMOVAL_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_CIRCULATEDIR_MODE, airpurifier_service_handle, | |
schema=LGE_AIRPURIFIER_SET_CIRCULATEDIR_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_SIGNALLIGHTING_MODE, airpurifier_service_handle, | |
schema=LGE_AIRPURIFIER_SET_SIGNALLIGHTING_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_AIRFAST_MODE, airpurifier_service_handle, | |
schema=LGE_AIRPURIFIER_SET_AIRFAST_MODE_SCHEMA) | |
# Register dehumidifier service(s) | |
hass.services.register( | |
DOMAIN, SERVICE_DEHUMIDIFIER_SET_AIRREMOVAL_MODE, dehum_service_handle, | |
schema=LGE_DEHUMIDIFIER_SET_AIRREMOVAL_MODE_SCHEMA) | |
# HVAC Main | |
class LGEHVACDEVICE(LGEDevice, ClimateDevice): | |
def __init__(self, client, device, name, model_type, config, celsius=True): | |
"""initialize a LGE HAVC Device.""" | |
LGEDevice.__init__(self, client, device) | |
self._celsius = celsius | |
import wideq | |
self._ac = wideq.ACDevice(client, device) | |
self._ac.monitor_start() | |
self._ac.monitor_start() | |
self._ac.delete_permission() | |
self._ac.delete_permission() | |
# The response from the monitoring query. | |
self._state = None | |
# Store a transient temperature when we've just set it. We also | |
# store the timestamp for when we set this value. | |
self._transient_temp = None | |
self._transient_time = None | |
self._name = name | |
self._type = model_type | |
try: | |
self._area = config[CONF_AREA] | |
except KeyError: | |
self._area = None | |
self.update() | |
@property | |
def name(self): | |
return self._name | |
@property | |
def device_type(self): | |
return self._type | |
@property | |
def supported_features(self): | |
if self.device_type == 'PAC': | |
if 'LEFTRIGHT' in self.support_swingmode: | |
return ( | |
SUPPORT_TARGET_TEMPERATURE | | |
SUPPORT_OPERATION_MODE | | |
SUPPORT_FAN_MODE | | |
SUPPORT_SWING_MODE | | |
SUPPORT_ON_OFF | |
) | |
else: | |
return ( | |
SUPPORT_TARGET_TEMPERATURE | | |
SUPPORT_OPERATION_MODE | | |
SUPPORT_FAN_MODE | | |
SUPPORT_ON_OFF | |
) | |
elif self.device_type == 'RAC': | |
if 'LEFT_RIGHT' in self.support_racsubmode: | |
return ( | |
SUPPORT_TARGET_TEMPERATURE | | |
SUPPORT_OPERATION_MODE | | |
SUPPORT_FAN_MODE | | |
SUPPORT_SWING_MODE | | |
SUPPORT_ON_OFF | |
) | |
else: | |
return ( | |
SUPPORT_TARGET_TEMPERATURE | | |
SUPPORT_OPERATION_MODE | | |
SUPPORT_FAN_MODE | | |
SUPPORT_ON_OFF | |
) | |
elif self.device_type == 'SAC_CST': | |
if 'LEFT_RIGHT' in self.support_racsubmode: | |
return ( | |
SUPPORT_TARGET_TEMPERATURE | | |
SUPPORT_OPERATION_MODE | | |
SUPPORT_FAN_MODE | | |
SUPPORT_SWING_MODE | | |
SUPPORT_ON_OFF | |
) | |
else: | |
return ( | |
SUPPORT_TARGET_TEMPERATURE | | |
SUPPORT_OPERATION_MODE | | |
SUPPORT_FAN_MODE | | |
SUPPORT_ON_OFF | |
) | |
@property | |
def state_attributes(self): | |
"""Return the optional state attributes.""" | |
data = {} | |
data = { | |
ATTR_CURRENT_TEMPERATURE: show_temp( | |
self.hass, self.current_temperature, self.temperature_unit, | |
self.precision), | |
ATTR_MIN_TEMP: show_temp( | |
self.hass, self.min_temp, self.temperature_unit, | |
self.precision), | |
ATTR_MAX_TEMP: show_temp( | |
self.hass, self.max_temp, self.temperature_unit, | |
self.precision), | |
ATTR_TEMPERATURE: show_temp( | |
self.hass, self.target_temperature, self.temperature_unit, | |
self.precision), | |
} | |
data[ATTR_DEVICE_TYPE] = self.device_type | |
data[ATTR_TARGET_TEMPERATURE] = self.target_temperature | |
data[ATTR_AIRCLEAN_MODE] = self.is_airclean_mode | |
data[ATTR_COOLPOWER_MODE] = self.is_coolpower_mode | |
data[ATTR_AUTODRY_MODE] = self.is_autodry_mode | |
data[ATTR_SMARTCARE_MODE] = self.is_smartcare_mode | |
data[ATTR_POWERSAVE_MODE] = self.is_powersave_mode | |
data[ATTR_LONGPOWER_MODE] = self.is_longpower_mode | |
data[ATTR_UP_DOWN_MODE] = self.is_up_down_mode | |
data[ATTR_SENSORMON_MODE] = self.is_sensormon_mode | |
if self.is_wdirvstep_mode != '지원안함': | |
data[ATTR_WDIRVSTEP_MODE] = self.is_wdirvstep_mode | |
if self.is_wdirvstep_mode != '지원안함': | |
data[ATTR_WDIRHSTEP_MODE] = self.is_wdirhstep_mode | |
if self.is_jet_mode != '지원안함': | |
data[ATTR_JET_MODE] = self.is_jet_mode | |
data[ATTR_HUMIDITY] = self.humidity | |
if self.sensorpm1 is not None: | |
data[ATTR_SENSORPM1] = self.sensorpm1 | |
if self.sensorpm2 is not None: | |
data[ATTR_SENSORPM2] = self.sensorpm2 | |
if self.sensorpm10 is not None: | |
data[ATTR_SENSORPM10] = self.sensorpm10 | |
if self.total_air_polution is not None: | |
data[ATTR_TOTALAIRPOLUTION] = self.total_air_polution | |
if self.air_polution is not None: | |
data[ATTR_AIRPOLUTION] = self.air_polution | |
data[ATTR_STATUS] = self.current_status | |
data[ATTR_FILTER_STATE] = self.filter_state | |
data[ATTR_MFILTER_STATE] = self.mfilter_state | |
data[ATTR_OUTDOOR_TOTAL_INSTANTPOWER] = self.outtotalinstantpower | |
data[ATTR_INOUTDOOR_INSTANTPOWER] = self.inoutinstantpower | |
data[ATTR_POWER_USAGE_DAY] = self.energy_usage_day | |
data[ATTR_POWER_USAGE_WEEK] = self.energy_usage_week | |
data[ATTR_POWER_USAGE_MONTH] = self.energy_usage_month | |
data[ATTR_ELEC_FARE] = self.elec_fare | |
data[ATTR_SLEEP_TIME] = self.is_sleep_timer | |
if self._area is not None: | |
data[ATTR_OUTDOOR_TEMPERATURE] = self.outdoor_weather['ct'] | |
data[ATTR_OUTDOOR_HUMIDITY] = self.outdoor_weather['ch'] | |
data[ATTR_OUTDOOR_NOW_PM25] = self.outdoor_weather['pm25'] | |
data[ATTR_OUTDOOR_TODAY_MORNING_PM25] = self.outdoor_weather['pm25_1'] | |
data[ATTR_OUTDOOR_TODAY_AFTERNOON_PM25] = self.outdoor_weather['pm25_2'] | |
data[ATTR_OUTDOOR_TOMORROW_MORNING_PM25] = self.outdoor_weather['pm25_3'] | |
data[ATTR_OUTDOOR_TOMORROW_AFTERNOON_PM25] = self.outdoor_weather['pm25_4'] | |
supported_features = self.supported_features | |
if supported_features & SUPPORT_FAN_MODE: | |
data[ATTR_FAN_MODE] = self.current_fan_mode | |
if self.fan_list: | |
data[ATTR_FAN_LIST] = self.fan_list | |
if supported_features & SUPPORT_OPERATION_MODE: | |
data[ATTR_OPERATION_MODE] = self.current_operation | |
if self.operation_list: | |
data[ATTR_OPERATION_LIST] = self.operation_list | |
if supported_features & SUPPORT_SWING_MODE: | |
data[ATTR_SWING_MODE] = self.current_swing_mode | |
if self.swing_list: | |
data[ATTR_SWING_LIST] = self.swing_list | |
return data | |
@property | |
def is_on(self): | |
if self._state: | |
return self._state.is_on | |
@property | |
def current_status(self): | |
if self.is_on == True: | |
return 'ON' | |
elif self.is_on == False: | |
return 'OFF' | |
def turn_on(self): | |
LOGGER.info('Turning on...') | |
self._ac.set_on(True) | |
LOGGER.info('...done.') | |
def turn_off(self): | |
LOGGER.info('Turning off...') | |
self._ac.set_on(False) | |
LOGGER.info('...done.') | |
@property | |
def support_oplist(self): | |
return self._state.support_oplist | |
@property | |
def support_fanlist(self): | |
mode = self._state.windstrength_state | |
if mode.name in SINGLE_FANMODES.keys(): | |
return self._state.support_fanlist | |
else: | |
return mode.name | |
@property | |
def support_windmode(self): | |
return self._state.support_windmode | |
@property | |
def support_pacmode(self): | |
return self._state.support_pacmode | |
@property | |
def support_racmode(self): | |
return self._state.support_racmode | |
@property | |
def support_racsubmode(self): | |
return self._state.support_racsubmode | |
@property | |
def support_swingmode(self): | |
return self._state.support_swingmode | |
@property | |
def support_reservemode(self): | |
return self._state.support_reservemode | |
@property | |
def support_airpolution(self): | |
return self._state.support_airpolution | |
@property | |
def operation_list(self): | |
if self.device_type == 'PAC': | |
if 'FAN' in self.support_oplist: | |
return list(WITHFANMODES.values()) | |
else: | |
return list(MODES.values()) | |
elif self.device_type == 'RAC': | |
if 'HEAT' not in self.support_oplist: | |
if 'AIRCLEAN' and 'AI' in self.support_oplist: | |
return list(RAC_MODE_ONE.values()) | |
elif 'HEAT' in self.support_oplist: | |
return list(RAC_SACMODES.values()) | |
elif self.device_type == 'SAC_CST': | |
return list(RAC_SACMODES.values()) | |
@property | |
def current_operation(self): | |
if self._state: | |
mode = self._state.mode | |
if self.device_type == 'PAC': | |
if 'FAN' in self.support_oplist: | |
return WITHFANMODES[mode.name] | |
else: | |
return MODES[mode.name] | |
if self.device_type == 'RAC': | |
if 'HEAT' not in self.support_oplist: | |
if 'AIRCLEAN' and 'AI' in self.support_oplist: | |
return RAC_MODE_ONE[mode.name] | |
elif 'HEAT' in self.support_oplist: | |
return RAC_SACMODES[mode.name] | |
elif self.device_type == 'SAC_CST': | |
return RAC_SACMODES[mode.name] | |
def set_operation_mode(self, operation_mode): | |
import wideq | |
# Invert the modes mapping. | |
modes_inv = {v: k for k, v in MODES.items()} | |
withfan_modes_inv = {v: k for k, v in WITHFANMODES.items()} | |
rac_sacmodes_inv = {v: k for k, v in RAC_SACMODES.items()} | |
rac_mode_one_inv = {v: k for k, v in RAC_MODE_ONE.items()} | |
if self.device_type == 'PAC': | |
if 'FAN' in self.support_oplist: | |
mode = wideq.ACMode[withfan_modes_inv[operation_mode]] | |
else: | |
mode = wideq.ACMode[modes_inv[operation_mode]] | |
elif self.device_type == 'RAC': | |
if 'HEAT' not in self.support_oplist: | |
if 'AIRCLEAN' and 'AI' in self.support_oplist: | |
mode = wideq.ACMode[rac_mode_one_inv[operation_mode]] | |
elif 'HEAT' in self.support_oplist: | |
mode = wideq.ACMode[rac_sacmodes_inv[operation_mode]] | |
elif self.device_type == 'SAC_CST': | |
mode = wideq.ACMode[rac_sacmodes_inv[operation_mode]] | |
self._ac.set_mode(mode) | |
@property | |
def fan_list(self): | |
if self.device_type == 'PAC': | |
if 'SYSTEM_LOW' in self.support_fanlist: | |
return list(SINGLE_FANMODES.values()) | |
else: | |
return list(FANMODES.values()) | |
elif self.device_type == 'RAC': | |
return list(RAC_SACFANMODES.values()) | |
elif self.device_type == 'SAC_CST': | |
return list(RAC_SACFANMODES.values()) | |
@property | |
def current_fan_mode(self): | |
if self._state: | |
mode = self._state.windstrength_state | |
if self.device_type == 'PAC': | |
if 'SYSTEM_LOW' in self.support_fanlist: | |
return SINGLE_FANMODES[mode.name] | |
else: | |
return FANMODES[mode.name] | |
elif self.device_type == 'RAC': | |
return RAC_SACFANMODES[mode.name] | |
elif self.device_type == 'SAC_CST': | |
return RAC_SACFANMODES[mode.name] | |
def set_fan_mode(self, fan_mode): | |
import wideq | |
# Invert the modes mapping. | |
fanmodes_inv = {v: k for k, v in FANMODES.items()} | |
single_fanmodes_inv = {v: k for k, v in SINGLE_FANMODES.items()} | |
rac_sacfanmodes_inv = {v: k for k, v in RAC_SACFANMODES.items()} | |
if self.device_type == 'PAC': | |
if 'SYSTEM_LOW' in self.support_fanlist: | |
mode = wideq.ACWindstrength[single_fanmodes_inv[fan_mode]] | |
else: | |
mode = wideq.ACWindstrength[fanmodes_inv[fan_mode]] | |
elif self.device_type == 'RAC': | |
mode = wideq.ACWindstrength[rac_sacfanmodes_inv[fan_mode]] | |
elif self.device_type == 'SAC_CST': | |
mode = wideq.ACWindstrength[rac_sacfanmodes_inv[fan_mode]] | |
self._ac.set_windstrength(mode) | |
@property | |
def swing_list(self): | |
if self.device_type == 'PAC': | |
if 'LEFTRIGHT' in self.support_swingmode: | |
return list(SWINGMODES.values()) | |
else: | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
return list(RAC_SACSWINGMODES.values()) | |
elif self.device_type == 'SAC_CST': | |
return list(RAC_SACSWINGMODES.values()) | |
@property | |
def current_swing_mode(self): | |
if self._state: | |
mode = self._state.wdirleftright_state | |
if self.device_type == 'PAC': | |
if 'LEFTRIGHT' in self.support_swingmode: | |
return SWINGMODES[mode.name] | |
else: | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
return RAC_SACSWINGMODES[mode.name] | |
elif self.device_type == 'SAC_CST': | |
return RAC_SACSWINGMODES[mode.name] | |
def set_swing_mode(self, swing_mode): | |
import wideq | |
swingmodes_inv = {v: k for k, v in SWINGMODES.items()} | |
rac_sacswingmodes_inv = {v: k for k, v in RAC_SACSWINGMODES.items()} | |
if self.device_type == 'PAC': | |
if 'LEFTRIGHT' in self.support_swingmode: | |
mode = wideq.WDIRLEFTRIGHT[swingmodes_inv[swing_mode]] | |
else: | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
mode = wideq.WDIRLEFTRIGHT[rac_sacswingmodes_inv[swing_mode]] | |
elif self.device_type == 'SAC_CST': | |
mode = wideq.WDIRLEFTRIGHT[rac_sacswingmodes_inv[swing_mode]] | |
self._ac.set_wind_leftright(mode) | |
@property | |
def is_wdirhstep_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
mode = self._state.wdirhstep_state | |
return WDIRHSTEP[mode.name] | |
elif self.device_type == 'SAC_CST': | |
mode = self._state.wdirhstep_state | |
return WDIRHSTEP[mode.name] | |
def wdirhstep_mode(self, wdirhstep_mode): | |
import wideq | |
wdirhstepmodes_inv = {v: k for k, v in WDIRHSTEP.items()} | |
if self.device_type == 'PAC': | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
mode = wideq.WDIRHSTEP[wdirhstepmodes_inv[wdirhstep_mode]] | |
elif self.device_type == 'SAC_CST': | |
vstep_state = self._state.wdirvstep_state | |
mode = wideq.WDIRHSTEP[wdirhstepmodes_inv[wdirhstep_mode]] | |
self._ac.set_wdirhstep(mode) | |
@property | |
def is_wdirvstep_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
try: | |
mode = self._state.wdirvstep_state | |
return WDIRVSTEP[mode.name] | |
except ValueError: | |
fourvain_mode = self._state.fourvain_wdirvstep_state | |
return WDIRVSTEP[fourvain_mode.name] | |
elif self.device_type == 'SAC_CST': | |
try: | |
mode = self._state.wdirvstep_state | |
return WDIRVSTEP[mode.name] | |
except ValueError: | |
fourvain_mode = self._state.fourvain_wdirvstep_state | |
return WDIRVSTEP[fourvain_mode.name] | |
def wdirvstep_mode(self, wdirvstep_mode): | |
import wideq | |
wdirvstepmodes_inv = {v: k for k, v in WDIRVSTEP.items()} | |
if self.device_type == 'PAC': | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
vstep_state = self._state.wdirvstep_state | |
if int(vstep_state.value) < 150: | |
mode = wideq.WDIRVSTEP[wdirvstepmodes_inv[wdirvstep_mode]] | |
elif int(vstep_state.value) > 150: | |
mode = wideq.FOURVAIN_WDIRVSTEP[wdirvstepmodes_inv[wdirvstep_mode]] | |
elif self.device_type == 'SAC_CST': | |
vstep_state = self._state.wdirvstep_state | |
if int(vstep_state.value) < 150: | |
mode = wideq.WDIRVSTEP[wdirvstepmodes_inv[wdirvstep_mode]] | |
elif int(vstep_state.value) > 150: | |
mode = wideq.FOURVAIN_WDIRVSTEP[wdirvstepmodes_inv[wdirvstep_mode]] | |
self._ac.set_wdirvstep(mode) | |
@property | |
def is_airclean_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
if 'AIRCLEAN' in self.support_pacmode: | |
mode = self._state.airclean_state | |
else: | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
if 'AIRCLEAN' in self.support_racmode: | |
mode = self._state.airclean_state | |
else: | |
return '지원안함' | |
elif self.device_type == 'SAC_CST': | |
mode = self._state.sac_airclean_state | |
return ACETCMODES[mode.name] | |
def airclean_mode(self, airclean_mode): | |
name = 'AirClean' | |
if airclean_mode == 'ON': | |
if self.device_type == 'PAC': | |
if 'AIRCLEAN' in self.support_pacmode: | |
self._ac.set_airclean(True) | |
elif self.device_type == 'RAC': | |
if 'AIRCLEAN' in self.support_racmode: | |
self._ac.set_airclean(True) | |
elif self.device_type == 'SAC_CST': | |
self._ac.set_etc_mode(name, True) | |
elif airclean_mode == 'OFF': | |
if self.device_type == 'PAC': | |
if 'AIRCLEAN' in self.support_pacmode: | |
self._ac.set_airclean(False) | |
elif self.device_type == 'RAC': | |
if 'AIRCLEAN' in self.support_racmode: | |
self._ac.set_airclean(False) | |
elif self.device_type == 'SAC_CST': | |
self._ac.set_etc_mode(name, False) | |
@property | |
def is_autodry_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
if 'AUTODRY'in self.support_pacmode: | |
mode = self._state.autodry_state | |
return ACETCMODES[mode.name] | |
else: | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
if 'AUTODRY'in self.support_racmode: | |
mode = self._state.autodry_state | |
return ACETCMODES[mode.name] | |
else: | |
return '지원안함' | |
elif self.device_type == 'SAC_CST': | |
return '지원안함' | |
return ACETCMODES[mode.name] | |
def autodry_mode(self, autodry_mode): | |
name = 'AutoDry' | |
if autodry_mode == 'ON': | |
if self.device_type == 'PAC': | |
if 'AUTODRY'in self.support_pacmode: | |
self._ac.set_etc_mode(name, True) | |
elif self.device_type == 'RAC': | |
if 'AUTODRY'in self.support_racmode: | |
self._ac.set_etc_mode(name, True) | |
elif autodry_mode == 'OFF': | |
if self.device_type == 'PAC': | |
if 'AUTODRY'in self.support_pacmode: | |
self._ac.set_etc_mode(name, False) | |
elif self.device_type == 'RAC': | |
if 'AUTODRY'in self.support_racmode: | |
self._ac.set_etc_mode(name, False) | |
@property | |
def is_smartcare_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
if 'SMARTCARE' in self.support_windmode: | |
mode = self._state.smartcare_state | |
else: | |
return '지원안함' | |
return ACETCMODES[mode.name] | |
elif self.device_type == 'RAC': | |
return '지원안함' | |
elif self.device_type == 'SAC_CST': | |
return '지원안함' | |
def smartcare_mode(self, smartcare_mode): | |
name = 'SmartCare' | |
if self.device_type == 'PAC': | |
if 'SMARTCARE' in self.support_windmode: | |
if smartcare_mode == 'ON': | |
self._ac.set_etc_mode(name, True) | |
elif smartcare_mode == 'OFF': | |
self._ac.set_etc_mode(name, False) | |
else: | |
return '지원안함' | |
@property | |
def is_powersave_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
if 'POWERSAVE'in self.support_pacmode: | |
mode = self._state.powersave_state | |
else: | |
return '지원안함' | |
else: | |
mode = self._state.powersave_state | |
return ACETCMODES[mode.name] | |
def powersave_mode(self, powersave_mode): | |
name = 'PowerSave' | |
if self.device_type == 'PAC': | |
if 'POWERSAVE'in self.support_pacmode: | |
if powersave_mode == 'ON': | |
self._ac.set_etc_mode(name, True) | |
else: | |
return '지원안함' | |
else: | |
if powersave_mode == 'ON': | |
self._ac.set_etc_mode(name, True) | |
@property | |
def is_coolpower_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
if 'ICEVALLEY' in self.support_windmode: | |
mode = self._state.icevalley_state | |
return ACETCMODES[mode.name] | |
else: | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
return '지원안함' | |
elif self.device_type == 'SAC_CST': | |
return '지원안함' | |
def coolpower_mode(self, coolpower_mode): | |
name = 'IceValley' | |
if self.device_type == 'PAC': | |
if 'ICEVALLEY' in self.support_windmode: | |
if coolpower_mode == 'ON': | |
self._ac.set_etc_mode(name, True) | |
elif coolpower_mode == 'OFF': | |
self._ac.set_etc_mode(name, False) | |
else: | |
return '지원안함' | |
else: | |
return '지원안함' | |
@property | |
def is_longpower_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
if 'LONGPOWER' in self.support_windmode: | |
mode = self._state.longpower_state | |
return ACETCMODES[mode.name] | |
else: | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
return '지원안함' | |
elif self.device_type == 'SAC_CST': | |
return '지원안함' | |
def longpower_mode(self, longpower_mode): | |
name = 'FlowLongPower' | |
if self.device_type == 'PAC': | |
if 'LONGPOWER' in self.support_windmode: | |
if longpower_mode == 'ON': | |
self._ac.set_etc_mode(name, True) | |
elif longpower_mode == 'OFF': | |
self._ac.set_etc_mode(name, False) | |
else: | |
return '지원안함' | |
@property | |
def is_up_down_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
if 'UPDOWN' in self.support_swingmode: | |
mode = self._state.wdirupdown_state | |
return ACETCMODES[mode.name] | |
elif self.device_type == 'RAC': | |
if 'UP_DOWN' in self.support_racsubmode: | |
mode = self._state.wdirupdown_state | |
return ACETCMODES[mode.name] | |
else: | |
return '지원안함' | |
def up_down_mode(self, up_down_mode): | |
name = 'WDirUpDown' | |
if up_down_mode == 'ON': | |
if self.device_type == 'PAC': | |
if 'UPDOWN' in self.support_swingmode: | |
self._ac.set_etc_mode(name, True) | |
elif self.device_type == 'RAC': | |
if 'UP_DOWN' in self.support_racsubmode: | |
self._ac.set_etc_mode(name, True) | |
else: | |
return '지원안함' | |
elif up_down_mode == 'OFF': | |
if self.device_type == 'PAC': | |
if 'UPDOWN' in self.support_swingmode: | |
self._ac.set_etc_mode(name, False) | |
elif self.device_type == 'RAC': | |
if 'UP_DOWN' in self.support_racsubmode: | |
self._ac.set_etc_mode(name, False) | |
else: | |
return '지원안함' | |
@property | |
def is_sensormon_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
mode = self._state.sensormon_state | |
return ACETCMODES[mode.name] | |
elif self.device_type == 'RAC': | |
return '지원안함' | |
elif self.device_type == 'SAC_CST': | |
return '지원안함' | |
def sensormon_mode(self, sensormon_mode): | |
name = 'SensorMon' | |
if self.device_type == 'PAC': | |
if sensormon_mode == 'ON': | |
self._ac.set_etc_mode(name, True) | |
elif sensormon_mode == 'OFF': | |
self._ac.set_etc_mode(name, False) | |
@property | |
def is_jet_mode(self): | |
if self._state: | |
if self.device_type == 'PAC': | |
return '지원안함' | |
elif self.device_type == 'RAC': | |
mode = self._state.jet_state | |
return ACETCMODES[mode.name] | |
elif self.device_type == 'SAC_CST': | |
mode = self._state.jet_state | |
return ACETCMODES[mode.name] | |
def jet_mode(self, jet_mode): | |
name = 'Jet' | |
if self.device_type == 'RAC': | |
if jet_mode == 'ON': | |
self._ac.set_etc_mode(name, True) | |
elif jet_mode == 'OFF': | |
self._ac.set_etc_mode(name, False) | |
elif self.device_type == 'SAC_CST': | |
if jet_mode == 'ON': | |
self._ac.set_etc_mode(name, True) | |
elif jet_mode == 'OFF': | |
self._ac.set_etc_mode(name, False) | |
@property | |
def is_sleep_timer(self): | |
if 'SLEEPTIMER' in self.support_reservemode: | |
return self._state.sleeptime | |
def sleep_timer(self, sleep_time): | |
if 'SLEEPTIMER' in self.support_reservemode: | |
self._ac.set_sleep_time(sleep_time) | |
@property | |
def filter_state(self): | |
data = self._ac.get_filter_state() | |
usetime = data['UseTime'] | |
changeperiod = data['ChangePeriod'] | |
if changeperiod == '0': | |
return '지원안함' | |
else: | |
use = int(usetime)/int(changeperiod) | |
remain = (1 - use)*100 | |
return int(remain) | |
@property | |
def mfilter_state(self): | |
data = self._ac.get_mfilter_state() | |
remaintime = data['RemainTime'] | |
changeperiod = data['ChangePeriod'] | |
if changeperiod == '0': | |
return '지원안함' | |
else: | |
remain = int(remaintime)/int(changeperiod) | |
return int(remain * 100) | |
@property | |
def outdoor_weather(self): | |
if self._area is not None: | |
data = self._ac.get_outdoor_weather(self._area) | |
return data | |
@property | |
def outtotalinstantpower(self): | |
return self._ac.get_outtotalinstantpower() | |
@property | |
def inoutinstantpower(self): | |
return self._ac.get_inoutinstantpower() | |
@property | |
def energy_usage_day(self): | |
data = int(self._ac.get_energy_usage_day()) | |
energy = format(data/1000,'.2f') | |
return energy | |
@property | |
def usage_time_day(self): | |
data = int(self._ac.get_usage_time_day()) | |
time = format(data/60, '.2f') | |
return time | |
@property | |
def energy_usage_week(self): | |
data = int(self._ac.get_energy_usage_week()) | |
energy = format(data/1000,'.2f') | |
return energy | |
@property | |
def usage_time_day(self): | |
data = int(self._ac.get_usage_time_week()) | |
time = format(data/60, '.2f') | |
return time | |
@property | |
def energy_usage_month(self): | |
data = int(self._ac.get_energy_usage_month()) | |
energy = format(data/1000,'.2f') | |
return energy | |
@property | |
def usage_time_day(self): | |
data = int(self._ac.get_usage_time_month()) | |
time = format(data/60, '.2f') | |
return time | |
@property | |
def elec_fare(self): | |
monthly_usage = int(self._ac.get_energy_usage_month())/1000 | |
if monthly_usage <= 200: | |
fare = 910 + monthly_usage * 93.3 | |
elif monthly_usage <=400: | |
fare = 1600 + monthly_usage * 187.9 | |
elif monthly_usage > 400: | |
fare = 7300 + monthly_usage * 280.6 | |
return format(round(fare), ',') | |
@property | |
def humidity(self): | |
if self._state: | |
if 'SENSOR_HUMID_SUPPORT' in self.support_airpolution: | |
return self._state.humidity | |
else: | |
return None | |
@property | |
def sensorpm1(self): | |
if self._state: | |
if 'PM1_SUPPORT' in self.support_airpolution: | |
return self._state.sensorpm1 | |
else: | |
return None | |
@property | |
def sensorpm2(self): | |
if self._state: | |
if 'PM2_SUPPORT' in self.support_airpolution: | |
return self._state.sensorpm2 | |
else: | |
return None | |
@property | |
def sensorpm10(self): | |
if self._state: | |
if 'PM10_SUPPORT' in self.support_airpolution: | |
return self._state.sensorpm2 | |
else: | |
return None | |
@property | |
def air_polution(self): | |
if self._state: | |
if 'TOTALCLEAN_SUPPORT' in self.support_airpolution: | |
mode = self._state.air_polution | |
return APSMELL[mode.name] | |
else: | |
return None | |
@property | |
def total_air_polution(self): | |
if self._state: | |
if 'TOTALCLEAN_SUPPORT' in self.support_airpolution: | |
mode = self._state.total_air_polution | |
return APTOTALAIRPOLUTION[mode.name] | |
else: | |
return None | |
@property | |
def temperature_unit(self): | |
if self._celsius: | |
return const.TEMP_CELSIUS | |
else: | |
return const.TEMP_FAHRENHEIT | |
@property | |
def min_temp(self): | |
if self._celsius: | |
if self.device_type == 'PAC': | |
return TEMP_MIN_C | |
elif self.device_type == 'RAC': | |
return TEMP_MIN_HEAT_C | |
elif self.device_type == 'SAC_CST': | |
return TEMP_MIN_HEAT_C | |
return climate.ClimateDevice.min_temp.fget(self) | |
@property | |
def max_temp(self): | |
if self._celsius: | |
if self.device_type == 'PAC': | |
return TEMP_MAX_C | |
elif self.device_type == 'RAC': | |
return TEMP_MAX_HEAT_C | |
elif self.device_type == 'SAC_CST': | |
return TEMP_MAX_HEAT_C | |
return climate.ClimateDevice.max_temp.fget(self) | |
@property | |
def current_temperature(self): | |
if self._state: | |
if self._celsius: | |
return self._state.temp_cur_c | |
@property | |
def target_temperature(self): | |
# Use the recently-set target temperature if it was set recently | |
# (within TRANSIENT_EXP seconds ago). | |
if self._transient_temp: | |
interval = time.time() - self._transient_time | |
if interval < TRANSIENT_EXP: | |
return self._transient_temp | |
else: | |
self._transient_temp = None | |
# Otherwise, actually use the device's state. | |
if self._state: | |
if self._celsius: | |
return self._state.temp_cfg_c | |
else: | |
return self._state.temp_cfg_f | |
def set_temperature(self, **kwargs): | |
temperature = kwargs['temperature'] | |
self._transient_temp = temperature | |
self._transient_time = time.time() | |
LOGGER.info('Setting temperature to %s...', temperature) | |
if self._celsius: | |
self._ac.set_celsius(temperature) | |
else: | |
self._ac.set_fahrenheit(temperature) | |
LOGGER.info('Temperature set.') | |
def update(self): | |
import wideq | |
LOGGER.info('Updating %s.', self.name) | |
for iteration in range(MAX_RETRIES): | |
LOGGER.info('Polling...') | |
try: | |
state = self._ac.poll() | |
except wideq.NotLoggedInError: | |
LOGGER.info('Session expired. Refreshing.') | |
self._client.refresh() | |
self._ac.monitor_start() | |
self._ac.monitor_start() | |
self._ac.delete_permission() | |
self._ac.delete_permission() | |
continue | |
if state: | |
LOGGER.info('Status updated.') | |
self._state = state | |
self._client.refresh() | |
self._ac.monitor_start() | |
self._ac.monitor_start() | |
self._ac.delete_permission() | |
self._ac.delete_permission() | |
return | |
LOGGER.info('No status available yet.') | |
time.sleep(2 ** iteration) | |
# We tried several times but got no result. This might happen | |
# when the monitoring request gets into a bad state, so we | |
# restart the task. | |
LOGGER.warn('Status update failed.') | |
self._ac.monitor_start() | |
self._ac.monitor_start() | |
self._ac.delete_permission() | |
self._ac.delete_permission() | |
# Refrigerator Main | |
class LGEREFDEVICE(LGEDevice): | |
def __init__(self, client, device, name, model_type): | |
"""initialize a LGE Refrigerator Device.""" | |
LGEDevice.__init__(self, client, device) | |
import wideq | |
self._ref = wideq.RefDevice(client, device) | |
self._ref.monitor_start() | |
self._ref.monitor_start() | |
self._ref.delete_permission() | |
self._ref.delete_permission() | |
# The response from the monitoring query. | |
self._state = None | |
# Store a transient temperature when we've just set it. We also | |
# store the timestamp for when we set this value. | |
self._transient_temp = None | |
self._transient_time = None | |
self._name = name | |
self._type = model_type | |
self.update() | |
@property | |
def name(self): | |
return self._name | |
@property | |
def device_type(self): | |
return self._type | |
@property | |
def supported_features(self): | |
""" none """ | |
@property | |
def state_attributes(self): | |
"""Return the optional state attributes.""" | |
data={} | |
data[ATTR_DEVICE_TYPE] = self.device_type | |
data[ATTR_REFRIGERATOR_TEMPERATURE] = self.current_reftemp | |
data[ATTR_FREEZER_TEMPERATURE] = self.current_freezertemp | |
data[ATTR_ICEPLUS_STATE] = self.ice_plus_state | |
data[ATTR_ICEPLUS_LIST] = self.ice_plus_list | |
if self.fresh_air_filter_list != '지원안함': | |
data[ATTR_FRESHAIRFILTER_STATE] = self.fresh_air_filter_state | |
data[ATTR_FRESHAIRFILTER_LIST] = self.fresh_air_filter_list | |
if self.smart_saving_mode != '지원안함': | |
data[ATTR_SMARTSAVING_MODE] = self.smart_saving_mode | |
if self.smart_saving_state != '지원안함': | |
data[ATTR_SMARTSAVING_STATE] = self.smart_saving_state | |
if self.water_filter_state != '지원안함': | |
data[ATTR_WATERFILTER_STATE] = self.water_filter_state | |
data[ATTR_DOOR_STATE] = self.door_state | |
data[ATTR_LOCKING_STATE] = self.locking_state | |
if self.active_saving_state != '지원안함': | |
data[ATTR_ACTIVESAVING_STATE] = self.active_saving_state | |
return data | |
@property | |
def state(self): | |
if self._state: | |
return '켜짐' | |
else: | |
return '꺼짐' | |
@property | |
def current_reftemp(self): | |
if self._state: | |
return self._state.current_reftemp | |
def set_ref_temperature(self, refrigerator_temperature): | |
self._ref.set_reftemp(refrigerator_temperature) | |
@property | |
def current_freezertemp(self): | |
if self._state: | |
return self._state.current_freezertemp | |
def set_freezer_temperature(self, freezer_temperature): | |
self._ref.set_freezertemp(freezer_temperature) | |
@property | |
def ice_plus_list(self): | |
return list(ICEPLUSMODES.values()) | |
@property | |
def ice_plus_state(self): | |
if self._state: | |
mode = self._state.iceplus_state | |
return ICEPLUSMODES[mode.name] | |
def set_iceplus_mode(self, iceplus_mode): | |
import wideq | |
# Invert the modes mapping. | |
modes_inv = {v: k for k, v in ICEPLUSMODES.items()} | |
mode = wideq.ICEPLUS[modes_inv[iceplus_mode]] | |
self._ref.set_iceplus(mode) | |
@property | |
def fresh_air_filter_list(self): | |
if self._state: | |
mode = self._state.freshairfilter_state | |
if mode == '255': | |
return '지원안함' | |
else: | |
if mode.name in FRESHAIRFILTERMODES: | |
return list(FRESHAIRFILTERMODES.values()) | |
elif mode.name in SMARTCAREMODES: | |
return list(SMARTCAREMODES.values()) | |
@property | |
def fresh_air_filter_state(self): | |
if self._state: | |
mode = self._state.freshairfilter_state | |
if mode.name in FRESHAIRFILTERMODES: | |
return FRESHAIRFILTERMODES[mode.name] | |
elif mode.name in SMARTCAREMODES: | |
return SMARTCAREMODES[mode.name] | |
def set_fresh_air_filter_mode(self, freshairfilter_mode): | |
import wideq | |
# Invert the modes mapping. | |
modes_inv = {v: k for k, v in FRESHAIRFILTERMODES.items()} | |
smartmodes_inv = {v: k for k, v in SMARTCAREMODES.items()} | |
if freshairfilter_mode in modes_inv: | |
mode = wideq.FRESHAIRFILTER[modes_inv[freshairfilter_mode]] | |
elif freshairfilter_mode in smartmodes_inv: | |
mode = wideq.FRESHAIRFILTER[smartmodes_inv[freshairfilter_mode]] | |
self._ref.set_freshairfilter(mode) | |
@property | |
def smart_saving_mode(self): | |
if self._state: | |
data = self._state.smartsaving_mode | |
if data == "@RE_SMARTSAVING_MODE_NIGHT_W": | |
return 'NIGHT' | |
elif data == "@RE_SMARTSAVING_MODE_CUSTOM_W": | |
return 'CUSTOM' | |
elif data == "@CP_TERM_USE_NOT_W": | |
return 'OFF' | |
else: | |
return '지원안함' | |
@property | |
def water_filter_state(self): | |
if self._state: | |
data = self._state.waterfilter_state | |
if data == '255': | |
return '지원안함' | |
else: | |
return data | |
@property | |
def door_state(self): | |
if self._state: | |
return self._state.door_state | |
@property | |
def smart_saving_state(self): | |
if self._state: | |
data = self._state.smartsaving_state | |
if data == '255': | |
return '지원안함' | |
else: | |
return self._state.smartsaving_state | |
@property | |
def locking_state(self): | |
if self._state: | |
return self._state.locking_state | |
@property | |
def active_saving_state(self): | |
if self._state: | |
data = self._state.activesaving_state | |
if data == '255': | |
return '지원안함' | |
else: | |
return data | |
def update(self): | |
import wideq | |
LOGGER.info('Updating %s.', self.name) | |
for iteration in range(MAX_RETRIES): | |
LOGGER.info('Polling...') | |
try: | |
state = self._ref.poll() | |
except wideq.NotLoggedInError: | |
LOGGER.info('Session expired. Refreshing.') | |
self._client.refresh() | |
self._ref.monitor_start() | |
self._ref.monitor_start() | |
self._ref.delete_permission() | |
self._ref.delete_permission() | |
continue | |
if state: | |
LOGGER.info('Status updated.') | |
self._state = state | |
self._client.refresh() | |
self._ref.monitor_start() | |
self._ref.monitor_start() | |
self._ref.delete_permission() | |
self._ref.delete_permission() | |
return | |
LOGGER.info('No status available yet.') | |
time.sleep(2 ** iteration) | |
# We tried several times but got no result. This might happen | |
# when the monitoring request gets into a bad state, so we | |
# restart the task. | |
LOGGER.warn('Status update failed.') | |
self._ref.monitor_start() | |
self._ref.monitor_start() | |
self._ref.delete_permission() | |
self._ref.delete_permission() | |
# Air Purifier Main | |
class LGEAPDEVICE(LGEDevice, ClimateDevice): | |
def __init__(self, client, device, name, model_type, celsius=True): | |
"""initialize a LGE Air Purifier Device.""" | |
LGEDevice.__init__(self, client, device) | |
import wideq | |
self._ap = wideq.APDevice(client, device) | |
self._ap.monitor_start() | |
self._ap.monitor_start() | |
self._ap.delete_permission() | |
self._ap.delete_permission() | |
# The response from the monitoring query. | |
self._state = None | |
self._name = name | |
self._type = model_type | |
self.update() | |
@property | |
def name(self): | |
return self._name | |
@property | |
def device_type(self): | |
return self._type | |
@property | |
def supported_features(self): | |
return ( | |
SUPPORT_OPERATION_MODE | | |
SUPPORT_FAN_MODE | | |
SUPPORT_SWING_MODE | | |
SUPPORT_ON_OFF | |
) | |
@property | |
def state_attributes(self): | |
"""Return the optional state attributes.""" | |
supported_features = self.supported_features | |
data = {} | |
data[ATTR_DEVICE_TYPE] = self.device_type | |
data[ATTR_STATUS] = self.current_status | |
if supported_features & SUPPORT_OPERATION_MODE: | |
data[ATTR_OPERATION_MODE] = self.current_operation | |
if self.operation_list: | |
data[ATTR_OPERATION_LIST] = self.operation_list | |
if supported_features & SUPPORT_FAN_MODE: | |
data[ATTR_FAN_MODE] = self.current_fan_mode | |
if self.fan_list: | |
data[ATTR_FAN_LIST] = self.fan_list | |
if supported_features & SUPPORT_SWING_MODE: | |
data[ATTR_SWING_MODE] = self.current_circulate_mode | |
if self.circulate_list: | |
data[ATTR_SWING_LIST] = self.circulate_list | |
data[ATTR_AIRREMOVAL_MODE] = self.is_airremoval_mode | |
data[ATTR_CIRCULATEDIR_MODE] = self.is_circulatedir_mode | |
data[ATTR_SIGNALLIGHTING_MODE] = self.is_signallighting_mode | |
data[ATTR_AIRFAST_MODE] = self.is_airfast_mode | |
data[ATTR_SENSORPM1] = self.sensorpm1 | |
data[ATTR_SENSORPM2] = self.sensorpm2 | |
data[ATTR_SENSORPM10] = self.sensorpm10 | |
data[ATTR_TOTALAIRPOLUTION] = self.total_air_polution | |
data[ATTR_AIRPOLUTION] = self.air_polution | |
data[ATTR_FILTER_STATE] = self.filter_state | |
return data | |
@property | |
def is_on(self): | |
if self._state: | |
return self._state.is_on | |
@property | |
def current_status(self): | |
if self.is_on == True: | |
return 'ON' | |
elif self.is_on == False: | |
return 'OFF' | |
def turn_on(self): | |
LOGGER.info('Turning on...') | |
self._ap.set_on(True) | |
LOGGER.info('...done.') | |
def turn_off(self): | |
LOGGER.info('Turning off...') | |
self._ap.set_on(False) | |
LOGGER.info('...done.') | |
@property | |
def support_oplist(self): | |
return self._state.support_oplist | |
@property | |
def operation_list(self): | |
if 'CLEAN' in self.support_oplist: | |
return list(SINGLECLEANMODES.values()) | |
else: | |
return list(APMODES.values()) | |
@property | |
def current_operation(self): | |
if self._state: | |
mode = self._state.mode | |
if 'CLEAN' in self.support_oplist: | |
return SINGLECLEANMODES[mode.name] | |
else: | |
return APMODES[mode.name] | |
def set_operation_mode(self, operation_mode): | |
import wideq | |
# Invert the modes mapping. | |
modes_inv = {v: k for k, v in APMODES.items()} | |
singlecleanmodes_inv = {v: k for k, v in SINGLECLEANMODES.items()} | |
if 'CLEAN' in self.support_oplist: | |
mode = wideq.APOPMode[singlecleanmodes_inv[operation_mode]] | |
else: | |
mode = wideq.APOPMode[modes_inv[operation_mode]] | |
self._ap.set_mode(mode) | |
@property | |
def fan_list(self): | |
if 'CLEAN' in self.support_oplist: | |
return list(APSINGLECLEAN_FANMODES.values()) | |
else: | |
return list(APFANMODES.values()) | |
@property | |
def current_fan_mode(self): | |
if self._state: | |
mode = self._state.windstrength_state | |
if 'CLEAN' in self.support_oplist: | |
return APSINGLECLEAN_FANMODES[mode.name] | |
else: | |
return APFANMODES[mode.name] | |
def set_fan_mode(self, fan_mode): | |
import wideq | |
# Invert the modes mapping. | |
fanmodes_inv = {v: k for k, v in APFANMODES.items()} | |
singleclean_fanmodes_inv = {v: k for k, v in APSINGLECLEAN_FANMODES.items()} | |
if 'CLEAN' in self.support_oplist: | |
mode = wideq.APWindStrength[singleclean_fanmodes_inv[fan_mode]] | |
else: | |
mode = wideq.APWindStrength[fanmodes_inv[fan_mode]] | |
self._ap.set_windstrength(mode) | |
@property | |
def circulate_list(self): | |
if 'CLEAN' in self.support_oplist: | |
return '지원안함' | |
else: | |
return list(APCIRCULATEMODES.values()) | |
@property | |
def current_circulate_mode(self): | |
if self._state: | |
if 'CLEAN' in self.support_oplist: | |
return '지원안함' | |
else: | |
mode = self._state.circulatestrength_state | |
return APCIRCULATEMODES[mode.name] | |
def set_swing_mode(self, circulate_mode): | |
import wideq | |
circulatemodes_inv = {v: k for k, v in APCIRCULATEMODES.items()} | |
if 'CLEAN' in self.support_oplist: | |
return '지원안함' | |
else: | |
mode = wideq.APCirculateStrength[circulatemodes_inv[circulate_mode]] | |
self._ap.set_circulatestrength(mode) | |
@property | |
def is_airremoval_mode(self): | |
if self._state: | |
mode = self._state.airremoval_state | |
return APETCMODES[mode.name] | |
def airremoval_mode(self, airremoval_mode): | |
if airremoval_mode == '켜짐': | |
self._ap.set_airremoval(True) | |
elif airremoval_mode == '꺼짐': | |
self._ap.set_airremoval(False) | |
@property | |
def is_circulatedir_mode(self): | |
if self._state: | |
if 'CLEAN' in self.support_oplist: | |
return '지원안함' | |
else: | |
mode = self._state.circulatedir_state | |
return APETCMODES[mode.name] | |
def circulatedir_mode(self, circulatedir_mode): | |
if 'CLEAN' in self.support_oplist: | |
return '지원안함' | |
else: | |
if circulatedir_mode == '켜짐': | |
self._ap.set_circulatedir(True) | |
elif circulatedir_mode == '꺼짐': | |
self._ap.set_circulatedir(False) | |
@property | |
def is_signallighting_mode(self): | |
if self._state: | |
if 'CLEAN' in self.support_oplist: | |
return '지원안함' | |
else: | |
mode = self._state.signallighting_state | |
return APETCMODES[mode.name] | |
@property | |
def is_airfast_mode(self): | |
if self._state: | |
if 'CLEAN' in self.support_oplist: | |
mode = self._state.airfast_state | |
else: | |
return '지원안함' | |
return APETCMODES[mode.name] | |
def airfast_mode(self, airfast_mode): | |
if 'CLEAN' in self.support_oplist: | |
if airfast_mode == '켜짐': | |
self._ap.set_airfast(True) | |
elif airfast_mode == '꺼짐': | |
self._ap.set_airfast(False) | |
else: | |
return '지원안함' | |
@property | |
def filter_state(self): | |
data = self._ap.get_filter_state() | |
usetime = data['UseTime'] | |
changeperiod = data['ChangePeriod'] | |
if changeperiod == '0': | |
return '지원안함' | |
else: | |
use = int(usetime)/int(changeperiod) | |
remain = (1 - use)*100 | |
return int(remain) | |
@property | |
def sensorpm1(self): | |
if self._state: | |
return self._state.sensorpm1 | |
@property | |
def sensorpm2(self): | |
if self._state: | |
return self._state.sensorpm2 | |
@property | |
def sensorpm10(self): | |
if self._state: | |
return self._state.sensorpm10 | |
@property | |
def air_polution(self): | |
if self._state: | |
mode = self._state.air_polution | |
return APSMELL[mode.name] | |
@property | |
def total_air_polution(self): | |
if self._state: | |
mode = self._state.total_air_polution | |
return APTOTALAIRPOLUTION[mode.name] | |
def update(self): | |
import wideq | |
LOGGER.info('Updating %s.', self.name) | |
for iteration in range(MAX_RETRIES): | |
LOGGER.info('Polling...') | |
try: | |
state = self._ap.poll() | |
except wideq.NotLoggedInError: | |
LOGGER.info('Session expired. Refreshing.') | |
self._client.refresh() | |
self._ap.monitor_start() | |
self._ap.monitor_start() | |
self._ap.delete_permission() | |
self._ap.delete_permission() | |
continue | |
if state: | |
LOGGER.info('Status updated.') | |
self._state = state | |
self._client.refresh() | |
self._ap.monitor_start() | |
self._ap.monitor_start() | |
self._ap.delete_permission() | |
self._ap.delete_permission() | |
return | |
LOGGER.info('No status available yet.') | |
time.sleep(2 ** iteration) | |
# We tried several times but got no result. This might happen | |
# when the monitoring request gets into a bad state, so we | |
# restart the task. | |
LOGGER.warn('Status update failed.') | |
self._ap.monitor_start() | |
self._ap.monitor_start() | |
self._ap.delete_permission() | |
self._ap.delete_permission() | |
# Dehumidifier Main | |
class LGEDEHUMDEVICE(LGEDevice, ClimateDevice): | |
def __init__(self, client, device, name, model_type): | |
"""initialize a LGE Dehumidifer Device.""" | |
LGEDevice.__init__(self, client, device) | |
import wideq | |
self._dehum = wideq.DehumDevice(client, device) | |
self._dehum.monitor_start() | |
self._dehum.monitor_start() | |
self._dehum.delete_permission() | |
self._dehum.delete_permission() | |
# The response from the monitoring query. | |
self._state = None | |
self._transient_hum = None | |
self._transient_time = None | |
self._name = name | |
self._type = model_type | |
self.update() | |
@property | |
def name(self): | |
return self._name | |
@property | |
def device_type(self): | |
return self._type | |
@property | |
def supported_features(self): | |
return ( | |
SUPPORT_TARGET_HUMIDITY | | |
SUPPORT_TARGET_HUMIDITY_HIGH | | |
SUPPORT_TARGET_HUMIDITY_LOW | | |
SUPPORT_OPERATION_MODE | | |
SUPPORT_FAN_MODE | | |
SUPPORT_ON_OFF | |
) | |
@property | |
def state_attributes(self): | |
"""Return the optional state attributes.""" | |
data = {} | |
data[ATTR_AIRREMOVAL_MODE] = self.is_airremoval_mode | |
data[ATTR_STATUS] = self.current_status | |
if self.target_humidity_step is not None: | |
data[ATTR_TARGET_HUMIDITY_STEP] = self.target_humidity_step | |
supported_features = self.supported_features | |
if supported_features & SUPPORT_FAN_MODE: | |
data[ATTR_FAN_MODE] = self.current_fan_mode | |
if self.fan_list: | |
data[ATTR_FAN_LIST] = self.fan_list | |
if supported_features & SUPPORT_OPERATION_MODE: | |
data[ATTR_OPERATION_MODE] = self.current_operation | |
if self.operation_list: | |
data[ATTR_OPERATION_LIST] = self.operation_list | |
if supported_features & SUPPORT_TARGET_HUMIDITY: | |
data[ATTR_HUMIDITY] = self.target_humidity | |
data[ATTR_CURRENT_HUMIDITY] = self.current_humidity | |
if supported_features & SUPPORT_TARGET_HUMIDITY_LOW: | |
data[ATTR_MIN_HUMIDITY] = self.min_humidity | |
if supported_features & SUPPORT_TARGET_HUMIDITY_HIGH: | |
data[ATTR_MAX_HUMIDITY] = self.max_humidity | |
return data | |
@property | |
def is_on(self): | |
if self._state: | |
return self._state.is_on | |
@property | |
def current_status(self): | |
if self._state.is_on == True: | |
return 'ON' | |
elif self._state.is_on == False: | |
return 'OFF' | |
def turn_on(self): | |
LOGGER.info('Turning on...') | |
self._dehum.set_on(True) | |
LOGGER.info('...done.') | |
def turn_off(self): | |
LOGGER.info('Turning off...') | |
self._dehum.set_on(False) | |
LOGGER.info('...done.') | |
@property | |
def operation_list(self): | |
return list(DEHUMMODES.values()) | |
@property | |
def current_operation(self): | |
if self._state: | |
mode = self._state.mode | |
return DEHUMMODES[mode.name] | |
def set_operation_mode(self, operation_mode): | |
import wideq | |
# Invert the modes mapping. | |
modes_inv = {v: k for k, v in DEHUMMODES.items()} | |
mode = wideq.DEHUMOPMode[modes_inv[operation_mode]] | |
self._dehum.set_mode(mode) | |
@property | |
def fan_list(self): | |
return list(DEHUMFANMODES.values()) | |
@property | |
def current_fan_mode(self): | |
if self._state: | |
mode = self._state.windstrength_state | |
return DEHUMFANMODES[mode.name] | |
def set_fan_mode(self, fan_mode): | |
import wideq | |
# Invert the modes mapping. | |
fanmodes_inv = {v: k for k, v in DEHUMFANMODES.items()} | |
mode = wideq.DEHUMWindStrength[fanmodes_inv[fan_mode]] | |
self._dehum.set_windstrength(mode) | |
@property | |
def is_airremoval_mode(self): | |
if self._state: | |
mode = self._state.airremoval_state | |
return DEHUMAIRREMOVALMODES[mode.name] | |
def airremoval_mode(self, airremoval_mode): | |
if airremoval_mode == '켜짐': | |
self._dehum.set_airremoval(True) | |
elif airremoval_mode == '꺼짐': | |
self._dehum.set_airremoval(False) | |
@property | |
def min_humidity(self): | |
return HUM_MIN | |
@property | |
def max_humidity(self): | |
return HUM_MAX | |
@property | |
def target_humidity_step(self): | |
return HUM_STEP | |
@property | |
def current_humidity(self): | |
if self._state: | |
return self._state.current_humidity | |
@property | |
def target_humidity(self): | |
if self._state: | |
return self._state.target_humidity | |
def set_humidity(self, humidity): | |
LOGGER.info('Setting humidity to %s...', humidity) | |
self._dehum.set_humidity(humidity) | |
LOGGER.info('humidity set.') | |
def update(self): | |
import wideq | |
LOGGER.info('Updating %s.', self.name) | |
for iteration in range(MAX_RETRIES): | |
LOGGER.info('Polling...') | |
try: | |
state = self._dehum.poll() | |
except wideq.NotLoggedInError: | |
LOGGER.info('Session expired. Refreshing.') | |
self._client.refresh() | |
self._dehum.monitor_start() | |
self._dehum.monitor_start() | |
self._dehum.delete_permission() | |
self._dehum.delete_permission() | |
continue | |
if state: | |
LOGGER.info('Status updated.') | |
self._state = state | |
self._client.refresh() | |
self._dehum.monitor_start() | |
self._dehum.monitor_start() | |
self._dehum.delete_permission() | |
self._dehum.delete_permission() | |
return | |
LOGGER.info('No status available yet.') | |
time.sleep(2 ** iteration) | |
# We tried several times but got no result. This might happen | |
# when the monitoring request gets into a bad state, so we | |
# restart the task. | |
LOGGER.warn('Status update failed.') | |
self._dehum.monitor_start() | |
self._dehum.monitor_start() | |
self._dehum.delete_permission() | |
self._dehum.delete_permission() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import threading | |
import voluptuous as vol | |
import json | |
from homeassistant.components import fan | |
from homeassistant.components.fan import ( | |
FanEntity) | |
from custom_components.smartthinq import ( | |
DOMAIN, LGE_DEVICES, LGEDevice) | |
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa | |
import homeassistant.helpers.config_validation as cv | |
from homeassistant import const | |
from homeassistant.const import ( | |
ATTR_ENTITY_ID, CONF_NAME, CONF_TOKEN, CONF_ENTITY_ID,) | |
import time | |
import wideq | |
LGE_AIRPURIFIER_DEVICES = 'lge_AirPurifier_devices' | |
CONF_MAC = 'mac' | |
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | |
vol.Required(CONF_NAME): cv.string, | |
vol.Required(CONF_MAC): cv.string, | |
}) | |
# For Air Purifier | |
#----------------------------------------------------------- | |
SUPPORT_SET_SPEED = 1 | |
CONF_AIRFAST_MODE = 'airfast_mode' | |
CONF_AIRREMOVAL_MODE = 'airremoval_mode' | |
ATTR_SPEED_OFF = '꺼짐' | |
ATTR_AIRREMOVAL_MODE = 'airremoval_mode' | |
ATTR_AIRFAST_MODE = 'airfast_mode' | |
ATTR_SPEED = 'speed' | |
ATTR_SPEED_LIST = 'speed_list' | |
ATTR_DEVICE_TYPE = 'device_type' | |
ATTR_STATUS = 'current_status' | |
ATTR_SENSORPM1 = 'PM1' | |
ATTR_SENSORPM2 = 'PM2' | |
ATTR_SENSORPM10 = 'PM10' | |
ATTR_TOTALAIRPOLUTION = 'total_air_polution' | |
ATTR_FILTER_STATE = 'filter_state' | |
ATTR_AIRPOLUTION = 'air_polution' | |
SERVICE_SET_AIRREMOVAL_MODE = 'lge_airpurifier_set_airremoval_mode' | |
SERVICE_SET_AIRFAST_MODE = 'lge_airpurifier_set_airfast_mode' | |
APSINGLECLEAN_FANMODES_LIST = { | |
'LOWST_LOW': wideq.STATE_AIRPURIFIER_LOWST_LOW, | |
'LOWST': wideq.STATE_AIRPURIFIER_LOWST, | |
'LOW': wideq.STATE_AIRPURIFIER_LOW, | |
'LOW_MID': wideq.STATE_AIRPURIFIER_LOW_MID, | |
'MID': wideq.STATE_AIRPURIFIER_MID, | |
'MID_HIGH': wideq.STATE_AIRPURIFIER_MID_HIGH, | |
'HIGH': wideq.STATE_AIRPURIFIER_HIGH, | |
'AUTO': wideq.STATE_AIRPURIFIER_AUTO, | |
} | |
APSINGLECLEAN_FANMODES = { | |
'LOW': wideq.STATE_AIRPURIFIER_LOW, | |
'MID': wideq.STATE_AIRPURIFIER_MID, | |
'HIGH': wideq.STATE_AIRPURIFIER_HIGH, | |
'AUTO': wideq.STATE_AIRPURIFIER_AUTO, | |
} | |
APETCMODES = { | |
'NOT_SUPPORTED': wideq.STATE_AIRPURIFIER_NOT_SUPPORTED, | |
'ON': wideq.STATE_AIRPURIFIER_ON, | |
'OFF': wideq.STATE_AIRPURIFIER_OFF, | |
} | |
APTOTALAIRPOLUTION = { | |
'NOT_SUPPORT': wideq.STATE_AIRPURIFIER_NOT_SUPPORTED, | |
'GOOD': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_GOOD, | |
'NORMAL': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_NORMAL, | |
'BAD': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_BAD, | |
'VERYBAD': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_VERYBAD | |
} | |
APSMELL = { | |
'NOT_SUPPORT': wideq.STATE_AIRPURIFIER_NOT_SUPPORTED, | |
'WEEK': wideq.STATE_AIRPURIFIER_SMELL_WEEK, | |
'NORMAL': wideq.STATE_AIRPURIFIER_TOTALAIRPOLUTION_NORMAL, | |
'STRONG': wideq.STATE_AIRPURIFIER_SMELL_STRONG, | |
'VERYSTRONG': wideq.STATE_AIRPURIFIER_SMELL_VERYSTRONG | |
} | |
LGE_AIRPURIFIER_SET_AIRREMOVAL_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_AIRREMOVAL_MODE): cv.string, | |
}) | |
LGE_AIRPURIFIER_SET_AIRFAST_MODE_SCHEMA = vol.Schema({ | |
vol.Required(CONF_ENTITY_ID): cv.entity_id, | |
vol.Required(CONF_AIRFAST_MODE): cv.string, | |
}) | |
MAX_RETRIES = 5 | |
LOGGER = logging.getLogger(__name__) | |
def setup_platform(hass, config, add_entities, discovery_info=None): | |
import wideq | |
refresh_token = hass.data[CONF_TOKEN] | |
client = wideq.Client.from_token(refresh_token) | |
name = config[CONF_NAME] | |
conf_mac = config[CONF_MAC] | |
"""Set up the LGE entity.""" | |
for device_id in hass.data[LGE_DEVICES]: | |
device = client.get_device(device_id) | |
model = client.model_info(device) | |
mac = device.macaddress | |
model_type = model.model_type | |
if device.type == wideq.DeviceType.AIR_PURIFIER: | |
LGE_AIRPURIFIER_DEVICES = [] | |
if mac == conf_mac.lower(): | |
ap_entity = LGEAPDEVICE(client, device, name, model_type) | |
LGE_AIRPURIFIER_DEVICES.append(ap_entity) | |
add_entities(LGE_AIRPURIFIER_DEVICES) | |
LOGGER.debug("LGE AirPurifier is added") | |
def airpurifier_service_handle(service): | |
"""Handle the AirPurifier services.""" | |
entity_ids = service.data.get(ATTR_ENTITY_ID) | |
airremoval_mode = service.data.get(CONF_AIRREMOVAL_MODE) | |
airfast_mode = service.data.get(CONF_AIRFAST_MODE) | |
if service.service == SERVICE_SET_AIRREMOVAL_MODE: | |
ap_entity.airremoval_mode(airremoval_mode) | |
elif service.service == SERVICE_SET_AIRFAST_MODE: | |
ap_entity.airfast_mode(airfast_mode) | |
# Register air purifier service(s) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_AIRREMOVAL_MODE, airpurifier_service_handle, | |
schema=LGE_AIRPURIFIER_SET_AIRREMOVAL_MODE_SCHEMA) | |
hass.services.register( | |
DOMAIN, SERVICE_SET_AIRFAST_MODE, airpurifier_service_handle, | |
schema=LGE_AIRPURIFIER_SET_AIRFAST_MODE_SCHEMA) | |
# Air Purifier Main | |
class LGEAPDEVICE(LGEDevice, FanEntity): | |
def __init__(self, client, device, name, model_type): | |
"""initialize a LGE Air Purifier Device.""" | |
LGEDevice.__init__(self, client, device) | |
import wideq | |
self._ap = wideq.APDevice(client, device) | |
self._ap.monitor_start() | |
self._ap.monitor_start() | |
self._ap.delete_permission() | |
self._ap.delete_permission() | |
# The response from the monitoring query. | |
self._state = None | |
self._type = model_type | |
self._name = name | |
self.update() | |
@property | |
def name(self): | |
return self._name | |
@property | |
def device_type(self): | |
return self._type | |
@property | |
def supported_features(self): | |
return SUPPORT_SET_SPEED | |
@property | |
def state_attributes(self): | |
"""Return the optional state attributes.""" | |
supported_features = self.supported_features | |
data = {} | |
data[ATTR_DEVICE_TYPE] = self.device_type | |
data[ATTR_STATUS] = self.current_status | |
if supported_features & SUPPORT_SET_SPEED: | |
data[ATTR_SPEED] = self.speed | |
if self.speed_list: | |
data[ATTR_SPEED_LIST] = self.speed_list | |
data[ATTR_AIRREMOVAL_MODE] = self.is_airremoval_mode | |
data[ATTR_AIRFAST_MODE] = self.is_airfast_mode | |
data[ATTR_SENSORPM1] = self.sensorpm1 | |
data[ATTR_SENSORPM2] = self.sensorpm2 | |
data[ATTR_SENSORPM10] = self.sensorpm10 | |
data[ATTR_TOTALAIRPOLUTION] = self.total_air_polution | |
data[ATTR_AIRPOLUTION] = self.air_polution | |
data[ATTR_FILTER_STATE] = self.filter_state | |
return data | |
@property | |
def is_on(self): | |
if self._state: | |
return self._state.is_on | |
@property | |
def current_status(self): | |
if self.is_on == True: | |
return '켜짐' | |
elif self.is_on == False: | |
return '꺼짐' | |
def turn_on(self, speed = None, **kwargs) -> None: | |
if speed is not None: | |
self.set_speed(speed) | |
else: | |
LOGGER.info('Turning on...') | |
self._ap.set_on(True) | |
LOGGER.info('...done.') | |
def turn_off(self, speed = None, **kwargs) -> None: | |
LOGGER.info('Turning off...') | |
self._ap.set_on(False) | |
LOGGER.info('...done.') | |
@property | |
def support_oplist(self): | |
return self._state.support_oplist | |
@property | |
def speed_list(self): | |
return list(APSINGLECLEAN_FANMODES.values()) | |
@property | |
def speed(self) -> str: | |
if self._state: | |
mode = self._state.windstrength_state | |
return APSINGLECLEAN_FANMODES_LIST[mode.name] | |
def set_speed(self, speed_mode) -> None: | |
import wideq | |
# Invert the modes mapping. | |
singleclean_fanmodes_inv = {v: k for k, v in APSINGLECLEAN_FANMODES.items()} | |
mode = wideq.APWindStrength[singleclean_fanmodes_inv[speed_mode]] | |
self._ap.set_windstrength(mode) | |
@property | |
def is_airremoval_mode(self): | |
if self._state: | |
mode = self._state.airremoval_state | |
return APETCMODES[mode.name] | |
def airremoval_mode(self, airremoval_mode): | |
if airremoval_mode == '켜짐': | |
self._ap.set_airremoval(True) | |
elif airremoval_mode == '꺼짐': | |
self._ap.set_airremoval(False) | |
@property | |
def is_airfast_mode(self): | |
if self._state: | |
if 'CLEAN' in self.support_oplist: | |
mode = self._state.airfast_state | |
else: | |
return '지원안함' | |
return APETCMODES[mode.name] | |
def airfast_mode(self, airfast_mode): | |
if 'CLEAN' in self.support_oplist: | |
if airfast_mode == '켜짐': | |
self._ap.set_airfast(True) | |
elif airfast_mode == '꺼짐': | |
self._ap.set_airfast(False) | |
else: | |
return '지원안함' | |
@property | |
def filter_state(self): | |
data = self._ap.get_filter_state() | |
usetime = data['UseTime'] | |
changeperiod = data['ChangePeriod'] | |
if changeperiod == '0': | |
return '지원안함' | |
else: | |
use = int(usetime)/int(changeperiod) | |
remain = (1 - use)*100 | |
return int(remain) | |
@property | |
def sensorpm1(self): | |
if self._state: | |
return self._state.sensorpm1 | |
@property | |
def sensorpm2(self): | |
if self._state: | |
return self._state.sensorpm2 | |
@property | |
def sensorpm10(self): | |
if self._state: | |
return self._state.sensorpm10 | |
@property | |
def air_polution(self): | |
if self._state: | |
mode = self._state.air_polution | |
return APSMELL[mode.name] | |
@property | |
def total_air_polution(self): | |
if self._state: | |
mode = self._state.total_air_polution | |
return APTOTALAIRPOLUTION[mode.name] | |
def update(self): | |
import wideq | |
LOGGER.info('Updating %s.', self.name) | |
for iteration in range(MAX_RETRIES): | |
LOGGER.info('Polling...') | |
try: | |
state = self._ap.poll() | |
except wideq.NotLoggedInError: | |
LOGGER.info('Session expired. Refreshing.') | |
self._client.refresh() | |
self._ap.monitor_start() | |
self._ap.monitor_start() | |
self._ap.delete_permission() | |
self._ap.delete_permission() | |
continue | |
if state: | |
LOGGER.info('Status updated.') | |
self._state = state | |
self._client.refresh() | |
self._ap.monitor_start() | |
self._ap.monitor_start() | |
self._ap.delete_permission() | |
self._ap.delete_permission() | |
return | |
LOGGER.info('No status available yet.') | |
time.sleep(2 ** iteration) | |
# We tried several times but got no result. This might happen | |
# when the monitoring request gets into a bad state, so we | |
# restart the task. | |
LOGGER.warn('Status update failed.') | |
self._ap.monitor_start() | |
self._ap.monitor_start() | |
self._ap.delete_permission() | |
self._ap.delete_permission() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"domain": "smartthinq", | |
"name": "Smartthinq", | |
"documentation": "https://github.com/wkd8176/hass-smartthinq", | |
"requirements": [], | |
"dependencies": [], | |
"codeowners": [ | |
"@wkd8176", | |
"@boralyl" | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import voluptuous as vol | |
import json | |
from datetime import timedelta | |
import time | |
from homeassistant.components import sensor | |
from custom_components.smartthinq import ( | |
DOMAIN, LGE_DEVICES, LGEDevice) | |
import homeassistant.helpers.config_validation as cv | |
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa | |
from homeassistant.const import ( | |
ATTR_ENTITY_ID, CONF_NAME, CONF_TOKEN, CONF_ENTITY_ID) | |
from homeassistant.exceptions import PlatformNotReady | |
import wideq | |
LGE_WASHER_DEVICES = 'lge_washer_devices' | |
LGE_DRYER_DEVICES = 'lge_dryer_devices' | |
LGE_WATERPURIFIER_DEVICES = 'lge_waterpurifier_devices' | |
CONF_MAC = 'mac' | |
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | |
vol.Required(CONF_NAME): cv.string, | |
vol.Required(CONF_MAC): cv.string, | |
}) | |
# For WASHER | |
#----------------------------------------------------------- | |
ATTR_CURRENT_STATUS = 'current_status' | |
ATTR_RUN_STATE = 'run_state' | |
ATTR_PRE_STATE = 'pre_state' | |
ATTR_REMAIN_TIME = 'remain_time' | |
ATTR_INITIAL_TIME = 'initial_time' | |
ATTR_RESERVE_TIME = 'reserve_time' | |
ATTR_CURRENT_COURSE = 'current_course' | |
ATTR_ERROR_STATE = 'error_state' | |
ATTR_WASH_OPTION_STATE = 'wash_option_state' | |
ATTR_SPIN_OPTION_STATE = 'spin_option_state' | |
ATTR_WATERTEMP_OPTION_STATE = 'watertemp_option_state' | |
ATTR_RINSECOUNT_OPTION_STATE = 'rinsecount_option_state' | |
ATTR_DRYLEVEL_STATE = 'drylevel_state' | |
ATTR_FRESHCARE_MODE = 'freshcare_mode' | |
ATTR_CHILDLOCK_MODE = 'childlock_mode' | |
ATTR_STEAM_MODE = 'steam_mode' | |
ATTR_DOORLOCK_MODE = 'doorlock_mode' | |
ATTR_BUZZER_MODE = 'buzzer_mode' | |
ATTR_STERILIZE_MODE = 'sterilize_mode' | |
ATTR_HEATER_MODE = 'heater_mode' | |
ATTR_TURBOSHOT_MODE = 'turboshot_mode' | |
ATTR_TUBCLEAN_COUNT = 'tubclean_count' | |
ATTR_LOAD_LEVEL = 'load_level' | |
ATTR_DEVICE_TYPE = 'device_type' | |
ATTR_WATERLEVEL_STATE = 'waterlevel_state' | |
ATTR_WATERFLOW_STATE = 'waterflow_state' | |
ATTR_SOAK_STATE = 'soak_state' | |
WASHERCOURSES = { | |
'NORMAL': 'Normal',#wideq.STATE_WASHER_COURSE_NORMAL, | |
'HEAVYDUTY': wideq.STATE_WASHER_COURSE_HEAVYDUTY, | |
'COTTON': wideq.STATE_WASHER_APCOURSE_COTTON, | |
'SPEEDWASH_DRY': wideq.STATE_WASHER_APCOURSE_SPEEDWASH_DRY, | |
'SPEEDWASH': wideq.STATE_WASHER_APCOURSE_SPEEDWASH, | |
'SINGLE_SHIRT_DRY': wideq.STATE_WASHER_APCOURSE_SINGLE_SHIRT_DRY, | |
'RINSESPIN': wideq.STATE_WASHER_APCOURSE_RINSESPIN, | |
'SPEEDBOIL': wideq.STATE_WASHER_APCOURSE_SPEEDBOIL, | |
'ALLERGYCARE': wideq.STATE_WASHER_APCOURSE_ALLERGYCARE, | |
'STEAMCLEANING': wideq.STATE_WASHER_APCOURSE_STEAMCLEANING, | |
'BABYWEAR': wideq.STATE_WASHER_APCOURSE_BABYWEAR, | |
'BLANKET_ROB': wideq.STATE_WASHER_APCOURSE_BLANKET_ROB, | |
'UTILITY': wideq.STATE_WASHER_APCOURSE_UTILITY, | |
'BLANKET': wideq.STATE_WASHER_APCOURSE_BLANKET, | |
'LINGERIE_WOOL': wideq.STATE_WASHER_APCOURSE_LINGERIE_WOOL, | |
'COLDWASH': wideq.STATE_WASHER_APCOURSE_COLDWASH, | |
'TUBCLEAN_SANITARY': wideq.STATE_WASHER_APCOURSE_TUBCLEAN_SANITARY, | |
'PERM_PRESS': wideq.STATE_WASHER_COURSE_PERM_PRESS, | |
'ALLERGIENE': wideq.STATE_WASHER_COURSE_ALLERGIENE, | |
'SANITARY': wideq.STATE_WASHER_COURSE_SANITARY, | |
'BRIGHT_WHITES': wideq.STATE_WASHER_COURSE_BRIGHT_WHITES, | |
'DELICATES': wideq.STATE_WASHER_COURSE_DELICATES, | |
'MINI_SMALL_LOAD': wideq.STATE_WASHER_COURSE_SMALL_LOAD, | |
'MINI_UNDERWEAR': wideq.STATE_WASHER_COURSE_UNDERWEAR, | |
'MINI_WOOL': wideq.STATE_WASHER_COURSE_WOOL, | |
'MINI_BOILING': wideq.STATE_WASHER_COURSE_BOILING, | |
'MINI_BABYCARE': wideq.STATE_WASHER_COURSE_BABYCARE, | |
'MINI_RINSE_SPIN': wideq.STATE_WASHER_COURSE_RINSE_SPIN, | |
'MINI_TUBCLEAN': wideq.STATE_WASHER_COURSE_TUBCLEAN, | |
'TL_NORMAL': wideq.STATE_WASHER_COURSE_NORMAL, | |
'TL_WOOL_DELICATE': wideq.STATE_WASHER_COURSE_WOOL_DELICATE, | |
'TL_SPEEDWASH': wideq.STATE_WASHER_APCOURSE_SPEEDWASH, | |
'TL_BEDDING': wideq.STATE_WASHER_COURSE_BEDDING, | |
'TL_TUBCLEAN': wideq.STATE_WASHER_COURSE_TUBCLEAN, | |
'TL_TOWEL': wideq.STATE_WASHER_COURSE_TOWEL, | |
'TL_SPORTSWEAR': wideq.STATE_WASHER_APCOURSE_UTILITY, | |
'TL_PREWASH_NORMAL': wideq.STATE_WASHER_COURSE_PREWASH_NORMAL, | |
'TL_SAFETY_NORMAL': wideq.STATE_WASHER_COURSE_SAFETY_NORMAL, | |
} | |
WASHERSMARTCOURSES = { | |
'SILENT': wideq.STATE_WASHER_SMARTCOURSE_SILENT, | |
'SMALL_LOAD': wideq.STATE_WASHER_COURSE_SMALL_LOAD, | |
'SKIN_CARE': wideq.STATE_WASHER_SMARTCOURSE_SKIN_CARE, | |
'RAINY_SEASON': wideq.STATE_WASHER_SMARTCOURSE_RAINY_SEASON, | |
'SWEAT_STAIN': wideq.STATE_WASHER_SMARTCOURSE_SWEAT_STAIN, | |
'SINGLE_GARMENT': wideq.STATE_WASHER_SMARTCOURSE_SINGLE_GARMENT, | |
'SCHOOL_UNIFORM': wideq.STATE_WASHER_SMARTCOURSE_SCHOOL_UNIFORM, | |
'STATIC_REMOVAL': wideq.STATE_WASHER_SMARTCOURSE_STATIC_REMOVAL, | |
'COLOR_CARE': wideq.STATE_WASHER_SMARTCOURSE_COLOR_CARE, | |
'SPIN_ONLY': wideq.STATE_WASHER_SMARTCOURSE_SPIN_ONLY, | |
'DEODORIZATION': wideq.STATE_WASHER_SMARTCOURSE_DEODORIZATION, | |
'BEDDING_CARE': wideq.STATE_WASHER_SMARTCOURSE_BEDDING_CARE, | |
'CLOTH_CARE': wideq.STATE_WASHER_SMARTCOURSE_CLOTH_CARE, | |
'SMART_RINSE': wideq.STATE_WASHER_SMARTCOURSE_SMART_RINSE, | |
'ECO_WASH': wideq.STATE_WASHER_SMARTCOURSE_ECO_WASH, | |
'MINIWASH_SKIN_CARE': wideq.STATE_WASHER_SMARTCOURSE_SKIN_CARE, | |
'COLD_WASH': wideq.STATE_WASHER_SMARTCOURSE_COLD_WASH, | |
'KR_COLD_WASH': wideq.STATE_WASHER_SMARTCOURSE_COLD_WASH, | |
'MINIWASH_CLOTHS_CARE': wideq.STATE_WASHER_SMARTCOURSE_CLOTH_CARE, | |
'MINIWASH_SMART_RINSE': wideq.STATE_WASHER_SMARTCOURSE_SMART_RINSE, | |
'SOILED_ITEMS': wideq.STATE_WASHER_SMARTCOURSE_SOILED_ITEMS, | |
'KR_SOILED_ITEMS': wideq.STATE_WASHER_SMARTCOURSE_SOILED_ITEMS, | |
'MINIWASH_SPIN_ONLY': wideq.STATE_WASHER_SMARTCOURSE_SPIN_ONLY, | |
'TL_SWEAT_SPOT_REMOVE': wideq.STATE_WASHER_SMARTCOURSE_SWEAT_STAIN, | |
'TL_SINGLE_SPEED': wideq.STATE_WASHER_SMARTCOURSE_SINGLE_SPEED, | |
'TL_COLOR_PROTECT': wideq.STATE_WASHER_SMARTCOURSE_COLOR_PROTECT, | |
'TL_CHILDREN_WEAR': wideq.STATE_WASHER_SMARTCOURSE_CHILDREN_WEAR, | |
'TL_RAINY_SEASON': wideq.STATE_WASHER_SMARTCOURSE_RAINY_SEASON, | |
'TL_SWIM_WEAR': wideq.STATE_WASHER_SMARTCOURSE_SWIN_WEAR, | |
'TL_CURTAINS': wideq.STATE_WASHER_SMARTCOURSE_CURTAINS, | |
'TL_JEANS': wideq.STATE_WASHER_SMARTCOURSE_JEAN, | |
'TL_LINGERIE': wideq.STATE_WASHER_SMARTCOURSE_LINGERIE, | |
'TL_FOOD_WASTE': wideq.STATE_WASHER_SMARTCOURSE_FOOD_WASTE, | |
'TL_SILENT': wideq.STATE_WASHER_SMARTCOURSE_SILENT, | |
'TL_HEAVY_SPIN': wideq.STATE_WASHER_SMARTCOURSE_HEAVY_SPIN, | |
'TL_SMALL_LOAD': wideq.STATE_WASHER_SMARTCOURSE_SMALL_LOAD, | |
'TL_BIG_LOAD': wideq.STATE_WASHER_SMARTCOURSE_BIG_LOAD, | |
} | |
WASHERRUNSTATES = { | |
'OFF': wideq.STATE_WASHER_POWER_OFF, | |
'INITIAL': wideq.STATE_WASHER_INITIAL, | |
'PAUSE': wideq.STATE_WASHER_PAUSE, | |
'ERROR_AUTO_OFF': wideq.STATE_WASHER_ERROR_AUTO_OFF, | |
'RESERVE': wideq.STATE_WASHER_RESERVE, | |
'DETECTING': wideq.STATE_WASHER_DETECTING, | |
'SOAK': wideq.STATE_WASHER_SOAK, | |
'ADD_DRAIN': wideq.STATE_WASHER_ADD_DRAIN, | |
'DETERGENT_AMOUNT': wideq.STATE_WASHER_DETERGENT_AMOUT, | |
'RUNNING': wideq.STATE_WASHER_RUNNING, | |
'PREWASH': wideq.STATE_WASHER_PREWASH, | |
'RINSING': wideq.STATE_WASHER_RINSING, | |
'RINSE_HOLD': wideq.STATE_WASHER_RINSE_HOLD, | |
'SPINNING': wideq.STATE_WASHER_SPINNING, | |
'DRYING': wideq.STATE_WASHER_DRYING, | |
'COMPLETE': wideq.STATE_WASHER_END, | |
'END': wideq.STATE_WASHER_END, | |
'FRESHCARE': wideq.STATE_WASHER_FRESHCARE, | |
'TCL_ALARM_NORMAL': wideq.STATE_WASHER_TCL_ALARM_NORMAL, | |
'FROZEN_PREVENT_INITIAL': wideq.STATE_WASHER_FROZEN_PREVENT_INITIAL, | |
'FROZEN_PREVENT_RUNNING': wideq.STATE_WASHER_FROZEN_PREVENT_RUNNING, | |
'FROZEN_PREVENT_PAUSE': wideq.STATE_WASHER_FROZEN_PREVENT_PAUSE, | |
'ERROR': wideq.STATE_WASHER_ERROR, | |
} | |
SOILLEVELSTATES = { | |
'NO_SELECT': wideq.STATE_WASHER_TERM_NO_SELECT, | |
'LIGHT': wideq.STATE_WASHER_SOILLEVEL_LIGHT, | |
'NORMAL': wideq.STATE_WASHER_SOILLEVEL_NORMAL, | |
'HEAVY': wideq.STATE_WASHER_SOILLEVEL_HEAVY, | |
'PRE_WASH': wideq.STATE_WASHER_SOILLEVEL_PRE_WASH, | |
'SOAKING': wideq.STATE_WASHER_SOILLEVEL_SOAKING, | |
'OFF': wideq.STATE_WASHER_POWER_OFF, | |
'TRHEE': wideq.STATE_WASHER_SOILLEVEL_THREE, | |
'SIX': wideq.STATE_WASHER_SOILLEVEL_SIX, | |
'TEN': wideq.STATE_WASHER_SOILLEVEL_TEN, | |
'TWELVE': wideq.STATE_WASHER_SOILLEVEL_TWELVE, | |
'FOURTEEN': wideq.STATE_WASHER_SOILLEVEL_FOURTEEN, | |
'SEVENTEEN': wideq.STATE_WASHER_SOILLEVEL_SEVENTEEN, | |
'NINETEEN': wideq.STATE_WASHER_SOILLEVEL_NINETEEN, | |
'TWENTYONE': wideq.STATE_WASHER_SOILLEVEL_TWENTYONE, | |
'TWENTYTHREE': wideq.STATE_WASHER_SOILLEVEL_TWENTYTHREE, | |
'TWENTYFIVE': wideq.STATE_WASHER_SOILLEVEL_TWENTYFIVE, | |
} | |
WATERTEMPSTATES = { | |
'NO_SELECT': wideq.STATE_WASHER_TERM_NO_SELECT, | |
'COLD' : wideq.STATE_WASHER_WATERTEMP_COLD, | |
'THIRTY' : wideq.STATE_WASHER_WATERTEMP_30, | |
'FOURTY' : wideq.STATE_WASHER_WATERTEMP_40, | |
'SIXTY': wideq.STATE_WASHER_WATERTEMP_60, | |
'NINTYFIVE': wideq.STATE_WASHER_WATERTEMP_95, | |
'OFF': wideq.STATE_WASHER_POWER_OFF, | |
'TL_COLD' : wideq.STATE_WASHER_WATERTEMP_COLD, | |
'TL_WARM': wideq.STATE_WASHER_WATERTEMP_WARM, | |
'TL_NORMAL': wideq.STATE_WASHER_WATERTEMP_NORMAL, | |
'TL_COLD_WARM': wideq.STATE_WASHER_WATERTEMP_COLD_WARM, | |
'TL_30' : wideq.STATE_WASHER_WATERTEMP_30, | |
'TL_40' : wideq.STATE_WASHER_WATERTEMP_40, | |
'TL_60' : wideq.STATE_WASHER_WATERTEMP_60, | |
'TL_90' : wideq.STATE_WASHER_WATERTEMP_90, | |
'TL_35' : wideq.STATE_WASHER_WATERTEMP_35, | |
'TL_38' : wideq.STATE_WASHER_WATERTEMP_38, | |
} | |
SPINSPEEDSTATES = { | |
'NO_SELECT': wideq.STATE_WASHER_TERM_NO_SELECT, | |
'EXTRA_LOW' : wideq.STATE_WASHER_SPINSPEED_EXTRA_LOW, | |
'LOW' : wideq.STATE_WASHER_SPINSPEED_LOW, | |
'MEDIUM' : wideq.STATE_WASHER_SPINSPEED_MEDIUM, | |
'HIGH': wideq.STATE_WASHER_SPINSPEED_HIGH, | |
'EXTRA_HIGH': wideq.STATE_WASHER_SPINSPEED_EXTRA_HIGH, | |
'OFF': wideq.STATE_WASHER_SPINSPEED_OFF, | |
'ON' : wideq.STATE_WASHER_SPINSPEED_ON, | |
'TL_LOW': wideq.STATE_WASHER_SPINSPEED_LOW, | |
'TL_MEDIUM': wideq.STATE_WASHER_SPINSPEED_MEDIUM, | |
'TL_HIGH': wideq.STATE_WASHER_SPINSPEED_HIGH, | |
'TL_ULTRA': wideq.STATE_WASHER_SPINSPEED_ULTRA, | |
'TL_DRYFIT': wideq.STATE_WASHER_SPINSPEED_DRYFIT, | |
'TL_DELICACY': wideq.STATE_WASHER_SPINSPEED_DELICACY | |
} | |
RINSECOUNTSTATES = { | |
'NO_SELECT': wideq.STATE_WASHER_TERM_NO_SELECT, | |
'ZERO': wideq.STATE_WASHER_RINSECOUNT_0, | |
'ONE' : wideq.STATE_WASHER_RINSECOUNT_1, | |
'TWO' : wideq.STATE_WASHER_RINSECOUNT_2, | |
'THREE' : wideq.STATE_WASHER_RINSECOUNT_3, | |
'FOUR': wideq.STATE_WASHER_RINSECOUNT_4, | |
'FIVE': wideq.STATE_WASHER_RINSECOUNT_5, | |
'OFF': wideq.STATE_WASHER_RINSECOUNT_OFF, | |
'MINI_0' : wideq.STATE_WASHER_TERM_NO_SELECT, | |
'MINI_1' : wideq.STATE_WASHER_RINSECOUNT_1, | |
'MINI_2' : wideq.STATE_WASHER_RINSECOUNT_2, | |
'MINI_3' : wideq.STATE_WASHER_RINSECOUNT_3, | |
'MINI_4': wideq.STATE_WASHER_RINSECOUNT_4, | |
'MINI_5': wideq.STATE_WASHER_RINSECOUNT_5, | |
'MINI_6': wideq.STATE_WASHER_RINSECOUNT_6, | |
'TL_1': wideq.STATE_WASHER_RINSECOUNT_1, | |
'TL_2': wideq.STATE_WASHER_RINSECOUNT_2, | |
'TL_3': wideq.STATE_WASHER_RINSECOUNT_3, | |
'TL_4': wideq.STATE_WASHER_RINSECOUNT_4, | |
'TL_5': wideq.STATE_WASHER_RINSECOUNT_5, | |
'TL_1_INTENSIVE': wideq.STATE_WASHER_RINSECOUNT_1_INTENSIVE, | |
'TL_2_INTENSIVE': wideq.STATE_WASHER_RINSECOUNT_2_INTENSIVE, | |
'TL_3_INTENSIVE': wideq.STATE_WASHER_RINSECOUNT_3_INTENSIVE, | |
'TL_4_INTENSIVE': wideq.STATE_WASHER_RINSECOUNT_4_INTENSIVE, | |
'TL_5_INTENSIVE': wideq.STATE_WASHER_RINSECOUNT_5_INTENSIVE, | |
} | |
DRYLEVELSTATES = { | |
'NO_SELECT': wideq.STATE_WASHER_TERM_NO_SELECT, | |
'WIND' : wideq.STATE_WASHER_DRYLEVEL_WIND, | |
'TURBO' : wideq.STATE_WASHER_DRYLEVEL_TURBO, | |
'TIME_30' : wideq.STATE_WASHER_DRYLEVEL_TIME_30, | |
'TIME_60': wideq.STATE_WASHER_DRYLEVEL_TIME_60, | |
'TIME_90': wideq.STATE_WASHER_DRYLEVEL_TIME_90, | |
'TIME_120': wideq.STATE_WASHER_DRYLEVEL_TIME_120, | |
'TIME_150': wideq.STATE_WASHER_DRYLEVEL_TIME_150, | |
'OFF': wideq.STATE_WASHER_POWER_OFF, | |
} | |
WASHERERRORS = { | |
'ERROR_dE2' : wideq.STATE_WASHER_ERROR_dE2, | |
'ERROR_IE' : wideq.STATE_WASHER_ERROR_IE, | |
'ERROR_OE' : wideq.STATE_WASHER_ERROR_OE, | |
'ERROR_UE' : wideq.STATE_WASHER_ERROR_UE, | |
'ERROR_FE' : wideq.STATE_WASHER_ERROR_FE, | |
'ERROR_PE' : wideq.STATE_WASHER_ERROR_PE, | |
'ERROR_tE' : wideq.STATE_WASHER_ERROR_tE, | |
'ERROR_LE' : wideq.STATE_WASHER_ERROR_LE, | |
'ERROR_CE' : wideq.STATE_WASHER_ERROR_CE, | |
'ERROR_PF' : wideq.STATE_WASHER_ERROR_PF, | |
'ERROR_FF' : wideq.STATE_WASHER_ERROR_FF, | |
'ERROR_dCE' : wideq.STATE_WASHER_ERROR_dCE, | |
'ERROR_EE' : wideq.STATE_WASHER_ERROR_EE, | |
'ERROR_PS' : wideq.STATE_WASHER_ERROR_PS, | |
'ERROR_dE1' : wideq.STATE_WASHER_ERROR_dE1, | |
'ERROR_LOE' : wideq.STATE_WASHER_ERROR_LOE, | |
'NO_ERROR' : wideq.STATE_NO_ERROR, | |
'OFF': wideq.STATE_DRYER_POWER_OFF, | |
'TL_ERROR_IE' : wideq.STATE_WASHER_ERROR_IE, | |
'TL_ERROR_OE' : wideq.STATE_WASHER_ERROR_OE, | |
'TL_ERROR_UE' : wideq.STATE_WASHER_ERROR_UE, | |
'TL_ERROR_DE1' : wideq.STATE_WASHER_ERROR_dE1, | |
'TL_ERROR_PE' : wideq.STATE_WASHER_ERROR_PE, | |
'TL_ERROR_DO_W' : wideq.STATE_WASHER_ERROR_TL_DO_W, | |
'TL_ERROR_LE' : wideq.STATE_WASHER_ERROR_TL_LE, | |
'TL_ERROR_AE' : wideq.STATE_WASHER_ERROR_TL_AE, | |
'TL_ERROR_TE' : wideq.STATE_WASHER_ERROR_tE, | |
'TL_ERROR_FE' : wideq.STATE_WASHER_ERROR_FE, | |
'TL_ERROR_DE2' : wideq.STATE_WASHER_ERROR_dE2, | |
'TL_ERROR_FF' : wideq.STATE_WASHER_ERROR_FF, | |
'TL_ERROR_E7' : wideq.STATE_WASHER_ERROR_E7, | |
'TL_ERROR_LE1': wideq.STATE_WASHER_ERROR_LE1, | |
'TL_ERROR_DL': wideq.STATE_WASHER_ERROR_DL, | |
'TL_ERROR_E3': wideq.STATE_WASHER_ERROR_E3, | |
} | |
WATERLEVEL = { | |
'NOT_SUPPORTED': wideq.STATE_WASHER_NOT_SUPPORTED, | |
'WLEVEL_1': wideq.STATE_WASHER_WATERLEVEL_1, | |
'WLEVEL_2': wideq.STATE_WASHER_WATERLEVEL_2, | |
'WLEVEL_3': wideq.STATE_WASHER_WATERLEVEL_3, | |
'WLEVEL_4': wideq.STATE_WASHER_WATERLEVEL_4, | |
'WLEVEL_5': wideq.STATE_WASHER_WATERLEVEL_5, | |
'WLEVEL_6': wideq.STATE_WASHER_WATERLEVEL_6, | |
'WLEVEL_7': wideq.STATE_WASHER_WATERLEVEL_7, | |
'WLEVEL_8': wideq.STATE_WASHER_WATERLEVEL_8, | |
'WLEVEL_9': wideq.STATE_WASHER_WATERLEVEL_9, | |
'WLEVEL_10': wideq.STATE_WASHER_WATERLEVEL_10, | |
} | |
WATERFLOW = { | |
'NOT_SUPPORTED': wideq.STATE_WASHER_NOT_SUPPORTED, | |
'DELICATE': wideq.STATE_WASHER_WATERFLOW_DELICATE, | |
'MEDIUM': wideq.STATE_WASHER_WATERFLOW_MEDIUM, | |
'HIGH': wideq.STATE_WASHER_WATERFLOW_HIGH, | |
} | |
SOAK = { | |
'NOT_SUPPORTED': wideq.STATE_WASHER_NOT_SUPPORTED, | |
'FIFTEEN': wideq.STATE_WASHER_SOAK_FIFTEEN, | |
'THIRTY': wideq.STATE_WASHER_SOAK_THIRTY, | |
'FOURTY': wideq.STATE_WASHER_SOAK_FOURTY, | |
'FOURTYFIVE': wideq.STATE_WASHER_SOAK_FOURTYFIVE, | |
'FIFTY': wideq.STATE_WASHER_SOAK_FIFTY, | |
'SIXTY': wideq.STATE_WASHER_SOAK_SIXTY, | |
'ONETWENTY': wideq.STATE_WASHER_SOAK_ONETWENTY, | |
'ONEEIGHTY': wideq.STATE_WASHER_SOAK_ONEEIGHTY, | |
'TWOFOURTY': wideq.STATE_WASHER_SOAK_TWOFOURTY, | |
'THREEHUNDRED': wideq.STATE_WASHER_SOAK_THREEHUNDRED, | |
'THREESIXTY': wideq.STATE_WASHER_SOAK_THREESIXTY, | |
'FOUREIGHTY': wideq.STATE_WASHER_SOAK_FOUREIGHTY, | |
'SIXHUNDRED': wideq.STATE_WASHER_SOAK_SIXHUNDRED, | |
} | |
OPTIONITEMMODES = { | |
'ON': wideq.STATE_OPTIONITEM_ON, | |
'OFF': wideq.STATE_OPTIONITEM_OFF, | |
} | |
# For DRYER | |
#----------------------------------------------------------- | |
ATTR_DRYLEVEL_STATE = 'drylevel_state' | |
ATTR_ECOHYBRID_STATAE = 'ecohybrid_state' | |
ATTR_ECOHYBRID_LIST = 'ecohybrid_list' | |
ATTR_PROCESS_STATE = 'process_state' | |
ATTR_CURRENT_SMARTCOURSE = 'current_smartcourse' | |
ATTR_ANTICREASE_MODE = 'anticrease_mode' | |
ATTR_SELFCLEANING_MODE = 'selfcleaning_mode' | |
ATTR_DAMPDRYBEEP_MODE = 'dampdrybeep_mode' | |
ATTR_HANDIRON_MODE = 'handiron_mode' | |
ATTR_RESERVE_INITIAL_TIME = 'reserve_initial_time' | |
ATTR_RESERVE_REMAIN_TIME = 'reserve_remain_time' | |
ATTR_DEVICE_TYPE = 'device_type' | |
DRYERRUNSTATES = { | |
'COOLING': wideq.STATE_DRYER_PROCESS_COOLING, | |
'OFF': wideq.STATE_DRYER_POWER_OFF, | |
'INITIAL': wideq.STATE_DRYER_INITIAL, | |
'DRYING': wideq.STATE_DRYER_DRYING, | |
'RUNNING': wideq.STATE_DRYER_RUNNING, | |
'PAUSE': wideq.STATE_DRYER_PAUSE, | |
'END': wideq.STATE_DRYER_END, | |
'ERROR': wideq.STATE_DRYER_ERROR, | |
'SMART_DIAGNOSIS': wideq.STATE_DRYER_SMART_DIAGNOSIS, | |
'WRINKLE_CARE': wideq.STATE_DRYER_WRINKLE_CARE, | |
} | |
PROCESSSTATES = { | |
'DETECTING': wideq.STATE_DRYER_PROCESS_DETECTING, | |
'STEAM': wideq.STATE_DRYER_PROCESS_STEAM, | |
'DRY': wideq.STATE_DRYER_PROCESS_DRY, | |
'COOLING': wideq.STATE_DRYER_PROCESS_COOLING, | |
'ANTI_CREASE': wideq.STATE_DRYER_PROCESS_ANTI_CREASE, | |
'END': wideq.STATE_DRYER_PROCESS_END, | |
'OFF': wideq.STATE_DRYER_POWER_OFF, | |
} | |
DRYLEVELMODES = { | |
'IRON' : wideq.STATE_DRY_LEVEL_IRON, | |
'CUPBOARD' : wideq.STATE_DRY_LEVEL_CUPBOARD, | |
'EXTRA' : wideq.STATE_DRY_LEVEL_EXTRA, | |
'OFF': wideq.STATE_DRYER_POWER_OFF, | |
'DAMP': wideq.STATE_DRY_LEVEL_DAMP, | |
'LESS': wideq.STATE_DRY_LEVEL_LESS, | |
'NORMAL': wideq.STATE_DRY_LEVEL_NORMAL, | |
'MORE' : wideq.STATE_DRY_LEVEL_MORE, | |
'VERY': wideq.STATE_DRY_LEVEL_VERY, | |
} | |
ECOHYBRIDMODES = { | |
'ECO' : wideq.STATE_ECOHYBRID_ECO, | |
'NORMAL' : wideq.STATE_ECOHYBRID_NORMAL, | |
'TURBO' : wideq.STATE_ECOHYBRID_TURBO, | |
'OFF': wideq.STATE_DRYER_POWER_OFF, | |
} | |
COURSES = { | |
'Cotton Soft' : wideq.STATE_COURSE_COTTON_SOFT, | |
'Bulky Item' : wideq.STATE_COURSE_BULKY_ITEM, | |
'Easy Care' : wideq.STATE_COURSE_EASY_CARE, | |
'Cotton' : wideq.STATE_COURSE_COTTON, | |
'Sports Wear' : wideq.STATE_COURSE_SPORTS_WEAR, | |
'Quick Dry' : wideq.STATE_COURSE_QUICK_DRY, | |
'Wool' : wideq.STATE_COURSE_WOOL, | |
'Rack Dry' : wideq.STATE_COURSE_RACK_DRY, | |
'Cool Air' : wideq.STATE_COURSE_COOL_AIR, | |
'Warm Air' : wideq.STATE_COURSE_WARM_AIR, | |
'Bedding' : wideq.STATE_COURSE_BEDDING_BRUSH, | |
'Sterilization' : wideq.STATE_COURSE_STERILIZATION, | |
'Speed Dry': wideq.STATE_COURSE_SPEED_DRY, | |
'Power' : wideq.STATE_COURSE_POWER, | |
'Refresh': wideq.STATE_COURSE_REFRESH, | |
'OFF': wideq.STATE_DRYER_POWER_OFF, | |
'Normal': wideq.STATE_COURSE_NORMAL, | |
'Heavy Duty': wideq.STATE_COURSE_HEAVY_DUTY, | |
'Towels': wideq.STATE_COURSE_TOWELS, | |
'PermPress': wideq.STATE_COURSE_PERM_PRESS, | |
'Delicates': wideq.STATE_COURSE_DELICATES, | |
'Bedding / Bulky Large': wideq.STATE_COURSE_BEDDING, | |
'Anti Bacterial': wideq.STATE_COURSE_ANTI_BACTERIAL, | |
'Air Dry': wideq.STATE_COURSE_AIR_DRY, | |
'Steam Fresh': wideq.STATE_COURSE_STEAM_FRESH, | |
'Steam Sanitary': wideq.STATE_COURSE_STEAM_SANITARY, | |
'Time Dry': wideq.STATE_COURSE_TIME_DRY, | |
} | |
SMARTCOURSES = { | |
'Gym Clothes' : wideq.STATE_SMARTCOURSE_GYM_CLOTHES, | |
'Rainy Season' : wideq.STATE_SMARTCOURSE_RAINY_SEASON, | |
'Deodorization' : wideq.STATE_SMARTCOURSE_DEODORIZATION, | |
'Small Load' : wideq.STATE_SMARTCOURSE_SMALL_LOAD, | |
'Lingerie' : wideq.STATE_SMARTCOURSE_LINGERIE, | |
'Easy Iron' : wideq.STATE_SMARTCOURSE_EASY_IRON, | |
'SUPER_DRY' : wideq.STATE_SMARTCOURSE_SUPER_DRY, | |
'Economic Dry' : wideq.STATE_SMARTCOURSE_ECONOMIC_DRY, | |
'Big Size Item' : wideq.STATE_SMARTCOURSE_BIG_SIZE_ITEM, | |
'Minimize Wrinkles' : wideq.STATE_SMARTCOURSE_MINIMIZE_WRINKLES, | |
'Full Size Load' : wideq.STATE_SMARTCOURSE_FULL_SIZE_LOAD, | |
'Jean' : wideq.STATE_SMARTCOURSE_JEAN, | |
'OFF': wideq.STATE_DRYER_POWER_OFF, | |
} | |
DRYERERRORS = { | |
'ERROR_DOOR' : wideq.STATE_ERROR_DOOR, | |
'ERROR_DRAINMOTOR' : wideq.STATE_ERROR_DRAINMOTOR, | |
'ERROR_LE1' : wideq.STATE_ERROR_LE1, | |
'ERROR_TE1' : wideq.STATE_ERROR_TE1, | |
'ERROR_TE2' : wideq.STATE_ERROR_TE2, | |
'ERROR_TE5' : wideq.STATE_ERROR_TE5, | |
'ERROR_TE6' : wideq.STATE_ERROR_TE6, | |
'ERROR_PS': wideq.STATE_ERROR_PS, | |
'ERROR_NP': wideq.STATE_ERROR_NP, | |
'ERROR_F1' : wideq.STATE_ERROR_F1, | |
'ERROR_LE2' : wideq.STATE_ERROR_LE2, | |
'ERROR_AE' : wideq.STATE_ERROR_AE, | |
'ERROR_dE4' : wideq.STATE_ERROR_dE4, | |
'ERROR_NOFILTER' : wideq.STATE_ERROR_NOFILTER, | |
'ERROR_EMPTYWATER' : wideq.STATE_ERROR_EMPTYWATER, | |
'ERROR_CE1' : wideq.STATE_ERROR_CE1, | |
'NO_ERROR' : wideq.STATE_NO_ERROR, | |
'OFF': wideq.STATE_DRYER_POWER_OFF, | |
} | |
OPTIONITEMMODES = { | |
'ON': wideq.STATE_OPTIONITEM_ON, | |
'OFF': wideq.STATE_OPTIONITEM_OFF, | |
} | |
# For WATER PURIFIER | |
#----------------------------------------------------------- | |
ATTR_COLD_WATER_USAGE_DAY = 'cold_water_usage_day' | |
ATTR_NORMAL_WATER_USAGE_DAY = 'normal_water_usage_day' | |
ATTR_HOT_WATER_USAGE_DAY = 'hot_water_usage_day' | |
ATTR_TOTAL_WATER_USAGE_DAY = 'total_water_usage_day' | |
ATTR_COLD_WATER_USAGE_WEEK = 'cold_water_usage_week' | |
ATTR_NORMAL_WATER_USAGE_WEEK = 'normal_water_usage_week' | |
ATTR_HOT_WATER_USAGE_WEEK = 'hot_water_usage_week' | |
ATTR_TOTAL_WATER_USAGE_WEEK = 'total_water_usage_week' | |
ATTR_COLD_WATER_USAGE_MONTH = 'cold_water_usage_month' | |
ATTR_NORMAL_WATER_USAGE_MONTH = 'normal_water_usage_month' | |
ATTR_HOT_WATER_USAGE_MONTH = 'hot_water_usage_month' | |
ATTR_TOTAL_WATER_USAGE_MONTH = 'total_water_usage_month' | |
ATTR_COLD_WATER_USAGE_YEAR = 'cold_water_usage_year' | |
ATTR_NORMAL_WATER_USAGE_YEAR = 'normal_water_usage_year' | |
ATTR_HOT_WATER_USAGE_YEAR = 'hot_water_usage_year' | |
ATTR_TOTAL_WATER_USAGE_YEAR = 'total_water_usage_year' | |
ATTR_COCKCLEAN_STATE = 'cockcelan_state' | |
ATTR_DEVICE_TYPE = 'device_type' | |
COCKCLEANMODES = { | |
'WAITING': wideq.STATE_WATERPURIFIER_COCKCLEAN_WAIT, | |
'COCKCLEANING': wideq.STATE_WATERPURIFIER_COCKCLEAN_ON, | |
} | |
MAX_RETRIES = 5 | |
LOGGER = logging.getLogger(__name__) | |
def setup_platform(hass, config, add_entities, discovery_info=None): | |
import wideq | |
refresh_token = hass.data[CONF_TOKEN] | |
client = wideq.Client.from_token(refresh_token) | |
name = config[CONF_NAME] | |
conf_mac = config[CONF_MAC] | |
"""Set up the LGE entity.""" | |
for device_id in hass.data[LGE_DEVICES]: | |
device = client.get_device(device_id) | |
model = client.model_info(device) | |
model_type = model.model_type | |
mac = device.macaddress | |
if device.type == wideq.DeviceType.WASHER: | |
LGE_WASHER_DEVICES = [] | |
if mac == conf_mac.lower(): | |
LOGGER.debug("Creating new LGE Washer") | |
washer_entity = LGEWASHERDEVICE(client, device, name, model_type) | |
LGE_WASHER_DEVICES.append(washer_entity) | |
add_entities(LGE_WASHER_DEVICES) | |
LOGGER.debug("LGE Washer is added") | |
if device.type == wideq.DeviceType.DRYER: | |
LGE_DRYER_DEVICES = [] | |
if mac == conf_mac.lower(): | |
LOGGER.debug("Creating new LGE Dryer") | |
dryer_entity = LGEDRYERDEVICE(client, device, name, model_type) | |
LGE_DRYER_DEVICES.append(dryer_entity) | |
add_entities(LGE_DRYER_DEVICES) | |
LOGGER.debug("LGE Dryer is added") | |
if device.type == wideq.DeviceType.WATER_PURIFIER: | |
LGE_WATERPURIFIER_DEVICES = [] | |
if mac == conf_mac.lower(): | |
waterpurifier_entity = LGEWATERPURIFIERDEVICE(client, device, name, model_type) | |
LGE_WATERPURIFIER_DEVICES.append(waterpurifier_entity) | |
add_entities(LGE_WATERPURIFIER_DEVICES) | |
LOGGER.debug("LGE WATER PURIFIER is added") | |
# WASHER Main | |
class LGEWASHERDEVICE(LGEDevice): | |
def __init__(self, client, device, name, model_type): | |
"""initialize a LGE Washer Device.""" | |
LGEDevice.__init__(self, client, device) | |
import wideq | |
self._washer = wideq.WasherDevice(client, device) | |
self._washer.monitor_start(raise_error=False) | |
self._washer.delete_permission(raise_error=False) | |
# The response from the monitoring query. | |
self._state = None | |
self._name = name | |
self._type = model_type | |
self.update() | |
@property | |
def name(self): | |
return self._name | |
@property | |
def device_type(self): | |
return self._type | |
@property | |
def supported_features(self): | |
""" none """ | |
@property | |
def state_attributes(self): | |
"""Return the optional state attributes.""" | |
data={} | |
data[ATTR_DEVICE_TYPE] = self.device_type | |
data[ATTR_RUN_STATE] = self.current_run_state | |
data[ATTR_PRE_STATE] = self.pre_state | |
data[ATTR_REMAIN_TIME] = self.remain_time | |
data[ATTR_INITIAL_TIME] = self.initial_time | |
data[ATTR_RESERVE_TIME] = self.reserve_time | |
data[ATTR_CURRENT_COURSE] = self.current_course | |
data[ATTR_ERROR_STATE] = self.error_state | |
data[ATTR_WASH_OPTION_STATE] = self.wash_option_state | |
data[ATTR_SPIN_OPTION_STATE] = self.spin_option_state | |
data[ATTR_WATERTEMP_OPTION_STATE] = self.watertemp_option_state | |
data[ATTR_RINSECOUNT_OPTION_STATE] = self.rinsecount_option_state | |
if self.device_type == 'TL': | |
if self.waterlevel_state != 'NOT_SUPPORTED': | |
data[ATTR_WATERLEVEL_STATE] = self.waterlevel_state | |
if self.waterflow_state != 'NOT_SUPPORTED': | |
data[ATTR_WATERFLOW_STATE] = self.waterflow_state | |
if self.soak_state != 'NOT_SUPPORTED': | |
data[ATTR_SOAK_STATE] = self.soak_state | |
if self.device_type == 'FL': | |
data[ATTR_DRYLEVEL_STATE] = self.drylevel_state | |
data[ATTR_LOAD_LEVEL] = self.load_level | |
data[ATTR_FRESHCARE_MODE] = self.freshcare_mode | |
data[ATTR_TUBCLEAN_COUNT] = self.tubclean_count | |
data[ATTR_CHILDLOCK_MODE] = self.childlock_mode | |
data[ATTR_STEAM_MODE] = self.steam_mode | |
data[ATTR_TURBOSHOT_MODE] = self.turboshot_mode | |
if self.device_type == 'TL': | |
data[ATTR_DOORLOCK_MODE] = self.doorlock_mode | |
data[ATTR_BUZZER_MODE] = self.buzzer_mode | |
data[ATTR_STERILIZE_MODE] = self.sterilize_mode | |
data[ATTR_HEATER_MODE] = self.heater_mode | |
return data | |
@property | |
def state(self): | |
if self._state: | |
run = self._state.run_state | |
return WASHERRUNSTATES[run.name] | |
return 'unavailable' | |
@property | |
def current_run_state(self): | |
if self._state: | |
run = self._state.run_state | |
return WASHERRUNSTATES[run.name] | |
@property | |
def pre_state(self): | |
if self._state: | |
pre = self._state.pre_state | |
return WASHERRUNSTATES[pre.name] | |
@property | |
def remain_time(self): | |
if self._state: | |
remain_hour = self._state.remaintime_hour | |
remain_min = self._state.remaintime_min | |
remaintime = [remain_hour, remain_min] | |
if int(remain_min) < 10: | |
return ":0".join(remaintime) | |
else: | |
return ":".join(remaintime) | |
@property | |
def initial_time(self): | |
if self._state: | |
initial_hour = self._state.initialtime_hour | |
initial_min = self._state.initialtime_min | |
initialtime = [initial_hour, initial_min] | |
if self.state == 'OFF': | |
return "0:00" | |
else: | |
if int(initial_min) < 10: | |
return ":0".join(initialtime) | |
else: | |
return ":".join(initialtime) | |
@property | |
def reserve_time(self): | |
if self._state: | |
reserve_hour = self._state.reservetime_hour | |
reserve_min = self._state.reservetime_min | |
reservetime = [reserve_hour, reserve_min] | |
if self.state == 'OFF': | |
return "0:00" | |
else: | |
if int(reserve_min) < 10: | |
return ":0".join(reservetime) | |
else: | |
return ":".join(reservetime) | |
@property | |
def current_course(self): | |
if self._state: | |
course = self._state.current_course(self.device_type) | |
smartcourse = self._state.current_smartcourse | |
if course == '다운로드코스': | |
return WASHERSMARTCOURSES[smartcourse.name] | |
elif course == 'OFF': | |
return 'OFF' | |
else: | |
return WASHERCOURSES[course.name] | |
@property | |
def error_state(self): | |
if self._state: | |
error = self._state.error_state | |
return WASHERERRORS[error] | |
@property | |
def wash_option_state(self): | |
if self._state: | |
wash_option = self._state.wash_option_state | |
if wash_option == 'OFF': | |
return SOILLEVELSTATES['OFF'] | |
else: | |
return SOILLEVELSTATES[wash_option.name] | |
@property | |
def spin_option_state(self): | |
if self._state: | |
spin_option = self._state.spin_option_state | |
if spin_option == 'OFF': | |
return SPINSPEEDSTATES['OFF'] | |
else: | |
return SPINSPEEDSTATES[spin_option.name] | |
@property | |
def watertemp_option_state(self): | |
if self._state: | |
state = self._state | |
watertemp_option = self._state.water_temp_option_state(self.device_type) | |
if watertemp_option == 'OFF': | |
return WATERTEMPSTATES['OFF'] | |
else: | |
return WATERTEMPSTATES[watertemp_option.name] | |
@property | |
def rinsecount_option_state(self): | |
if self._state: | |
rinsecount_option = self._state.rinsecount_option_state | |
if rinsecount_option == 'OFF': | |
return RINSECOUNTSTATES['OFF'] | |
else: | |
return RINSECOUNTSTATES[rinsecount_option.name] | |
@property | |
def drylevel_state(self): | |
if self._state: | |
drylevel = self._state.drylevel_option_state | |
if drylevel == 'OFF': | |
return DRYLEVELSTATES['OFF'] | |
else: | |
return DRYLEVELSTATES[drylevel.name] | |
@property | |
def waterlevel_state(self): | |
if self._state: | |
waterlevel = self._state.waterlevel_option_state | |
return WATERLEVEL[waterlevel.name] | |
@property | |
def waterflow_state(self): | |
if self._state: | |
waterflow = self._state.waterflow_option_state | |
return WATERFLOW[waterflow.name] | |
@property | |
def soak_state(self): | |
if self._state: | |
soak = self._state.soak_option_state | |
return SOAK[soak.name] | |
@property | |
def freshcare_mode(self): | |
if self._state: | |
mode = self._state.freshcare_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def childlock_mode(self): | |
if self._state: | |
mode = self._state.childlock_state(self.device_type) | |
return OPTIONITEMMODES[mode] | |
@property | |
def steam_mode(self): | |
if self._state: | |
state = self._state | |
mode = self._state.steam_state(self.device_type) | |
return OPTIONITEMMODES[mode] | |
@property | |
def turboshot_mode(self): | |
if self._state: | |
state = self._state | |
mode = self._state.turboshot_state(self.device_type) | |
return OPTIONITEMMODES[mode] | |
@property | |
def doorlock_mode(self): | |
if self._state: | |
mode = self._state.doorlock_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def buzzer_mode(self): | |
if self._state: | |
mode = self._state.buzzer_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def sterilize_mode(self): | |
if self._state: | |
mode = self._state.sterilize_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def heater_mode(self): | |
if self._state: | |
mode = self._state.heater_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def tubclean_count(self): | |
if self._state: | |
return self._state.tubclean_count | |
@property | |
def load_level(self): | |
if self._state: | |
load_level = self._state.load_level | |
if load_level == 1: | |
return 'Washing' | |
elif load_level == 2: | |
return 'Low' | |
elif load_level == 3: | |
return 'Medium' | |
elif load_level == 4: | |
return 'Heavy' | |
else: | |
return 'None' | |
def update(self): | |
import wideq | |
LOGGER.info('Updating %s.', self.name) | |
for iteration in range(MAX_RETRIES): | |
LOGGER.info('Polling...') | |
if self.state == 'unavailable': | |
# If the washer is unavailible, try to connect again. | |
# If successful, try updating the state again. If not, skip | |
# doing the udpate, this means the washer is not turned on. | |
try: | |
self._washer.monitor_start() | |
self._washer.delete_permission() | |
except wideq.NotConnectError: | |
return | |
except wideq.NotLoggedInError: | |
self._client.refresh() | |
continue | |
try: | |
state = self._washer.poll() | |
except wideq.NotLoggedInError: | |
LOGGER.info('Session expired. Refreshing.') | |
self._client.refresh() | |
self._washer.monitor_start() | |
self._washer.monitor_start() | |
self._washer.delete_permission() | |
self._washer.delete_permission() | |
continue | |
except wideq.NotConnectError: | |
self._state = None | |
return | |
if state: | |
LOGGER.info('Status updated.') | |
self._state = state | |
self._client.refresh() | |
self._washer.monitor_start() | |
self._washer.monitor_start() | |
self._washer.delete_permission() | |
self._washer.delete_permission() | |
return | |
LOGGER.info('No status available yet.') | |
time.sleep(2 ** iteration) | |
# We tried several times but got no result. This might happen | |
# when the monitoring request gets into a bad state, so we | |
# restart the task. | |
LOGGER.warn('Status update failed.') | |
self._washer.monitor_start() | |
self._washer.monitor_start() | |
self._washer.delete_permission() | |
self._washer.delete_permission() | |
# DRYER Main | |
class LGEDRYERDEVICE(LGEDevice): | |
def __init__(self, client, device, name, model_type): | |
"""initialize a LGE Dryer Device.""" | |
LGEDevice.__init__(self, client, device) | |
import wideq | |
self._dryer = wideq.DryerDevice(client, device) | |
self._dryer.monitor_start() | |
self._dryer.monitor_start() | |
self._dryer.delete_permission() | |
self._dryer.delete_permission() | |
# The response from the monitoring query. | |
self._state = None | |
self._name = name | |
self._type = model_type | |
self.update() | |
@property | |
def name(self): | |
return self._name | |
@property | |
def device_type(self): | |
return self._type | |
@property | |
def supported_features(self): | |
""" none """ | |
@property | |
def state_attributes(self): | |
"""Return the optional state attributes.""" | |
data={} | |
data[ATTR_DEVICE_TYPE] = self.device_type | |
data[ATTR_RUN_STATE] = self.current_run_state | |
data[ATTR_REMAIN_TIME] = self.remain_time | |
data[ATTR_INITIAL_TIME] = self.initial_time | |
data[ATTR_RESERVE_REMAIN_TIME] = self.reserve_remain_time | |
data[ATTR_RESERVE_INITIAL_TIME] = self.reserve_initial_time | |
data[ATTR_CURRENT_COURSE] = self.current_course | |
data[ATTR_CURRENT_SMARTCOURSE] = self.current_smartcourse | |
data[ATTR_ERROR_STATE] = self.error_state | |
data[ATTR_DRYLEVEL_STATE] = self.drylevel_state | |
data[ATTR_ECOHYBRID_STATAE] = self.ecohybrid_state | |
data[ATTR_PROCESS_STATE] = self.current_process_state | |
data[ATTR_ANTICREASE_MODE] = self.anticrease_mode | |
data[ATTR_CHILDLOCK_MODE] = self.childlock_mode | |
data[ATTR_SELFCLEANING_MODE] = self.selfcleaning_mode | |
data[ATTR_DAMPDRYBEEP_MODE] = self.dampdrybeep_mode | |
data[ATTR_HANDIRON_MODE] = self.handiron_mode | |
return data | |
@property | |
def is_on(self): | |
if self._state: | |
return self._state.is_on | |
@property | |
def state(self): | |
if self._state: | |
run = self._state.run_state | |
return DRYERRUNSTATES[run.name] | |
@property | |
def current_run_state(self): | |
if self._state: | |
run = self._state.run_state | |
return DRYERRUNSTATES[run.name] | |
@property | |
def remain_time(self): | |
if self._state: | |
remain_hour = self._state.remaintime_hour | |
remain_min = self._state.remaintime_min | |
remaintime = [remain_hour, remain_min] | |
if int(remain_min) < 10: | |
return ":0".join(remaintime) | |
else: | |
return ":".join(remaintime) | |
@property | |
def initial_time(self): | |
if self._state: | |
initial_hour = self._state.initialtime_hour | |
initial_min = self._state.initialtime_min | |
initialtime = [initial_hour, initial_min] | |
if int(initial_min) < 10: | |
return ":0".join(initialtime) | |
else: | |
return ":".join(initialtime) | |
@property | |
def reserve_remain_time(self): | |
if self._state: | |
reserve_hour = self._state.reservetime_hour | |
reserve_min = self._state.reservetime_min | |
reservetime = [reserve_hour, reserve_min] | |
if int(reserve_min) < 10: | |
return ":0".join(reservetime) | |
else: | |
return ":".join(reservetime) | |
@property | |
def reserve_initial_time(self): | |
if self._state: | |
reserveinitial_hour = self._state.reserveinitialtime_hour | |
reserveinitial_min = self._state.reserveinitialtime_min | |
reserveinitialtime = [reserveinitial_hour, reserveinitial_min] | |
if int(reserveinitial_min) < 10: | |
return ":0".join(reserveinitialtime) | |
else: | |
return ":".join(reserveinitialtime) | |
@property | |
def current_course(self): | |
if self._state: | |
course = self._state.current_course | |
return COURSES[course] | |
@property | |
def current_smartcourse(self): | |
if self._state: | |
smartcourse = self._state.current_smartcourse | |
return SMARTCOURSES[smartcourse] | |
@property | |
def error_state(self): | |
if self._state: | |
error = self._state.error_state | |
return DRYERERRORS[error] | |
@property | |
def drylevel_state(self): | |
if self._state: | |
drylevel = self._state.drylevel_state | |
if drylevel == 'OFF': | |
return DRYLEVELMODES['OFF'] | |
else: | |
return DRYLEVELMODES[drylevel.name] | |
@property | |
def ecohybrid_state(self): | |
if self._state: | |
ecohybrid = self._state.ecohybrid_state | |
if ecohybrid == 'OFF': | |
return ECOHYBRIDMODES['OFF'] | |
else: | |
return ECOHYBRIDMODES[ecohybrid.name] | |
@property | |
def current_process_state(self): | |
if self._state: | |
process = self._state.process_state | |
if self.is_on == False: | |
return PROCESSSTATES['OFF'] | |
else: | |
return PROCESSSTATES[process.name] | |
@property | |
def anticrease_mode(self): | |
if self._state: | |
mode = self._state.anticrease_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def childlock_mode(self): | |
if self._state: | |
mode = self._state.childlock_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def selfcleaning_mode(self): | |
if self._state: | |
mode = self._state.selfcleaning_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def dampdrybeep_mode(self): | |
if self._state: | |
mode = self._state.dampdrybeep_state | |
return OPTIONITEMMODES[mode] | |
@property | |
def handiron_mode(self): | |
if self._state: | |
mode = self._state.handiron_state | |
return OPTIONITEMMODES[mode] | |
def update(self): | |
import wideq | |
LOGGER.info('Updating %s.', self.name) | |
for iteration in range(MAX_RETRIES): | |
LOGGER.info('Polling...') | |
try: | |
state = self._dryer.poll() | |
except wideq.NotLoggedInError: | |
LOGGER.info('Session expired. Refreshing.') | |
self._client.refresh() | |
self._dryer.monitor_start() | |
self._dryer.monitor_start() | |
self._dryer.delete_permission() | |
self._dryer.delete_permission() | |
continue | |
if state: | |
LOGGER.info('Status updated.') | |
self._state = state | |
self._client.refresh() | |
self._dryer.monitor_start() | |
self._dryer.monitor_start() | |
self._dryer.delete_permission() | |
self._dryer.delete_permission() | |
return | |
LOGGER.info('No status available yet.') | |
time.sleep(2 ** iteration) | |
# We tried several times but got no result. This might happen | |
# when the monitoring request gets into a bad state, so we | |
# restart the task. | |
LOGGER.warn('Status update failed.') | |
self._dryer.monitor_start() | |
self._dryer.monitor_start() | |
self._dryer.delete_permission() | |
self._dryer.delete_permission() | |
# WATER PURIFIER Main | |
class LGEWATERPURIFIERDEVICE(LGEDevice): | |
def __init__(self, client, device, name, model_type): | |
"""initialize a LGE WATER PURIFIER Device.""" | |
LGEDevice.__init__(self, client, device) | |
import wideq | |
self._wp = wideq.WPDevice(client, device) | |
self._wp.monitor_start() | |
self._wp.monitor_start() | |
self._wp.delete_permission() | |
self._wp.delete_permission() | |
# The response from the monitoring query. | |
self._state = None | |
self._name = name | |
self._type = model_type | |
self.update() | |
@property | |
def name(self): | |
return self._name | |
@property | |
def device_type(self): | |
return self._type | |
@property | |
def supported_features(self): | |
""" none """ | |
@property | |
def state_attributes(self): | |
"""Return the optional state attributes.""" | |
data={} | |
data[ATTR_DEVICE_TYPE] = self.device_type | |
data[ATTR_COLD_WATER_USAGE_DAY] = self.cold_water_usage_day | |
data[ATTR_NORMAL_WATER_USAGE_DAY] = self.normal_water_usage_day | |
data[ATTR_HOT_WATER_USAGE_DAY] = self.hot_water_usage_day | |
data[ATTR_TOTAL_WATER_USAGE_DAY] = self.total_water_usage_day | |
data[ATTR_COLD_WATER_USAGE_WEEK] = self.cold_water_usage_week | |
data[ATTR_NORMAL_WATER_USAGE_WEEK] = self.normal_water_usage_week | |
data[ATTR_HOT_WATER_USAGE_WEEK] = self.hot_water_usage_week | |
data[ATTR_TOTAL_WATER_USAGE_WEEK] = self.total_water_usage_week | |
data[ATTR_COLD_WATER_USAGE_MONTH] = self.cold_water_usage_month | |
data[ATTR_NORMAL_WATER_USAGE_MONTH] = self.normal_water_usage_month | |
data[ATTR_HOT_WATER_USAGE_MONTH] = self.hot_water_usage_month | |
data[ATTR_TOTAL_WATER_USAGE_MONTH] = self.total_water_usage_month | |
data[ATTR_COLD_WATER_USAGE_YEAR] = self.cold_water_usage_year | |
data[ATTR_NORMAL_WATER_USAGE_YEAR] = self.normal_water_usage_year | |
data[ATTR_HOT_WATER_USAGE_YEAR] = self.hot_water_usage_year | |
data[ATTR_TOTAL_WATER_USAGE_YEAR] = self.total_water_usage_year | |
data[ATTR_COCKCLEAN_STATE] = self.cockclean_status | |
return data | |
@property | |
def state(self): | |
if self._state: | |
mode = self._state.cockclean_state | |
return COCKCLEANMODES[mode.name] | |
else: | |
return 'OFF' | |
@property | |
def cold_water_usage_day(self): | |
data = self._wp.day_water_usage('C') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def normal_water_usage_day(self): | |
data = self._wp.day_water_usage('N') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def hot_water_usage_day(self): | |
data = self._wp.day_water_usage('H') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def total_water_usage_day(self): | |
cold = self.cold_water_usage_day | |
normal = self.normal_water_usage_day | |
hot = self.hot_water_usage_day | |
total = format((float(cold) + float(normal) + float(hot)), ".3f") | |
return total | |
@property | |
def cold_water_usage_week(self): | |
data = self._wp.week_water_usage('C') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def normal_water_usage_week(self): | |
data = self._wp.week_water_usage('N') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def hot_water_usage_week(self): | |
data = self._wp.week_water_usage('H') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def total_water_usage_week(self): | |
cold = self.cold_water_usage_week | |
normal = self.normal_water_usage_week | |
hot = self.hot_water_usage_week | |
total = format((float(cold) + float(normal) + float(hot)), ".3f") | |
return total | |
@property | |
def cold_water_usage_month(self): | |
data = self._wp.month_water_usage('C') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def normal_water_usage_month(self): | |
data = self._wp.month_water_usage('N') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def hot_water_usage_month(self): | |
data = self._wp.month_water_usage('H') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def total_water_usage_month(self): | |
cold = self.cold_water_usage_month | |
normal = self.normal_water_usage_month | |
hot = self.hot_water_usage_month | |
total = format((float(cold) + float(normal) + float(hot)), ".3f") | |
return total | |
@property | |
def cold_water_usage_year(self): | |
data = self._wp.year_water_usage('C') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def normal_water_usage_year(self): | |
data = self._wp.year_water_usage('N') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def hot_water_usage_year(self): | |
data = self._wp.year_water_usage('H') | |
usage = format((float(data) * 0.001), ".3f") | |
return usage | |
@property | |
def total_water_usage_year(self): | |
cold = self.cold_water_usage_year | |
normal = self.normal_water_usage_year | |
hot = self.hot_water_usage_year | |
total = format((float(cold) + float(normal) + float(hot)), ".3f") | |
return total | |
@property | |
def cockclean_status(self): | |
if self._state: | |
mode = self._state.cockclean_state | |
return COCKCLEANMODES[mode.name] | |
def update(self): | |
import wideq | |
LOGGER.info('Updating %s.', self.name) | |
for iteration in range(MAX_RETRIES): | |
LOGGER.info('Polling...') | |
try: | |
state = self._wp.poll() | |
except wideq.NotLoggedInError: | |
LOGGER.info('Session expired. Refreshing.') | |
self._client.refresh() | |
self._wp.monitor_start() | |
self._wp.monitor_start() | |
self._wp.delete_permission() | |
self._wp.delete_permission() | |
continue | |
if state: | |
LOGGER.info('Status updated.') | |
self._state = state | |
self._client.refresh() | |
self._wp.monitor_start() | |
self._wp.monitor_start() | |
self._wp.delete_permission() | |
self._wp.delete_permission() | |
return | |
LOGGER.info('No status available yet.') | |
time.sleep(2 ** iteration) | |
# We tried several times but got no result. This might happen | |
# when the monitoring request gets into a bad state, so we | |
# restart the task. | |
LOGGER.warn('Status update failed.') | |
self._wp.monitor_start() | |
self._wp.monitor_start() | |
self._wp.delete_permission() | |
self._wp.delete_permission() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Describes the format for available LGE HVAC services | |
lge_hvac_set_airclean_mode: | |
description: Set the hvac in airclen mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable airclean mode | |
example: 'climate.air_conditioner' | |
airclean_mode: | |
description: AirClean mode status | |
example: 'ON' | |
lge_hvac_set_coolpower_mode: | |
description: Set the hvac in coolpower mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable coolpower mode | |
example: 'climate.air_conditioner' | |
coolpower_mode: | |
description: CoolPower mode status | |
example: 'ON' | |
lge_hvac_set_autodry_mode: | |
description: Set the hvac in autodry mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable autodry mode | |
example: 'climate.air_conditioner' | |
autodry_mode: | |
description: AutoDry mode status | |
example: 'ON' | |
lge_hvac_set_smartcare_mode: | |
description: Set the hvac in smartcare mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable smartcare mode | |
example: 'climate.air_conditioner' | |
smartcare_mode: | |
description: SmartCare mode status | |
example: 'ON' | |
lge_hvac_set_powersave_mode: | |
description: Set the hvac in powersave mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable powersave mode | |
example: 'climate.air_conditioner' | |
powersave_mode: | |
description: PowerSave mode status | |
example: 'ON' | |
lge_hvac_set_longpower_mode: | |
description: Set the hvac in longpower mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable longpower mode | |
example: 'climate.air_conditioner' | |
longpower_mode: | |
description: LongPower mode status | |
example: 'ON' | |
lge_hvac_set_up_down_mode: | |
description: Set the hvac in up/down mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable up/down mode | |
example: 'climate.air_conditioner' | |
up_down_mode: | |
description: up/down mode status | |
example: 'ON' | |
lge_hvac_set_sensormon_mode: | |
description: Set the hvac in sensormon mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable sensormon mode | |
example: 'climate.air_conditioner' | |
sensormon_mode: | |
description: sensormon mode status | |
example: 'ON' | |
lge_hvac_set_jet_mode: | |
description: Set the hvac in jet mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable jet mode | |
example: 'climate.air_conditioner' | |
jet_mode: | |
description: jet mode status | |
example: 'ON' | |
lge_hvac_set_wdirhstep_mode: | |
description: Set the hvac in wdirhstep mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable wdirhstep mode | |
example: 'climate.air_conditioner' | |
wdirhstep_mode: | |
description: wdirhstep mode status | |
example: '1단계' | |
lge_hvac_set_wdirvstep_mode: | |
description: Set the hvac in wdirvstep mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable wdirvstep mode | |
example: 'climate.air_conditioner' | |
wdirvstep_mode: | |
description: wdirvstep mode status | |
example: '1단계' | |
lge_hvac_set_wswirl_mode: | |
description: Set the hvac in wswirl mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to enable/disable wswirl mode | |
example: 'climate.air_conditioner' | |
wswirl_mode: | |
description: wswirl mode status | |
example: 'ON' | |
lge_hvac_set_sleep_timer: | |
description: Set the hvac in sleep timer | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set sleep timer | |
example: 'climate.air_conditioner' | |
sleep_time: | |
description: sleep time | |
example: '30' | |
# Describes the format for available LGE Refrigerator services | |
lge_ref_set_refrigerator_temperature: | |
description: Set the refrigerator temperature. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set refrigerator temperature | |
example: 'climate.refrigerator' | |
refrigerator_temperature: | |
description: refrigerator_temperature | |
example: '3' | |
lge_ref_set_freezer_temperature: | |
description: Set the freezer temperature. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set freezer temperature | |
example: 'climate.refrigerator' | |
freezer_temperature: | |
description: freezer_temperature | |
example: '-18' | |
lge_ref_set_iceplus_mode: | |
description: Set the iceplus mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set iceplus mode | |
example: 'climate.refrigerator' | |
iceplus_mode: | |
description: iceplus_mode | |
example: 'ON' | |
lge_ref_set_freshairfilter_mode: | |
description: Set the freshairfilter mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set freshairfilter mode | |
example: 'climate.refrigerator' | |
freshairfilter_mode: | |
description: freshairfilter_mode | |
example: 'AUTO' | |
# Describes the format for available LGE Dehumidifier services | |
lge_dehumidifier_set_airremoval_mode: | |
description: Set the airrrmoval mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set airremoval mode | |
example: 'climate.dehumidifier' | |
airremoval_mode: | |
description: airremoval_mode | |
example: '켜짐' | |
# Describes the format for available LGE AirPurifier services | |
lge_airpurifier_set_airremoval_mode: | |
description: Set the airrrmoval mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set airremoval mode | |
example: 'climate.airpurifier' | |
airremoval_mode: | |
description: airremoval_mode | |
example: '켜짐' | |
lge_airpurifier_set_circulatedir_mode: | |
description: Set the circulatedir mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set circulatedir mode | |
example: 'climate.airpurifier' | |
circulatedir_mode: | |
description: circulatedir_mode | |
example: '켜짐' | |
lge_airpurifier_set_signallighting_mode: | |
description: Set the signallighting mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set signallighting mode | |
example: 'climate.airpurifier' | |
signallighting_mode: | |
description: signallighting_mode | |
example: '켜짐' | |
lge_airpurifier_set_airfast_mode: | |
description: Set the airfast mode. | |
fields: | |
entity_id: | |
description: Name(s) of the entities to set airfast mode | |
example: 'climate.airpurifier' | |
airfast_mode: | |
description: airfast_mode | |
example: '켜짐' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
from urllib.parse import urljoin, urlencode, urlparse, parse_qs | |
import uuid | |
import base64 | |
import json | |
import hashlib | |
import hmac | |
from datetime import datetime, timedelta | |
from collections import namedtuple | |
import enum | |
import time | |
GATEWAY_URL = 'https://kic.lgthinq.com:46030/api/common/gatewayUriList' | |
APP_KEY = 'wideq' | |
SECURITY_KEY = 'nuts_securitykey' | |
DATA_ROOT = 'lgedmRoot' | |
COUNTRY = 'US' | |
LANGUAGE = 'en-US' | |
SVC_CODE = 'SVC202' | |
CLIENT_ID = 'LGAO221A02' | |
OAUTH_SECRET_KEY = 'c053c2a6ddeb7ad97cb0eed0dcb31cf8' | |
OAUTH_CLIENT_KEY = 'LGAO221A02' | |
DATE_FORMAT = '%a, %d %b %Y %H:%M:%S +0000' | |
"""HVAC STATE""" | |
STATE_COOL = '냉방' | |
STATE_DRY = '제습' | |
STATE_HEAT = '난방' | |
STATE_AI = '인공지능' | |
STATE_FAN = '송풍' | |
STATE_AIRCLEAN = '공기청정' | |
STATE_MODE_ON = 'ON' | |
STATE_MODE_OFF = 'OFF' | |
STATE_LOW = '약풍' | |
STATE_MID = '중풍' | |
STATE_HIGH = '강풍' | |
STATE_AUTO = '자동' | |
STATE_POWER = '파워' | |
STATE_COOLPOWER = '쿨파워' | |
STATE_LONGPOWER = '롱파워' | |
STATE_RIGHT_LOW_LEFT_MID = '우약풍/좌중풍' | |
STATE_RIGHT_LOW_LEFT_HIGH = '우약풍/좌강풍' | |
STATE_RIGHT_MID_LEFT_LOW = '우중풍/좌약풍' | |
STATE_RIGHT_MID_LEFT_HIGH = '우중풍/좌강풍' | |
STATE_RIGHT_HIGH_LEFT_LOW = '우강풍/좌약풍' | |
STATE_RIGHT_HIGH_LEFT_MID = '우강풍/좌중풍' | |
STATE_RIGHT_ONLY_LOW = '우약풍' | |
STATE_RIGHT_ONLY_MID = '우중풍' | |
STATE_RIGHT_ONLY_HIGH = '우강풍' | |
STATE_LEFT_ONLY_LOW = '좌약풍' | |
STATE_LEFT_ONLY_MID = '좌중풍' | |
STATE_LEFT_ONLY_HIGH = '좌강풍' | |
STATE_LEFT_RIGHT = '좌/우' | |
STATE_LEFT_RIGHT_ON = '좌/우' | |
STATE_RIGHTSIDE_LEFT_RIGHT = '우측 좌/우' | |
STATE_LEFTSIDE_LEFT_RIGHT = '좌측 좌/우' | |
STATE_LEFT_RIGHT_STOP = '정지' | |
STATE_WDIRVSTEP_OFF = '꺼짐' | |
STATE_WDIRVSTEP_FIRST = '1단계' | |
STATE_WDIRVSTEP_SECOND = '2단계' | |
STATE_WDIRVSTEP_THIRD = '3단계' | |
STATE_WDIRVSTEP_FOURTH = '4단계' | |
STATE_WDIRVSTEP_FIFTH = '5단계' | |
STATE_WDIRVSTEP_SIXTH = '6단계' | |
STATE_WDIRVSTEP_AUTO = '자동' | |
STATE_WDIRHSTEP_OFF = '꺼짐' | |
STATE_WDIRHSTEP_FIRST = '1단계' | |
STATE_WDIRHSTEP_SECOND = '2단계' | |
STATE_WDIRHSTEP_THIRD = '3단계' | |
STATE_WDIRHSTEP_FOURTH = '4단계' | |
STATE_WDIRHSTEP_FIFTH = '5단계' | |
STATE_WDIRHSTEP_THIRTEENTH = '좌측' | |
STATE_WDIRHSTEP_THIRTYFIFTH = '우측' | |
STATE_WDIRHSTEP_AUTO = '자동' | |
"""REFRIGERATOR STATE""" | |
STATE_ICE_PLUS_ON = '켜짐' | |
STATE_ICE_PLUS_OFF = '꺼짐' | |
STATE_ICE_PLUS_FREEZE = '급속 냉동' | |
STATE_ICE_PLUS = '특급 냉동' | |
STATE_REF_MODE_OFF = '꺼짐' | |
STATE_FRESH_AIR_FILTER_REPLACE_FILTER = '필터교체필요' | |
STATE_FRESH_AIR_FILTER_SMART_CARE_ON = '켜짐' | |
STATE_FRESH_AIR_FILTER_SMART_CARE_OFF = '꺼짐' | |
STATE_FRESH_AIR_FILTER_SMART_CARE_WAIT = '대기' | |
STATE_FRESH_AIR_FILTER_POWER = '파워' | |
STATE_FRESH_AIR_FILTER_AUTO = '자동' | |
STATE_FRESH_AIR_FILTER_OFF = '꺼짐' | |
STATE_SMART_SAVING_NIGHT = 'NIGHT' | |
STATE_SMART_SAVING_CUSTOM = 'CUSTOM' | |
STATE_SMART_SAVING_OFF = 'OFF' | |
STATE_REF_WATERFILTER_OK = '정상' | |
STATE_REF_WATERFILTER_REPLACE = '교체필요' | |
STATE_REF_WATERFILTER_NO_FILTER = '정수기없음' | |
STATE_REF_ACTIVESAVING_ZERO = '0' | |
STATE_REF_ACTIVESAVING_ONE = '1' | |
STATE_REF_ACTIVESAVING_TWO = '2' | |
STATE_REF_ACTIVESAVING_THREE = '3' | |
"""DRYER STATE""" | |
STATE_DRYER_POWER_OFF = 'Off' | |
STATE_DRYER_INITIAL = 'Initial' | |
STATE_DRYER_RUNNING = 'Running' | |
STATE_DRYER_DRYING = "Drying" | |
STATE_DRYER_PAUSE = 'Pause' | |
STATE_DRYER_END = 'End' | |
STATE_DRYER_ERROR = 'Error' | |
STATE_DRYER_SMART_DIAGNOSIS = "Smart Diagnosis" | |
STATE_DRYER_WRINKLE_CARE = "Wrinkle Care" | |
STATE_DRYER_PROCESS_DETECTING = 'Detecting' | |
STATE_DRYER_PROCESS_STEAM = 'Steam' | |
STATE_DRYER_PROCESS_DRY = 'Dry' | |
STATE_DRYER_PROCESS_COOLING = 'Cooling' | |
STATE_DRYER_PROCESS_ANTI_CREASE = 'Anti-crease' | |
STATE_DRYER_PROCESS_END = 'End' | |
STATE_DRY_LEVEL_IRON = 'Iron' | |
STATE_DRY_LEVEL_CUPBOARD = 'Cupboard' | |
STATE_DRY_LEVEL_EXTRA = 'Extra' | |
STATE_DRY_LEVEL_DAMP = "Damp" | |
STATE_DRY_LEVEL_LESS = "Less" | |
STATE_DRY_LEVEL_MORE = "More" | |
STATE_DRY_LEVEL_NORMAL = "Normal" | |
STATE_DRY_LEVEL_VERY = "Very" | |
STATE_ECOHYBRID_ECO = 'Eco' | |
STATE_ECOHYBRID_NORMAL = 'Normal' | |
STATE_ECOHYBRID_TURBO = 'Turbo' | |
STATE_COURSE_COTTON_SOFT = 'Cotton Soft' | |
STATE_COURSE_BULKY_ITEM = 'Bulky Item' | |
STATE_COURSE_EASY_CARE = 'Easy Care' | |
STATE_COURSE_COTTON = 'Cotton' | |
STATE_COURSE_SPORTS_WEAR = 'Sportswear' | |
STATE_COURSE_QUICK_DRY = 'Quick Dry' | |
STATE_COURSE_WOOL = 'Wool' | |
STATE_COURSE_RACK_DRY = 'Rack Dry' | |
STATE_COURSE_COOL_AIR = 'Cool Air' | |
STATE_COURSE_WARM_AIR = 'Warm Air' | |
STATE_COURSE_BEDDING_BRUSH = 'Bedding Brush' | |
STATE_COURSE_STERILIZATION = 'Sterilization' | |
STATE_COURSE_REFRESH = 'Refresh' | |
STATE_COURSE_POWER = 'Power' | |
STATE_COURSE_NORMAL = 'Normal' | |
STATE_COURSE_SPEED_DRY = 'Speed Dry' | |
STATE_COURSE_HEAVY_DUTY = "Heavy Duty" | |
STATE_COURSE_TOWELS = "Towels" | |
STATE_COURSE_PERM_PRESS = "Permenant Press" | |
STATE_COURSE_DELICATES = "Delicates" | |
STATE_COURSE_BEDDING = "Bedding" | |
STATE_COURSE_AIR_DRY = "Air Dry" | |
STATE_COURSE_TIME_DRY = "Time Dry" | |
STATE_COURSE_ANTI_BACTERIAL = "Anti Bacterial" | |
STATE_COURSE_STEAM_FRESH = "Steam Fresh" | |
STATE_COURSE_STEAM_SANITARY = "Steam Sanitary" | |
STATE_SMARTCOURSE_GYM_CLOTHES = '운동복' | |
STATE_SMARTCOURSE_RAINY_SEASON = '장마철' | |
STATE_SMARTCOURSE_DEODORIZATION = '리프레쉬' | |
STATE_SMARTCOURSE_SMALL_LOAD = '소량 건조' | |
STATE_SMARTCOURSE_LINGERIE = '란제리' | |
STATE_SMARTCOURSE_EASY_IRON = '촉촉 건조' | |
STATE_SMARTCOURSE_SUPER_DRY = '강력 건조' | |
STATE_SMARTCOURSE_ECONOMIC_DRY = '절약 건조' | |
STATE_SMARTCOURSE_BIG_SIZE_ITEM = '큰 빨래 건조' | |
STATE_SMARTCOURSE_MINIMIZE_WRINKLES = '구김 완화 건조' | |
STATE_SMARTCOURSE_FULL_SIZE_LOAD = '다량건조' | |
STATE_SMARTCOURSE_JEAN = '청바지' | |
STATE_ERROR_DOOR = "Error door" | |
STATE_ERROR_DRAINMOTOR = "Error drainmotor" | |
STATE_ERROR_LE1 = "Error le1" | |
STATE_ERROR_TE1 = "Error te1" | |
STATE_ERROR_TE2 = "Error te2" | |
STATE_ERROR_TE5 = "Error te5" | |
STATE_ERROR_TE6 = "Error te6" | |
STATE_ERROR_PS = "High Power" | |
STATE_ERROR_NP = "nP" | |
STATE_ERROR_F1 = "Error f1" | |
STATE_ERROR_LE2 = "Error le2" | |
STATE_ERROR_AE = "Error ae" | |
STATE_ERROR_dE4 = "Error de4" | |
STATE_ERROR_NOFILTER = "Error nofilter" | |
STATE_ERROR_EMPTYWATER = "Error emptywater" | |
STATE_ERROR_CE1 = "Error ce1" | |
STATE_NO_ERROR = "No Error" | |
STATE_OPTIONITEM_ON = 'On' | |
STATE_OPTIONITEM_OFF = 'Off' | |
"""WASHER STATE""" | |
STATE_WASHER_POWER_OFF = 'Off' | |
STATE_WASHER_INITIAL = 'Initial' | |
STATE_WASHER_PAUSE = 'Pause' | |
STATE_WASHER_ERROR_AUTO_OFF = 'Error Auto Off' | |
STATE_WASHER_RESERVE = 'Reserve' | |
STATE_WASHER_DETECTING = 'Detecting' | |
STATE_WASHER_SOAK = "Soak" | |
STATE_WASHER_ADD_DRAIN = 'ADD_DRAIN' | |
STATE_WASHER_DETERGENT_AMOUT = 'Detergent Amount' | |
STATE_WASHER_RUNNING = 'Running' | |
STATE_WASHER_PREWASH = 'Prewash' | |
STATE_WASHER_RINSING = 'Rinsing' | |
STATE_WASHER_RINSE_HOLD = 'Rinsing Hold' | |
STATE_WASHER_SPINNING = 'Spinning' | |
STATE_WASHER_DRYING = 'Drying' | |
STATE_WASHER_END = 'End' | |
STATE_WASHER_FRESHCARE = 'FreshCare' | |
STATE_WASHER_TCL_ALARM_NORMAL = 'TCL Alarm Normal' | |
STATE_WASHER_FROZEN_PREVENT_INITIAL = 'Frozen prevent initial' | |
STATE_WASHER_FROZEN_PREVENT_RUNNING = 'Frozen prevent running' | |
STATE_WASHER_FROZEN_PREVENT_PAUSE = 'Frozen prevent pause' | |
STATE_WASHER_ERROR = 'Error' | |
STATE_WASHER_SOILLEVEL_LIGHT = 'Light' | |
STATE_WASHER_SOILLEVEL_NORMAL = 'Normal' | |
STATE_WASHER_SOILLEVEL_HEAVY = 'Heavy' | |
STATE_WASHER_SOILLEVEL_PRE_WASH = 'Prewash' | |
STATE_WASHER_SOILLEVEL_SOAKING = 'Soaking' | |
STATE_WASHER_SOILLEVEL_THREE = "3" | |
STATE_WASHER_SOILLEVEL_SIX = "분" | |
STATE_WASHER_SOILLEVEL_TEN = "10" | |
STATE_WASHER_SOILLEVEL_TWELVE = "12" | |
STATE_WASHER_SOILLEVEL_FOURTEEN = "14" | |
STATE_WASHER_SOILLEVEL_SEVENTEEN = "17" | |
STATE_WASHER_SOILLEVEL_NINETEEN = "19" | |
STATE_WASHER_SOILLEVEL_TWENTYONE = "21" | |
STATE_WASHER_SOILLEVEL_TWENTYTHREE = "23" | |
STATE_WASHER_SOILLEVEL_TWENTYFIVE = "25" | |
STATE_WASHER_WATERTEMP_COLD = 'Cold' | |
STATE_WASHER_WATERTEMP_WARM = "Warm" | |
STATE_WASHER_WATERTEMP_NORMAL = "Normal" | |
STATE_WASHER_WATERTEMP_COLD_WARM = "Cold / Warm" | |
STATE_WASHER_WATERTEMP_30 = '30℃' | |
STATE_WASHER_WATERTEMP_40 = '40℃' | |
STATE_WASHER_WATERTEMP_60 = '60℃' | |
STATE_WASHER_WATERTEMP_95 = '95℃' | |
STATE_WASHER_WATERTEMP_90 = '90℃' | |
STATE_WASHER_WATERTEMP_35 = '35℃' | |
STATE_WASHER_WATERTEMP_38 = '38℃' | |
STATE_WASHER_SPINSPEED_NO_SELET = "No select" | |
STATE_WASHER_SPINSPEED_EXTRA_LOW = "Extra Low" | |
STATE_WASHER_SPINSPEED_LOW = "Low" | |
STATE_WASHER_SPINSPEED_MEDIUM = "Medium" | |
STATE_WASHER_SPINSPEED_HIGH = "High" | |
STATE_WASHER_SPINSPEED_EXTRA_HIGH = "Extra High" | |
STATE_WASHER_SPINSPEED_ON = 'On' | |
STATE_WASHER_SPINSPEED_OFF = 'Off' | |
STATE_WASHER_SPINSPEED_ULTRA = "Ultra" | |
STATE_WASHER_SPINSPEED_DRYFIT = "Dryfit" | |
STATE_WASHER_SPINSPEED_DELICACY = "Delicacy" | |
STATE_WASHER_RINSECOUNT_1 = '1' | |
STATE_WASHER_RINSECOUNT_2 = '2' | |
STATE_WASHER_RINSECOUNT_3 = '3' | |
STATE_WASHER_RINSECOUNT_4 = '4' | |
STATE_WASHER_RINSECOUNT_5 = '5' | |
STATE_WASHER_RINSECOUNT_6 = '6' | |
STATE_WASHER_RINSECOUNT_OFF = 'Off' | |
STATE_WASHER_RINSECOUNT_1_INTENSIVE = "1 Intensive" | |
STATE_WASHER_RINSECOUNT_2_INTENSIVE = "2 Intensive" | |
STATE_WASHER_RINSECOUNT_3_INTENSIVE = "3 Intensive" | |
STATE_WASHER_RINSECOUNT_4_INTENSIVE = "4 Intensive" | |
STATE_WASHER_RINSECOUNT_5_INTENSIVE = "5 Intensive" | |
STATE_WASHER_DRYLEVEL_WIND = 'Wind' | |
STATE_WASHER_DRYLEVEL_TURBO = 'Turbo' | |
STATE_WASHER_DRYLEVEL_TIME_30 = 'Time 30' | |
STATE_WASHER_DRYLEVEL_TIME_60 = 'Time 60' | |
STATE_WASHER_DRYLEVEL_TIME_90 = 'Time 90' | |
STATE_WASHER_DRYLEVEL_TIME_120 = 'Time 120' | |
STATE_WASHER_DRYLEVEL_TIME_150 = 'Time 150' | |
STATE_WASHER_NO_ERROR = "No Error" | |
STATE_WASHER_ERROR_dE2 = "DE2 Error - Door Lock Error" | |
STATE_WASHER_ERROR_IE = "IE Error - No Fill Error" | |
STATE_WASHER_ERROR_OE = "OE Error - Not Draining Error" | |
STATE_WASHER_ERROR_UE = "UE Error - Out of Balance Load" | |
STATE_WASHER_ERROR_FE = "FE Error - Overfill Error" | |
STATE_WASHER_ERROR_PE = "PE Error - Water Sensor Error" | |
STATE_WASHER_ERROR_LE = "LE Error - Locked Motor Error" | |
STATE_WASHER_ERROR_tE = "tE Error - Thermistor Error" | |
STATE_WASHER_ERROR_dHE = "dHE Error" | |
STATE_WASHER_ERROR_CE = "CE Error" | |
STATE_WASHER_ERROR_PF = "PF Error - Power Failure Error" | |
STATE_WASHER_ERROR_FF = "FF Error - Freeze Error" | |
STATE_WASHER_ERROR_dCE = "dCE Error" | |
STATE_WASHER_ERROR_EE = "EE Error - EEPROM Error" | |
STATE_WASHER_ERROR_PS = "PS Error" | |
STATE_WASHER_ERROR_dE1 = "DE1 Error - Door Open Error" | |
STATE_WASHER_ERROR_LOE = "LOE Error - Sliding Lid Open Error" | |
STATE_WASHER_ERROR_TL_DO_W = 'Washer error tl do w' | |
STATE_WASHER_ERROR_TL_LE = 'Washer error tl le' | |
STATE_WASHER_ERROR_TL_AE = 'Washer error tl ae' | |
STATE_WASHER_ERROR_E7 = 'Washer error e7' | |
STATE_WASHER_ERROR_LE1 = 'Washer error le1' | |
STATE_WASHER_ERROR_DL = 'Washer error dl' | |
STATE_WASHER_ERROR_E3 = 'Washer error e3' | |
STATE_WASHER_WATERLEVEL_1 = "1" | |
STATE_WASHER_WATERLEVEL_2 = "2" | |
STATE_WASHER_WATERLEVEL_3 = "3" | |
STATE_WASHER_WATERLEVEL_4 = "4" | |
STATE_WASHER_WATERLEVEL_5 = "5" | |
STATE_WASHER_WATERLEVEL_6 = "6" | |
STATE_WASHER_WATERLEVEL_7 = "7" | |
STATE_WASHER_WATERLEVEL_8 = "8" | |
STATE_WASHER_WATERLEVEL_9 = "9" | |
STATE_WASHER_WATERLEVEL_10 = "10" | |
STATE_WASHER_WATERFLOW_DELICATE = "Delicate" | |
STATE_WASHER_WATERFLOW_MEDIUM = "Medium" | |
STATE_WASHER_WATERFLOW_HIGH = "High" | |
STATE_WASHER_SOAK_FIFTEEN = "15" | |
STATE_WASHER_SOAK_THIRTY = "30" | |
STATE_WASHER_SOAK_FOURTY = "40" | |
STATE_WASHER_SOAK_FOURTYFIVE = "45" | |
STATE_WASHER_SOAK_FIFTY = "50" | |
STATE_WASHER_SOAK_SIXTY = "60" | |
STATE_WASHER_SOAK_ONETWENTY = "120" | |
STATE_WASHER_SOAK_ONEEIGHTY = "180" | |
STATE_WASHER_SOAK_TWOFOURTY = "240" | |
STATE_WASHER_SOAK_THREEHUNDRED = "300" | |
STATE_WASHER_SOAK_THREESIXTY = "360" | |
STATE_WASHER_SOAK_FOUREIGHTY = "480" | |
STATE_WASHER_SOAK_SIXHUNDRED = "600" | |
STATE_WASHER_APCOURSE_COTTON = 'Cotton' | |
STATE_WASHER_APCOURSE_SPEEDWASH_DRY = 'Speedwash Dry' | |
STATE_WASHER_APCOURSE_SPEEDWASH = 'Speedwash' | |
STATE_WASHER_APCOURSE_SINGLE_SHIRT_DRY = 'Single Shirt Dry' | |
STATE_WASHER_APCOURSE_RINSESPIN = 'Rinse Spin' | |
STATE_WASHER_APCOURSE_SPEEDBOIL = 'Speed Boil' | |
STATE_WASHER_APCOURSE_ALLERGYCARE = 'Allergy Care' | |
STATE_WASHER_APCOURSE_STEAMCLEANING = 'Steam Cleaning' | |
STATE_WASHER_APCOURSE_BABYWEAR = 'Baby Wear' | |
STATE_WASHER_APCOURSE_BLANKET_ROB = 'Blanket Rob' | |
STATE_WASHER_APCOURSE_UTILITY = 'Utility' | |
STATE_WASHER_APCOURSE_BLANKET = 'Blanket' | |
STATE_WASHER_APCOURSE_LINGERIE_WOOL = 'Lingerie Wool' | |
STATE_WASHER_APCOURSE_COLDWASH = 'Cold Wash' | |
STATE_WASHER_APCOURSE_TUBCLEAN_SANITARY = 'Tubclean Sanitary' | |
STATE_WASHER_APCOURSE_DOWNLOAD_COUSE = 'Download Course' | |
STATE_WASHER_COURSE_HEAVYDUTY = 'Heavyduty' | |
STATE_WASHER_COURSE_SMALL_LOAD = 'Small load' | |
STATE_WASHER_COURSE_UNDERWEAR = 'Underwear' | |
STATE_WASHER_COURSE_WOOL = 'Wool' | |
STATE_WASHER_COURSE_BOILING = 'Boiling' | |
STATE_WASHER_COURSE_BABYCARE = 'Babycare' | |
STATE_WASHER_COURSE_RINSE_SPIN = 'Rinse spin' | |
STATE_WASHER_COURSE_TUBCLEAN = 'Tubclean' | |
STATE_WASHER_COURSE_NORMAL = "Normal" | |
STATE_WASHER_COURSE_WOOL_DELICATE = "Wool delicate" | |
STATE_WASHER_COURSE_BEDDING = "Bedding" | |
STATE_WASHER_COURSE_TOWEL = "Towel" | |
STATE_WASHER_COURSE_PREWASH_NORMAL = "Prewash normal" | |
STATE_WASHER_COURSE_SAFETY_NORMAL = "Safety normal" | |
STATE_WASHER_COURSE_PERM_PRESS = "Perm-Press" | |
STATE_WASHER_COURSE_ALLERGIENE = "Allergiene" | |
STATE_WASHER_COURSE_SANITARY = "Sanitary" | |
STATE_WASHER_COURSE_BRIGHT_WHITES = "Bright Whites" | |
STATE_WASHER_COURSE_DELICATES = "Delicates" | |
STATE_WASHER_SMARTCOURSE_SILENT = 'Silent' | |
STATE_WASHER_SMARTCOURSE_SMALL_LOAD = 'Small Load' | |
STATE_WASHER_SMARTCOURSE_SKIN_CARE = 'Skin Care' | |
STATE_WASHER_SMARTCOURSE_RAINY_SEASON = 'Rainy Season' | |
STATE_WASHER_SMARTCOURSE_SWEAT_STAIN = 'Sweat Stain' | |
STATE_WASHER_SMARTCOURSE_SINGLE_GARMENT = 'Single Garment' | |
STATE_WASHER_SMARTCOURSE_SCHOOL_UNIFORM = 'School Uniform' | |
STATE_WASHER_SMARTCOURSE_STATIC_REMOVAL = 'Static Removal' | |
STATE_WASHER_SMARTCOURSE_COLOR_CARE = 'Color Care' | |
STATE_WASHER_SMARTCOURSE_SPIN_ONLY = 'Spin ONly' | |
STATE_WASHER_SMARTCOURSE_DEODORIZATION = 'Deoderization' | |
STATE_WASHER_SMARTCOURSE_BEDDING_CARE = 'Bedding Care' | |
STATE_WASHER_SMARTCOURSE_CLOTH_CARE = 'Cloth Care' | |
STATE_WASHER_SMARTCOURSE_SMART_RINSE = 'Smart Rinse' | |
STATE_WASHER_SMARTCOURSE_ECO_WASH = 'Eco Wash' | |
STATE_WASHER_SMARTCOURSE_COLD_WASH = 'Cold Wash' | |
STATE_WASHER_SMARTCOURSE_SOILED_ITEMS = 'Soiled Items' | |
STATE_WASHER_SMARTCOURSE_SINGLE_SPEED = 'Single Speed' | |
STATE_WASHER_SMARTCOURSE_COLOR_PROTECT = 'Color Protect' | |
STATE_WASHER_SMARTCOURSE_CHILDREN_WEAR = "Children Wear" | |
STATE_WASHER_SMARTCOURSE_SWIN_WEAR = "Swimwear" | |
STATE_WASHER_SMARTCOURSE_CURTAINS = "Curtains" | |
STATE_WASHER_SMARTCOURSE_JEAN = "Jean" | |
STATE_WASHER_SMARTCOURSE_LINGERIE = "Lingerie" | |
STATE_WASHER_SMARTCOURSE_FOOD_WASTE = "Food Waste" | |
STATE_WASHER_SMARTCOURSE_HEAVY_SPIN = "Heavy Spin" | |
STATE_WASHER_SMARTCOURSE_BIG_LOAD = "Big Load" | |
STATE_WASHER_TERM_NO_SELECT = 'Term No Select' | |
STATE_WASHER_NOT_SUPPORTED = 'Not Supported' | |
STATE_WASHER_OPTIONITEM_ON = 'On' | |
STATE_WASHER_OPTIONITEM_OFF = 'Off' | |
STATE_WASHER_RINSECOUNT_0 = "Washer rinsecount 0" | |
STATE_WASHER_RINSECOUNT_1 = "Washer rinsecount 1" | |
STATE_WASHER_RINSECOUNT_2 = "Washer rinsecount 2" | |
STATE_WASHER_RINSECOUNT_3 = "Washer rinsecount 3" | |
STATE_WASHER_RINSECOUNT_4 = "Washer rinsecount 4" | |
STATE_WASHER_RINSECOUNT_5 = "Washer rinsecount 5" | |
STATE_WASHER_RINSECOUNT_6 = "Washer rinsecount 6" | |
STATE_WASHER_RINSECOUNT_OFF = 'Off' | |
STATE_WASHER_RINSECOUNT_1_INTENSIVE = "1" | |
STATE_WASHER_RINSECOUNT_2_INTENSIVE = "2" | |
STATE_WASHER_RINSECOUNT_3_INTENSIVE = "3" | |
STATE_WASHER_RINSECOUNT_4_INTENSIVE = "4" | |
STATE_WASHER_RINSECOUNT_5_INTENSIVE = "5" | |
"""DEHUMIDIFIER STATE""" | |
STATE_DEHUM_ON = '동작 중' | |
STATE_DEHUM_OFF = '꺼짐' | |
STATE_DEHUM_OPMODE_SMART_DEHUM = '스마트제습' | |
STATE_DEHUM_OPMODE_FAST_DEHUM = '쾌속제습' | |
STATE_DEHUM_OPMODE_SILENT_DEHUM = '저소음제습' | |
STATE_DEHUM_OPMODE_CONCENTRATION_DRY = '집중건조' | |
STATE_DEHUM_OPMODE_CLOTHING_DRY = '의류건조' | |
STATE_DEHUM_OPMODE_IONIZER = '공기제균' | |
STATE_DEHUM_WINDSTRENGTH_LOW = '약풍' | |
STATE_DEHUM_WIDESTRENGTH_HIGH = '강풍' | |
STATE_DEHUM_AIRREMOVAL_ON = '켜짐' | |
STATE_DEHUM_AIRREMOVAL_OFF = '꺼짐' | |
"""WATERPURIFIER STATE""" | |
STATE_WATERPURIFIER_COCKCLEAN_WAIT = '셀프케어 대기 중' | |
STATE_WATERPURIFIER_COCKCLEAN_ON = '셀프케어 진행 중' | |
"""AIRPURIFIER STATE""" | |
STATE_AIRPURIFIER_ON = '켜짐' | |
STATE_AIRPURIFIER_OFF = '꺼짐' | |
STATE_AIRPURIFIER_CIRCULATOR_CLEAN = '클린부스터' | |
STATE_AIRPURIFIER_BABY_CARE = '싱글청정' | |
STATE_AIRPURIFIER_CLEAN = '청정모드' | |
STATE_AIRPURIFIER_DUAL_CLEAN = '듀얼청정' | |
STATE_AIRPURIFIER_AUTO_MODE = '오토모드' | |
STATE_AIRPURIFIER_LOWST_LOW = '최약' | |
STATE_AIRPURIFIER_LOWST = '미약' | |
STATE_AIRPURIFIER_LOW = '약' | |
STATE_AIRPURIFIER_LOW_MID = '중약' | |
STATE_AIRPURIFIER_MID = '중' | |
STATE_AIRPURIFIER_MID_HIGH = '중강' | |
STATE_AIRPURIFIER_HIGH = '강' | |
STATE_AIRPURIFIER_POWER = '파워' | |
STATE_AIRPURIFIER_AUTO = '자동' | |
STATE_AIRPURIFIER_LONGPOWER = '롱파워' | |
STATE_AIRPURIFIER_SHOWER = '샤워풍' | |
STATE_AIRPURIFIER_FOREST = '숲바람' | |
STATE_AIRPURIFIER_TURBO = '터보' | |
STATE_AIRPURIFIER_FASTWIND = '빠른바람' | |
STATE_AIRPURIFIER_CIR_LOWST_LOW = '청정세기_최약' | |
STATE_AIRPURIFIER_CIR_LOWST = '청정세기_미약' | |
STATE_AIRPURIFIER_CIR_LOW = '청정세기_약' | |
STATE_AIRPURIFIER_CIR_LOW_MID = '청정세기_중약' | |
STATE_AIRPURIFIER_CIR_MID = '청정세기_중' | |
STATE_AIRPURIFIER_CIR_MID_HIGH = '청정세기_중강' | |
STATE_AIRPURIFIER_CIR_HIGH = '청정세기_강' | |
STATE_AIRPURIFIER_CIR_POWER = '청정세기_파워' | |
STATE_AIRPURIFIER_CIR_AUTO = '청정세기_자동' | |
STATE_AIRPURIFIER_CIR_LINK = '청정세기_링크' | |
STATE_AIRPURIFIER_TOTALAIRPOLUTION_GOOD = '좋음' | |
STATE_AIRPURIFIER_TOTALAIRPOLUTION_NORMAL = '보통' | |
STATE_AIRPURIFIER_TOTALAIRPOLUTION_BAD = '나쁨' | |
STATE_AIRPURIFIER_TOTALAIRPOLUTION_VERYBAD = '매우나쁨' | |
STATE_AIRPURIFIER_SMELL_WEEK = '약함' | |
STATE_AIRPURIFIER_SMELL_NORMAL = '보통' | |
STATE_AIRPURIFIER_SMELL_STRONG = '강함' | |
STATE_AIRPURIFIER_SMELL_VERYSTRONG = '매우강함' | |
STATE_AIRPURIFIER_NOT_SUPPORTED = '지원안함' | |
#"""HVAC STATE""" | |
#STATE_COOL = "Cool" | |
#STATE_DRY = "Dry" | |
#STATE_AIRCLEAN = 'ON' | |
#STATE_AIRCLEAN_OFF = 'OFF' | |
#STATE_SMARTCARE = 'ON' | |
#STATE_SMARTCARE_OFF = 'OFF' | |
#STATE_AUTODRY = 'ON' | |
#STATE_AUTODRY_OFF = 'OFF' | |
#STATE_POWERSAVE = 'ON' | |
#STATE_POWERSAVE_OFF = 'OFF' | |
#STATE_COOLPOWER = 'ON' | |
#STATE_COOLPOWER_OFF = 'OFF' | |
#STATE_LONGPOWER = 'ON' | |
#STATE_LONGPOWER_OFF = 'OFF' | |
# | |
#STATE_LOW = "Low" | |
#STATE_MID = "Mid" | |
#STATE_HIGH = "High" | |
#STATE_RIGHT_LOW_LEFT_MID = "Right low left mid" | |
#STATE_RIGHT_LOW_LEFT_HIGH = "Right low left high" | |
#STATE_RIGHT_MID_LEFT_LOW = "Right mid left low" | |
#STATE_RIGHT_MID_LEFT_HIGH = "Right mid left high" | |
#STATE_RIGHT_HIGH_LEFT_LOW = "Right high left low" | |
#STATE_RIGHT_HIGH_LEFT_MID = "Right high left mid" | |
#STATE_RIGHT_ONLY_LOW = "Right only low" | |
#STATE_RIGHT_ONLY_MID = "Right only mid" | |
#STATE_RIGHT_ONLY_HIGH = "Right only high" | |
#STATE_LEFT_ONLY_LOW = "Left only low" | |
#STATE_LEFT_ONLY_MID = "Left only mid" | |
#STATE_LEFT_ONLY_HIGH = "Left only high" | |
# | |
#STATE_LEFT_RIGHT = "Left right" | |
#STATE_RIGHTSIDE_LEFT_RIGHT = "Rightside left right" | |
#STATE_LEFTSIDE_LEFT_RIGHT = "Leftside left right" | |
#STATE_LEFT_RIGHT_STOP = "Left right stop" | |
# | |
#STATE_UP_DOWN = 'ON' | |
#STATE_UP_DOWN_STOP = 'OFF' | |
# | |
#"""REFRIGERATOR STATE""" | |
#STATE_ICE_PLUS = 'ON' | |
#STATE_ICE_PLUS_OFF = 'OFF' | |
# | |
#STATE_FRESH_AIR_FILTER_POWER = "Fresh air filter power" | |
#STATE_FRESH_AIR_FILTER_AUTO = "Fresh air filter auto" | |
#STATE_FRESH_AIR_FILTER_OFF = "Fresh air filter off" | |
# | |
#STATE_SMART_SAVING_NIGHT = 'NIGHT' | |
#STATE_SMART_SAVING_CUSTOM = 'CUSTOM' | |
#STATE_SMART_SAVING_OFF = 'OFF' | |
# | |
#"""DRYER STATE""" | |
#STATE_DRYER_POWER_OFF = "N/A" | |
#STATE_DRYER_OFF = "Power Off" | |
#STATE_DRYER_DRYING = "Drying" | |
STATE_DRYER_SMART_DIAGNOSIS = "Smart Diagnosis" | |
STATE_DRYER_WRINKLE_CARE = "Wrinkle Care" | |
#STATE_DRYER_INITIAL = "Initial" | |
#STATE_DRYER_RUNNING = "Running" | |
#STATE_DRYER_PAUSE = "Pause" | |
#STATE_DRYER_COOLING = "Cooling" | |
#STATE_DRYER_END = "End" | |
#STATE_DRYER_ERROR = "Error" | |
# | |
#STATE_DRYER_PROCESS_DETECTING = "Dryer process detecting" | |
#STATE_DRYER_PROCESS_STEAM = "Dryer process steam" | |
#STATE_DRYER_PROCESS_DRY = "Dryer process dry" | |
#STATE_DRYER_PROCESS_COOLING = "Dryer process cooling" | |
#STATE_DRYER_PROCESS_ANTI_CREASE = "Dryer process anti crease" | |
#STATE_DRYER_PROCESS_END = "Dryer process end" | |
# | |
#STATE_DRY_LEVEL_IRON = "Iron" | |
#STATE_DRY_LEVEL_CUPBOARD = "Cupboard" | |
#STATE_DRY_LEVEL_EXTRA = "Extra" | |
#STATE_DRY_LEVEL_DAMP = "Damp" | |
#STATE_DRY_LEVEL_LESS = "Less" | |
#STATE_DRY_LEVEL_MORE = "More" | |
#STATE_DRY_LEVEL_NORMAL = "Normal" | |
#STATE_DRY_LEVEL_VERY = "Very" | |
# | |
#STATE_DRY_TEMP_ULTRA_LOW = "Ultra Low" | |
#STATE_DRY_TEMP_LOW = "Low" | |
#STATE_DRY_TEMP_MEDIUM = "Medium" | |
#STATE_DRY_TEMP_MID_HIGH = "Mid High" | |
#STATE_DRY_TEMP_HIGH = "High" | |
# | |
#STATE_ECOHYBRID_ECO = "Ecohybrid eco" | |
#STATE_ECOHYBRID_NORMAL = "Ecohybrid normal" | |
#STATE_ECOHYBRID_TURBO = "Ecohybrid turbo" | |
# | |
#STATE_COURSE_COTTON_SOFT = "Cotton Soft" | |
#STATE_COURSE_BULKY_ITEM = "Bulky Item" | |
#STATE_COURSE_EASY_CARE = "Easy Care" | |
#STATE_COURSE_COTTON = "Cotton" | |
#STATE_COURSE_SPORTS_WEAR = "Sports Wear" | |
#STATE_COURSE_QUICK_DRY = "Quick Dry" | |
#STATE_COURSE_WOOL = "Wool" | |
#STATE_COURSE_RACK_DRY = "Rack Dry" | |
#STATE_COURSE_COOL_AIR = "Cool Air" | |
#STATE_COURSE_WARM_AIR = "Warm Air" | |
#STATE_COURSE_BEDDING_BRUSH = "Bedding Brush" | |
#STATE_COURSE_STERILIZATION = "Sterilization" | |
#STATE_COURSE_POWER = "Power" | |
#STATE_COURSE_REFRESH = "Refresh" | |
#STATE_COURSE_NORMAL = "Normal" | |
#STATE_COURSE_SPEED_DRY = "Speed Dry" | |
# | |
#STATE_SMARTCOURSE_GYM_CLOTHES = "Smartcourse gym clothes" | |
#STATE_SMARTCOURSE_RAINY_SEASON = "Smartcourse rainy season" | |
#STATE_SMARTCOURSE_DEODORIZATION = "Smartcourse deodorization" | |
#STATE_SMARTCOURSE_SMALL_LOAD = "Smartcourse small load" | |
#STATE_SMARTCOURSE_LINGERIE = "Smartcourse lingerie" | |
#STATE_SMARTCOURSE_EASY_IRON = "Smartcourse easy iron" | |
#STATE_SMARTCOURSE_SUPER_DRY = "Smartcourse super dry" | |
#STATE_SMARTCOURSE_ECONOMIC_DRY = "Smartcourse economic dry" | |
#STATE_SMARTCOURSE_BIG_SIZE_ITEM = "Smartcourse big size item" | |
#STATE_SMARTCOURSE_MINIMIZE_WRINKLES = "Smartcourse minimize wrinkles" | |
#STATE_SMARTCOURSE_FULL_SIZE_LOAD = "Smartcourse full size load" | |
#STATE_SMARTCOURSE_JEAN = "Smartcourse jean" | |
# | |
#STATE_ERROR_DOOR = "Error door" | |
#STATE_ERROR_DRAINMOTOR = "Error drainmotor" | |
#STATE_ERROR_LE1 = "Error le1" | |
#STATE_ERROR_TE1 = "Error te1" | |
#STATE_ERROR_TE2 = "Error te2" | |
#STATE_ERROR_F1 = "Error f1" | |
#STATE_ERROR_LE2 = "Error le2" | |
#STATE_ERROR_AE = "Error ae" | |
#STATE_ERROR_dE4 = "Error de4" | |
#STATE_ERROR_NOFILTER = "Error nofilter" | |
#STATE_ERROR_EMPTYWATER = "Error emptywater" | |
#STATE_ERROR_CE1 = "Error ce1" | |
#STATE_NO_ERROR = "No Error" | |
# | |
#STATE_OPTIONITEM_ON = "On" | |
#STATE_OPTIONITEM_OFF = "Off" | |
# | |
#"""WASHER STATE""" | |
#STATE_WASHER_OFF = "Power Off" | |
#STATE_WASHER_POWER_OFF = "N/A" | |
#STATE_WASHER_INITIAL = "Initial" | |
#STATE_WASHER_PAUSE = "Pause" | |
#STATE_WASHER_ERROR_AUTO_OFF = "Error auto off" | |
#STATE_WASHER_RESERVE = "Reserve" | |
#STATE_WASHER_DETECTING = "Detecting" | |
#STATE_WASHER_ADD_DRAIN = "Add drain" | |
#STATE_WASHER_DETERGENT_AMOUT = "Detergent amout" | |
#STATE_WASHER_RUNNING = "Running" | |
#STATE_WASHER_PREWASH = "Pre-wash" | |
#STATE_WASHER_RINSING = "Rinsing" | |
#STATE_WASHER_RINSE_HOLD = "Rinse Hold" | |
#STATE_WASHER_SPINNING = "Spinning" | |
#STATE_WASHER_SOAK = "Soaking" | |
#STATE_WASHER_COMPLETE = "Complete" | |
#STATE_WASHER_FIRMWARE = "Firmware" | |
#STATE_WASHER_SMART_DIAGNOSIS = "Smart Diagnosis" | |
#STATE_WASHER_DRYING = "Drying" | |
#STATE_WASHER_END = "End" | |
#STATE_WASHER_FRESHCARE = "Freshcare" | |
#STATE_WASHER_TCL_ALARM_NORMAL = "TCL alarm normal" | |
#STATE_WASHER_FROZEN_PREVENT_INITIAL = "Frozen prevent initial" | |
#STATE_WASHER_FROZEN_PREVENT_RUNNING = "Frozen prevent running" | |
#STATE_WASHER_FROZEN_PREVENT_PAUSE = "Frozen prevent pause" | |
#STATE_WASHER_ERROR = "Error" | |
# | |
#STATE_WASHER_WATERLEVEL_1 = "1" | |
#STATE_WASHER_WATERLEVEL_2 = "2" | |
#STATE_WASHER_WATERLEVEL_3 = "3" | |
#STATE_WASHER_WATERLEVEL_4 = "4" | |
#STATE_WASHER_WATERLEVEL_5 = "5" | |
#STATE_WASHER_WATERLEVEL_6 = "6" | |
#STATE_WASHER_WATERLEVEL_7 = "7" | |
#STATE_WASHER_WATERLEVEL_8 = "8" | |
#STATE_WASHER_WATERLEVEL_9 = "9" | |
#STATE_WASHER_WATERLEVEL_10 = "10" | |
# | |
#STATE_WASHER_WATERFLOW_DELICATE = "Delicate" | |
#STATE_WASHER_WATERFLOW_MEDIUM = "Medium" | |
#STATE_WASHER_WATERFLOW_HIGH = "High" | |
# | |
#STATE_WASHER_SOAK_FIFTEEN = "15" | |
#STATE_WASHER_SOAK_THIRTY = "30" | |
#STATE_WASHER_SOAK_FOURTY = "40" | |
#STATE_WASHER_SOAK_FOURTYFIVE = "45" | |
#STATE_WASHER_SOAK_FIFTY = "50" | |
#STATE_WASHER_SOAK_SIXTY = "60" | |
#STATE_WASHER_SOAK_ONETWENTY = "120" | |
#STATE_WASHER_SOAK_ONEEIGHTY = "180" | |
#STATE_WASHER_SOAK_TWOFOURTY = "240" | |
#STATE_WASHER_SOAK_THREEHUNDRED = "300" | |
#STATE_WASHER_SOAK_THREESIXTY = "360" | |
#STATE_WASHER_SOAK_FOUREIGHTY = "480" | |
#STATE_WASHER_SOAK_SIXHUNDRED = "600" | |
# | |
#STATE_WASHER_SOILLEVEL_LIGHT = "Light" | |
#STATE_WASHER_SOILLEVEL_LIGHT_NORMAL = "Light Normal" | |
#STATE_WASHER_SOILLEVEL_NORMAL = "Normal" | |
#STATE_WASHER_SOILLEVEL_NORMAL_HEAVY = "Normal Heavy" | |
#STATE_WASHER_SOILLEVEL_HEAVY = "Heavy" | |
#STATE_WASHER_SOILLEVEL_PRE_WASH = "Pre-wash" | |
#STATE_WASHER_SOILLEVEL_SOAKING = "Soaking" | |
#STATE_WASHER_SOILLEVEL_THREE = "3" | |
#STATE_WASHER_SOILLEVEL_SIX = "6" | |
#STATE_WASHER_SOILLEVEL_TEN = "10" | |
#STATE_WASHER_SOILLEVEL_TWELVE = "12" | |
#STATE_WASHER_SOILLEVEL_FOURTEEN = "14" | |
#STATE_WASHER_SOILLEVEL_SEVENTEEN = "17" | |
#STATE_WASHER_SOILLEVEL_NINETEEN = "19" | |
#STATE_WASHER_SOILLEVEL_TWENTYONE = "21" | |
#STATE_WASHER_SOILLEVEL_TWENTYTHREE = "23" | |
#STATE_WASHER_SOILLEVEL_TWENTYFIVE = "25" | |
# | |
#STATE_WASHER_WATERTEMP_TAP_COLD = "Tap Cold" | |
#STATE_WASHER_WATERTEMP_COLD = "Cold" | |
#STATE_WASHER_WATERTEMP_SEMI_WARM = "Semi-Warm" | |
#STATE_WASHER_WATERTEMP_WARM = "Warm" | |
#STATE_WASHER_WATERTEMP_HOT = "Hot" | |
#STATE_WASHER_WATERTEMP_EXTRA_HOT = "Extra Hot" | |
#STATE_WASHER_WATERTEMP_30 = '30' | |
#STATE_WASHER_WATERTEMP_40 = '40' | |
#STATE_WASHER_WATERTEMP_60 = '60' | |
#STATE_WASHER_WATERTEMP_95 = '95' | |
#STATE_WASHER_WATERTEMP_NORMAL = "Normal" | |
#STATE_WASHER_WATERTEMP_COLD_WARM = "Cold Warm" | |
#STATE_WASHER_WATERTEMP_90 = '90℃' | |
#STATE_WASHER_WATERTEMP_35 = '35℃' | |
#STATE_WASHER_WATERTEMP_38 = '38℃' | |
# | |
#STATE_WASHER_SPINSPEED_NO_SELET = "No select" | |
#STATE_WASHER_SPINSPEED_EXTRA_LOW = "Extra Low" | |
#STATE_WASHER_SPINSPEED_LOW = "Low" | |
#STATE_WASHER_SPINSPEED_MEDIUM = "Medium" | |
#STATE_WASHER_SPINSPEED_HIGH = "High" | |
#STATE_WASHER_SPINSPEED_EXTRA_HIGH = "Extra High" | |
#STATE_WASHER_SPINSPEED_ON = 'On' | |
#STATE_WASHER_SPINSPEED_OFF = 'Off' | |
#STATE_WASHER_SPINSPEED_ULTRA = "Ultra" | |
#STATE_WASHER_SPINSPEED_DRYFIT = "Dryfit" | |
#STATE_WASHER_SPINSPEED_DELICACY = "Delicacy" | |
# | |
#STATE_WASHER_RINSECOUNT_0 = "Washer rinsecount 0" | |
#STATE_WASHER_RINSECOUNT_1 = "Washer rinsecount 1" | |
#STATE_WASHER_RINSECOUNT_2 = "Washer rinsecount 2" | |
#STATE_WASHER_RINSECOUNT_3 = "Washer rinsecount 3" | |
#STATE_WASHER_RINSECOUNT_4 = "Washer rinsecount 4" | |
#STATE_WASHER_RINSECOUNT_5 = "Washer rinsecount 5" | |
#STATE_WASHER_RINSECOUNT_6 = "Washer rinsecount 6" | |
#STATE_WASHER_RINSECOUNT_OFF = 'Off' | |
#STATE_WASHER_RINSECOUNT_1_INTENSIVE = "1" | |
#STATE_WASHER_RINSECOUNT_2_INTENSIVE = "2" | |
#STATE_WASHER_RINSECOUNT_3_INTENSIVE = "3" | |
#STATE_WASHER_RINSECOUNT_4_INTENSIVE = "4" | |
#STATE_WASHER_RINSECOUNT_5_INTENSIVE = "5" | |
# | |
#STATE_WASHER_DRYLEVEL_WIND = "Washer drylevel wind" | |
#STATE_WASHER_DRYLEVEL_TURBO = "Washer drylevel turbo" | |
#STATE_WASHER_DRYLEVEL_TIME_30 = "Washer drylevel time 30" | |
#STATE_WASHER_DRYLEVEL_TIME_60 = "Washer drylevel time 60" | |
#STATE_WASHER_DRYLEVEL_TIME_90 = "Washer drylevel time 90" | |
#STATE_WASHER_DRYLEVEL_TIME_120 = "Washer drylevel time 120" | |
#STATE_WASHER_DRYLEVEL_TIME_150 = "Washer drylevel time 150" | |
# | |
#STATE_WASHER_NO_ERROR = "No Error" | |
#STATE_WASHER_ERROR_dE2 = "Washer error de2" | |
#STATE_WASHER_ERROR_IE = "Washer error ie" | |
#STATE_WASHER_ERROR_OE = "Washer error oe" | |
#STATE_WASHER_ERROR_UE = "Washer error ue" | |
#STATE_WASHER_ERROR_FE = "Washer error fe" | |
#STATE_WASHER_ERROR_PE = "Washer error pe" | |
#STATE_WASHER_ERROR_LE = "Washer error le" | |
#STATE_WASHER_ERROR_tE = "Washer error te" | |
#STATE_WASHER_ERROR_dHE = "Washer error dhe" | |
#STATE_WASHER_ERROR_CE = "Washer error ce" | |
#STATE_WASHER_ERROR_PF = "Washer error pf" | |
#STATE_WASHER_ERROR_FF = "Washer error ff" | |
#STATE_WASHER_ERROR_dCE = "Washer error dce" | |
#STATE_WASHER_ERROR_EE = "Washer error ee" | |
#STATE_WASHER_ERROR_PS = "Washer error ps" | |
#STATE_WASHER_ERROR_dE1 = "Washer error de1" | |
#STATE_WASHER_ERROR_LOE = "Washer error loe" | |
#STATE_WASHER_ERROR_TL_DO_W = 'Washer error tl do w' | |
#STATE_WASHER_ERROR_TL_LE = 'Washer error tl le' | |
#STATE_WASHER_ERROR_TL_AE = 'Washer error tl ae' | |
#STATE_WASHER_ERROR_E7 = 'Washer error e7' | |
#STATE_WASHER_ERROR_LE1 = 'Washer error le1' | |
#STATE_WASHER_ERROR_DL = 'Washer error dl' | |
#STATE_WASHER_ERROR_E3 = 'Washer error e3' | |
# | |
#STATE_WASHER_APCOURSE_COTTON = "Washer apcourse cotton" | |
#STATE_WASHER_APCOURSE_SPEEDWASH_DRY = "Washer apcourse speedwash dry" | |
#STATE_WASHER_APCOURSE_SPEEDWASH = "Washer apcourse speedwash" | |
#STATE_WASHER_APCOURSE_SINGLE_SHIRT_DRY = "Washer apcourse single shirt dry" | |
#STATE_WASHER_APCOURSE_RINSESPIN = "Washer apcourse rinsespin" | |
#STATE_WASHER_APCOURSE_SPEEDBOIL = "Washer apcourse speedboil" | |
#STATE_WASHER_APCOURSE_ALLERGYCARE = "Washer apcourse allergycare" | |
#STATE_WASHER_APCOURSE_STEAMCLEANING = "Washer apcourse steamcleaning" | |
#STATE_WASHER_APCOURSE_BABYWEAR = "Washer apcourse babywear" | |
#STATE_WASHER_APCOURSE_BLANKET_ROB = "Washer apcourse blanket rob" | |
#STATE_WASHER_APCOURSE_UTILITY = "Washer apcourse utility" | |
#STATE_WASHER_APCOURSE_BLANKET = "Washer apcourse blanket" | |
#STATE_WASHER_APCOURSE_LINGERIE_WOOL = "Washer apcourse lingerie wool" | |
#STATE_WASHER_APCOURSE_COLDWASH = "Washer apcourse coldwash" | |
#STATE_WASHER_APCOURSE_TUBCLEAN_SANITARY = "Washer apcourse tubclean sanitary" | |
#STATE_WASHER_APCOURSE_DOWNLOAD_COUSE = "Washer apcourse download couse" | |
# | |
#STATE_WASHER_COURSE_SMALL_LOAD = "Small" | |
#STATE_WASHER_COURSE_NORMAL = "Normal" | |
#STATE_WASHER_COURSE_HEAVY_DUTY = "Heavy Duty" | |
#STATE_WASHER_COURSE_DELICATES = "Delicates" | |
#STATE_WASHER_COURSE_WATER_PROOF = "Waterproof" | |
#STATE_WASHER_COURSE_SPEED_WASH = "Speed Wash" | |
#STATE_WASHER_COURSE_BEDDING = "Bedding" | |
#STATE_WASHER_COURSE_TUB_CLEAN = "Tub Clean" | |
#STATE_WASHER_COURSE_RINSE_SPIN = "Rinse Spin" | |
#STATE_WASHER_COURSE_SPIN_ONLY = "Spin Only" | |
#STATE_WASHER_COURSE_PREWASH_PLUS = "Prewash Plus" | |
#STATE_WASHER_COURSE_UNDERWEAR = "Underwear" | |
#STATE_WASHER_COURSE_WOOL = "Wool" | |
#STATE_WASHER_COURSE_WOOL_DELICATE = "Wool Delicate" | |
#STATE_WASHER_COURSE_BOILING = "Boiling" | |
#STATE_WASHER_COURSE_BABYCARE = "Babycare" | |
#STATE_WASHER_COURSE_TUBCLEAN = "Tube clean" | |
#STATE_WASHER_COURSE_TOWEL = "Towerl" | |
#STATE_WASHER_COURSE_PREWASH_NORMAL = "Prewash Normal" | |
#STATE_WASHER_COURSE_SAFETY_NORMAL = "Saftey Normal" | |
# | |
#STATE_WASHER_SMARTCOURSE_SILENT = "Washer smartcourse silent" | |
#STATE_WASHER_SMARTCOURSE_SMALL_LOAD = "Washer smartcourse small load" | |
#STATE_WASHER_SMARTCOURSE_SKIN_CARE = "Washer smartcourse skin care" | |
#STATE_WASHER_SMARTCOURSE_RAINY_SEASON = "Washer smartcourse rainy season" | |
#STATE_WASHER_SMARTCOURSE_SWEAT_STAIN = "Washer smartcourse sweat stain" | |
#STATE_WASHER_SMARTCOURSE_SINGLE_GARMENT = "Washer smartcourse single garment" | |
#STATE_WASHER_SMARTCOURSE_SCHOOL_UNIFORM = "Washer smartcourse school uniform" | |
#STATE_WASHER_SMARTCOURSE_STATIC_REMOVAL = "Washer smartcourse static removal" | |
#STATE_WASHER_SMARTCOURSE_COLOR_CARE = "Washer smartcourse color care" | |
#STATE_WASHER_SMARTCOURSE_SPIN_ONLY = "Washer smartcourse spin only" | |
#STATE_WASHER_SMARTCOURSE_DEODORIZATION = "Washer smartcourse deodorization" | |
#STATE_WASHER_SMARTCOURSE_BEDDING_CARE = "Washer smartcourse bedding care" | |
#STATE_WASHER_SMARTCOURSE_CLOTH_CARE = "Washer smartcourse cloth care" | |
#STATE_WASHER_SMARTCOURSE_SMART_RINSE = "Washer smartcourse smart rinse" | |
#STATE_WASHER_SMARTCOURSE_ECO_WASH = "Washer smartcourse eco wash" | |
#STATE_WASHER_SMARTCOURSE_COLD_WASH = 'Washer smartcourse cold wash' | |
#STATE_WASHER_SMARTCOURSE_SOILED_ITEMS = 'Washer smartcourse soiled items' | |
#STATE_WASHER_SMARTCOURSE_SINGLE_SPEED = 'Washer smartcourse single speed' | |
#STATE_WASHER_SMARTCOURSE_COLOR_PROTECT = 'Washer smartcourse color protect' | |
#STATE_WASHER_SMARTCOURSE_CHILDREN_WEAR = "Washer smartcourse children wear" | |
#STATE_WASHER_SMARTCOURSE_SWIN_WEAR = "Washer smartcourse swim wear" | |
#STATE_WASHER_SMARTCOURSE_CURTAINS = "Washer smartcourse curtains" | |
#STATE_WASHER_SMARTCOURSE_JEAN = "Washer smartcourse jean" | |
#STATE_WASHER_SMARTCOURSE_LINGERIE = "Washer smartcourse lingerie" | |
#STATE_WASHER_SMARTCOURSE_FOOD_WASTE = "Washer smartcourse food waste" | |
#STATE_WASHER_SMARTCOURSE_HEAVY_SPIN = "Washer smartcourse heavy spin" | |
#STATE_WASHER_SMARTCOURSE_BIG_LOAD = "Washer smartcourse big load" | |
# | |
# | |
#STATE_WASHER_TERM_NO_SELECT = "N/A" | |
#STATE_WASHER_NOT_SUPPORTED = "Not Supported" | |
# | |
#STATE_WASHER_OPTIONITEM_ON = "On" | |
#STATE_WASHER_OPTIONITEM_OFF = "Off" | |
# | |
#"""DEHUMIDIFIER STATE""" | |
#STATE_DEHUM_ON = '동작 중' | |
#STATE_DEHUM_OFF = '꺼짐' | |
# | |
#STATE_DEHUM_OPMODE_SMART_DEHUM = '스마트제습' | |
#STATE_DEHUM_OPMODE_FAST_DEHUM = '쾌속제습' | |
#STATE_DEHUM_OPMODE_SILENT_DEHUM = '저소음제습' | |
#STATE_DEHUM_OPMODE_CONCENTRATION_DRY = '집중건조' | |
#STATE_DEHUM_OPMODE_CLOTHING_DRY = '의류건조' | |
#STATE_DEHUM_OPMODE_IONIZER = '공기제균' | |
# | |
#STATE_DEHUM_WINDSTRENGTH_LOW = '약풍' | |
#STATE_DEHUM_WIDESTRENGTH_HIGH = '강풍' | |
# | |
#STATE_DEHUM_AIRREMOVAL_ON = '켜짐' | |
#STATE_DEHUM_AIRREMOVAL_OFF = '꺼짐' | |
# | |
#"""WATERPURIFIER STATE""" | |
#STATE_WATERPURIFIER_COCKCLEAN_WAIT = '셀프케어 대기 중' | |
#STATE_WATERPURIFIER_COCKCLEAN_ON = '셀프케어 진행 중' | |
# | |
#"""AIRPURIFIER STATE""" | |
#STATE_AIRPURIFIER_ON = '켜짐' | |
#STATE_AIRPURIFIER_OFF = '꺼짐' | |
# | |
#STATE_AIRPURIFIER_CIRCULATOR_CLEAN = '클린부스터' | |
#STATE_AIRPURIFIER_BABY_CARE = '싱글청정' | |
#STATE_AIRPURIFIER_CLEAN = '청정모드' | |
#STATE_AIRPURIFIER_DUAL_CLEAN = '듀얼청정' | |
#STATE_AIRPURIFIER_AUTO_MODE = '오토모드' | |
# | |
#STATE_AIRPURIFIER_LOWST_LOW = '최약' | |
#STATE_AIRPURIFIER_LOWST = '미약' | |
#STATE_AIRPURIFIER_LOW = '약' | |
#STATE_AIRPURIFIER_LOW_MID = '중약' | |
#STATE_AIRPURIFIER_MID = '중' | |
#STATE_AIRPURIFIER_MID_HIGH = '중강' | |
#STATE_AIRPURIFIER_HIGH = '강' | |
#STATE_AIRPURIFIER_POWER = '파워' | |
#STATE_AIRPURIFIER_AUTO = '자동' | |
#STATE_AIRPURIFIER_LONGPOWER = '롱파워' | |
#STATE_AIRPURIFIER_SHOWER = '샤워풍' | |
#STATE_AIRPURIFIER_FOREST = '숲바람' | |
#STATE_AIRPURIFIER_TURBO = '터보' | |
#STATE_AIRPURIFIER_FASTWIND = '빠른바람' | |
# | |
#STATE_AIRPURIFIER_CIR_LOWST_LOW = '청정세기_최약' | |
#STATE_AIRPURIFIER_CIR_LOWST = '청정세기_미약' | |
#STATE_AIRPURIFIER_CIR_LOW = '청정세기_약' | |
#STATE_AIRPURIFIER_CIR_LOW_MID = '청정세기_중약' | |
#STATE_AIRPURIFIER_CIR_MID = '청정세기_중' | |
#STATE_AIRPURIFIER_CIR_MID_HIGH = '청정세기_중강' | |
#STATE_AIRPURIFIER_CIR_HIGH = '청정세기_강' | |
#STATE_AIRPURIFIER_CIR_POWER = '청정세기_파워' | |
#STATE_AIRPURIFIER_CIR_AUTO = '청정세기_자동' | |
#STATE_AIRPURIFIER_CIR_LINK = '청정세기_링크' | |
# | |
#STATE_AIRPURIFIER_TOTALAIRPOLUTION_GOOD = '좋음' | |
#STATE_AIRPURIFIER_TOTALAIRPOLUTION_NORMAL = '보통' | |
#STATE_AIRPURIFIER_TOTALAIRPOLUTION_BAD = '나쁨' | |
#STATE_AIRPURIFIER_TOTALAIRPOLUTION_VERYBAD = '매우나쁨' | |
# | |
#STATE_AIRPURIFIER_SMELL_WEEK = '약함' | |
#STATE_AIRPURIFIER_SMELL_NORMAL = '보통' | |
#STATE_AIRPURIFIER_SMELL_STRONG = '강함' | |
#STATE_AIRPURIFIER_SMELL_VERYSTRONG = '매우강함' | |
# | |
#STATE_AIRPURIFIER_NOT_SUPPORTED = '지원안함' | |
def gen_uuid(): | |
return str(uuid.uuid4()) | |
def oauth2_signature(message, secret): | |
"""Get the base64-encoded SHA-1 HMAC digest of a string, as used in | |
OAauth2 request signatures. | |
Both the `secret` and `message` are given as text strings. We use | |
their UTF-8 equivalents. | |
""" | |
secret_bytes = secret.encode('utf8') | |
hashed = hmac.new(secret_bytes, message.encode('utf8'), hashlib.sha1) | |
digest = hashed.digest() | |
return base64.b64encode(digest) | |
def as_list(obj): | |
"""Wrap non-lists in lists. | |
If `obj` is a list, return it unchanged. Otherwise, return a | |
single-element list containing it. | |
""" | |
if isinstance(obj, list): | |
return obj | |
else: | |
return [obj] | |
class APIError(Exception): | |
"""An error reported by the API.""" | |
def __init__(self, code, message): | |
self.code = code | |
self.message = message | |
class NotLoggedInError(APIError): | |
"""The session is not valid or expired.""" | |
def __init__(self): | |
pass | |
class TokenError(APIError): | |
"""An authentication token was rejected.""" | |
def __init__(self): | |
pass | |
class MonitorError(APIError): | |
"""Monitoring a device failed, possibly because the monitoring | |
session failed and needs to be restarted. | |
""" | |
def __init__(self, device_id, code): | |
self.device_id = device_id | |
self.code = code | |
class NotConnectError(APIError): | |
"""The session is not valid or expired.""" | |
def __init__(self): | |
pass | |
def lgedm_post(url, data=None, access_token=None, session_id=None): | |
"""Make an HTTP request in the format used by the API servers. | |
In this format, the request POST data sent as JSON under a special | |
key; authentication sent in headers. Return the JSON data extracted | |
from the response. | |
The `access_token` and `session_id` are required for most normal, | |
authenticated requests. They are not required, for example, to load | |
the gateway server data or to start a session. | |
""" | |
headers = { | |
'x-thinq-application-key': APP_KEY, | |
'x-thinq-security-key': SECURITY_KEY, | |
'Accept': 'application/json', | |
} | |
if access_token: | |
headers['x-thinq-token'] = access_token | |
if session_id: | |
headers['x-thinq-jsessionId'] = session_id | |
res = requests.post(url, json={DATA_ROOT: data}, headers=headers) | |
out = res.json()[DATA_ROOT] | |
# Check for API errors. | |
if 'returnCd' in out: | |
code = out['returnCd'] | |
if code != '0000': | |
message = out['returnMsg'] | |
if code == "0102": | |
raise NotLoggedInError() | |
elif code == "0106": | |
raise NotConnectError() | |
elif code == "0010": | |
return out | |
else: | |
raise APIError(code, message) | |
return out | |
def gateway_info(): | |
"""Load information about the hosts to use for API interaction. | |
""" | |
return lgedm_post( | |
GATEWAY_URL, | |
{'countryCode': COUNTRY, 'langCode': LANGUAGE}, | |
) | |
def oauth_url(auth_base): | |
"""Construct the URL for users to log in (in a browser) to start an | |
authenticated session. | |
""" | |
url = urljoin(auth_base, 'login/sign_in') | |
query = urlencode({ | |
'country': COUNTRY, | |
'language': LANGUAGE, | |
'svcCode': SVC_CODE, | |
'authSvr': 'oauth2', | |
'client_id': CLIENT_ID, | |
'division': 'ha', | |
'grant_type': 'password', | |
}) | |
return '{}?{}'.format(url, query) | |
def parse_oauth_callback(url): | |
"""Parse the URL to which an OAuth login redirected to obtain two | |
tokens: an access token for API credentials, and a refresh token for | |
getting updated access tokens. | |
""" | |
params = parse_qs(urlparse(url).query) | |
return params['access_token'][0], params['refresh_token'][0] | |
def login(api_root, access_token): | |
"""Use an access token to log into the API and obtain a session and | |
return information about the session. | |
""" | |
url = urljoin(api_root + '/', 'member/login') | |
data = { | |
'countryCode': COUNTRY, | |
'langCode': LANGUAGE, | |
'loginType': 'EMP', | |
'token': access_token, | |
} | |
return lgedm_post(url, data) | |
def refresh_auth(oauth_root, refresh_token): | |
"""Get a new access_token using a refresh_token. | |
May raise a `TokenError`. | |
""" | |
token_url = urljoin(oauth_root, '/oauth2/token') | |
data = { | |
'grant_type': 'refresh_token', | |
'refresh_token': refresh_token, | |
} | |
# The timestamp for labeling OAuth requests can be obtained | |
# through a request to the date/time endpoint: | |
# https://us.lgeapi.com/datetime | |
# But we can also just generate a timestamp. | |
timestamp = datetime.utcnow().strftime(DATE_FORMAT) | |
# The signature for the requests is on a string consisting of two | |
# parts: (1) a fake request URL containing the refresh token, and (2) | |
# the timestamp. | |
req_url = ('/oauth2/token?grant_type=refresh_token&refresh_token=' + | |
refresh_token) | |
sig = oauth2_signature('{}\n{}'.format(req_url, timestamp), | |
OAUTH_SECRET_KEY) | |
headers = { | |
'lgemp-x-app-key': OAUTH_CLIENT_KEY, | |
'lgemp-x-signature': sig, | |
'lgemp-x-date': timestamp, | |
'Accept': 'application/json', | |
} | |
res = requests.post(token_url, data=data, headers=headers) | |
res_data = res.json() | |
if res_data['status'] != 1: | |
raise TokenError() | |
return res_data['access_token'] | |
class Gateway(object): | |
def __init__(self, auth_base, api_root, oauth_root): | |
self.auth_base = auth_base | |
self.api_root = api_root | |
self.oauth_root = oauth_root | |
@classmethod | |
def discover(cls): | |
gw = gateway_info() | |
return cls(gw['empUri'], gw['thinqUri'], gw['oauthUri']) | |
def oauth_url(self): | |
return oauth_url(self.auth_base) | |
class Auth(object): | |
def __init__(self, gateway, access_token, refresh_token): | |
self.gateway = gateway | |
self.access_token = access_token | |
self.refresh_token = refresh_token | |
@classmethod | |
def from_url(cls, gateway, url): | |
"""Create an authentication using an OAuth callback URL. | |
""" | |
access_token, refresh_token = parse_oauth_callback(url) | |
return cls(gateway, access_token, refresh_token) | |
def start_session(self): | |
"""Start an API session for the logged-in user. Return the | |
Session object and a list of the user's devices. | |
""" | |
session_info = login(self.gateway.api_root, self.access_token) | |
session_id = session_info['jsessionId'] | |
return Session(self, session_id), as_list(session_info['item']) | |
def refresh(self): | |
"""Refresh the authentication, returning a new Auth object. | |
""" | |
new_access_token = refresh_auth(self.gateway.oauth_root, | |
self.refresh_token) | |
return Auth(self.gateway, new_access_token, self.refresh_token) | |
class Session(object): | |
def __init__(self, auth, session_id): | |
self.auth = auth | |
self.session_id = session_id | |
def post(self, path, data=None): | |
"""Make a POST request to the API server. | |
This is like `lgedm_post`, but it pulls the context for the | |
request from an active Session. | |
""" | |
url = urljoin(self.auth.gateway.api_root + '/', path) | |
return lgedm_post(url, data, self.auth.access_token, self.session_id) | |
def get_devices(self): | |
"""Get a list of devices associated with the user's account. | |
Return a list of dicts with information about the devices. | |
""" | |
return as_list(self.post('device/deviceList')['item']) | |
def monitor_start(self, device_id): | |
"""Begin monitoring a device's status. | |
Return a "work ID" that can be used to retrieve the result of | |
monitoring. | |
""" | |
res = self.post('rti/rtiMon', { | |
'cmd': 'Mon', | |
'cmdOpt': 'Start', | |
'deviceId': device_id, | |
'workId': gen_uuid(), | |
}) | |
return res['workId'] | |
def monitor_poll(self, device_id, work_id): | |
"""Get the result of a monitoring task. | |
`work_id` is a string ID retrieved from `monitor_start`. Return | |
a status result, which is a bytestring, or None if the | |
monitoring is not yet ready. | |
May raise a `MonitorError`, in which case the right course of | |
action is probably to restart the monitoring task. | |
""" | |
work_list = [{'deviceId': device_id, 'workId': work_id}] | |
res = self.post('rti/rtiResult', {'workList': work_list})['workList'] | |
# The return data may or may not be present, depending on the | |
# monitoring task status. | |
if 'returnData' in res: | |
# The main response payload is base64-encoded binary data in | |
# the `returnData` field. This sometimes contains JSON data | |
# and sometimes other binary data. | |
return base64.b64decode(res['returnData']) | |
else: | |
return None | |
# Check for errors. | |
code = res.get('returnCode') # returnCode can be missing. | |
if code != '0000': | |
raise MonitorError(device_id, code) | |
def monitor_stop(self, device_id, work_id): | |
"""Stop monitoring a device.""" | |
self.post('rti/rtiMon', { | |
'cmd': 'Mon', | |
'cmdOpt': 'Stop', | |
'deviceId': device_id, | |
'workId': work_id, | |
}) | |
def set_device_operation(self, device_id, values): | |
"""Control a device's settings. | |
`values` is a key/value map containing the settings to update. | |
""" | |
return self.post('rti/rtiControl', { | |
'cmd': 'Control', | |
'cmdOpt': 'Operation', | |
'value': values, | |
'deviceId': device_id, | |
'workId': gen_uuid(), | |
'data': '', | |
}) | |
def set_device_controls(self, device_id, values): | |
"""Control a device's settings. | |
`values` is a key/value map containing the settings to update. | |
""" | |
return self.post('rti/rtiControl', { | |
'cmd': 'Control', | |
'cmdOpt': 'Set', | |
'value': values, | |
'deviceId': device_id, | |
'workId': gen_uuid(), | |
'data': '', | |
}) | |
def get_device_config(self, device_id, key, category='Config'): | |
"""Get a device configuration option. | |
The `category` string should probably either be "Config" or | |
"Control"; the right choice appears to depend on the key. | |
""" | |
res = self.post('rti/rtiControl', { | |
'cmd': category, | |
'cmdOpt': 'Get', | |
'value': key, | |
'deviceId': device_id, | |
'workId': gen_uuid(), | |
'data': '', | |
}) | |
return res['returnData'] | |
def delete_permission(self, device_id): | |
self.post('rti/delControlPermission', { | |
'deviceId': device_id, | |
}) | |
def get_power_data(self, device_id, period): | |
res = self.post('aircon/inquiryPowerData', { | |
'deviceId': device_id, | |
'period': period, | |
}) | |
code = res.get('returnCd') # returnCode can be missing. | |
if code == '0000': | |
return res['powerData'] | |
elif code == '0010': | |
return '0' | |
else: | |
raise MonitorError(device_id, code) | |
def get_water_usage(self, device_id, typeCode, sDate, eDate): | |
res = self.post('rms/inquiryWaterConsumptionInfo', { | |
'deviceId': device_id, | |
'type': typeCode, | |
'startDate': sDate, | |
'endDate': eDate, | |
}) | |
code = res.get('returnCd') # returnCode can be missing. | |
if code != '0000': | |
raise MonitorError(device_id, code) | |
else: | |
return res['item'] | |
def get_outdoor_weather(self, area): | |
res = self.post('weather/weatherNewsData',{ | |
'area': area | |
}) | |
code = res.get('returnCd') # returnCode can be missing. | |
if code != '0000': | |
raise MonitorError(device_id, code) | |
else: | |
return res | |
def get_dustsensor_data(self): | |
res = self.post('v2/devices/97b2fc516b00b58c376cd8123f56cc8f/data?data=sensor.pm25%2Bsensor.pm10%2Bsensor.pm1&type=last') | |
""" | |
code = res.get('returnCd') # returnCode can be missing. | |
if code != '0000': | |
raise MonitorError(device_id, code) | |
else: | |
""" | |
print(res) | |
with open('/config/wideq-1/dust_sensor_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(res, dumpfile, ensure_ascii=False, indent="\t") | |
return res | |
class Monitor(object): | |
"""A monitoring task for a device. | |
This task is robust to some API-level failures. If the monitoring | |
task expires, it attempts to start a new one automatically. This | |
makes one `Monitor` object suitable for long-term monitoring. | |
""" | |
def __init__(self, session, device_id): | |
self.session = session | |
self.device_id = device_id | |
def start(self): | |
self.work_id = self.session.monitor_start(self.device_id) | |
def stop(self): | |
self.session.monitor_stop(self.device_id, self.work_id) | |
def poll(self): | |
"""Get the current status data (a bytestring) or None if the | |
device is not yet ready. | |
""" | |
self.work_id = self.session.monitor_start(self.device_id) | |
try: | |
return self.session.monitor_poll(self.device_id, self.work_id) | |
except MonitorError: | |
# Try to restart the task. | |
self.stop() | |
self.start() | |
return None | |
@staticmethod | |
def decode_json(data): | |
"""Decode a bytestring that encodes JSON status data.""" | |
return json.loads(data.decode('utf8')) | |
def poll_json(self): | |
"""For devices where status is reported via JSON data, get the | |
decoded status result (or None if status is not available). | |
""" | |
data = self.poll() | |
return self.decode_json(data) if data else None | |
def __enter__(self): | |
self.start() | |
return self | |
def __exit__(self, type, value, tb): | |
self.stop() | |
class Client(object): | |
"""A higher-level API wrapper that provides a session more easily | |
and allows serialization of state. | |
""" | |
def __init__(self, gateway=None, auth=None, session=None): | |
# The three steps required to get access to call the API. | |
self._gateway = gateway | |
self._auth = auth | |
self._session = session | |
# The last list of devices we got from the server. This is the | |
# raw JSON list data describing the devices. | |
self._devices = None | |
# Cached model info data. This is a mapping from URLs to JSON | |
# responses. | |
self._model_info = {} | |
@property | |
def gateway(self): | |
if not self._gateway: | |
self._gateway = Gateway.discover() | |
return self._gateway | |
@property | |
def auth(self): | |
if not self._auth: | |
assert False, "unauthenticated" | |
return self._auth | |
@property | |
def session(self): | |
if not self._session: | |
self._session, self._devices = self.auth.start_session() | |
return self._session | |
@property | |
def devices(self): | |
"""DeviceInfo objects describing the user's devices. | |
""" | |
if not self._devices: | |
self._devices = self.session.get_devices() | |
return (DeviceInfo(d) for d in self._devices) | |
def get_device(self, device_id): | |
"""Look up a DeviceInfo object by device ID. | |
Return None if the device does not exist. | |
""" | |
for device in self.devices: | |
if device.id == device_id: | |
return device | |
return None | |
@classmethod | |
def load(cls, state): | |
"""Load a client from serialized state. | |
""" | |
client = cls() | |
if 'gateway' in state: | |
data = state['gateway'] | |
client._gateway = Gateway( | |
data['auth_base'], data['api_root'], data['oauth_root'] | |
) | |
if 'auth' in state: | |
data = state['auth'] | |
client._auth = Auth( | |
client.gateway, data['access_token'], data['refresh_token'] | |
) | |
if 'session' in state: | |
client._session = Session(client.auth, state['session']) | |
if 'model_info' in state: | |
client._model_info = state['model_info'] | |
return client | |
def dump(self): | |
"""Serialize the client state.""" | |
out = { | |
'model_info': self._model_info, | |
} | |
if self._gateway: | |
out['gateway'] = { | |
'auth_base': self._gateway.auth_base, | |
'api_root': self._gateway.api_root, | |
'oauth_root': self._gateway.oauth_root, | |
} | |
if self._auth: | |
out['auth'] = { | |
'access_token': self._auth.access_token, | |
'refresh_token': self._auth.refresh_token, | |
} | |
if self._session: | |
out['session'] = self._session.session_id | |
return out | |
def refresh(self): | |
self._auth = self.auth.refresh() | |
self._session, self._devices = self.auth.start_session() | |
@classmethod | |
def from_token(cls, refresh_token): | |
"""Construct a client using just a refresh token. | |
This allows simpler state storage (e.g., for human-written | |
configuration) but it is a little less efficient because we need | |
to reload the gateway servers and restart the session. | |
""" | |
client = cls() | |
client._auth = Auth(client.gateway, None, refresh_token) | |
client.refresh() | |
return client | |
def model_info(self, device): | |
"""For a DeviceInfo object, get a ModelInfo object describing | |
the model's capabilities. | |
""" | |
url = device.model_info_url | |
if url not in self._model_info: | |
self._model_info[url] = device.load_model_info() | |
return ModelInfo(self._model_info[url]) | |
class DeviceType(enum.Enum): | |
"""The category of device.""" | |
REFRIGERATOR = 101 | |
KIMCHI_REFRIGERATOR = 102 | |
WATER_PURIFIER = 103 | |
WASHER = 201 | |
DRYER = 202 | |
STYLER = 203 | |
DISHWASHER = 204 | |
OVEN = 301 | |
MICROWAVE = 302 | |
COOKTOP = 303 | |
HOOD = 304 | |
AC = 401 | |
AIR_PURIFIER = 402 | |
DEHUMIDIFIER = 403 | |
ROBOT_KING = 501 | |
TV = 701 | |
BOILER = 801 | |
SPEAKER = 901 | |
HOMEVU = 902 | |
ARCH = 1001 | |
MISSG = 3001 | |
SENSOR = 3002 | |
SOLAR_SENSOR = 3102 | |
IOT_LIGHTING = 3003 | |
IOT_MOTION_SENSOR = 3004 | |
IOT_SMART_PLUG = 3005 | |
IOT_DUST_SENSOR = 3006 | |
EMS_AIR_STATION = 4001 | |
AIR_SENSOR = 4003 | |
PURICARE_AIR_DETECTOR = 4004 | |
V2PHONE = 6001 | |
HOMEROBOT = 9000 | |
class DeviceInfo(object): | |
"""Details about a user's device. | |
This is populated from a JSON dictionary provided by the API. | |
""" | |
def __init__(self, data): | |
self.data = data | |
@property | |
def model_id(self): | |
return self.data['modelNm'] | |
@property | |
def id(self): | |
return self.data['deviceId'] | |
@property | |
def model_info_url(self): | |
return self.data['modelJsonUrl'] | |
@property | |
def name(self): | |
return self.data['alias'] | |
@property | |
def macaddress(self): | |
return self.data['macAddress'] | |
@property | |
def model_name(self): | |
return self.data['modelNm'] | |
@property | |
def type(self): | |
"""The kind of device, as a `DeviceType` value.""" | |
""" | |
with open('/config/wideq-1/device_info.json','w', encoding="utf-8") as dumpfile: | |
json.dump(self.data, dumpfile, ensure_ascii=False, indent="\t") | |
""" | |
return DeviceType(self.data['deviceType']) | |
def load_model_info(self): | |
"""Load JSON data describing the model's capabilities. | |
""" | |
return requests.get(self.model_info_url).json() | |
EnumValue = namedtuple('EnumValue', ['options']) | |
RangeValue = namedtuple('RangeValue', ['min', 'max', 'step']) | |
BitValue = namedtuple('BitValue', ['options']) | |
ReferenceValue = namedtuple('ReferenceValue', ['reference']) | |
class ModelInfo(object): | |
"""A description of a device model's capabilities. | |
""" | |
def __init__(self, data): | |
self.data = data | |
@property | |
def model_type(self): | |
return self.data['Info']['modelType'] | |
def value_type(self, name): | |
if name in self.data['Value']: | |
return self.data['Value'][name]['type'] | |
else: | |
return None | |
def value(self, name): | |
"""Look up information about a value. | |
Return either an `EnumValue` or a `RangeValue`. | |
""" | |
d = self.data['Value'][name] | |
if d['type'] in ('Enum', 'enum'): | |
return EnumValue(d['option']) | |
elif d['type'] == 'Range': | |
return RangeValue(d['option']['min'], d['option']['max'], d['option']['step']) | |
elif d['type'] == 'Bit': | |
bit_values = {} | |
for bit in d['option']: | |
bit_values[bit['startbit']] = { | |
'value' : bit['value'], | |
'length' : bit['length'], | |
} | |
return BitValue( | |
bit_values | |
) | |
elif d['type'] == 'Reference': | |
ref = d['option'][0] | |
return ReferenceValue( | |
self.data[ref] | |
) | |
elif d['type'] == 'Boolean': | |
return EnumValue({'0': 'False', '1' : 'True'}) | |
elif d['type'] == 'String': | |
pass | |
else: | |
assert False, "unsupported value type {}".format(d['type']) | |
def default(self, name): | |
"""Get the default value, if it exists, for a given value. | |
""" | |
return self.data['Value'][name]['default'] | |
def option_item(self, name): | |
"""Get the default value, if it exists, for a given value. | |
""" | |
options = self.value(name).options | |
return options | |
def enum_value(self, key, name): | |
"""Look up the encoded value for a friendly enum name. | |
""" | |
options = self.value(key).options | |
options_inv = {v: k for k, v in options.items()} # Invert the map. | |
return options_inv[name] | |
def enum_name(self, key, value): | |
"""Look up the friendly enum name for an encoded value. | |
""" | |
if not self.value_type(key): | |
return str(value) | |
options = self.value(key).options | |
return options[value] | |
def range_name(self, key): | |
"""Look up the value of a RangeValue. Not very useful other than for comprehension | |
""" | |
return key | |
def bit_name(self, key, bit_index, value): | |
"""Look up the friendly name for an encoded bit value | |
""" | |
if not self.value_type(key): | |
return str(value) | |
options = self.value(key).options | |
if not self.value_type(options[bit_index]['value']): | |
return str(value) | |
enum_options = self.value(options[bit_index]['value']).options | |
return enum_options[value] | |
def reference_name(self, key, value): | |
"""Look up the friendly name for an encoded reference value | |
""" | |
value = str(value) | |
if not self.value_type(key): | |
return value | |
reference = self.value(key).reference | |
if value in reference: | |
comment = reference[value]['name'] | |
return comment if comment else reference[value]['_comment'] | |
else: | |
return '-' | |
def reference_comment(self, key, value): | |
"""Look up the friendly name for an encoded reference value | |
""" | |
value = str(value) | |
if not self.value_type(key): | |
return value | |
reference = self.value(key).reference | |
if value in reference: | |
comment = reference[value]['_comment'] | |
return comment if comment else reference[value]['label'] | |
else: | |
return '-' | |
@property | |
def binary_monitor_data(self): | |
"""Check that type of monitoring is BINARY(BYTE). | |
""" | |
return self.data['Monitoring']['type'] == 'BINARY(BYTE)' | |
def decode_monitor_binary(self, data): | |
"""Decode binary encoded status data. | |
""" | |
decoded = {} | |
for item in self.data['Monitoring']['protocol']: | |
key = item['value'] | |
value = 0 | |
for v in data[item['startByte']:item['startByte'] + item['length']]: | |
value = (value << 8) + v | |
decoded[key] = str(value) | |
return decoded | |
def decode_monitor_json(self, data): | |
"""Decode a bytestring that encodes JSON status data.""" | |
return json.loads(data.decode('utf8')) | |
def decode_monitor(self, data): | |
"""Decode status data.""" | |
if self.binary_monitor_data: | |
return self.decode_monitor_binary(data) | |
else: | |
return self.decode_monitor_json(data) | |
class Device(object): | |
"""A higher-level interface to a specific device. | |
Unlike `DeviceInfo`, which just stores data *about* a device, | |
`Device` objects refer to their client and can perform operations | |
regarding the device. | |
""" | |
def __init__(self, client, device): | |
"""Create a wrapper for a `DeviceInfo` object associated with a | |
`Client`. | |
""" | |
self.client = client | |
self.device = device | |
self.model = client.model_info(device) | |
def _set_operation(self, value): | |
"""Set a device's operation for a given `value`. | |
""" | |
self.client.session.set_device_controls( | |
self.device.id, | |
value, | |
) | |
def _set_control(self, key, value): | |
"""Set a device's control for `key` to `value`. | |
""" | |
self.client.session.set_device_controls( | |
self.device.id, | |
{key: value}, | |
) | |
def _set_control_ac_wdirstep(self, key, value): | |
"""Set a device's control for `key` to `value`. | |
""" | |
self.client.session.set_device_controls( | |
self.device.id, | |
{key: value}, | |
) | |
def _get_config(self, key): | |
"""Look up a device's configuration for a given value. | |
The response is parsed as base64-encoded JSON. | |
""" | |
data = self.client.session.get_device_config( | |
self.device.id, | |
key, | |
) | |
return json.loads(base64.b64decode(data).decode('utf8')) | |
def _get_control(self, key): | |
"""Look up a device's control value. | |
""" | |
data = self.client.session.get_device_config( | |
self.device.id, | |
key, | |
'Control', | |
) | |
# The response comes in a funky key/value format: "(key:value)". | |
_, value = data[1:-1].split(':') | |
return value | |
def _delete_permission(self): | |
self.client.session.delete_permission( | |
self.device.id, | |
) | |
def _get_power_data(self, sDate, eDate): | |
period = 'Day_'+sDate+'T000000Z/'+eDate+'T000000Z' | |
data = self.client.session.get_power_data( | |
self.device.id, | |
period, | |
) | |
return data | |
def _get_water_usage(self, typeCode, sDate, eDate): | |
data = self.client.session.get_water_usage( | |
self.device.id, | |
typeCode, | |
sDate, | |
eDate, | |
) | |
return data | |
def _get_dustsensor_data(self): | |
data = self.client.session.get_dustsensor_data() | |
""" | |
code = res.get('returnCd') # returnCode can be missing. | |
if code != '0000': | |
raise MonitorError(device_id, code) | |
else: | |
""" | |
print(data) | |
with open('/config/wideq-1/dust_sensor_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(data, dumpfile, ensure_ascii=False, indent="\t") | |
return data | |
"""------------------for Air Conditioner""" | |
class ACMode(enum.Enum): | |
"""The operation mode for an AC/HVAC device.""" | |
OFF = "@OFF" | |
NOT_SUPPORTED = "@NON" | |
COOL = "@AC_MAIN_OPERATION_MODE_COOL_W" | |
DRY = "@AC_MAIN_OPERATION_MODE_DRY_W" | |
FAN = "@AC_MAIN_OPERATION_MODE_FAN_W" | |
AI = "@AC_MAIN_OPERATION_MODE_AI_W" | |
HEAT = "@AC_MAIN_OPERATION_MODE_HEAT_W" | |
AIRCLEAN = "@AC_MAIN_OPERATION_MODE_AIRCLEAN_W" | |
ACO = "@AC_MAIN_OPERATION_MODE_ACO_W" | |
AROMA = "@AC_MAIN_OPERATION_MODE_AROMA_W" | |
ENERGY_SAVING = "@AC_MAIN_OPERATION_MODE_ENERGY_SAVING_W" | |
SMARTCARE = "@AC_MAIN_WIND_MODE_SMARTCARE_W" | |
ICEVALLEY = "@AC_MAIN_WIND_MODE_ICEVALLEY_W" | |
LONGPOWER = "@AC_MAIN_WIND_MODE_LONGPOWER_W" | |
class ACWindstrength(enum.Enum): | |
"""The wind strength mode for an AC/HVAC device.""" | |
NOT_SUPPORTED = "@NON" | |
FIX = "@AC_MAIN_WIND_DIRECTION_FIX_W" | |
LOW = "@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W" | |
MID = "@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|AC_MAIN_WIND_STRENGTH_MID_RIGHT_W" | |
HIGH = "@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W" | |
COOLPOWER = "@AC_MAIN_WIND_STRENGTH_POWER_LEFT_W|AC_MAIN_WIND_STRENGTH_POWER_RIGHT_W" | |
LONGPOWER ="@AC_MAIN_WIND_STRENGTH_LONGPOWER_LEFT_W|AC_MAIN_WIND_STRENGTH_LONGPOWER_RIGHT_W" | |
AUTO = "@AC_MAIN_WIND_STRENGTH_AUTO_LEFT_W|AC_MAIN_WIND_STRENGTH_AUTO_RIGHT_W" | |
RIGHT_LOW_LEFT_MID = "@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W" | |
RIGHT_LOW_LEFT_HIGH = "@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W" | |
RIGHT_MID_LEFT_LOW = "@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|AC_MAIN_WIND_STRENGTH_MID_RIGHT_W" | |
RIGHT_MID_LEFT_HIGH = "@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|AC_MAIN_WIND_STRENGTH_MID_RIGHT_W" | |
RIGHT_HIGH_LEFT_LOW = "@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W" | |
RIGHT_HIGH_LEFT_MID = "@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W" | |
RIGHT_ONLY_LOW = "@AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W" | |
RIGHT_ONLY_MID = "@AC_MAIN_WIND_STRENGTH_MID_RIGHT_W" | |
RIGHT_ONLY_HIGH = "@AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W" | |
LEFT_ONLY_LOW = "@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W" | |
LEFT_ONLY_MID = "@AC_MAIN_WIND_STRENGTH_MID_LEFT_W" | |
LEFT_ONLY_HIGH = "@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W" | |
SYSTEM_SLOW = "@AC_MAIN_WIND_STRENGTH_SLOW_W" | |
SYSTEM_LOW = "@AC_MAIN_WIND_STRENGTH_LOW_W" | |
SYSTEM_MID = "@AC_MAIN_WIND_STRENGTH_MID_W" | |
SYSTEM_HIGH = "@AC_MAIN_WIND_STRENGTH_HIGH_W" | |
SYSTEM_POWER = "@AC_MAIN_WIND_STRENGTH_POWER_W" | |
SYSTEM_AUTO = "@AC_MAIN_WIND_STRENGTH_AUTO_W" | |
SYSTEM_LOW_CLEAN = "@AC_MAIN_WIND_STRENGTH_LOW_CLEAN_W" | |
SYSTEM_MID_CLEAN = "@AC_MAIN_WIND_STRENGTH_MID_CLEAN_W" | |
SYSTEM_HIGH_CLEAN = "@AC_MAIN_WIND_STRENGTH_HIGH_CLEAN_W" | |
class ACSwingMode(enum.Enum): | |
FIX = "@AC_MAIN_WIND_DIRECTION_FIX_W" | |
UPDOWN = "@AC_MAIN_WIND_DIRECTION_UP_DOWN_W" | |
LEFTRIGHT = "@AC_MAIN_WIND_DIRECTION_LEFT_RIGHT_W" | |
class ACReserveMode(enum.Enum): | |
NONE = "@NON" | |
SLEEPTIMER = "@SLEEP_TIMER" | |
EASYTIMER = "@EASY_TIMER" | |
ONOFFTIMER = "@ONOFF_TIMER" | |
TIMEBS = "@TIMEBS_ONOFF" | |
WEEKLYSCHEDULE = "@WEEKLY_SCHEDULE" | |
class ACEXTRAMode(enum.Enum): | |
NONE = "@NON" | |
POWERSAVE = "@ENERGYSAVING" | |
AUTODRY = "@AUTODRY" | |
AIRCLEAN = "@AIRCLEAN" | |
ECOMODE = "@ECOMODE" | |
POWERSAVEDRY = "@ENERGYSAVINGDRY" | |
INDIVIDUALCTRL = "@INDIVIDUALCTRL" | |
COMBINATION_OF_COMMAND = "@COMBINATION_OF_COMMAND" | |
QUITE_MODE = "@QUITE_MODE" | |
class ACRACSubMode(enum.Enum): | |
NONE = "@NON" | |
UP_DOWN = "@AC_MAIN_WIND_DIRECTION_SWING_UP_DOWN_W" | |
LEFT_RIGHT = "@AC_MAIN_WIND_DIRECTION_SWING_LEFT_RIGHT_W" | |
JET = "@AC_MAIN_WIND_MODE_JET_W" | |
class ACAirPolution(enum.Enum): | |
NONE = "@NON" | |
MONITORING_SUPPORT = "@SENSOR_MONITORING_SET_SUPPORT" | |
TOTALCLEAN_SUPPORT = "@TOTAL_CLEAN_SUPPORT" | |
PM1_SUPPORT = "@PM1_0_SUPPORT" | |
PM10_SUPPORT = "@PM10_SUPPORT" | |
PM2_SUPPORT = "@PM2_5_SUPPORT" | |
SENSOR_HUMID_SUPPORT = "@SENSOR_HUMID_SUPPORT" | |
YELLOW_DUST_MON_SUPPORT = "@YELLOW_DUST_MON_SUPPORT" | |
class ACOp(enum.Enum): | |
"""Whether a device is on or off.""" | |
OFF = "@AC_MAIN_OPERATION_OFF_W" | |
RIGHT_ON = "@AC_MAIN_OPERATION_RIGHT_ON_W" | |
LEFT_ON = "@AC_MAIN_OPERATION_LEFT_ON_W" | |
ALL_ON = "@AC_MAIN_OPERATION_ALL_ON_W" | |
class AIRCLEAN(enum.Enum): | |
OFF = "@AC_MAIN_AIRCLEAN_OFF_W" | |
ON = "@AC_MAIN_AIRCLEAN_ON_W" | |
class WDIRLEFTRIGHT(enum.Enum): | |
LEFT_RIGHT_STOP = "@OFF" | |
LEFT_RIGTH_ON = "@ON" | |
RIGHTSIDE_LEFT_RIGHT = "@RIGHT_ON" | |
LEFTSIDE_LEFT_RIGHT = "@LEFT_ON" | |
LEFT_RIGHT = "@ALL_ON" | |
class WDIRVSTEP(enum.Enum): | |
OFF = "0" | |
FIRST = "1" | |
SECOND = "2" | |
THIRD = "3" | |
FOURTH = "4" | |
FIFTH = "5" | |
SIXTH = "6" | |
AUTO = "100" | |
class WDIRHSTEP(enum.Enum): | |
OFF = "0" | |
FIRST = "1" | |
SECOND = "2" | |
THIRD = "3" | |
FOURTH = "4" | |
FIFTH = "5" | |
THIRTEENTH = "13" | |
THIRTYFIFTH = "35" | |
AUTO = "100" | |
class FOURVAIN_WDIRVSTEP(enum.Enum): | |
OFF = "0" | |
FIRST = "8737" | |
SECOND = "8738" | |
THIRD = "8739" | |
FOURTH = "8740" | |
FIFTH = "8741" | |
SIXTH = "8742" | |
class ACETCMODE(enum.Enum): | |
OFF = "@OFF" | |
ON = "@ON" | |
class ACDevice(Device): | |
"""Higher-level operations on an AC/HVAC device, such as a heat | |
pump. | |
""" | |
@property | |
def f2c(self): | |
"""Get a dictionary mapping Fahrenheit to Celsius temperatures for | |
this device. | |
Unbelievably, SmartThinQ devices have their own lookup tables | |
for mapping the two temperature scales. You can get *close* by | |
using a real conversion between the two temperature scales, but | |
precise control requires using the custom LUT. | |
""" | |
mapping = self.model.value('TempFahToCel').options | |
return {int(f): c for f, c in mapping.items()} | |
@property | |
def c2f(self): | |
"""Get an inverse mapping from Celsius to Fahrenheit. | |
Just as unbelievably, this is not exactly the inverse of the | |
`f2c` map. There are a few values in this reverse mapping that | |
are not in the other. | |
""" | |
mapping = self.model.value('TempCelToFah').options | |
out = {} | |
for c, f in mapping.items(): | |
try: | |
c_num = int(c) | |
except ValueError: | |
c_num = float(c) | |
out[c_num] = f | |
return out | |
def set_celsius(self, c): | |
"""Set the device's target temperature in Celsius degrees. | |
""" | |
self._set_control('TempCfg', c) | |
def set_fahrenheit(self, f): | |
"""Set the device's target temperature in Fahrenheit degrees. | |
""" | |
self.set_celsius(self.f2c[f]) | |
def set_on(self, is_on): | |
"""Turn on or off the device (according to a boolean). | |
""" | |
op = ACOp.ALL_ON if is_on else ACOp.OFF | |
op_value = self.model.enum_value('Operation', op.value) | |
self._set_control('Operation', op_value) | |
def set_mode(self, mode): | |
"""Set the device's operating mode to an `OpMode` value. | |
""" | |
mode_value = self.model.enum_value('OpMode', mode.value) | |
self._set_control('OpMode', mode_value) | |
def set_windstrength(self, mode): | |
"""Set the device's operating mode to an `windstrength` value. | |
""" | |
windstrength_value = self.model.enum_value('WindStrength', mode.value) | |
self._set_control('WindStrength', windstrength_value) | |
def set_wind_leftright(self, mode): | |
wdir_value = self.model.enum_value('WDirLeftRight', mode.value) | |
self._set_control('WDirLeftRight', wdir_value) | |
def set_wdirhstep(self, mode): | |
self._set_control_ac_wdirstep('WDirHStep',int(mode.value)) | |
def set_wdirvstep(self, mode): | |
self._set_control_ac_wdirstep('WDirVStep',int(mode.value)) | |
def set_airclean(self, is_on): | |
mode = AIRCLEAN.ON if is_on else AIRCLEAN.OFF | |
mode_value = self.model.enum_value('AirClean', mode.value) | |
self._set_control('AirClean', mode_value) | |
def set_etc_mode(self, name, is_on): | |
mode = ACETCMODE.ON if is_on else ACETCMODE.OFF | |
mode_value = self.model.enum_value(name, mode.value) | |
self._set_control(name, mode_value) | |
def set_sleep_time(self, sleeptime): | |
self._set_control('SleepTime', sleeptime) | |
def get_filter_state(self): | |
"""Get information about the filter.""" | |
return self._get_config('Filter') | |
def get_mfilter_state(self): | |
"""Get information about the "MFilter" (not sure what this is). | |
""" | |
return self._get_config('MFilter') | |
def get_energy_target(self): | |
"""Get the configured energy target data.""" | |
return self._get_config('EnergyDesiredValue') | |
def get_light(self): | |
"""Get a Boolean indicating whether the display light is on.""" | |
value = self._get_control('DisplayControl') | |
return value == '0' # Seems backwards, but isn't. | |
def get_volume(self): | |
"""Get the speaker volume level.""" | |
value = self._get_control('SpkVolume') | |
return int(value) | |
def monitor_start(self): | |
"""Start monitoring the device's status.""" | |
self.mon = Monitor(self.client.session, self.device.id) | |
self.mon.start() | |
def monitor_stop(self): | |
"""Stop monitoring the device's status.""" | |
self.mon.stop() | |
def delete_permission(self): | |
self._delete_permission() | |
def get_outdoor_weather(self, area): | |
data = self.client.session.get_outdoor_weather(area) | |
return data | |
def get_dustsensor(self, device_id): | |
data = self.client.session.get_dustsensor_data(device_id) | |
def get_energy_usage_day(self): | |
sDate = datetime.today().strftime("%Y%m%d") | |
eDate = sDate | |
data = self._get_power_data(sDate, eDate) | |
if data == '0': | |
return data | |
else: | |
energy_data = data.split('_') | |
energy = int(energy_data[2]) | |
return energy | |
def get_usage_time_day(self): | |
sDate = datetime.today().strftime("%Y%m%d") | |
eDate = sDate | |
data = self._get_power_data(sDate, eDate) | |
if data == '0': | |
return data | |
else: | |
time_data = data.split('_') | |
time = int(energy_data[1]) | |
return time | |
def get_energy_usage_week(self): | |
weekday = datetime.today().weekday() | |
startdate = datetime.today() + timedelta(days=-(weekday+1)) | |
enddate = datetime.today() + timedelta(days=(6-(weekday+1))) | |
sDate = datetime.date(startdate).strftime("%Y%m%d") | |
eDate = datetime.date(enddate).strftime("%Y%m%d") | |
data = self._get_power_data(sDate, eDate) | |
if data == '0': | |
return data | |
else: | |
value = data.split('/') | |
value_no = len(value) | |
energy = [] | |
i = 0 | |
for i in range(0, value_no): | |
energy_data = value[i].split('_') | |
energy.append(int(energy_data[2])) | |
i = i+1 | |
energy_sum = sum(energy) | |
return energy_sum | |
def get_usage_time_week(self): | |
weekday = datetime.today().weekday() | |
startdate = datetime.today() + timedelta(days=-(weekday+1)) | |
enddate = datetime.today() + timedelta(days=(6-(weekday+1))) | |
sDate = datetime.date(startdate).strftime("%Y%m%d") | |
eDate = datetime.date(enddate).strftime("%Y%m%d") | |
data = self._get_power_data(sDate, eDate) | |
if data == '0': | |
return data | |
else: | |
value = data.split('/') | |
value_no = len(value) | |
time = [] | |
i = 0 | |
for i in range(0, value_no): | |
time_data = value[i].split('_') | |
time.append(int(time_data[1])) | |
i = i+1 | |
time_sum = sum(time) | |
return time_sum | |
def get_energy_usage_month(self): | |
weekday = datetime.today().weekday() | |
startdate = datetime.today().replace(day=1) | |
sDate = datetime.date(startdate).strftime("%Y%m%d") | |
eDate = datetime.today().strftime("%Y%m%d") | |
data = self._get_power_data(sDate, eDate) | |
if data == '0': | |
return data | |
else: | |
value = data.split('/') | |
value_no = len(value) | |
energy = [] | |
i = 0 | |
for i in range(0, value_no): | |
energy_data = value[i].split('_') | |
energy.append(int(energy_data[2])) | |
i = i+1 | |
energy_sum = sum(energy) | |
return energy_sum | |
def get_usage_time_month(self): | |
weekday = datetime.today().weekday() | |
startdate = datetime.today().replace(day=1) | |
sDate = datetime.date(startdate).strftime("%Y%m%d") | |
eDate = datetime.today().strftime("%Y%m%d") | |
data = self._get_power_data(sDate, eDate) | |
if data == '0': | |
return data | |
else: | |
value = data.split('/') | |
value_no = len(value) | |
time = [] | |
i = 0 | |
for i in range(0, value_no): | |
time_data = value[i].split('_') | |
time.append(int(time_data[1])) | |
i = i+1 | |
time_sum = sum(time) | |
return time_sum | |
def get_outtotalinstantpower(self): | |
value = self._get_config('OutTotalInstantPower') | |
return value['OutTotalInstantPower'] | |
def get_inoutinstantpower(self): | |
value = self._get_config('InOutInstantPower') | |
return value['InOutInstantPower'] | |
def poll(self): | |
"""Poll the device's current state. | |
Monitoring must be started first with `monitor_start`. Return | |
either an `ACStatus` object or `None` if the status is not yet | |
available. | |
""" | |
data = self.mon.poll() | |
if data: | |
res = self.model.decode_monitor(data) | |
""" | |
with open('/config/wideq/hvac_polled_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(res, dumpfile, ensure_ascii=False, indent="\t") | |
""" | |
return ACStatus(self, res) | |
else: | |
return None | |
class ACStatus(object): | |
"""Higher-level information about an AC device's current status. | |
""" | |
def __init__(self, ac, data): | |
self.ac = ac | |
self.data = data | |
@staticmethod | |
def _str_to_num(s): | |
"""Convert a string to either an `int` or a `float`. | |
Troublingly, the API likes values like "18", without a trailing | |
".0",LEF for whole numbers. So we use `int`s for integers and | |
`float`s for non-whole numbers. | |
""" | |
f = float(s) | |
if f == int(f): | |
return int(f) | |
else: | |
return f | |
@property | |
def is_on(self): | |
op = ACOp(self.lookup_enum('Operation')) | |
return op != ACOp.OFF | |
@property | |
def temp_cur_c(self): | |
return self._str_to_num(self.data['TempCur']) | |
@property | |
def temp_cur_f(self): | |
return self.ac.c2f[self.temp_cur_c] | |
@property | |
def temp_cfg_c(self): | |
return self._str_to_num(self.data['TempCfg']) | |
@property | |
def temp_cfg_f(self): | |
return self.ac.c2f[self.temp_cfg_c] | |
def lookup_enum(self, key): | |
return self.ac.model.enum_name(key, self.data.get(key, '-')) | |
@property | |
def support_oplist(self): | |
dict_support_opmode = self.ac.model.option_item('SupportOpMode') | |
support_opmode = [] | |
for option in dict_support_opmode.values(): | |
support_opmode.append(ACMode(option).name) | |
return support_opmode | |
@property | |
def support_windmode(self): | |
dict_support_windmode = self.ac.model.option_item('SupportWindMode') | |
support_windmode = [] | |
for option in dict_support_windmode.values(): | |
support_windmode.append(ACMode(option).name) | |
return support_windmode | |
@property | |
def support_fanlist(self): | |
dict_support_fanmode = self.ac.model.option_item('SupportWindStrength') | |
support_fanmode = [] | |
for option in dict_support_fanmode.values(): | |
support_fanmode.append(ACWindstrength(option).name) | |
return support_fanmode | |
@property | |
def support_swingmode(self): | |
dict_support_swingmode = self.ac.model.option_item('SupportWindDir') | |
support_swingmode = [] | |
for option in dict_support_swingmode.values(): | |
support_swingmode.append(ACSwingMode(option).name) | |
return support_swingmode | |
@property | |
def support_pacmode(self): | |
if self.ac.model.model_type == 'PAC': | |
dict_support_pacmode = self.ac.model.option_item('SupportPACMode') | |
support_pacmode = [] | |
for option in dict_support_pacmode.values(): | |
support_pacmode.append(ACEXTRAMode(option).name) | |
return support_pacmode | |
@property | |
def support_racmode(self): | |
if self.ac.model.model_type == 'RAC': | |
dict_support_racmode = self.ac.model.option_item('SupportRACMode') | |
support_racmode = [] | |
for option in dict_support_racmode.values(): | |
support_racmode.append(ACEXTRAMode(option).name) | |
return support_racmode | |
@property | |
def support_racsubmode(self): | |
if self.ac.model.model_type == 'RAC' or self.ac.model.model_type == 'SAC_CST': | |
dict_support_racsubmode = self.ac.model.option_item('SupportRACSubMode') | |
support_racsubmode = [] | |
for option in dict_support_racsubmode.values(): | |
support_racsubmode.append(ACRACSubMode(option).name) | |
return support_racsubmode | |
@property | |
def support_reservemode(self): | |
dict_support_reservemode = self.ac.model.option_item('SupportReserve') | |
support_reservemode = [] | |
for option in dict_support_reservemode.values(): | |
support_reservemode.append(ACReserveMode(option).name) | |
return support_reservemode | |
@property | |
def support_airpolution(self): | |
dict_support_airpolution = self.ac.model.option_item('SupportAirPolution') | |
support_airpolution = [] | |
for option in dict_support_airpolution.values(): | |
support_airpolution.append(ACAirPolution(option).name) | |
return support_airpolution | |
@property | |
def mode(self): | |
return ACMode(self.lookup_enum('OpMode')) | |
@property | |
def windstrength_state(self): | |
return ACWindstrength(self.lookup_enum('WindStrength')) | |
@property | |
def wdirleftright_state(self): | |
return WDIRLEFTRIGHT(self.lookup_enum('WDirLeftRight')) | |
@property | |
def wdirupdown_state(self): | |
return ACETCMODE(self.lookup_enum('WDirUpDown')) | |
@property | |
def airclean_state(self): | |
return AIRCLEAN(self.lookup_enum('AirClean')) | |
@property | |
def wdirvstep_state(self): | |
return WDIRVSTEP(self.data['WDirVStep']) | |
@property | |
def wdirhstep_state(self): | |
return WDIRHSTEP(self.data['WDirHStep']) | |
@property | |
def fourvain_wdirvstep_state(self): | |
return FOURVAIN_WDIRVSTEP(self.data['WDirVStep']) | |
@property | |
def sac_airclean_state(self): | |
return ACETCMODE(self.lookup_enum('AirClean')) | |
@property | |
def icevalley_state(self): | |
return ACETCMODE(self.lookup_enum('IceValley')) | |
@property | |
def longpower_state(self): | |
return ACETCMODE(self.lookup_enum('FlowLongPower')) | |
@property | |
def autodry_state(self): | |
return ACETCMODE(self.lookup_enum('AutoDry')) | |
@property | |
def smartcare_state(self): | |
return ACETCMODE(self.lookup_enum('SmartCare')) | |
@property | |
def sensormon_state(self): | |
return ACETCMODE(self.lookup_enum('SensorMon')) | |
@property | |
def powersave_state(self): | |
return ACETCMODE(self.lookup_enum('PowerSave')) | |
@property | |
def jet_state(self): | |
return ACETCMODE(self.lookup_enum('Jet')) | |
@property | |
def humidity(self): | |
return self.data['SensorHumidity'] | |
@property | |
def sensorpm1(self): | |
return self.data['SensorPM1'] | |
@property | |
def sensorpm2(self): | |
return self.data['SensorPM2'] | |
@property | |
def sensorpm10(self): | |
return self.data['SensorPM10'] | |
@property | |
def sleeptime(self): | |
return self.data['SleepTime'] | |
@property | |
def total_air_polution(self): | |
return APTOTALAIRPOLUTION(self.data['TotalAirPolution']) | |
@property | |
def air_polution(self): | |
return APSMELL(self.data['AirPolution']) | |
"""------------------for Refrigerator""" | |
class ICEPLUS(enum.Enum): | |
OFF = "@CP_OFF_EN_W" | |
ON = "@CP_ON_EN_W" | |
ICE_PLUS = "@RE_TERM_ICE_PLUS_W" | |
ICE_PLUS_FREEZE = "@RE_MAIN_SPEED_FREEZE_TERM_W" | |
ICE_PLUS_OFF = "@CP_TERM_OFF_KO_W" | |
class FRESHAIRFILTER(enum.Enum): | |
OFF = "@CP_TERM_OFF_KO_W" | |
AUTO = "@RE_STATE_FRESH_AIR_FILTER_MODE_AUTO_W" | |
POWER = "@RE_STATE_FRESH_AIR_FILTER_MODE_POWER_W" | |
REPLACE_FILTER = "@RE_STATE_REPLACE_FILTER_W" | |
SMARTCARE_ON = "@RE_STATE_SMART_SMART_CARE_ON" | |
SMARTCARE_OFF = "@RE_STATE_SMART_SMART_CARE_OFF" | |
SMARTCARE_WAIT = "@RE_STATE_SMART_SMART_CARE_WAIT" | |
class SMARTSAVING(enum.Enum): | |
OFF = "@CP_TERM_USE_NOT_W" | |
NIGHT = "@RE_SMARTSAVING_MODE_NIGHT_W" | |
CUSTOM = "@RE_SMARTSAVING_MODE_CUSTOM_W" | |
class RefDevice(Device): | |
def set_reftemp(self, temp): | |
"""Set the refrigerator temperature. | |
""" | |
temp_value = self.model.enum_value('TempRefrigerator_C', temp) | |
self._set_control('RETM', temp_value) | |
def set_freezertemp(self, temp): | |
"""Set the freezer temperature. | |
""" | |
temp_value = self.model.enum_value('TempFreezer_C', temp) | |
self._set_control('REFT', temp_value) | |
def set_iceplus(self, mode): | |
"""Set the device's operating mode to an `iceplus` value. | |
""" | |
iceplus_value = self.model.enum_value('IcePlus', mode.value) | |
self._set_control('REIP', iceplus_value) | |
def set_freshairfilter(self, mode): | |
"""Set the device's operating mode to an `freshairfilter` value. | |
""" | |
freshairfilter_value = self.model.enum_value('FreshAirFilter', mode.value) | |
self._set_control('REHF', freshairfilter_value) | |
def set_activesaving(self, value): | |
self._set_control('REAS', value) | |
def monitor_start(self): | |
"""Start monitoring the device's status.""" | |
self.mon = Monitor(self.client.session, self.device.id) | |
self.mon.start() | |
def monitor_stop(self): | |
"""Stop monitoring the device's status.""" | |
self.mon.stop() | |
def delete_permission(self): | |
self._delete_permission() | |
def poll(self): | |
"""Poll the device's current state. | |
Monitoring must be started first with `monitor_start`. Return | |
either an `ACStatus` object or `None` if the status is not yet | |
available. | |
""" | |
data = self.mon.poll() | |
if data: | |
res = self.model.decode_monitor(data) | |
""" | |
with open('/config/wideq/ref_polled_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(res, dumpfile, ensure_ascii=False, indent="\t") | |
""" | |
return RefStatus(self, res) | |
else: | |
return None | |
class RefStatus(object): | |
"""Higher-level information about an Ref device's current status. | |
""" | |
def __init__(self, ref, data): | |
self.ref = ref | |
self.data = data | |
def lookup_enum(self, key): | |
try: | |
value = self.data[key] | |
return self.ref.model.enum_name(key, value) | |
except KeyError: | |
return value | |
def lookup_enum_temp(self, key, value): | |
return self.ref.model.enum_name(key, value) | |
@property | |
def current_reftemp(self): | |
temp = self.lookup_enum('TempRefrigerator') | |
return self.lookup_enum_temp('TempRefrigerator_C', temp) | |
@property | |
def current_midtemp(self): | |
temp = self.lookup_enum('TempMiddle') | |
return self.lookup_enum_temp('TempMiddle_C', temp) | |
@property | |
def current_freezertemp(self): | |
temp = self.lookup_enum('TempFreezer') | |
return self.lookup_enum_temp('TempFreezer_C', temp) | |
@property | |
def iceplus_state(self): | |
return ICEPLUS(self.lookup_enum('IcePlus')) | |
@property | |
def freshairfilter_state(self): | |
filter_state = self.lookup_enum('FreshAirFilter') | |
if filter_state == '255': | |
return '255' | |
else: | |
return FRESHAIRFILTER(self.lookup_enum('FreshAirFilter')) | |
@property | |
def smartsaving_mode(self): | |
return self.lookup_enum('SmartSavingMode') | |
@property | |
def waterfilter_state(self): | |
try: | |
waterfilter = self.lookup_enum('WaterFilterUsedMonth') | |
except AttributeError: | |
return self.data['WaterFilterUsedMonth'] | |
if waterfilter: | |
return waterfilter | |
@property | |
def door_state(self): | |
return self.lookup_enum('DoorOpenState') | |
@property | |
def smartsaving_state(self): | |
return self.lookup_enum('SmartSavingModeStatus') | |
@property | |
def locking_state(self): | |
return self.lookup_enum('LockingStatus') | |
@property | |
def activesaving_state(self): | |
return self.data['ActiveSavingStatus'] | |
"""------------------for Dryer""" | |
class DRYERSTATE(enum.Enum): | |
""" | |
From my dryer: | |
"State": { | |
"type": "Enum", | |
"default": "0", | |
"option": { | |
"0": "@WM_STATE_POWER_OFF_W", | |
"1": "@WM_STATE_INITIAL_W", | |
"2": "@WM_STATE_RUNNING_W", | |
"3": "@WM_STATE_PAUSE_W", | |
"4": "@WM_STATE_END_W", | |
"5": "@WM_STATE_ERROR_W", | |
"8": "@WM_STATE_SMART_DIAGNOSIS_W", | |
"50": "@WM_STATE_DRYING_W", | |
"51": "@WM_STATE_COOLING_W", | |
"56": "@WM_STATE_WRINKLECARE_W" | |
} | |
} | |
""" | |
OFF = "@WM_STATE_POWER_OFF_W" | |
INITIAL = "@WM_STATE_INITIAL_W" | |
RUNNING = "@WM_STATE_RUNNING_W" | |
DRYING = "@WM_STATE_DRYING_W" | |
PAUSE = "@WM_STATE_PAUSE_W" | |
END = "@WM_STATE_END_W" | |
ERROR = "@WM_STATE_ERROR_W" | |
COOLING = "@WM_STATE_COOLING_W" | |
SMART_DIAGNOSIS = "@WM_STATE_SMART_DIAGNOSIS_W" | |
WRINKLE_CARE = "@WM_STATE_WRINKLECARE_W" | |
class DRYERPROCESSSTATE(enum.Enum): | |
DETECTING = "@WM_STATE_DETECTING_W" | |
STEAM = "@WM_STATE_STEAM_W" | |
DRY = "@WM_STATE_DRY_W" | |
COOLING = "@WM_STATE_COOLING_W" | |
ANTI_CREASE = "@WM_STATE_ANTI_CREASE_W" | |
END = "@WM_STATE_END_W" | |
OFF = "-" | |
class DRYLEVEL(enum.Enum): | |
""" | |
From my dryer: | |
"DryLevel": { | |
"type": "Enum", | |
"default": "0", | |
"label": "@WM_DRY27_BUTTON_DRY_LEVEL_W", | |
"option": { | |
"0": "-", | |
"1": "@WM_DRY27_DRY_LEVEL_DAMP_W", | |
"2": "@WM_DRY27_DRY_LEVEL_LESS_W", | |
"3": "@WM_DRY27_DRY_LEVEL_NORMAL_W", | |
"4": "@WM_DRY27_DRY_LEVEL_MORE_W", | |
"5": "@WM_DRY27_DRY_LEVEL_VERY_W" | |
} | |
} | |
""" | |
IRON = "@WM_DRY27_DRY_LEVEL_IRON_W" | |
CUPBOARD = "@WM_DRY27_DRY_LEVEL_CUPBOARD_W" | |
EXTRA = "@WM_DRY27_DRY_LEVEL_EXTRA_W" | |
# My Dryer | |
OFF = "-" | |
DAMP = "@WM_DRY27_DRY_LEVEL_DAMP_W" | |
LESS = "@WM_DRY27_DRY_LEVEL_LESS_W" | |
NORMAL = "@WM_DRY27_DRY_LEVEL_NORMAL_W" | |
MORE = "@WM_DRY27_DRY_LEVEL_MORE_W" | |
VERY = "@WM_DRY27_DRY_LEVEL_VERY_W" | |
class ECOHYBRID(enum.Enum): | |
ECO = "@WM_DRY24_ECO_HYBRID_ECO_W" | |
NORMAL = "@WM_DRY24_ECO_HYBRID_NORMAL_W" | |
TURBO = "@WM_DRY24_ECO_HYBRID_TURBO_W" | |
class DRYERERROR(enum.Enum): | |
ERROR_DOOR = "@WM_US_DRYER_ERROR_DE_W" | |
ERROR_DRAINMOTOR = "@WM_US_DRYER_ERROR_OE_W" | |
ERROR_LE1 = "@WM_US_DRYER_ERROR_LE1_W" | |
ERROR_TE1 = "@WM_US_DRYER_ERROR_TE1_W" | |
ERROR_TE2 = "@WM_US_DRYER_ERROR_TE2_W" | |
ERROR_TE5 = "@WM_US_DRYER_ERROR_TE5_W" | |
ERROR_TE6 = "@WM_US_DRYER_ERROR_TE6_W" | |
ERROR_PS = "@WM_US_DRYER_ERROR_PS_W" | |
ERROR_NP = "@WM_US_DRYER_ERROR_NP_GAS_W" | |
ERROR_F1 = "@WM_US_DRYER_ERROR_F1_W" | |
ERROR_LE2 = "@WM_US_DRYER_ERROR_LE2_W" | |
ERROR_AE = "@WM_US_DRYER_ERROR_AE_W" | |
ERROR_dE4 = "@WM_WW_FL_ERROR_DE4_W" | |
ERROR_NOFILTER = "@WM_US_DRYER_ERROR_NOFILTER_W" | |
ERROR_EMPTYWATER = "@WM_US_DRYER_ERROR_EMPTYWATER_W" | |
ERROR_CE1 = "@WM_US_DRYER_ERROR_CE1_W" | |
class DryerDevice(Device): | |
def monitor_start(self): | |
"""Start monitoring the device's status.""" | |
self.mon = Monitor(self.client.session, self.device.id) | |
self.mon.start() | |
def monitor_stop(self): | |
"""Stop monitoring the device's status.""" | |
self.mon.stop() | |
def delete_permission(self): | |
self._delete_permission() | |
def poll(self): | |
"""Poll the device's current state. | |
Monitoring must be started first with `monitor_start`. Return | |
either an `ACStatus` object or `None` if the status is not yet | |
available. | |
""" | |
data = self.mon.poll() | |
if data: | |
res = self.model.decode_monitor(data) | |
""" | |
with open('/config/wideq/dryer_polled_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(res, dumpfile, ensure_ascii=False, indent="\t") | |
""" | |
return DryerStatus(self, res) | |
else: | |
return None | |
class DryerStatus(object): | |
"""Higher-level information about an Ref device's current status. | |
""" | |
def __init__(self, dryer, data): | |
self.dryer = dryer | |
self.data = data | |
def lookup_enum(self, key): | |
return self.dryer.model.enum_name(key, self.data.get(key, '-')) | |
def lookup_reference_comment(self, key): | |
return self.dryer.model.reference_comment(key, self.data[key]) | |
def lookup_bit(self, key, index): | |
bit_value = int(self.data[key]) | |
bit_index = 2 ** index | |
mode = bin(bit_value & bit_index) | |
if mode == bin(0): | |
return 'OFF' | |
else: | |
return 'ON' | |
@property | |
def is_on(self): | |
run_state = DRYERSTATE(self.lookup_enum('State')) | |
return run_state != DRYERSTATE.OFF | |
@property | |
def run_state(self): | |
return DRYERSTATE(self.lookup_enum('State')) | |
@property | |
def remaintime_hour(self): | |
return self.data['Remain_Time_H'] | |
@property | |
def remaintime_min(self): | |
return self.data['Remain_Time_M'] | |
@property | |
def initialtime_hour(self): | |
return self.data['Initial_Time_H'] | |
@property | |
def initialtime_min(self): | |
return self.data['Initial_Time_M'] | |
@property | |
def reservetime_hour(self): | |
return self.data.get('Reserve_Time_H', '0') | |
@property | |
def reservetime_min(self): | |
return self.data.get('Reserve_Time_M', '0') | |
@property | |
def reserveinitialtime_hour(self): | |
return self.data.get('Reserve_Initial_Time_H', '0') | |
@property | |
def reserveinitialtime_min(self): | |
return self.data.get('Reserve_Initial_Time_M', '0') | |
@property | |
def current_course(self): | |
course = self.lookup_reference_comment('Course') | |
if course == '-': | |
return 'OFF' | |
else: | |
return course | |
@property | |
def error_state(self): | |
error = self.lookup_reference_comment('Error') | |
if error == '-': | |
return 'OFF' | |
elif error == 'No Error': | |
return 'NO_ERROR' | |
else: | |
return DRYERERROR(error) | |
@property | |
def drylevel_state(self): | |
drylevel = self.lookup_enum('DryLevel') | |
if drylevel == '-': | |
return 'OFF' | |
return DRYLEVEL(drylevel) | |
@property | |
def ecohybrid_state(self): | |
ecohybrid = self.lookup_enum('EcoHybrid') | |
if ecohybrid == '-': | |
return 'OFF' | |
return ECOHYBRID(ecohybrid) | |
@property | |
def process_state(self): | |
return DRYERPROCESSSTATE(self.lookup_enum('ProcessState')) | |
@property | |
def current_smartcourse(self): | |
smartcourse = self.lookup_reference_comment('SmartCourse') | |
if smartcourse == '-': | |
return 'OFF' | |
else: | |
return smartcourse | |
@property | |
def anticrease_state(self): | |
return self.lookup_bit('Option1', 1) | |
@property | |
def childlock_state(self): | |
return self.lookup_bit('Option1', 4) | |
@property | |
def selfcleaning_state(self): | |
return self.lookup_bit('Option1', 5) | |
@property | |
def dampdrybeep_state(self): | |
return self.lookup_bit('Option1', 6) | |
@property | |
def handiron_state(self): | |
return self.lookup_bit('Option1', 7) | |
"""------------------for Washer""" | |
class WASHERCOURSE(enum.Enum): | |
""" | |
From wideq_states.json: | |
>>> pprint.pprint([(c.get('_comment', 'No Comment'), c.get('name', 'No Name'), c.get('id')) for c in courses]) | |
[('Normal', '@WM_MX_COURSE_NORMAL_W', 6), | |
('Heavy Duty', '@WM_MX_COURSE_HEAVY_DUTY_W', 5), | |
('Bedding', '@WM_MX_COURSE_BEDDING_W', 4), | |
('Perm.Press', '@WM_MX_COURSE_PERMPRESS_W', 8), | |
('Towels', '@WM_MX_COURSE_TOWELS_W', 10), | |
('Sanitary', '@WM_MX_COURSE_SANITARY_W', 3), | |
('Allergiene', '@WM_MX_COURSE_ALLERGIENE_W', 2), | |
('Bright Whites', '@WM_MX_COURSE_BRIGHT_WHITES_W', 7), | |
('Tub Clean', '@WM_MX_COURSE_TUB_CLEAN_W', 1), | |
('Delicates', '@WM_MX_COURSE_DELICATES_W', 9), | |
('Speed Wash', '@WM_MX_COURSE_SPEED_WASH_W', 11), | |
('DownloadCourse', 'No Name', 12)] | |
""" | |
HEAVYDUTY = "@WM_MX_COURSE_HEAVY_DUTY_W" | |
NORMAL = "@WM_MX_COURSE_NORMAL_W" | |
PERM_PRESS = "@WM_MX_COURSE_PERMPRESS_W" | |
COTTON = "@WM_KR_TT27_WD_WIFI_COURSE_COTTON_W" | |
SPEEDWASH_DRY = "@WM_KR_TT27_WD_WIFI_COURSE_SPEEDWASH_DRY_W" | |
SPEEDWASH = "@WM_KR_TT27_WD_WIFI_COURSE_SPEEDWASH_W" | |
SINGLE_SHIRT_DRY = "@WM_KR_TT27_WD_WIFI_COURSE_SINGLE_SHIRT_DRY_W" | |
RINSESPIN = "@WM_KR_TT27_WD_WIFI_COURSE_RINSESPIN_W" | |
SPEEDBOIL = "@WM_KR_TT27_WD_WIFI_COURSE_SPEEDBOIL_W" | |
ALLERGYCARE = "@WM_KR_TT27_WD_WIFI_COURSE_ALLERGYCARE_W" | |
ALLERGIENE = "@WM_MX_COURSE_ALLERGIENE_W" | |
STEAMCLEANING = "@WM_KR_TT27_WD_WIFI_COURSE_STEAMCLEANING_W" | |
BABYWEAR = "@WM_KR_TT27_WD_WIFI_COURSE_BABYWEAR_W" | |
BLANKET_ROB = "@WM_KR_TT27_WD_WIFI_COURSE_BLANKET_ROB_W" | |
UTILITY = "@WM_KR_TT27_WD_WIFI_COURSE_UTILITY_W" | |
BLANKET = "@WM_KR_TT27_WD_WIFI_COURSE_BLANKET_W" | |
LINGERIE_WOOL = "@WM_KR_TT27_WD_WIFI_COURSE_LINGERIE_WOOL_W" | |
COLDWASH = "@WM_KR_TT27_WD_WIFI_COURSE_COLDWASH_W" | |
SANITARY = "@WM_MX_COURSE_SANITARY_W" | |
BRIGHT_WHITES = "@WM_MX_COURSE_BRIGHT_WHITES_W" | |
DELICATES = "@WM_MX_COURSE_DELICATES_W" | |
TUBCLEAN_SANITARY = "@WM_KR_TT27_WD_WIFI_COURSE_TUBCLEAN_SANITARY_W" | |
MINI_SMALL_LOAD = "@WM_KR_TL_G+_MINI_GOOD_COURSE_SMALL_LOAD_W" | |
MINI_UNDERWEAR = "@WM_KR_TL_G+_MINI_GOOD_COURSE_UNDERWEAR_W" | |
MINI_WOOL = "@WM_KR_TL_G+_MINI_GOOD_COURSE_WOOL_W" | |
MINI_BOILING = "@WM_KR_TL_G+_MINI_GOOD_COURSE_BOILING_W" | |
MINI_BABYCARE = "@WM_KR_TL_G+_MINI_GOOD_COURSE_BABYCARE_W" | |
MINI_RINSE_SPIN = "@WM_KR_TL_G+_MINI_GOOD_COURSE_RINSE_SPIN_W" | |
MINI_TUBCLEAN = "@WM_KR_TL_G+_MINI_GOOD_COURSE_TUBCLEAN_W" | |
TL_NORMAL = "@WM_TL_MP_COURSE_NORMAL_W" | |
TL_WOOL_DELICATE = "@WM_TL_MP_COURSE_WOOL_DELICATE_W" | |
TL_SPEEDWASH = "@WM_MX_COURSE_SPEED_WASH_W" | |
TL_BEDDING = "@WM_MX_COURSE_BEDDING_W" | |
TL_TUBCLEAN = "@WM_MX_COURSE_TUB_CLEAN_W" | |
TL_TOWEL = "@WM_MX_COURSE_TOWELS_W" | |
TL_SPORTSWEAR = "@WM_TL_MP_COURSE_SPORTSWEAR_W" | |
TL_PREWASH_NORMAL = "@WM_TL_MP_COURSE_PREWASH_NORMAL_W" | |
TL_SAFETY_NORMAL = "@WM_TL_MP_COURSE_SAFETY_NORMAL_W" | |
class WASHERSMARTCOURSE(enum.Enum): | |
SILENT = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_SILENT_W" | |
SMALL_LOAD = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_SMALL_LOAD_W" | |
SKIN_CARE = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_SKIN_CARE_W" | |
RAINY_SEASON = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_RAINY_SEASON_W" | |
SWEAT_STAIN = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_SWEAT_STAIN_W" | |
SINGLE_GARMENT = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_SINGLE_GARMENT_W" | |
SCHOOL_UNIFORM = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_SCHOOL_UNIFORM_W" | |
STATIC_REMOVAL = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_STATIC_REMOVAL_W" | |
COLOR_CARE = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_COLOR_CARE_W" | |
SPIN_ONLY = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_SPIN_ONLY_W" | |
DEODORIZATION = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_DEODORIZATION_W" | |
BEDDING_CARE = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_BEDDING_CARE_W" | |
CLOTH_CARE = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_CLOTH_CARE_W" | |
SMART_RINSE = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_SMART_RINSE_W" | |
ECO_WASH = "@WM_KR_TT27_WD_WIFI_SMARTCOURSE_ECO_WASH_W" | |
MINIWASH_SKIN_CARE = "@WM_KR_TL_G+_MINI_GOOD_SMARTCOURSE_SKIN_CARE_W" | |
COLD_WASH = "@WM_WW_FL_SMARTCOURSE_COLD_WASH_W" | |
KR_COLD_WASH = "@WM_KR_FL_SMARTCOURSE_COLD_WASH_W" | |
MINIWASH_CLOTHS_CARE = "@WM_KR_TL_G+_MINI_GOOD_SMARTCOURSE_CLOTHS_CARE_W" | |
MINIWASH_SMART_RINSE = "@WM_KR_TL_G+_MINI_GOOD_SMARTCOURSE_SMART_RINSE_W" | |
SOILED_ITEMS = "@WM_WW_FL_SMARTCOURSE_LIGHTLY_SOILED_ITEMS_W" | |
KR_SOILED_ITEMS = "@WM_WW_FL_SMARTCOURSE_LIGHTLY_SOILED_ITEMS_W" | |
MINIWASH_SPIN_ONLY = "@WM_KR_TL_G+_MINI_GOOD_SMARTCOURSE_SPIN_ONLY_W" | |
TL_SWEAT_SPOT_REMOVE = "@WM_KR_TL_SMARTCOURSE_SWEAT_SPOT_REMOVE_W" | |
TL_SINGLE_SPEED = "@WM_KR_TL_SMARTCOURSE_SINGLE_SPEED_W" | |
TL_COLOR_PROTECT = "@WM_KR_TL_SMARTCOURSE_COLOR_PROTECT_W" | |
TL_CHILDREN_WEAR = "@WM_KR_TL_SMARTCOURSE_CHILDREN_WEAR_W" | |
TL_RAINY_SEASON = "@WM_KR_TL_SMARTCOURSE_RAINY_SEASON_W" | |
TL_SWIM_WEAR = "@WM_KR_TL_SMARTCOURSE_SWIM_WEAR_W" | |
TL_CURTAINS = "@WM_KR_TL_SMARTCOURSE_CURTAINS_W" | |
TL_JEANS = "@WM_KR_TL_SMARTCOURSE_JEANS_W" | |
TL_LINGERIE = "@WM_KR_TL_SMARTCOURSE_LINGERIE_W" | |
TL_FOOD_WASTE = "@WM_KR_TL_SMARTCOURSE_FOOD_WASTE_W" | |
TL_SILENT = "@WM_KR_TL_SMARTCOURSE_SILENT_W" | |
TL_HEAVY_SPIN = "@WM_KR_TL_SMARTCOURSE_HEAVY_SPIN_W" | |
TL_SMALL_LOAD = "@WM_KR_TL_SMARTCOURSE_SMALL_LOAD_W" | |
TL_BIG_LOAD = "@WM_KR_TL_SMARTCOURSE_BIG_LOAD_W" | |
# My Washer | |
SMALL_LOAD_MINE = "@WM_US_FL_SMARTCOURSE_SMALL_LOAD_W" | |
class WASHERSTATE(enum.Enum): | |
OFF = "@WM_STATE_POWER_OFF_W" | |
INITIAL = "@WM_STATE_INITIAL_W" | |
PAUSE = "@WM_STATE_PAUSE_W" | |
ERROR_AUTO_OFF = "@WM_STATE_ERROR_AUTO_OFF_W" | |
RESERVE = "@WM_STATE_RESERVE_W" | |
DETECTING = "@WM_STATE_DETECTING_W" | |
SOAK = "@WM_STATE_SOAK_W" | |
ADD_DRAIN = "WM_STATE_ADD_DRAIN_W" | |
DETERGENT_AMOUNT = "@WM_STATE_DETERGENT_AMOUNT_W" | |
RUNNING = "@WM_STATE_RUNNING_W" | |
PREWASH = "@WM_STATE_PREWASH_W" | |
RINSING = "@WM_STATE_RINSING_W" | |
RINSE_HOLD = "@WM_STATE_RINSE_HOLD_W" | |
SPINNING = "@WM_STATE_SPINNING_W" | |
DRYING = "@WM_STATE_DRYING_W" | |
COMPLETE = "@WM_STATE_COMPLETE_W" | |
END = "@WM_STATE_END_W" | |
FRESHCARE = "@WM_STATE_FRESHCARE_W" | |
TCL_ALARM_NORMAL = "TCL_ALARM_NORMAL" | |
FROZEN_PREVENT_INITIAL = "@WM_STATE_FROZEN_PREVENT_INITIAL_W" | |
FROZEN_PREVENT_RUNNING = "@WM_STATE_FROZEN_PREVENT_RUNNING_W" | |
FROZEN_PREVENT_PAUSE = "@WM_STATE_FROZEN_PREVENT_PAUSE_W" | |
class WASHERSOILLEVEL(enum.Enum): | |
NOT_SUPPORTED = "-" | |
NO_SELECT = "@WM_TERM_NO_SELECT_W" | |
LIGHT = "@WM_KR_TT27_WD_WIFI_OPTION_SOILLEVEL_LIGHT_W" | |
NORMAL = "@WM_KR_TT27_WD_WIFI_OPTION_SOILLEVEL_NORMAL_W" | |
HEAVY = "@WM_KR_TT27_WD_WIFI_OPTION_SOILLEVEL_HEAVY_W" | |
PRE_WASH = "@WM_KR_TT27_WD_WIFI_OPTION_SOILLEVEL_PRE_WASH_W" | |
SOAKING = "@WM_KR_TT27_WD_WIFI_OPTION_SOILLEVEL_SOAKING_W" | |
TRHEE = "@WM_OPTION_SOIL_3_W" | |
SIX = "@WM_OPTION_SOIL_6_W" | |
TEN = "@WM_OPTION_SOIL_10_W" | |
TWELVE = "@WM_OPTION_SOIL_12_W" | |
FOURTEEN = "@WM_OPTION_SOIL_14_W" | |
SEVENTEEN = "@WM_OPTION_SOIL_17_W" | |
NINETEEN = "@WM_OPTION_SOIL_19_W" | |
TWENTYONE = "@WM_OPTION_SOIL_21_W" | |
TWENTYTHREE = "@WM_OPTION_SOIL_23_W" | |
TWENTYFIVE = "@WM_OPTION_SOIL_25_W" | |
class WASHERWATERTEMP(enum.Enum): | |
NO_SELECT = "@WM_TERM_NO_SELECT_W" | |
COLD = "@WM_MX_OPTION_TEMP_COLD_W" | |
THIRTY = "@WM_KR_TT27_WD_WIFI_OPTION_WATERTEMP_30_W" | |
FOURTY = "@WM_KR_TT27_WD_WIFI_OPTION_WATERTEMP_40_W" | |
SIXTY = "@WM_KR_TT27_WD_WIFI_OPTION_WATERTEMP_60_W" | |
NINTYFIVE = "@WM_KR_TT27_WD_WIFI_OPTION_WATERTEMP_95_W" | |
TL_COLD = "@WM_MX_OPTION_TEMP_TAP_COLD_W" | |
TL_WARM = "@WM_MX_OPTION_TEMP_WARM_W" | |
TL_NORMAL = "@WM_OPTION_TEMP_NORMAL_W" | |
TL_COLD_WARM = "@WM_OPTION_TEMP_COLD_WARM_W" | |
TL_HOT = "@WM_OPTION_TEMP_HOT_W" | |
TL_EXTRA_HOT = "@WM_OPTION_TEMP_EXTRA_HOT_W" | |
TL_30 = "30" | |
TL_40 = "40" | |
TL_60 = "60" | |
TL_90 = "90" | |
TL_35 = "35" | |
TL_38 = "38" | |
class WASHERSPINSPEED(enum.Enum): | |
NO_SELECT = "@WM_TERM_NO_SELECT_W" | |
EXTRA_LOW = "@WM_KR_TT27_WD_WIFI_OPTION_SPINSPEED_EXTRA_LOW_W" | |
#LOW = "@WM_KR_TT27_WD_WIFI_OPTION_SPINSPEED_LOW_W" | |
LOW = "@WM_MX_OPTION_SPIN_LOW_W" | |
MEDIUM = "@WM_MX_OPTION_SPIN_MEDIUM_W" | |
#MEDIUM = "@WM_KR_TT27_WD_WIFI_OPTION_SPINSPEED_MEDIUM_W" | |
#HIGH = "@WM_KR_TT27_WD_WIFI_OPTION_SPINSPEED_HIGH_W" | |
HIGH = "@WM_MX_OPTION_SPIN_HIGH_W" | |
#EXTRA_HIGH = "@WM_KR_TT27_WD_WIFI_OPTION_SPINSPEED_EXTRA_HIGH_W" | |
EXTRA_HIGH = "@WM_MX_OPTION_SPIN_EXTRA_HIGH_W" | |
ON = "ON" | |
OFF = "OFF" | |
NOT_SUPPORTED = "-" | |
TL_LOW = "@WM_TL_MP_OPTION_SPIN_LOW_W" | |
TL_MEDIUM = "@WM_TL_MP_OPTION_SPIN_MEDIUM_W" | |
TL_HIGH = "@WM_TL_MP_OPTION_SPIN_MEDIUM_W" | |
TL_ULTRA = "@WM_TL_MP_OPTION_SPIN_ULTRA_W" | |
TL_DRYFIT = "@WM_TL_MP_OPTION_SPIN_DRYFIT_W" | |
TL_DELICACY = "@WM_TL_MP_OPTION_SPIN_DELICACY_W" | |
class WASHERRINSECOUNT(enum.Enum): | |
OFF = "-" | |
NO_SELECT = "@WM_TERM_NO_SELECT_W" | |
ZERO = "@WM_OPTION_RINSE_COUNT_0_TIME_W" | |
ONE = "@WM_OPTION_RINSE_COUNT_1_TIME_W" | |
TWO = "@WM_OPTION_RINSE_COUNT_2_TIME_W" | |
THREE = "@WM_OPTION_RINSE_COUNT_3_TIME_W" | |
FOUR = "@WM_KR_TT27_WD_WIFI_OPTION_RINSECOUNT_4_W" | |
FIVE = "@WM_KR_TT27_WD_WIFI_OPTION_RINSECOUNT_5_W" | |
MINI_0 = "0" | |
MINI_1 = "1" | |
MINI_2 = "2" | |
MINI_3 = "3" | |
MINI_4 = "4" | |
MINI_5 = "5" | |
MINI_6 = "6" | |
NOT_SUPPORTED = "-" | |
TL_1 = "@WM_OPTION_RINSE_1_W" | |
TL_2 = "@WM_OPTION_RINSE_2_W" | |
TL_3 = "@WM_OPTION_RINSE_3_W" | |
TL_4 = "@WM_OPTION_RINSE_4_W" | |
TL_5 = "@WM_OPTION_RINSE_5_W" | |
TL_1_INTENSIVE = "@WM_TL_MP_OPTION_RINSE_INTENSIVE_1_W" | |
TL_2_INTENSIVE = "@WM_TL_MP_OPTION_RINSE_INTENSIVE_2_W" | |
TL_3_INTENSIVE = "@WM_TL_MP_OPTION_RINSE_INTENSIVE_3_W" | |
TL_4_INTENSIVE = "@WM_TL_MP_OPTION_RINSE_INTENSIVE_4_W" | |
TL_5_INTENSIVE = "@WM_TL_MP_OPTION_RINSE_INTENSIVE_5_W" | |
class WASHERDRYLEVEL(enum.Enum): | |
NO_SELECT = "@WM_TERM_NO_SELECT_W" | |
WIND = "@WM_MX_OPTION_DRY_WIND_W" | |
TURBO = "@WM_MX_OPTION_DRY_TURBO_W" | |
TIME_30 = "@WM_OPTION_DRY_TIME_30_W" | |
TIME_60 = "@WM_OPTION_DRY_TIME_60_W" | |
TIME_90 = "@WM_OPTION_DRY_TIME_90_W" | |
TIME_120 = "@WM_OPTION_DRY_TIME_120_W" | |
TIME_150 = "@WM_OPTION_DRY_TIME_150_W" | |
class WASHERERROR(enum.Enum): | |
ERROR_dE2 = "@WM_KR_TT27_WD_WIFI_ERROR_DE2" | |
ERROR_IE = "@WM_KR_TT27_WD_WIFI_ERROR_IE" | |
ERROR_OE = "@WM_KR_TT27_WD_WIFI_ERROR_OE" | |
ERROR_UE = "@WM_KR_TT27_WD_WIFI_ERROR_UE" | |
ERROR_FE = "@WM_KR_TT27_WD_WIFI_ERROR_FE" | |
ERROR_PE = "@WM_KR_TT27_WD_WIFI_ERROR_PE" | |
ERROR_tE = "@WM_KR_TT27_WD_WIFI_ERROR_TE" | |
ERROR_LE = "@WM_KR_TT27_WD_WIFI_ERROR_LE" | |
ERROR_CE = "@WM_KR_TT27_WD_WIFI_ERROR_CE" | |
ERROR_dHE = "@WM_KR_TT27_WD_WIFI_ERROR_DHE" | |
ERROR_PF = "@WM_KR_TT27_WD_WIFI_ERROR_PF" | |
ERROR_FF = "@WM_KR_TT27_WD_WIFI_ERROR_FF" | |
ERROR_dCE = "@WM_KR_TT27_WD_WIFI_ERROR_DCE" | |
ERROR_EE = "@WM_KR_TT27_WD_WIFI_ERROR_EE" | |
ERROR_PS = "@WM_KR_TT27_WD_WIFI_ERROR_PS" | |
ERROR_dE1 = "@WM_KR_TT27_WD_WIFI_ERROR_DE1" | |
ERROR_LOE = "@WM_KR_TT27_WD_WIFI_ERROR_LOE" | |
TL_ERROR_IE = "@WM_KR_TL_ERROR_IE" | |
TL_ERROR_OE = "@WM_KR_TL_ERROR_OE" | |
TL_ERROR_UE = "@WM_KR_TL_ERROR_UE" | |
TL_ERROR_DE1 = "@WM_KR_TL_ERROR_DE1" | |
TL_ERROR_PE = "@WM_KR_TL_ERROR_PE" | |
TL_ERROR_DO_W = "@WM_KR_FL_ERROR_DO_W" | |
TL_ERROR_LE = "@WM_KR_TL_ERROR_LE" | |
TL_ERROR_AE = "@WM_KR_TL_ERROR_AE" | |
TL_ERROR_TE = "@WM_KR_TL_ERROR_TE" | |
TL_ERROR_FE = "@WM_KR_TL_ERROR_FE" | |
TL_ERROR_DE2 = "@WM_KR_TL_ERROR_DE2" | |
TL_ERROR_FF = "@WM_KR_TL_ERROR_FF" | |
TL_ERROR_E7 = "@WM_WW_G+_MINI_GOOD_ERROR_E7" | |
TL_ERROR_LE1 = "@WM_KR_TL_ERROR_LE1" | |
TL_ERROR_DL = "@WM_KR_TL_ERROR_DL" | |
TL_ERROR_E3 = "@WM_KR_TL_ERROR_E3" | |
class WASHERWATERLEVEL(enum.Enum): | |
NOT_SUPPORTED = "-" | |
WLEVEL_1 = "@WM_OPTION_WLEVEL_1_W" | |
WLEVEL_2 = "@WM_OPTION_WLEVEL_2_W" | |
WLEVEL_3 = "@WM_OPTION_WLEVEL_3_W" | |
WLEVEL_4 = "@WM_OPTION_WLEVEL_4_W" | |
WLEVEL_5 = "@WM_OPTION_WLEVEL_5_W" | |
WLEVEL_6 = "@WM_OPTION_WLEVEL_6_W" | |
WLEVEL_7 = "@WM_OPTION_WLEVEL_7_W" | |
WLEVEL_8 = "@WM_OPTION_WLEVEL_8_W" | |
WLEVEL_9 = "@WM_OPTION_WLEVEL_9_W" | |
WLEVEL_10 = "@WM_OPTION_WLEVEL_10_W" | |
class WASHERWATERFLOW(enum.Enum): | |
NOT_SUPPORTED = "-" | |
DELICATE = "@WM_OPTION_WFLOW_DELICATE_W" | |
MEDIUM = "@WM_OPTION_WFLOW_MEDIUM_W" | |
HIGH = "@WM_OPTION_WFLOW_HIGH_W" | |
class WASHERSOAK(enum.Enum): | |
NOT_SUPPORTED = "-" | |
FIFTEEN = "15" | |
THIRTY = "30" | |
FOURTY = "40" | |
FOURTYFIVE = "45" | |
FIFTY = "50" | |
SIXTY = "60" | |
ONETWENTY = "120" | |
ONEEIGHTY = "180" | |
TWOFOURTY = "240" | |
THREEHUNDRED = "300" | |
THREESIXTY = "360" | |
FOUREIGHTY = "480" | |
SIXHUNDRED = "600" | |
class WASHER_ETC(enum.Enum): | |
ON = "@CP_ON_EN_W" | |
OFF = "@CP_OFF_EN_W" | |
class WasherDevice(Device): | |
def monitor_start(self, raise_error=True): | |
"""Start monitoring the device's status.""" | |
self.mon = Monitor(self.client.session, self.device.id) | |
try: | |
self.mon.start() | |
except NotConnectError: | |
if raise_error: | |
raise | |
def monitor_stop(self): | |
"""Stop monitoring the device's status.""" | |
self.mon.stop() | |
def delete_permission(self, raise_error=True): | |
try: | |
self._delete_permission() | |
except NotConnectError: | |
if raise_error: | |
raise | |
def poll(self): | |
"""Poll the device's current state. | |
Monitoring must be started first with `monitor_start`. Return | |
either an `ACStatus` object or `None` if the status is not yet | |
available. | |
""" | |
data = self.mon.poll() | |
if data: | |
res = self.model.decode_monitor(data) | |
""" | |
with open('/config/wideq/washer_polled_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(res, dumpfile, ensure_ascii=False, indent="\t") | |
""" | |
return WasherStatus(self, res) | |
else: | |
return None | |
class WasherStatus(object): | |
def __init__(self, washer, data): | |
self.washer = washer | |
self.data = data | |
def lookup_enum(self, key, default='0'): | |
return self.washer.model.enum_name(key, self.data.get(key, default)) | |
def lookup_reference(self, key): | |
return self.washer.model.reference_name(key, self.data[key]) | |
def lookup_reference_comment(self, key): | |
return self.washer.model.reference_comment(key, self.data[key]) | |
def lookup_bit(self, key, index): | |
bit_value = int(self.data[key]) | |
bit_index = 2 ** index | |
mode = bin(bit_value & bit_index) | |
if mode == bin(0): | |
return 'OFF' | |
else: | |
return 'ON' | |
@property | |
def is_on(self): | |
run_state = WASHERSTATE(self.lookup_enum('State')) | |
return run_state != WASHERSTATE.OFF | |
@property | |
def run_state(self): | |
return WASHERSTATE(self.lookup_enum('State')) | |
@property | |
def pre_state(self): | |
return WASHERSTATE(self.lookup_enum('PreState')) | |
@property | |
def remaintime_hour(self): | |
return self.data['Remain_Time_H'] | |
@property | |
def remaintime_min(self): | |
return self.data['Remain_Time_M'] | |
@property | |
def initialtime_hour(self): | |
return self.data['Initial_Time_H'] | |
@property | |
def initialtime_min(self): | |
return self.data['Initial_Time_M'] | |
@property | |
def reservetime_hour(self): | |
return self.data.get('Reserve_Time_H', '0') | |
@property | |
def reservetime_min(self): | |
return self.data.get('Reserve_Time_M', '0') | |
def current_course(self, device_type): | |
if device_type == 'TL': | |
course = self.lookup_reference('Course') | |
else: | |
course = self.lookup_reference('APCourse') | |
if course == '-': | |
return 'OFF' | |
else: | |
return WASHERCOURSE(course) | |
@property | |
def error_state(self): | |
error = self.lookup_reference_comment('Error') | |
if error == '-': | |
return 'OFF' | |
elif error == 'No Error': | |
return 'NO_ERROR' | |
else: | |
return WASHERERROR(error) | |
@property | |
def wash_option_state(self): | |
soillevel = self.lookup_enum('SoilLevel', '-') | |
if soillevel == '-': | |
return 'OFF' | |
return WASHERSOILLEVEL(soillevel) | |
@property | |
def spin_option_state(self): | |
spinspeed = self.lookup_enum('SpinSpeed') | |
if spinspeed == '-': | |
return 'OFF' | |
return WASHERSPINSPEED(spinspeed) | |
def water_temp_option_state(self, device_type): | |
if device_type == 'TL': | |
water_temp = self.lookup_enum('WTemp') | |
else: | |
water_temp = self.lookup_enum('WaterTemp') | |
if water_temp == '-': | |
return 'OFF' | |
return WASHERWATERTEMP(water_temp) | |
@property | |
def rinsecount_option_state(self): | |
rinsecount = self.lookup_enum('RinseCount') | |
if rinsecount == '-': | |
return 'OFF' | |
return WASHERRINSECOUNT(rinsecount) | |
@property | |
def drylevel_option_state(self): | |
drylevel = self.lookup_enum('DryLevel') | |
if drylevel == '-': | |
return 'OFF' | |
return WASHERDRYLEVEL(drylevel) | |
@property | |
def waterlevel_option_state(self): | |
waterlevel = self.lookup_enum('WLevel') | |
return WASHERWATERLEVEL(waterlevel) | |
@property | |
def waterflow_option_state(self): | |
waterflow = self.lookup_enum('WFlow') | |
return WASHERWATERFLOW(waterflow) | |
@property | |
def soak_option_state(self): | |
soak = self.lookup_enum('Soak') | |
return WASHERSOAK(soak) | |
@property | |
def current_smartcourse(self): | |
smartcourse = self.lookup_reference('SmartCourse') | |
if smartcourse == '-': | |
return 'OFF' | |
else: | |
return WASHERSMARTCOURSE(smartcourse) | |
@property | |
def freshcare_state(self): | |
return self.lookup_bit('Option1', 1) | |
def childlock_state(self, device_type): | |
if device_type == 'TL': | |
return self.lookup_bit('Option1', 0) | |
else: | |
return self.lookup_bit('Option1', 3) | |
@property | |
def doorlock_state(self): | |
return self.lookup_bit('Option1', 3) | |
def steam_state(self, device_type): | |
if device_type == 'TL': | |
return self.lookup_bit('Option1', 2) | |
else: | |
return self.lookup_bit('Option1', 4) | |
def turboshot_state(self, device_type): | |
if device_type == 'TL': | |
return self.lookup_bit('Option2', 3) | |
else: | |
return self.lookup_bit('Option2', 7) | |
@property | |
def buzzer_state(self): | |
return self.lookup_bit('Option2', 0) | |
@property | |
def sterilize_state(self): | |
return self.lookup_bit('Option2', 1) | |
@property | |
def heater_state(self): | |
return self.lookup_bit('Option2', 2) | |
@property | |
def tubclean_count(self): | |
return self.data['TCLCount'] | |
@property | |
def load_level(self): | |
return self.lookup_enum('LoadLevel') | |
"""------------------for Dehumidifier""" | |
class DEHUMOperation(enum.Enum): | |
ON = "@operation_on" | |
OFF = "@operation_off" | |
class DEHUMOPMode(enum.Enum): | |
SMART_DEHUM = "@AP_MAIN_MID_OPMODE_SMART_DEHUM_W" | |
FAST_DEHUM = "@AP_MAIN_MID_OPMODE_FAST_DEHUM_W" | |
SILENT_DEHUM = "@AP_MAIN_MID_OPMODE_CILENT_DEHUM_W" | |
CONCENTRATION_DRY = "@AP_MAIN_MID_OPMODE_CONCENTRATION_DRY_W" | |
CLOTHING_DRY = "@AP_MAIN_MID_OPMODE_CLOTHING_DRY_W" | |
IONIZER = "@AP_MAIN_MID_OPMODE_IONIZER_W" | |
class DEHUMWindStrength(enum.Enum): | |
LOW = "@AP_MAIN_MID_WINDSTRENGTH_DHUM_LOW_W" | |
HIGH = "@AP_MAIN_MID_WINDSTRENGTH_DHUM_HIGH_W" | |
class DEHUMAIRREMOVAL(enum.Enum): | |
OFF = "@AP_OFF_W" | |
ON = "@AP_ON_W" | |
class DIAGCODE(enum.Enum): | |
FAN_ERROR = "@ERROR_FAN" | |
NORMAL = "@NORMAL" | |
EEPROM_ERROR = "@ERROR_EEPROM" | |
class DehumDevice(Device): | |
def set_on(self, is_on): | |
mode = DEHUMOperation.ON if is_on else DEHUMOperation.OFF | |
mode_value = self.model.enum_value('Operation', mode.value) | |
self._set_control('Operation', mode_value) | |
def set_mode(self, mode): | |
mode_value = self.model.enum_value('OpMode', mode.value) | |
self._set_control('OpMode', mode_value) | |
def set_humidity(self, hum): | |
"""Set the device's target temperature in Celsius degrees. | |
""" | |
self._set_control('HumidityCfg', hum) | |
def set_windstrength(self, mode): | |
windstrength_value = self.model.enum_value('WindStrength', mode.value) | |
self._set_control('WindStrength', windstrength_value) | |
def set_airremoval(self, is_on): | |
mode = DEHUMAIRREMOVAL.ON if is_on else DEHUMAIRREMOVAL.OFF | |
mode_value = self.model.enum_value('AirRemoval', mode.value) | |
self._set_control('AirRemoval', mode_value) | |
def monitor_start(self): | |
"""Start monitoring the device's status.""" | |
self.mon = Monitor(self.client.session, self.device.id) | |
self.mon.start() | |
def monitor_stop(self): | |
"""Stop monitoring the device's status.""" | |
self.mon.stop() | |
def delete_permission(self): | |
self._delete_permission() | |
def poll(self): | |
"""Poll the device's current state. | |
Monitoring must be started first with `monitor_start`. Return | |
either an `ACStatus` object or `None` if the status is not yet | |
available. | |
""" | |
data = self.mon.poll() | |
if data: | |
res = self.model.decode_monitor(data) | |
""" | |
with open('/config/wideq/dehumidifier_polled_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(res, dumpfile, ensure_ascii=False, indent="\t") | |
""" | |
return DEHUMStatus(self, res) | |
else: | |
return None | |
class DEHUMStatus(object): | |
"""Higher-level information about an AC device's current status. | |
""" | |
def __init__(self, dehum, data): | |
self.dehum = dehum | |
self.data = data | |
def lookup_enum(self, key): | |
return self.dehum.model.enum_name(key, self.data.get(key, '-')) | |
@property | |
def is_on(self): | |
op = DEHUMOperation(self.lookup_enum('Operation')) | |
return op == DEHUMOperation.ON | |
@property | |
def mode(self): | |
return DEHUMOPMode(self.lookup_enum('OpMode')) | |
@property | |
def windstrength_state(self): | |
return DEHUMWindStrength(self.lookup_enum('WindStrength')) | |
@property | |
def airremoval_state(self): | |
return DEHUMAIRREMOVAL(self.lookup_enum('AirRemoval')) | |
@property | |
def current_humidity(self): | |
return self.data['SensorHumidity'] | |
@property | |
def target_humidity(self): | |
return self.data['HumidityCfg'] | |
"""------------------for Water Purifier""" | |
class COCKCLEAN(enum.Enum): | |
WAITING = "@WP_WAITING_W" | |
COCKCLEANING = "@WP_COCK_CLEANING_W" | |
class WPDevice(Device): | |
def day_water_usage(self, watertype): | |
typeCode = 'DAY' | |
sDate = datetime.today().strftime("%Y%m%d") | |
res = self._get_water_usage(typeCode, sDate, sDate) | |
data = res['itemDetail'] | |
for usage_data in data: | |
if usage_data['waterType'] == watertype: | |
return usage_data['waterAmount'] | |
def week_water_usage(self, watertype): | |
typeCode = 'WEEK' | |
amount = 0 | |
weekday = datetime.today().weekday() | |
startdate = datetime.today() + timedelta(days=-(weekday+1)) | |
enddate = datetime.today() + timedelta(days=(6-(weekday+1))) | |
sDate = datetime.date(startdate).strftime("%Y%m%d") | |
eDate = datetime.date(enddate).strftime("%Y%m%d") | |
res = self._get_water_usage(typeCode, sDate, eDate) | |
for weekdata in res: | |
for usage_data in weekdata['itemDetail']: | |
if usage_data['waterType'] == watertype: | |
amount = amount + int(usage_data['waterAmount']) | |
return amount | |
def month_water_usage(self, watertype): | |
typeCode = 'MONTH' | |
startdate = datetime.today().replace(day=1) | |
sDate = datetime.date(startdate).strftime("%Y%m%d") | |
eDate = datetime.today().strftime("%Y%m%d") | |
res = self._get_water_usage(typeCode, sDate, eDate) | |
data = res['itemDetail'] | |
for usage_data in data: | |
if usage_data['waterType'] == watertype: | |
return usage_data['waterAmount'] | |
def year_water_usage(self, watertype): | |
typeCode = 'YEAR' | |
startdate = datetime.today().replace(month=1, day=1) | |
sDate = datetime.date(startdate).strftime("%Y%m%d") | |
eDate = datetime.today().strftime("%Y%m%d") | |
res = self._get_water_usage(typeCode, sDate, eDate) | |
data = res['itemDetail'] | |
for usage_data in data: | |
if usage_data['waterType'] == watertype: | |
return usage_data['waterAmount'] | |
def monitor_start(self): | |
"""Start monitoring the device's status.""" | |
self.mon = Monitor(self.client.session, self.device.id) | |
self.mon.start() | |
def monitor_stop(self): | |
"""Stop monitoring the device's status.""" | |
self.mon.stop() | |
def delete_permission(self): | |
self._delete_permission() | |
def poll(self): | |
"""Poll the device's current state. | |
Monitoring must be started first with `monitor_start`. Return | |
either an `ACStatus` object or `None` if the status is not yet | |
available. | |
""" | |
data = self.mon.poll() | |
if data: | |
res = self.model.decode_monitor(data) | |
""" | |
with open('/config/wideq/waterpurifier_polled_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(cockclean, dumpfile, ensure_ascii=False, indent="\t") | |
""" | |
return WPStatus(self, res) | |
else: | |
return None | |
class WPStatus(object): | |
def __init__(self, wp, data): | |
self.wp = wp | |
self.data = data | |
def lookup_enum(self, key): | |
return self.wp.model.enum_name(key, self.data.get(key, '-')) | |
@property | |
def cockclean_state(self): | |
return COCKCLEAN(self.lookup_enum('CockClean')) | |
"""------------------for Air Purifier""" | |
class APOperation(enum.Enum): | |
ON = "@operation_on" | |
OFF = "@operation_off" | |
class APOPMode(enum.Enum): | |
NONE = "@NON" | |
CLEANBOOSTER = "@AP_MAIN_MID_OPMODE_CIRCULATOR_CLEAN_W" | |
SINGLECLEAN = "@AP_MAIN_MID_OPMODE_BABY_CARE_W" | |
CLEAN = "@AP_MAIN_MID_OPMODE_CLEAN_W" | |
DUALCLEAN = "@AP_MAIN_MID_OPMODE_DUAL_CLEAN_W" | |
AUTO = "@AP_MAIN_MID_OPMODE_AUTO_W" | |
class APWindStrength(enum.Enum): | |
LOWST_LOW = "@AP_MAIN_MID_WINDSTRENGTH_LOWST_LOW_W" | |
LOWST = "@AP_MAIN_MID_WINDSTRENGTH_LOWST_W" | |
LOW = "@AP_MAIN_MID_WINDSTRENGTH_LOW_W" | |
LOW_MID = "@AP_MAIN_MID_WINDSTRENGTH_LOW_MID_W" | |
MID = "@AP_MAIN_MID_WINDSTRENGTH_MID_W" | |
MID_HIGH = "@AP_MAIN_MID_WINDSTRENGTH_MID_HIGH_W" | |
HIGH = "@AP_MAIN_MID_WINDSTRENGTH_HIGH_W" | |
POWER = "@AP_MAIN_MID_WINDSTRENGTH_POWER_W" | |
AUTO = "@AP_MAIN_MID_WINDSTRENGTH_AUTO_W" | |
LONGPOWER = "@AP_MAIN_MID_WINDSTRENGTH_LONGPOWWER_W" | |
SHOWER = "@AP_MAIN_MID_WINDSTRENGTH_SHOWER_W" | |
FOREST = "@AP_MAIN_MID_WINDSTRENGTH_FOREST_W" | |
TURBO = "@AP_MAIN_MID_WINDSTRENGTH_TURBO_W" | |
FASTWIND = "@AP_MAIN_MID_WINDSTRENGTH_FASTWIND_W" | |
class APCirculateStrength(enum.Enum): | |
NOT_SUPPORTED = "@NON" | |
LOWST_LOW = '@AP_MAIN_MID_CIRCULATORSTRENGTH_LOWST_LOW_W' | |
LOWST = "@AP_MAIN_MID_CIRCULATORSTRENGTH_LOWST_W" | |
LOW = "@AP_MAIN_MID_CIRCULATORSTRENGTH_LOW_W" | |
LOW_MID = "@AP_MAIN_MID_CIRCULATORSTRENGTH_LOW_MID_W" | |
MID = "@AP_MAIN_MID_CIRCULATORSTRENGTH_MID_W" | |
MID_HIGH = "@AP_MAIN_MID_CIRCULATORSTRENGTH_MID_HIGH_W" | |
HIGH = "@AP_MAIN_MID_CIRCULATORSTRENGTH_HIGH_W" | |
POWER = "@AP_MAIN_MID_CIRCULATORSTRENGTH_POWER_W" | |
AUTO = "@AP_MAIN_MID_CIRCULATORSTRENGTH_AUTO_W" | |
LINK = "@AP_MAIN_MID_CIRCULATORSTRENGTH_LINK_W" | |
class APETCMODE(enum.Enum): | |
NOT_SUPPORT = "@NONSUPPORT" | |
OFF = "@AP_OFF_W" | |
ON = "@AP_ON_W" | |
class APTOTALAIRPOLUTION(enum.Enum): | |
NOT_SUPPORT = '0' | |
GOOD = '1' | |
NORMAL = '2' | |
BAD = '3' | |
VERYBAD = '4' | |
class APSMELL(enum.Enum): | |
NOT_SUPPORT = '0' | |
WEEK = '1' | |
NORMAL = '2' | |
STRONG = '3' | |
VERYSTRONG = '4' | |
class APDevice(Device): | |
def set_on(self, is_on): | |
mode = APOperation.ON if is_on else APOperation.OFF | |
mode_value = self.model.enum_value('Operation', mode.value) | |
self._set_control('Operation', mode_value) | |
def set_mode(self, mode): | |
mode_value = self.model.enum_value('OpMode', mode.value) | |
self._set_control('OpMode', mode_value) | |
def set_windstrength(self, mode): | |
windstrength_value = self.model.enum_value('WindStrength', mode.value) | |
self._set_control('WindStrength', windstrength_value) | |
def set_circulatestrength(self, mode): | |
circulatestrength_value = self.model.enum_value('CirculateStrength', mode.value) | |
self._set_control('CirculateStrength', circulatestrength_value) | |
def set_circulatedir(self, is_on): | |
mode = APETCMODE.ON if is_on else APETCMODE.OFF | |
mode_value = self.model.enum_value('CirculateDir', mode.value) | |
self._set_control('CirculateDir', mode_value) | |
def set_airremoval(self, is_on): | |
mode = APETCMODE.ON if is_on else APETCMODE.OFF | |
mode_value = self.model.enum_value('AirRemoval', mode.value) | |
self._set_control('AirRemoval', mode_value) | |
def set_signallighting(self, is_on): | |
mode = APETCMODE.ON if is_on else APETCMODE.OFF | |
mode_value = self.model.enum_value('SignalLighting', mode.value) | |
self._set_control('SignalLighting', mode_value) | |
def set_airfast(self, is_on): | |
mode = APETCMODE.ON if is_on else APETCMODE.OFF | |
mode_value = self.model.enum_value('AirFast', mode.value) | |
self._set_control('AirFast', mode_value) | |
def get_filter_state(self): | |
"""Get information about the filter.""" | |
return self._get_config('Filter') | |
def monitor_start(self): | |
"""Start monitoring the device's status.""" | |
self.mon = Monitor(self.client.session, self.device.id) | |
self.mon.start() | |
def monitor_stop(self): | |
"""Stop monitoring the device's status.""" | |
self.mon.stop() | |
def delete_permission(self): | |
self._delete_permission() | |
def poll(self): | |
"""Poll the device's current state. | |
Monitoring must be started first with `monitor_start`. Return | |
either an `ACStatus` object or `None` if the status is not yet | |
available. | |
""" | |
data = self.mon.poll() | |
if data: | |
res = self.model.decode_monitor(data) | |
""" | |
with open('/config/wideq/airpurifier_polled_data.json','w', encoding="utf-8") as dumpfile: | |
json.dump(res, dumpfile, ensure_ascii=False, indent="\t") | |
""" | |
return APStatus(self, res) | |
else: | |
return None | |
class APStatus(object): | |
def __init__(self, ap, data): | |
self.ap = ap | |
self.data = data | |
def lookup_enum(self, key): | |
return self.ap.model.enum_name(key, self.data.get(key, '-')) | |
@property | |
def is_on(self): | |
op = APOperation(self.lookup_enum('Operation')) | |
return op == APOperation.ON | |
@property | |
def mode(self): | |
return APOPMode(self.lookup_enum('OpMode')) | |
@property | |
def support_oplist(self): | |
dict_support_opmode = self.ap.model.option_item('SupportOpMode') | |
support_opmode = [] | |
for option in dict_support_opmode.values(): | |
support_opmode.append(APOPMode(option).name) | |
return support_opmode | |
@property | |
def windstrength_state(self): | |
return APWindStrength(self.lookup_enum('WindStrength')) | |
@property | |
def circulatestrength_state(self): | |
return APCirculateStrength(self.lookup_enum('CirculateStrength')) | |
@property | |
def circulatedir_state(self): | |
return APETCMODE(self.lookup_enum('CirculateDir')) | |
@property | |
def airremoval_state(self): | |
return APETCMODE(self.lookup_enum('AirRemoval')) | |
@property | |
def signallighting_state(self): | |
return APETCMODE(self.lookup_enum('SignalLighting')) | |
@property | |
def airfast_state(self): | |
return APETCMODE(self.lookup_enum('AirFast')) | |
@property | |
def sensorpm1(self): | |
return self.data['SensorPM1'] | |
@property | |
def sensorpm2(self): | |
return self.data['SensorPM2'] | |
@property | |
def sensorpm10(self): | |
return self.data['SensorPM10'] | |
@property | |
def total_air_polution(self): | |
return APTOTALAIRPOLUTION(self.data['TotalAirPolution']) | |
@property | |
def air_polution(self): | |
return APSMELL(self.data['AirPolution']) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment