Skip to content

Instantly share code, notes, and snippets.

@boralyl
Created March 26, 2020 04:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save boralyl/511a8d669c58331f29b04058214945f6 to your computer and use it in GitHub Desktop.
Save boralyl/511a8d669c58331f29b04058214945f6 to your computer and use it in GitHub Desktop.
Home Assistant LG Washer/Dryer Custom Component
"""
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
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()
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()
{
"domain": "smartthinq",
"name": "Smartthinq",
"documentation": "https://github.com/wkd8176/hass-smartthinq",
"requirements": [],
"dependencies": [],
"codeowners": [
"@wkd8176",
"@boralyl"
]
}
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()
# 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: '켜짐'
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