test_beok_tr9b_thermostat.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. from homeassistant.components.binary_sensor import BinarySensorDeviceClass
  2. from homeassistant.components.climate.const import ClimateEntityFeature, HVACMode
  3. from homeassistant.components.number.const import NumberDeviceClass
  4. from homeassistant.const import PRECISION_TENTHS, UnitOfTemperature
  5. from ..const import BEOK_TR9B_PAYLOAD
  6. from ..mixins.binary_sensor import MultiBinarySensorTests
  7. from ..mixins.climate import TargetTemperatureTests
  8. from ..mixins.lock import BasicLockTests
  9. from ..mixins.number import MultiNumberTests
  10. from ..mixins.select import MultiSelectTests
  11. from ..mixins.switch import BasicSwitchTests
  12. from .base_device_tests import TuyaDeviceTestCase
  13. POWER_DPS = "1"
  14. HVACMODE_DPS = "2"
  15. ANTIFROST_DPS = "10"
  16. TEMPERATURE_DPS = "16"
  17. MAXTEMP_DPS = "19"
  18. UNIT_DPS = "23"
  19. CURRENTTEMP_DPS = "24"
  20. MINTEMP_DPS = "26"
  21. SCHED_DPS = "31"
  22. VALVE_DPS = "36"
  23. LOCK_DPS = "40"
  24. ERROR_DPS = "45"
  25. UNKNOWN101_DPS = "101"
  26. UNKNOWN102_DPS = "102"
  27. class TestBeokTR9BThermostat(
  28. MultiBinarySensorTests,
  29. BasicLockTests,
  30. MultiNumberTests,
  31. MultiSelectTests,
  32. BasicSwitchTests,
  33. TargetTemperatureTests,
  34. TuyaDeviceTestCase,
  35. ):
  36. __test__ = True
  37. def setUp(self):
  38. self.setUpForConfig(
  39. "beok_tr9b_thermostat.yaml",
  40. BEOK_TR9B_PAYLOAD,
  41. )
  42. self.subject = self.entities.get("climate")
  43. self.setUpTargetTemperature(
  44. TEMPERATURE_DPS,
  45. self.subject,
  46. min=41.0,
  47. max=99.0,
  48. scale=10,
  49. step=10,
  50. )
  51. self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
  52. self.setUpMultiSelect(
  53. [
  54. {
  55. "dps": SCHED_DPS,
  56. "name": "select_schedule",
  57. "options": {
  58. "5_2": "Weekday+Weekend",
  59. "6_1": "Mon-Sat+Sun",
  60. "7": "Daily",
  61. },
  62. },
  63. {
  64. "dps": UNIT_DPS,
  65. "name": "select_temperature_unit",
  66. "options": {
  67. "c": "celsius",
  68. "f": "fahrenheit",
  69. },
  70. },
  71. ],
  72. )
  73. self.setUpBasicSwitch(
  74. ANTIFROST_DPS,
  75. self.entities.get("switch_anti_frost"),
  76. )
  77. self.setUpMultiBinarySensors(
  78. [
  79. {
  80. "dps": ERROR_DPS,
  81. "name": "binary_sensor_problem",
  82. "device_class": BinarySensorDeviceClass.PROBLEM,
  83. "testdata": (1, 0),
  84. },
  85. {
  86. "dps": VALVE_DPS,
  87. "name": "binary_sensor_valve",
  88. "device_class": BinarySensorDeviceClass.OPENING,
  89. "testdata": ("open", "close"),
  90. },
  91. ],
  92. )
  93. self.setUpMultiNumber(
  94. [
  95. {
  96. "dps": MINTEMP_DPS,
  97. "name": "number_low_temperature_limit",
  98. "device_class": NumberDeviceClass.TEMPERATURE,
  99. "min": 5.0,
  100. "max": 300.0,
  101. "step": 1.0,
  102. "scale": 10,
  103. "unit": UnitOfTemperature.CELSIUS,
  104. },
  105. {
  106. "dps": MAXTEMP_DPS,
  107. "name": "number_high_temperature_limit",
  108. "device_class": NumberDeviceClass.TEMPERATURE,
  109. "min": 5.0,
  110. "max": 300.0,
  111. "step": 1.0,
  112. "scale": 10,
  113. "unit": UnitOfTemperature.CELSIUS,
  114. },
  115. ],
  116. )
  117. self.mark_secondary(
  118. [
  119. "binary_sensor_problem",
  120. "binary_sensor_valve",
  121. "lock_child_lock",
  122. "number_low_temperature_limit",
  123. "number_high_temperature_limit",
  124. "select_schedule",
  125. "select_temperature_unit",
  126. "switch_anti_frost",
  127. ],
  128. )
  129. def test_supported_features(self):
  130. self.assertEqual(
  131. self.subject.supported_features,
  132. ClimateEntityFeature.TARGET_TEMPERATURE
  133. | ClimateEntityFeature.TURN_OFF
  134. | ClimateEntityFeature.TURN_ON,
  135. )
  136. def test_temperature_unit(self):
  137. self.dps[UNIT_DPS] = "c"
  138. self.assertEqual(
  139. self.subject.temperature_unit,
  140. UnitOfTemperature.CELSIUS,
  141. )
  142. self.assertEqual(self.subject.target_temperature_step, 0.5)
  143. self.dps[UNIT_DPS] = "f"
  144. self.assertEqual(
  145. self.subject.temperature_unit,
  146. UnitOfTemperature.FAHRENHEIT,
  147. )
  148. self.assertEqual(self.subject.target_temperature_step, 1.0)
  149. def test_precision(self):
  150. self.assertEqual(self.subject.precision, PRECISION_TENTHS)
  151. def test_current_temperature(self):
  152. self.dps[CURRENTTEMP_DPS] = 685
  153. self.assertEqual(self.subject.current_temperature, 68.5)
  154. def test_hvac_mode(self):
  155. self.dps[POWER_DPS] = False
  156. self.dps[HVACMODE_DPS] = "auto"
  157. self.assertEqual(self.subject.hvac_mode, HVACMode.OFF)
  158. self.dps[POWER_DPS] = True
  159. self.assertEqual(self.subject.hvac_mode, HVACMode.AUTO)
  160. self.dps[HVACMODE_DPS] = "manual"
  161. self.assertEqual(self.subject.hvac_mode, HVACMode.HEAT)
  162. def test_hvac_modes(self):
  163. self.assertCountEqual(
  164. self.subject.hvac_modes,
  165. [
  166. HVACMode.HEAT,
  167. HVACMode.AUTO,
  168. HVACMode.OFF,
  169. ],
  170. )
  171. # Override - since min and max are set by attributes, the range
  172. # allowed when setting is wider than normal. The thermostat seems
  173. # to be configurable as at least a water heater (to 212F), as tuya
  174. # doc says max 300.0 for one matching device, and 1000.0 for
  175. # another (after scaling)
  176. async def test_set_target_temperature_fails_outside_valid_range(self):
  177. with self.assertRaisesRegex(
  178. ValueError,
  179. "temperature \\(4.5\\) must be between 5.0 and 300.0",
  180. ):
  181. await self.subject.async_set_target_temperature(4.5)
  182. with self.assertRaisesRegex(
  183. ValueError,
  184. "temperature \\(1001\\) must be between 5.0 and 300.0",
  185. ):
  186. await self.subject.async_set_target_temperature(1001)
  187. def test_extra_state_attributes(self):
  188. self.dps[UNKNOWN101_DPS] = 101
  189. self.dps[UNKNOWN102_DPS] = 102
  190. self.assertDictEqual(
  191. self.subject.extra_state_attributes,
  192. {"unknown_101": 101, "unknown_102": 102},
  193. )
  194. def test_multi_bsensor_extra_state_attributes(self):
  195. self.dps[ERROR_DPS] = 8
  196. self.assertDictEqual(
  197. self.multiBSensor["binary_sensor_problem"].extra_state_attributes,
  198. {"fault_code": 8},
  199. )