Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions aircon/aircon.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,19 @@ def queue_command(self, name: str, value) -> None:
# Device mode is set using t_control_value
if issubclass(data_type, enum.Enum):
data_value = data_type[value]
elif data_type is int and type(value) is str and '.' in value:
# Round rather than fail if the input is a float.
# This is commonly the case for temperatures converted by HA from Celsius.
data_value = round(float(value))
elif data_type is int:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason to check for "." here, if it's an int value that doesn't have a decimal place the float logic won't affect it.

# incoming data may be an int or float; it's likely to be a float for
# temperatures converted by HA to/from Celsius.
float_val = float(value)

# Granularity may be 0.5, in which case we round to the nearest 0.5, then apply precision
granularity = self._properties.get_granularity(name)
precision = self._properties.get_precision(name)
float_val = (round(float_val / granularity) * granularity) / precision

# Update value precision for value to be sent to the A/C
# We assume that only int types have a precision value
data_value = round(float_val)
else:
data_value = data_type(value)

Expand All @@ -174,11 +183,6 @@ def queue_command(self, name: str, value) -> None:
data_value = data_value.value
typed_value = data_type[value]

# Update value precision for value to be sent to the A/C
precision = self._properties.get_precision(name)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since precision only makes sense if the property is an int anyway, I've moved this to the int clause above

if precision != 1:
data_value = round(data_value / precision)

command = self._build_command(name, data_value)
# There are (usually) no acks on commands, so also queue an update to the
# property, to be run once the command is sent.
Expand Down
12 changes: 12 additions & 0 deletions aircon/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,19 @@ def get_base_type(cls, attr: str):

@classmethod
def get_precision(cls, attr: str):
"""Precision affects int values; they will be divided by the precision to get a result that's
sent to the device. A typical value is 0.1, which means that the value is multiplied by 10.
"""
return cls._get_metadata(attr).get('precision', 1)

@classmethod
def get_granularity(cls, attr: str):
"""Granularity affects int values. Any incoming float value v will be rounded to the nearest
granularity g by round(v/g) * g. A typical value is 0.5. Combined with precision of 0.1, this
can convert an incoming value of 20.1 to 200, or 20.4 to 205.
"""
return cls._get_metadata(attr).get('granularity', 1)

@classmethod
def get_read_only(cls, attr: str):
return cls._get_metadata(attr)['read_only']
Expand Down Expand Up @@ -404,6 +415,7 @@ class FglProperties(Properties):
metadata={
'base_type': 'integer',
'precision': 0.1,
'granularity': 0.5,
'read_only': False
})
af_vertical_direction: int = field(default=3,
Expand Down