test_goldair_gpph_heater.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. from homeassistant.components.binary_sensor import BinarySensorDeviceClass
  2. from homeassistant.components.climate.const import ClimateEntityFeature, HVACMode
  3. from homeassistant.components.sensor import SensorDeviceClass
  4. from homeassistant.const import (
  5. PERCENTAGE,
  6. PRECISION_WHOLE,
  7. UnitOfTemperature,
  8. UnitOfTime,
  9. )
  10. from ..const import GPPH_HEATER_PAYLOAD
  11. from ..helpers import assert_device_properties_set
  12. from ..mixins.binary_sensor import BasicBinarySensorTests
  13. from ..mixins.climate import TargetTemperatureTests
  14. from ..mixins.light import BasicLightTests
  15. from ..mixins.lock import BasicLockTests
  16. from ..mixins.number import BasicNumberTests
  17. from ..mixins.sensor import BasicSensorTests
  18. from .base_device_tests import TuyaDeviceTestCase
  19. HVACMODE_DPS = "1"
  20. TEMPERATURE_DPS = "2"
  21. CURRENTTEMP_DPS = "3"
  22. PRESET_DPS = "4"
  23. LOCK_DPS = "6"
  24. ERROR_DPS = "12"
  25. POWERLEVEL_DPS = "101"
  26. TIMER_DPS = "102"
  27. TIMERACT_DPS = "103"
  28. LIGHT_DPS = "104"
  29. SWING_DPS = "105"
  30. ECOTEMP_DPS = "106"
  31. class TestGoldairHeater(
  32. BasicBinarySensorTests,
  33. BasicLightTests,
  34. BasicLockTests,
  35. BasicNumberTests,
  36. BasicSensorTests,
  37. TargetTemperatureTests,
  38. TuyaDeviceTestCase,
  39. ):
  40. __test__ = True
  41. def setUp(self):
  42. self.setUpForConfig("goldair_gpph_heater.yaml", GPPH_HEATER_PAYLOAD)
  43. self.subject = self.entities.get("climate")
  44. self.setUpTargetTemperature(
  45. TEMPERATURE_DPS,
  46. self.subject,
  47. min=5.0,
  48. max=35.0,
  49. )
  50. self.setUpBasicLight(LIGHT_DPS, self.entities.get("light_display"))
  51. self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
  52. self.setUpBasicNumber(
  53. TIMER_DPS,
  54. self.entities.get("number_timer"),
  55. max=1440,
  56. step=60,
  57. unit=UnitOfTime.MINUTES,
  58. )
  59. self.setUpBasicSensor(
  60. POWERLEVEL_DPS,
  61. self.entities.get("sensor_power_level"),
  62. unit=PERCENTAGE,
  63. device_class=SensorDeviceClass.POWER_FACTOR,
  64. testdata=("2", 40),
  65. )
  66. self.setUpBasicBinarySensor(
  67. ERROR_DPS,
  68. self.entities.get("binary_sensor_problem"),
  69. device_class=BinarySensorDeviceClass.PROBLEM,
  70. testdata=(1, 0),
  71. )
  72. self.mark_secondary(
  73. [
  74. "light_display",
  75. "lock_child_lock",
  76. "number_timer",
  77. "sensor_power_level",
  78. "binary_sensor_problem",
  79. ]
  80. )
  81. def test_supported_features(self):
  82. self.assertEqual(
  83. self.subject.supported_features,
  84. (
  85. ClimateEntityFeature.TARGET_TEMPERATURE
  86. | ClimateEntityFeature.PRESET_MODE
  87. | ClimateEntityFeature.SWING_MODE
  88. | ClimateEntityFeature.TURN_OFF
  89. | ClimateEntityFeature.TURN_ON
  90. ),
  91. )
  92. def test_translation_key(self):
  93. self.assertEqual(self.subject.translation_key, "swing_as_powerlevel")
  94. def test_icon(self):
  95. self.dps[HVACMODE_DPS] = True
  96. self.assertEqual(self.subject.icon, "mdi:radiator")
  97. self.dps[HVACMODE_DPS] = False
  98. self.assertEqual(self.subject.icon, "mdi:radiator-disabled")
  99. self.dps[HVACMODE_DPS] = True
  100. self.dps[POWERLEVEL_DPS] = "stop"
  101. self.assertEqual(self.subject.icon, "mdi:radiator-disabled")
  102. def test_temperature_unit_returns_celsius(self):
  103. self.assertEqual(
  104. self.subject.temperature_unit,
  105. UnitOfTemperature.CELSIUS,
  106. )
  107. def test_precision(self):
  108. self.assertEqual(self.subject.precision, PRECISION_WHOLE)
  109. def test_target_temperature_in_eco_and_af_modes(self):
  110. self.dps[TEMPERATURE_DPS] = 25
  111. self.dps[ECOTEMP_DPS] = 15
  112. self.dps[PRESET_DPS] = "ECO"
  113. self.assertEqual(self.subject.target_temperature, 15)
  114. self.dps[PRESET_DPS] = "AF"
  115. self.assertIs(self.subject.target_temperature, None)
  116. def test_minimum_temperature(self):
  117. self.dps[PRESET_DPS] = "C"
  118. self.assertEqual(self.subject.min_temp, 5.0)
  119. self.dps[PRESET_DPS] = "ECO"
  120. self.assertEqual(self.subject.min_temp, 5.0)
  121. self.dps[PRESET_DPS] = "AF"
  122. self.assertEqual(self.subject.min_temp, 5.0)
  123. def test_maximum_target_temperature(self):
  124. self.dps[PRESET_DPS] = "C"
  125. self.assertEqual(self.subject.max_temp, 35.0)
  126. self.dps[PRESET_DPS] = "ECO"
  127. self.assertEqual(self.subject.max_temp, 21.0)
  128. self.dps[PRESET_DPS] = "AF"
  129. self.assertEqual(self.subject.max_temp, 5.0)
  130. async def test_legacy_set_temperature_with_preset_mode(self):
  131. async with assert_device_properties_set(
  132. self.subject._device, {PRESET_DPS: "C"}
  133. ):
  134. await self.subject.async_set_temperature(preset_mode="comfort")
  135. async def test_legacy_set_temperature_with_both_properties(self):
  136. async with assert_device_properties_set(
  137. self.subject._device,
  138. {
  139. TEMPERATURE_DPS: 25,
  140. PRESET_DPS: "C",
  141. },
  142. ):
  143. await self.subject.async_set_temperature(
  144. temperature=25, preset_mode="comfort"
  145. )
  146. async def test_set_target_temperature_in_eco_mode(self):
  147. self.dps[PRESET_DPS] = "ECO"
  148. async with assert_device_properties_set(
  149. self.subject._device, {ECOTEMP_DPS: 15}
  150. ):
  151. await self.subject.async_set_target_temperature(15)
  152. async def test_set_target_temperature_fails_outside_valid_range_in_eco(
  153. self,
  154. ):
  155. self.dps[PRESET_DPS] = "ECO"
  156. with self.assertRaisesRegex(
  157. ValueError, "eco_temperature \\(4\\) must be between 5.0 and 21.0"
  158. ):
  159. await self.subject.async_set_target_temperature(4)
  160. with self.assertRaisesRegex(
  161. ValueError, "eco_temperature \\(22\\) must be between 5.0 and 21.0"
  162. ):
  163. await self.subject.async_set_target_temperature(22)
  164. async def test_set_target_temperature_fails_in_anti_freeze(self):
  165. self.dps[PRESET_DPS] = "AF"
  166. with self.assertRaisesRegex(
  167. AttributeError, "temperature cannot be set at this time"
  168. ):
  169. await self.subject.async_set_target_temperature(25)
  170. def test_current_temperature(self):
  171. self.dps[CURRENTTEMP_DPS] = 25
  172. self.assertEqual(self.subject.current_temperature, 25)
  173. def test_humidity_unsupported(self):
  174. self.assertIsNone(self.subject.min_humidity)
  175. self.assertIsNone(self.subject.max_humidity)
  176. self.assertIsNone(self.subject.current_humidity)
  177. with self.assertRaises(NotImplementedError):
  178. self.subject.target_humidity
  179. async def test_set_humidity_unsupported(self):
  180. with self.assertRaises(NotImplementedError):
  181. await self.subject.async_set_humidity(50)
  182. def test_hvac_mode(self):
  183. self.dps[HVACMODE_DPS] = True
  184. self.assertEqual(self.subject.hvac_mode, HVACMode.HEAT)
  185. self.dps[HVACMODE_DPS] = False
  186. self.assertEqual(self.subject.hvac_mode, HVACMode.OFF)
  187. def test_hvac_modes(self):
  188. self.assertCountEqual(
  189. self.subject.hvac_modes,
  190. [HVACMode.OFF, HVACMode.HEAT],
  191. )
  192. async def test_turn_on(self):
  193. async with assert_device_properties_set(
  194. self.subject._device, {HVACMODE_DPS: True}
  195. ):
  196. await self.subject.async_set_hvac_mode(HVACMode.HEAT)
  197. async def test_turn_off(self):
  198. async with assert_device_properties_set(
  199. self.subject._device, {HVACMODE_DPS: False}
  200. ):
  201. await self.subject.async_set_hvac_mode(HVACMode.OFF)
  202. def test_preset_mode(self):
  203. self.dps[PRESET_DPS] = "C"
  204. self.assertEqual(self.subject.preset_mode, "comfort")
  205. self.dps[PRESET_DPS] = "ECO"
  206. self.assertEqual(self.subject.preset_mode, "eco")
  207. self.dps[PRESET_DPS] = "AF"
  208. self.assertEqual(self.subject.preset_mode, "away")
  209. self.dps[PRESET_DPS] = None
  210. self.assertIs(self.subject.preset_mode, None)
  211. def test_preset_modes(self):
  212. self.assertCountEqual(
  213. self.subject.preset_modes,
  214. ["comfort", "eco", "away"],
  215. )
  216. async def test_set_preset_mode_to_comfort(self):
  217. async with assert_device_properties_set(
  218. self.subject._device,
  219. {PRESET_DPS: "C"},
  220. ):
  221. await self.subject.async_set_preset_mode("comfort")
  222. async def test_set_preset_mode_to_eco(self):
  223. async with assert_device_properties_set(
  224. self.subject._device,
  225. {PRESET_DPS: "ECO"},
  226. ):
  227. await self.subject.async_set_preset_mode("eco")
  228. async def test_set_preset_mode_to_anti_freeze(self):
  229. async with assert_device_properties_set(
  230. self.subject._device,
  231. {PRESET_DPS: "AF"},
  232. ):
  233. await self.subject.async_set_preset_mode("away")
  234. def test_power_level_returns_user_power_level(self):
  235. self.dps[SWING_DPS] = "user"
  236. self.dps[POWERLEVEL_DPS] = "stop"
  237. self.assertEqual(self.subject.swing_mode, "stop")
  238. self.dps[POWERLEVEL_DPS] = "3"
  239. self.assertEqual(self.subject.swing_mode, "3")
  240. def test_non_user_swing_mode(self):
  241. self.dps[SWING_DPS] = "stop"
  242. self.assertEqual(self.subject.swing_mode, "stop")
  243. self.dps[SWING_DPS] = "auto"
  244. self.assertEqual(self.subject.swing_mode, "auto")
  245. self.dps[SWING_DPS] = None
  246. self.assertIs(self.subject.swing_mode, None)
  247. def test_swing_modes(self):
  248. self.assertCountEqual(
  249. self.subject.swing_modes,
  250. ["stop", "1", "2", "3", "4", "5", "auto"],
  251. )
  252. async def test_set_power_level_to_stop(self):
  253. async with assert_device_properties_set(
  254. self.subject._device,
  255. {POWERLEVEL_DPS: "stop", SWING_DPS: "stop"},
  256. ):
  257. await self.subject.async_set_swing_mode("stop")
  258. async def test_set_swing_mode_to_auto(self):
  259. async with assert_device_properties_set(
  260. self.subject._device,
  261. {SWING_DPS: "auto"},
  262. ):
  263. await self.subject.async_set_swing_mode("auto")
  264. async def test_set_power_level_to_numeric_value(self):
  265. async with assert_device_properties_set(
  266. self.subject._device,
  267. {SWING_DPS: "user", POWERLEVEL_DPS: "3"},
  268. ):
  269. await self.subject.async_set_swing_mode("3")
  270. def test_extra_state_attributes(self):
  271. self.dps[ERROR_DPS] = "something"
  272. self.dps[TIMER_DPS] = 5
  273. self.dps[TIMERACT_DPS] = True
  274. self.dps[POWERLEVEL_DPS] = 4
  275. self.assertDictEqual(
  276. self.subject.extra_state_attributes,
  277. {
  278. "error": "something",
  279. "timer": 5,
  280. "timer_mode": True,
  281. "power_level": "4",
  282. },
  283. )