Module wideq.ac
A Device
class representing air conditioning/climate devices.
Expand source code
"""A `Device` class representing air conditioning/climate devices.
"""
import enum
from .client import Device
from .util import lookup_enum
from .core import FailedRequestError
class ACJetMode(enum.Enum):
"""JET mode puts your AC into highest cooling or dry or
heat mode(for a certain amount of time) depending on what you choose
This mode Overrides following setting:
1. Vertical swing is set to @100
2. Temperature gets set to 18 after jet mode turns off
3. Fan speed is set to HIGH (@AC_MAIN_WIND_STRENGTH_HIGH_W)
after jet mode turns off
"""
OFF = "@OFF"
COOL = "@COOL_JET"
HEAT = "@HEAT_JET"
DRY = "@DRY_JET_W"
HIMALAYAS = "@HIMALAYAS_COOL"
class ACVSwingMode(enum.Enum):
"""The vertical swing mode for an AC/HVAC device.
Blades are numbered vertically from 1 (topmost)
to 6.
All is 100.
"""
OFF = "@OFF"
ONE = "@1"
TWO = "@2"
THREE = "@3"
FOUR = "@4"
FIVE = "@5"
SIX = "@6"
ALL = "@100"
class ACHSwingMode(enum.Enum):
"""The horizontal swing mode for an AC/HVAC device.
Blades are numbered horizontally from 1 (leftmost)
to 5.
Left half goes from 1-3, and right half goes from
3-5.
All is 100.
"""
OFF = "@OFF"
ONE = "@1"
TWO = "@2"
THREE = "@3"
FOUR = "@4"
FIVE = "@5"
LEFT_HALF = "@13"
RIGHT_HALF = "@35"
ALL = "@100"
class ACMode(enum.Enum):
"""The operation mode for an AC/HVAC device."""
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"
ENERGY_SAVER = "@AC_MAIN_OPERATION_MODE_ENERGY_SAVER_W"
class ACFanSpeed(enum.Enum):
"""The fan speed for an AC/HVAC device."""
SLOW = '@AC_MAIN_WIND_STRENGTH_SLOW_W'
SLOW_LOW = '@AC_MAIN_WIND_STRENGTH_SLOW_LOW_W'
LOW = '@AC_MAIN_WIND_STRENGTH_LOW_W'
LOW_MID = '@AC_MAIN_WIND_STRENGTH_LOW_MID_W'
MID = '@AC_MAIN_WIND_STRENGTH_MID_W'
MID_HIGH = '@AC_MAIN_WIND_STRENGTH_MID_HIGH_W'
HIGH = '@AC_MAIN_WIND_STRENGTH_HIGH_W'
POWER = '@AC_MAIN_WIND_STRENGTH_POWER_W'
AUTO = '@AC_MAIN_WIND_STRENGTH_AUTO_W'
NATURE = '@AC_MAIN_WIND_STRENGTH_NATURE_W'
R_LOW = '@AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W'
R_MID = '@AC_MAIN_WIND_STRENGTH_MID_RIGHT_W'
R_HIGH = '@AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W'
L_LOW = '@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W'
L_MID = '@AC_MAIN_WIND_STRENGTH_MID_LEFT_W'
L_HIGH = '@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W'
L_LOWR_LOW = '@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W'
L_LOWR_MID = '@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_MID_RIGHT_W'
L_LOWR_HIGH = '@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W'
L_MIDR_LOW = '@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W'
L_MIDR_MID = '@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_MID_RIGHT_W'
L_MIDR_HIGH = '@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W'
L_HIGHR_LOW = '@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W'
L_HIGHR_MID = '@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_MID_RIGHT_W'
L_HIGHR_HIGH = '@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W'
AUTO_2 = '@AC_MAIN_WIND_STRENGTH_AUTO_LEFT_W|' \
'AC_MAIN_WIND_STRENGTH_AUTO_RIGHT_W'
POWER_2 = '@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'
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" # Right fan only.
LEFT_ON = "@AC_MAIN_OPERATION_LEFT_ON_W" # Left fan only.
ALL_ON = "@AC_MAIN_OPERATION_ALL_ON_W" # Both fans (or only fan) 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
@property
def supported_operations(self):
"""Get a list of the ACOp Operations the device supports.
"""
mapping = self.model.value('Operation').options
return [ACOp(o) for i, o in mapping.items()]
@property
def supported_on_operation(self):
"""Get the most correct "On" operation the device supports.
:raises ValueError: If ALL_ON is not supported, but there are
multiple supported ON operations. If a model raises this,
its behaviour needs to be determined so this function can
make a better decision.
"""
operations = self.supported_operations
operations.remove(ACOp.OFF)
# This ON operation appears to be supported in newer AC models
if ACOp.ALL_ON in operations:
return ACOp.ALL_ON
# Older models, or possibly just the LP1419IVSM, do not support ALL_ON,
# instead advertising only a single operation of RIGHT_ON.
# Thus, if there's only one ON operation, we use that.
if len(operations) == 1:
return operations[0]
# Hypothetically, the API could return multiple ON operations, neither
# of which are ALL_ON. This will raise in that case, as we don't know
# what that model will expect us to do to turn everything on.
# Or, this code will never actually be reached! We can only hope. :)
raise ValueError(
f"could not determine correct 'on' operation:"
f" too many reported operations: '{str(operations)}'")
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_zones(self, zones):
"""Turn off or on the device's zones.
The `zones` parameter is a list of dicts with these keys:
- "No": The zone index. A string containing a number,
starting from 1.
- "Cfg": Whether the zone is enabled. A string, either "1" or
"0".
- "State": Whether the zone is open. Also "1" or "0".
"""
# Ensure at least one zone is enabled: we can't turn all zones
# off simultaneously.
on_count = sum(int(zone['State']) for zone in zones)
if on_count > 0:
zone_cmd = '/'.join(
'{}_{}'.format(zone['No'], zone['State'])
for zone in zones if zone['Cfg'] == '1'
)
self._set_control('DuctZone', zone_cmd)
def get_zones(self):
"""Get the status of the zones, including whether a zone is
configured.
The result is a list of dicts with the same format as described in
`set_zones`.
"""
return self._get_config('DuctZone')
def set_jet_mode(self, jet_opt):
"""Set jet mode to a value from the `ACJetMode` enum.
"""
jet_opt_value = self.model.enum_value('Jet', jet_opt.value)
self._set_control('Jet', jet_opt_value)
def set_fan_speed(self, speed):
"""Set the fan speed to a value from the `ACFanSpeed` enum.
"""
speed_value = self.model.enum_value('WindStrength', speed.value)
self._set_control('WindStrength', speed_value)
def set_horz_swing(self, swing):
"""Set the horizontal swing to a value from the `ACHSwingMode` enum.
"""
swing_value = self.model.enum_value('WDirHStep', swing.value)
self._set_control('WDirHStep', swing_value)
def set_vert_swing(self, swing):
"""Set the vertical swing to a value from the `ACVSwingMode` enum.
"""
swing_value = self.model.enum_value('WDirVStep', swing.value)
self._set_control('WDirVStep', swing_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_on(self, is_on):
"""Turn on or off the device (according to a boolean).
"""
op = self.supported_on_operation if is_on else ACOp.OFF
op_value = self.model.enum_value('Operation', op.value)
self._set_control('Operation', op_value)
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_outdoor_power(self):
"""Get instant power usage in watts of the outdoor unit"""
value = self._get_config('OutTotalInstantPower')
return value['OutTotalInstantPower']
def get_power(self):
"""Get the instant power usage in watts of the whole unit"""
value = self._get_config('InOutInstantPower')
return value['InOutInstantPower']
def get_light(self):
"""Get a Boolean indicating whether the display light is on."""
try:
value = self._get_control('DisplayControl')
return value == '0' # Seems backwards, but isn't.
except FailedRequestError:
# Device does not support reporting display light status.
# Since it's probably not changeable the it must be on.
return True
def get_volume(self):
"""Get the speaker volume level."""
try:
value = self._get_control('SpkVolume')
return int(value)
except FailedRequestError:
return 0 # Device does not support volume control.
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.
"""
# Abort if monitoring has not started yet.
if not hasattr(self, 'mon'):
return None
res = self.mon.poll_json()
if res:
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", 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 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]
@property
def mode(self):
return ACMode(lookup_enum('OpMode', self.data, self.ac))
@property
def fan_speed(self):
return ACFanSpeed(lookup_enum('WindStrength', self.data, self.ac))
@property
def horz_swing(self):
return ACHSwingMode(lookup_enum('WDirHStep', self.data, self.ac))
@property
def vert_swing(self):
return ACVSwingMode(lookup_enum('WDirVStep', self.data, self.ac))
@property
def is_on(self):
op = ACOp(lookup_enum('Operation', self.data, self.ac))
return op != ACOp.OFF
def __str__(self):
return "ACStatus(%r %r)" % (self.ac, self.data)
Classes
class ACDevice (client: Client, device: DeviceInfo)
-
Higher-level operations on an AC/HVAC device, such as a heat pump.
Create a wrapper for a
DeviceInfo
object associated with aClient
.Expand source code
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 @property def supported_operations(self): """Get a list of the ACOp Operations the device supports. """ mapping = self.model.value('Operation').options return [ACOp(o) for i, o in mapping.items()] @property def supported_on_operation(self): """Get the most correct "On" operation the device supports. :raises ValueError: If ALL_ON is not supported, but there are multiple supported ON operations. If a model raises this, its behaviour needs to be determined so this function can make a better decision. """ operations = self.supported_operations operations.remove(ACOp.OFF) # This ON operation appears to be supported in newer AC models if ACOp.ALL_ON in operations: return ACOp.ALL_ON # Older models, or possibly just the LP1419IVSM, do not support ALL_ON, # instead advertising only a single operation of RIGHT_ON. # Thus, if there's only one ON operation, we use that. if len(operations) == 1: return operations[0] # Hypothetically, the API could return multiple ON operations, neither # of which are ALL_ON. This will raise in that case, as we don't know # what that model will expect us to do to turn everything on. # Or, this code will never actually be reached! We can only hope. :) raise ValueError( f"could not determine correct 'on' operation:" f" too many reported operations: '{str(operations)}'") 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_zones(self, zones): """Turn off or on the device's zones. The `zones` parameter is a list of dicts with these keys: - "No": The zone index. A string containing a number, starting from 1. - "Cfg": Whether the zone is enabled. A string, either "1" or "0". - "State": Whether the zone is open. Also "1" or "0". """ # Ensure at least one zone is enabled: we can't turn all zones # off simultaneously. on_count = sum(int(zone['State']) for zone in zones) if on_count > 0: zone_cmd = '/'.join( '{}_{}'.format(zone['No'], zone['State']) for zone in zones if zone['Cfg'] == '1' ) self._set_control('DuctZone', zone_cmd) def get_zones(self): """Get the status of the zones, including whether a zone is configured. The result is a list of dicts with the same format as described in `set_zones`. """ return self._get_config('DuctZone') def set_jet_mode(self, jet_opt): """Set jet mode to a value from the `ACJetMode` enum. """ jet_opt_value = self.model.enum_value('Jet', jet_opt.value) self._set_control('Jet', jet_opt_value) def set_fan_speed(self, speed): """Set the fan speed to a value from the `ACFanSpeed` enum. """ speed_value = self.model.enum_value('WindStrength', speed.value) self._set_control('WindStrength', speed_value) def set_horz_swing(self, swing): """Set the horizontal swing to a value from the `ACHSwingMode` enum. """ swing_value = self.model.enum_value('WDirHStep', swing.value) self._set_control('WDirHStep', swing_value) def set_vert_swing(self, swing): """Set the vertical swing to a value from the `ACVSwingMode` enum. """ swing_value = self.model.enum_value('WDirVStep', swing.value) self._set_control('WDirVStep', swing_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_on(self, is_on): """Turn on or off the device (according to a boolean). """ op = self.supported_on_operation if is_on else ACOp.OFF op_value = self.model.enum_value('Operation', op.value) self._set_control('Operation', op_value) 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_outdoor_power(self): """Get instant power usage in watts of the outdoor unit""" value = self._get_config('OutTotalInstantPower') return value['OutTotalInstantPower'] def get_power(self): """Get the instant power usage in watts of the whole unit""" value = self._get_config('InOutInstantPower') return value['InOutInstantPower'] def get_light(self): """Get a Boolean indicating whether the display light is on.""" try: value = self._get_control('DisplayControl') return value == '0' # Seems backwards, but isn't. except FailedRequestError: # Device does not support reporting display light status. # Since it's probably not changeable the it must be on. return True def get_volume(self): """Get the speaker volume level.""" try: value = self._get_control('SpkVolume') return int(value) except FailedRequestError: return 0 # Device does not support volume control. 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. """ # Abort if monitoring has not started yet. if not hasattr(self, 'mon'): return None res = self.mon.poll_json() if res: return ACStatus(self, res) else: return None
Ancestors
Instance variables
var c2f
-
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.Expand source code
@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
var f2c
-
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.
Expand source code
@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()}
var supported_on_operation
-
Get the most correct "On" operation the device supports. :raises ValueError: If ALL_ON is not supported, but there are multiple supported ON operations. If a model raises this, its behaviour needs to be determined so this function can make a better decision.
Expand source code
@property def supported_on_operation(self): """Get the most correct "On" operation the device supports. :raises ValueError: If ALL_ON is not supported, but there are multiple supported ON operations. If a model raises this, its behaviour needs to be determined so this function can make a better decision. """ operations = self.supported_operations operations.remove(ACOp.OFF) # This ON operation appears to be supported in newer AC models if ACOp.ALL_ON in operations: return ACOp.ALL_ON # Older models, or possibly just the LP1419IVSM, do not support ALL_ON, # instead advertising only a single operation of RIGHT_ON. # Thus, if there's only one ON operation, we use that. if len(operations) == 1: return operations[0] # Hypothetically, the API could return multiple ON operations, neither # of which are ALL_ON. This will raise in that case, as we don't know # what that model will expect us to do to turn everything on. # Or, this code will never actually be reached! We can only hope. :) raise ValueError( f"could not determine correct 'on' operation:" f" too many reported operations: '{str(operations)}'")
var supported_operations
-
Get a list of the ACOp Operations the device supports.
Expand source code
@property def supported_operations(self): """Get a list of the ACOp Operations the device supports. """ mapping = self.model.value('Operation').options return [ACOp(o) for i, o in mapping.items()]
Methods
def get_energy_target(self)
-
Get the configured energy target data.
Expand source code
def get_energy_target(self): """Get the configured energy target data.""" return self._get_config('EnergyDesiredValue')
def get_filter_state(self)
-
Get information about the filter.
Expand source code
def get_filter_state(self): """Get information about the filter.""" return self._get_config('Filter')
def get_light(self)
-
Get a Boolean indicating whether the display light is on.
Expand source code
def get_light(self): """Get a Boolean indicating whether the display light is on.""" try: value = self._get_control('DisplayControl') return value == '0' # Seems backwards, but isn't. except FailedRequestError: # Device does not support reporting display light status. # Since it's probably not changeable the it must be on. return True
def get_mfilter_state(self)
-
Get information about the "MFilter" (not sure what this is).
Expand source code
def get_mfilter_state(self): """Get information about the "MFilter" (not sure what this is). """ return self._get_config('MFilter')
def get_outdoor_power(self)
-
Get instant power usage in watts of the outdoor unit
Expand source code
def get_outdoor_power(self): """Get instant power usage in watts of the outdoor unit""" value = self._get_config('OutTotalInstantPower') return value['OutTotalInstantPower']
def get_power(self)
-
Get the instant power usage in watts of the whole unit
Expand source code
def get_power(self): """Get the instant power usage in watts of the whole unit""" value = self._get_config('InOutInstantPower') return value['InOutInstantPower']
def get_volume(self)
-
Get the speaker volume level.
Expand source code
def get_volume(self): """Get the speaker volume level.""" try: value = self._get_control('SpkVolume') return int(value) except FailedRequestError: return 0 # Device does not support volume control.
def get_zones(self)
-
Get the status of the zones, including whether a zone is configured.
The result is a list of dicts with the same format as described in
set_zones
.Expand source code
def get_zones(self): """Get the status of the zones, including whether a zone is configured. The result is a list of dicts with the same format as described in `set_zones`. """ return self._get_config('DuctZone')
def poll(self)
-
Poll the device's current state.
Monitoring must be started first with
monitor_start
. Return either anACStatus
object orNone
if the status is not yet available.Expand source code
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. """ # Abort if monitoring has not started yet. if not hasattr(self, 'mon'): return None res = self.mon.poll_json() if res: return ACStatus(self, res) else: return None
def set_celsius(self, c)
-
Set the device's target temperature in Celsius degrees.
Expand source code
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.
Expand source code
def set_fahrenheit(self, f): """Set the device's target temperature in Fahrenheit degrees. """ self.set_celsius(self.f2c[f])
def set_fan_speed(self, speed)
-
Set the fan speed to a value from the
ACFanSpeed
enum.Expand source code
def set_fan_speed(self, speed): """Set the fan speed to a value from the `ACFanSpeed` enum. """ speed_value = self.model.enum_value('WindStrength', speed.value) self._set_control('WindStrength', speed_value)
def set_horz_swing(self, swing)
-
Set the horizontal swing to a value from the
ACHSwingMode
enum.Expand source code
def set_horz_swing(self, swing): """Set the horizontal swing to a value from the `ACHSwingMode` enum. """ swing_value = self.model.enum_value('WDirHStep', swing.value) self._set_control('WDirHStep', swing_value)
def set_jet_mode(self, jet_opt)
-
Set jet mode to a value from the
ACJetMode
enum.Expand source code
def set_jet_mode(self, jet_opt): """Set jet mode to a value from the `ACJetMode` enum. """ jet_opt_value = self.model.enum_value('Jet', jet_opt.value) self._set_control('Jet', jet_opt_value)
def set_mode(self, mode)
-
Set the device's operating mode to an
OpMode
value.Expand source code
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_on(self, is_on)
-
Turn on or off the device (according to a boolean).
Expand source code
def set_on(self, is_on): """Turn on or off the device (according to a boolean). """ op = self.supported_on_operation if is_on else ACOp.OFF op_value = self.model.enum_value('Operation', op.value) self._set_control('Operation', op_value)
def set_vert_swing(self, swing)
-
Set the vertical swing to a value from the
ACVSwingMode
enum.Expand source code
def set_vert_swing(self, swing): """Set the vertical swing to a value from the `ACVSwingMode` enum. """ swing_value = self.model.enum_value('WDirVStep', swing.value) self._set_control('WDirVStep', swing_value)
def set_zones(self, zones)
-
Turn off or on the device's zones.
The
zones
parameter is a list of dicts with these keys: - "No": The zone index. A string containing a number, starting from 1. - "Cfg": Whether the zone is enabled. A string, either "1" or "0". - "State": Whether the zone is open. Also "1" or "0".Expand source code
def set_zones(self, zones): """Turn off or on the device's zones. The `zones` parameter is a list of dicts with these keys: - "No": The zone index. A string containing a number, starting from 1. - "Cfg": Whether the zone is enabled. A string, either "1" or "0". - "State": Whether the zone is open. Also "1" or "0". """ # Ensure at least one zone is enabled: we can't turn all zones # off simultaneously. on_count = sum(int(zone['State']) for zone in zones) if on_count > 0: zone_cmd = '/'.join( '{}_{}'.format(zone['No'], zone['State']) for zone in zones if zone['Cfg'] == '1' ) self._set_control('DuctZone', zone_cmd)
Inherited members
class ACFanSpeed (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
The fan speed for an AC/HVAC device.
Expand source code
class ACFanSpeed(enum.Enum): """The fan speed for an AC/HVAC device.""" SLOW = '@AC_MAIN_WIND_STRENGTH_SLOW_W' SLOW_LOW = '@AC_MAIN_WIND_STRENGTH_SLOW_LOW_W' LOW = '@AC_MAIN_WIND_STRENGTH_LOW_W' LOW_MID = '@AC_MAIN_WIND_STRENGTH_LOW_MID_W' MID = '@AC_MAIN_WIND_STRENGTH_MID_W' MID_HIGH = '@AC_MAIN_WIND_STRENGTH_MID_HIGH_W' HIGH = '@AC_MAIN_WIND_STRENGTH_HIGH_W' POWER = '@AC_MAIN_WIND_STRENGTH_POWER_W' AUTO = '@AC_MAIN_WIND_STRENGTH_AUTO_W' NATURE = '@AC_MAIN_WIND_STRENGTH_NATURE_W' R_LOW = '@AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W' R_MID = '@AC_MAIN_WIND_STRENGTH_MID_RIGHT_W' R_HIGH = '@AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W' L_LOW = '@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W' L_MID = '@AC_MAIN_WIND_STRENGTH_MID_LEFT_W' L_HIGH = '@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W' L_LOWR_LOW = '@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W' L_LOWR_MID = '@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_MID_RIGHT_W' L_LOWR_HIGH = '@AC_MAIN_WIND_STRENGTH_LOW_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W' L_MIDR_LOW = '@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W' L_MIDR_MID = '@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_MID_RIGHT_W' L_MIDR_HIGH = '@AC_MAIN_WIND_STRENGTH_MID_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W' L_HIGHR_LOW = '@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_LOW_RIGHT_W' L_HIGHR_MID = '@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_MID_RIGHT_W' L_HIGHR_HIGH = '@AC_MAIN_WIND_STRENGTH_HIGH_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_HIGH_RIGHT_W' AUTO_2 = '@AC_MAIN_WIND_STRENGTH_AUTO_LEFT_W|' \ 'AC_MAIN_WIND_STRENGTH_AUTO_RIGHT_W' POWER_2 = '@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'
Ancestors
- enum.Enum
Class variables
var AUTO
var AUTO_2
var HIGH
var LONGPOWER
var LOW
var LOW_MID
var L_HIGH
var L_HIGHR_HIGH
var L_HIGHR_LOW
var L_HIGHR_MID
var L_LOW
var L_LOWR_HIGH
var L_LOWR_LOW
var L_LOWR_MID
var L_MID
var L_MIDR_HIGH
var L_MIDR_LOW
var L_MIDR_MID
var MID
var MID_HIGH
var NATURE
var POWER
var POWER_2
var R_HIGH
var R_LOW
var R_MID
var SLOW
var SLOW_LOW
class ACHSwingMode (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
The horizontal swing mode for an AC/HVAC device.
Blades are numbered horizontally from 1 (leftmost) to 5.
Left half goes from 1-3, and right half goes from 3-5.
All is 100.
Expand source code
class ACHSwingMode(enum.Enum): """The horizontal swing mode for an AC/HVAC device. Blades are numbered horizontally from 1 (leftmost) to 5. Left half goes from 1-3, and right half goes from 3-5. All is 100. """ OFF = "@OFF" ONE = "@1" TWO = "@2" THREE = "@3" FOUR = "@4" FIVE = "@5" LEFT_HALF = "@13" RIGHT_HALF = "@35" ALL = "@100"
Ancestors
- enum.Enum
Class variables
var ALL
var FIVE
var FOUR
var LEFT_HALF
var OFF
var ONE
var RIGHT_HALF
var THREE
var TWO
class ACJetMode (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
JET mode puts your AC into highest cooling or dry or heat mode(for a certain amount of time) depending on what you choose
This mode Overrides following setting: 1. Vertical swing is set to @100 2. Temperature gets set to 18 after jet mode turns off 3. Fan speed is set to HIGH (@AC_MAIN_WIND_STRENGTH_HIGH_W) after jet mode turns off
Expand source code
class ACJetMode(enum.Enum): """JET mode puts your AC into highest cooling or dry or heat mode(for a certain amount of time) depending on what you choose This mode Overrides following setting: 1. Vertical swing is set to @100 2. Temperature gets set to 18 after jet mode turns off 3. Fan speed is set to HIGH (@AC_MAIN_WIND_STRENGTH_HIGH_W) after jet mode turns off """ OFF = "@OFF" COOL = "@COOL_JET" HEAT = "@HEAT_JET" DRY = "@DRY_JET_W" HIMALAYAS = "@HIMALAYAS_COOL"
Ancestors
- enum.Enum
Class variables
var COOL
var DRY
var HEAT
var HIMALAYAS
var OFF
class ACMode (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
The operation mode for an AC/HVAC device.
Expand source code
class ACMode(enum.Enum): """The operation mode for an AC/HVAC device.""" 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" ENERGY_SAVER = "@AC_MAIN_OPERATION_MODE_ENERGY_SAVER_W"
Ancestors
- enum.Enum
Class variables
var ACO
var AI
var AIRCLEAN
var AROMA
var COOL
var DRY
var ENERGY_SAVER
var ENERGY_SAVING
var FAN
var HEAT
class ACOp (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
Whether a device is on or off.
Expand source code
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" # Right fan only. LEFT_ON = "@AC_MAIN_OPERATION_LEFT_ON_W" # Left fan only. ALL_ON = "@AC_MAIN_OPERATION_ALL_ON_W" # Both fans (or only fan) on.
Ancestors
- enum.Enum
Class variables
var ALL_ON
var LEFT_ON
var OFF
var RIGHT_ON
class ACStatus (ac, data)
-
Higher-level information about an AC device's current status.
Expand source code
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", 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 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] @property def mode(self): return ACMode(lookup_enum('OpMode', self.data, self.ac)) @property def fan_speed(self): return ACFanSpeed(lookup_enum('WindStrength', self.data, self.ac)) @property def horz_swing(self): return ACHSwingMode(lookup_enum('WDirHStep', self.data, self.ac)) @property def vert_swing(self): return ACVSwingMode(lookup_enum('WDirVStep', self.data, self.ac)) @property def is_on(self): op = ACOp(lookup_enum('Operation', self.data, self.ac)) return op != ACOp.OFF def __str__(self): return "ACStatus(%r %r)" % (self.ac, self.data)
Instance variables
var fan_speed
-
Expand source code
@property def fan_speed(self): return ACFanSpeed(lookup_enum('WindStrength', self.data, self.ac))
var horz_swing
-
Expand source code
@property def horz_swing(self): return ACHSwingMode(lookup_enum('WDirHStep', self.data, self.ac))
var is_on
-
Expand source code
@property def is_on(self): op = ACOp(lookup_enum('Operation', self.data, self.ac)) return op != ACOp.OFF
var mode
-
Expand source code
@property def mode(self): return ACMode(lookup_enum('OpMode', self.data, self.ac))
var temp_cfg_c
-
Expand source code
@property def temp_cfg_c(self): return self._str_to_num(self.data['TempCfg'])
var temp_cfg_f
-
Expand source code
@property def temp_cfg_f(self): return self.ac.c2f[self.temp_cfg_c]
var temp_cur_c
-
Expand source code
@property def temp_cur_c(self): return self._str_to_num(self.data['TempCur'])
var temp_cur_f
-
Expand source code
@property def temp_cur_f(self): return self.ac.c2f[self.temp_cur_c]
var vert_swing
-
Expand source code
@property def vert_swing(self): return ACVSwingMode(lookup_enum('WDirVStep', self.data, self.ac))
class ACVSwingMode (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
The vertical swing mode for an AC/HVAC device.
Blades are numbered vertically from 1 (topmost) to 6.
All is 100.
Expand source code
class ACVSwingMode(enum.Enum): """The vertical swing mode for an AC/HVAC device. Blades are numbered vertically from 1 (topmost) to 6. All is 100. """ OFF = "@OFF" ONE = "@1" TWO = "@2" THREE = "@3" FOUR = "@4" FIVE = "@5" SIX = "@6" ALL = "@100"
Ancestors
- enum.Enum
Class variables
var ALL
var FIVE
var FOUR
var OFF
var ONE
var SIX
var THREE
var TWO