|
24 | 24 | from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback |
25 | 25 |
|
26 | 26 | from . import TuyaConfigEntry |
27 | | -from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType |
28 | | -from .entity import TuyaEntity |
29 | | -from .models import ( |
30 | | - DPCodeBooleanWrapper, |
31 | | - DPCodeEnumWrapper, |
32 | | - DPCodeIntegerWrapper, |
33 | | - find_dpcode, |
| 27 | +from .const import ( |
| 28 | + CELSIUS_ALIASES, |
| 29 | + FAHRENHEIT_ALIASES, |
| 30 | + TUYA_DISCOVERY_NEW, |
| 31 | + DeviceCategory, |
| 32 | + DPCode, |
34 | 33 | ) |
| 34 | +from .entity import TuyaEntity |
| 35 | +from .models import DPCodeBooleanWrapper, DPCodeEnumWrapper, DPCodeIntegerWrapper |
35 | 36 |
|
36 | 37 | TUYA_HVAC_TO_HA = { |
37 | 38 | "auto": HVACMode.HEAT_COOL, |
@@ -90,80 +91,82 @@ class TuyaClimateEntityDescription(ClimateEntityDescription): |
90 | 91 | } |
91 | 92 |
|
92 | 93 |
|
| 94 | +def _get_temperature_wrapper( |
| 95 | + wrappers: list[DPCodeIntegerWrapper | None], aliases: set[str] |
| 96 | +) -> DPCodeIntegerWrapper | None: |
| 97 | + """Return first wrapper with matching unit.""" |
| 98 | + return next( |
| 99 | + ( |
| 100 | + wrapper |
| 101 | + for wrapper in wrappers |
| 102 | + if wrapper is not None |
| 103 | + and (unit := wrapper.type_information.unit) |
| 104 | + and unit.lower() in aliases |
| 105 | + ), |
| 106 | + None, |
| 107 | + ) |
| 108 | + |
| 109 | + |
93 | 110 | def _get_temperature_wrappers( |
94 | 111 | device: CustomerDevice, system_temperature_unit: UnitOfTemperature |
95 | 112 | ) -> tuple[DPCodeIntegerWrapper | None, DPCodeIntegerWrapper | None, UnitOfTemperature]: |
96 | 113 | """Get temperature wrappers for current and set temperatures.""" |
97 | | - current_temperature_wrapper: DPCodeIntegerWrapper | None = None |
98 | | - set_temperature_wrapper: DPCodeIntegerWrapper | None = None |
99 | | - |
100 | | - # Default to System Temperature Unit |
101 | | - temperature_unit = system_temperature_unit |
102 | | - |
103 | | - # If both temperature values for celsius and fahrenheit are present, |
104 | | - # use whatever the device is set to, with a fallback to celsius. |
105 | | - preferred_temperature_unit = None |
106 | | - if all( |
107 | | - dpcode in device.status |
108 | | - for dpcode in (DPCode.TEMP_CURRENT, DPCode.TEMP_CURRENT_F) |
109 | | - ) or all( |
110 | | - dpcode in device.status for dpcode in (DPCode.TEMP_SET, DPCode.TEMP_SET_F) |
111 | | - ): |
112 | | - preferred_temperature_unit = UnitOfTemperature.CELSIUS |
113 | | - if any( |
114 | | - "f" in device.status[dpcode].lower() |
115 | | - for dpcode in (DPCode.C_F, DPCode.TEMP_UNIT_CONVERT) |
116 | | - if isinstance(device.status.get(dpcode), str) |
117 | | - ): |
118 | | - preferred_temperature_unit = UnitOfTemperature.FAHRENHEIT |
119 | | - |
120 | | - # Figure out current temperature, use preferred unit or what is available |
121 | | - celsius_type = find_dpcode( |
122 | | - device, (DPCode.TEMP_CURRENT, DPCode.UPPER_TEMP), dptype=DPType.INTEGER |
| 114 | + # Get all possible temperature dpcodes |
| 115 | + temp_current = DPCodeIntegerWrapper.find_dpcode( |
| 116 | + device, (DPCode.TEMP_CURRENT, DPCode.UPPER_TEMP) |
123 | 117 | ) |
124 | | - fahrenheit_type = find_dpcode( |
125 | | - device, |
126 | | - (DPCode.TEMP_CURRENT_F, DPCode.UPPER_TEMP_F), |
127 | | - dptype=DPType.INTEGER, |
| 118 | + temp_current_f = DPCodeIntegerWrapper.find_dpcode( |
| 119 | + device, (DPCode.TEMP_CURRENT_F, DPCode.UPPER_TEMP_F) |
| 120 | + ) |
| 121 | + temp_set = DPCodeIntegerWrapper.find_dpcode( |
| 122 | + device, DPCode.TEMP_SET, prefer_function=True |
| 123 | + ) |
| 124 | + temp_set_f = DPCodeIntegerWrapper.find_dpcode( |
| 125 | + device, DPCode.TEMP_SET_F, prefer_function=True |
128 | 126 | ) |
129 | | - if fahrenheit_type and ( |
130 | | - preferred_temperature_unit == UnitOfTemperature.FAHRENHEIT |
131 | | - or ( |
132 | | - preferred_temperature_unit == UnitOfTemperature.CELSIUS and not celsius_type |
133 | | - ) |
134 | | - ): |
135 | | - temperature_unit = UnitOfTemperature.FAHRENHEIT |
136 | | - current_temperature_wrapper = DPCodeIntegerWrapper( |
137 | | - fahrenheit_type.dpcode, fahrenheit_type |
138 | | - ) |
139 | | - elif celsius_type: |
140 | | - temperature_unit = UnitOfTemperature.CELSIUS |
141 | | - current_temperature_wrapper = DPCodeIntegerWrapper( |
142 | | - celsius_type.dpcode, celsius_type |
143 | | - ) |
144 | 127 |
|
145 | | - # Figure out setting temperature, use preferred unit or what is available |
146 | | - celsius_type = find_dpcode( |
147 | | - device, DPCode.TEMP_SET, dptype=DPType.INTEGER, prefer_function=True |
| 128 | + # Get wrappers for celsius and fahrenheit |
| 129 | + # We need to check the unit of measurement |
| 130 | + current_celsius = _get_temperature_wrapper( |
| 131 | + [temp_current, temp_current_f], CELSIUS_ALIASES |
148 | 132 | ) |
149 | | - fahrenheit_type = find_dpcode( |
150 | | - device, DPCode.TEMP_SET_F, dptype=DPType.INTEGER, prefer_function=True |
| 133 | + current_fahrenheit = _get_temperature_wrapper( |
| 134 | + [temp_current_f, temp_current], FAHRENHEIT_ALIASES |
151 | 135 | ) |
152 | | - if fahrenheit_type and ( |
153 | | - preferred_temperature_unit == UnitOfTemperature.FAHRENHEIT |
154 | | - or ( |
155 | | - preferred_temperature_unit == UnitOfTemperature.CELSIUS and not celsius_type |
156 | | - ) |
| 136 | + set_celsius = _get_temperature_wrapper([temp_set, temp_set_f], CELSIUS_ALIASES) |
| 137 | + set_fahrenheit = _get_temperature_wrapper( |
| 138 | + [temp_set_f, temp_set], FAHRENHEIT_ALIASES |
| 139 | + ) |
| 140 | + |
| 141 | + # Return early if we have the right wrappers for the system unit |
| 142 | + if system_temperature_unit == UnitOfTemperature.FAHRENHEIT: |
| 143 | + if ( |
| 144 | + (current_fahrenheit and set_fahrenheit) |
| 145 | + or (current_fahrenheit and not set_celsius) |
| 146 | + or (set_fahrenheit and not current_celsius) |
| 147 | + ): |
| 148 | + return current_fahrenheit, set_fahrenheit, UnitOfTemperature.FAHRENHEIT |
| 149 | + if ( |
| 150 | + (current_celsius and set_celsius) |
| 151 | + or (current_celsius and not set_fahrenheit) |
| 152 | + or (set_celsius and not current_fahrenheit) |
157 | 153 | ): |
158 | | - set_temperature_wrapper = DPCodeIntegerWrapper( |
159 | | - fahrenheit_type.dpcode, fahrenheit_type |
160 | | - ) |
161 | | - elif celsius_type: |
162 | | - set_temperature_wrapper = DPCodeIntegerWrapper( |
163 | | - celsius_type.dpcode, celsius_type |
| 154 | + return current_celsius, set_celsius, UnitOfTemperature.CELSIUS |
| 155 | + |
| 156 | + # If we don't have the right wrappers, return whatever is available |
| 157 | + # and assume system unit |
| 158 | + if system_temperature_unit == UnitOfTemperature.FAHRENHEIT: |
| 159 | + return ( |
| 160 | + temp_current_f or temp_current, |
| 161 | + temp_set_f or temp_set, |
| 162 | + UnitOfTemperature.FAHRENHEIT, |
164 | 163 | ) |
165 | 164 |
|
166 | | - return current_temperature_wrapper, set_temperature_wrapper, temperature_unit |
| 165 | + return ( |
| 166 | + temp_current or temp_current_f, |
| 167 | + temp_set or temp_set_f, |
| 168 | + UnitOfTemperature.CELSIUS, |
| 169 | + ) |
167 | 170 |
|
168 | 171 |
|
169 | 172 | async def async_setup_entry( |
|
0 commit comments