test_minco_mh1823d_thermostat.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. from homeassistant.components.climate.const import (
  2. CURRENT_HVAC_HEAT,
  3. CURRENT_HVAC_IDLE,
  4. CURRENT_HVAC_OFF,
  5. HVAC_MODE_AUTO,
  6. HVAC_MODE_HEAT,
  7. HVAC_MODE_OFF,
  8. SUPPORT_PRESET_MODE,
  9. SUPPORT_TARGET_TEMPERATURE,
  10. )
  11. from homeassistant.components.sensor import SensorDeviceClass
  12. from homeassistant.const import (
  13. STATE_UNAVAILABLE,
  14. TEMP_CELSIUS,
  15. TEMP_FAHRENHEIT,
  16. )
  17. from ..const import MINCO_MH1823D_THERMOSTAT_PAYLOAD
  18. from ..helpers import assert_device_properties_set
  19. from ..mixins.climate import TargetTemperatureTests
  20. from ..mixins.lock import BasicLockTests
  21. from ..mixins.number import MultiNumberTests
  22. from ..mixins.select import MultiSelectTests
  23. from ..mixins.sensor import BasicSensorTests
  24. from ..mixins.switch import BasicSwitchTests
  25. from .base_device_tests import TuyaDeviceTestCase
  26. HVACMODE_DPS = "1"
  27. PRESET_DPS = "2"
  28. HVACACTION_DPS = "3"
  29. LOCK_DPS = "5"
  30. ANTIFROST_DPS = "9"
  31. UNKNOWN12_DPS = "12"
  32. SELECT_DPS = "18"
  33. UNIT_DPS = "19"
  34. TEMPERATURE_DPS = "22"
  35. TEMPF_DPS = "23"
  36. UNKNOWN32_DPS = "32"
  37. CURRENTTEMP_DPS = "33"
  38. CALIBINT_DPS = "35"
  39. CURTEMPF_DPS = "37"
  40. SCHEDULE_DPS = "39"
  41. UNKNOWN45_DPS = "45"
  42. EXTERNTEMP_DPS = "101"
  43. EXTTEMPF_DPS = "102"
  44. CALIBEXT_DPS = "103"
  45. CALIBSWING_DPS = "104"
  46. UNKNOWN105_DPS = "105"
  47. TEMPLIMIT_DPS = "106"
  48. TEMPLIMITF_DPS = "107"
  49. class TestMincoMH1823DThermostat(
  50. BasicLockTests,
  51. BasicSensorTests,
  52. BasicSwitchTests,
  53. MultiNumberTests,
  54. MultiSelectTests,
  55. TargetTemperatureTests,
  56. TuyaDeviceTestCase,
  57. ):
  58. __test__ = True
  59. def setUp(self):
  60. self.setUpForConfig(
  61. "minco_mh1823d_thermostat.yaml",
  62. MINCO_MH1823D_THERMOSTAT_PAYLOAD,
  63. )
  64. self.subject = self.entities.get("climate")
  65. self.setUpTargetTemperature(
  66. TEMPERATURE_DPS,
  67. self.subject,
  68. min=5,
  69. max=50,
  70. )
  71. self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
  72. self.setUpBasicSensor(
  73. EXTERNTEMP_DPS,
  74. self.entities.get("sensor_external_temperature"),
  75. unit=TEMP_CELSIUS,
  76. device_class=SensorDeviceClass.TEMPERATURE,
  77. state_class="measurement",
  78. testdata=(300, 30.0),
  79. )
  80. self.setUpBasicSwitch(ANTIFROST_DPS, self.entities.get("switch_anti_frost"))
  81. self.setUpMultiNumber(
  82. [
  83. {
  84. "name": "number_calibration_offset_internal",
  85. "dps": CALIBINT_DPS,
  86. "min": -9,
  87. "max": 9,
  88. "unit": TEMP_CELSIUS,
  89. },
  90. {
  91. "name": "number_calibration_offset_external",
  92. "dps": CALIBEXT_DPS,
  93. "min": -9,
  94. "max": 9,
  95. "unit": TEMP_CELSIUS,
  96. },
  97. {
  98. "name": "number_calibration_swing",
  99. "dps": CALIBSWING_DPS,
  100. "min": 1,
  101. "max": 9,
  102. "unit": TEMP_CELSIUS,
  103. },
  104. {
  105. "name": "number_high_temperature_limit",
  106. "dps": TEMPLIMIT_DPS,
  107. "min": 5,
  108. "max": 65,
  109. "unit": TEMP_CELSIUS,
  110. },
  111. ]
  112. )
  113. self.setUpMultiSelect(
  114. [
  115. {
  116. "name": "select_temperature_sensor",
  117. "dps": SELECT_DPS,
  118. "options": {
  119. "in": "Internal",
  120. "out": "External",
  121. },
  122. },
  123. {
  124. "name": "select_temperature_unit",
  125. "dps": UNIT_DPS,
  126. "options": {
  127. "c": "Celsius",
  128. "f": "Fahrenheit",
  129. },
  130. },
  131. {
  132. "name": "select_schedule",
  133. "dps": SCHEDULE_DPS,
  134. "options": {
  135. "7": "7 day",
  136. "5_2": "5+2 day",
  137. "6_1": "6+1 day",
  138. },
  139. },
  140. ]
  141. )
  142. self.mark_secondary(
  143. [
  144. "lock_child_lock",
  145. "number_calibration_offset_internal",
  146. "number_calibration_offset_external",
  147. "number_calibration_swing",
  148. "number_high_temperature_limit",
  149. "select_temperature_sensor",
  150. "select_temperature_unit",
  151. "select_schedule",
  152. "switch_anti_frost",
  153. ]
  154. )
  155. def test_supported_features(self):
  156. self.assertEqual(
  157. self.subject.supported_features,
  158. SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE,
  159. )
  160. def test_icon(self):
  161. self.dps[HVACMODE_DPS] = True
  162. self.dps[HVACACTION_DPS] = "start"
  163. self.assertEqual(self.subject.icon, "mdi:thermometer")
  164. self.dps[HVACACTION_DPS] = "stop"
  165. self.assertEqual(self.subject.icon, "mdi:thermometer-off")
  166. self.assertEqual(self.basicSwitch.icon, "mdi:snowflake-melt")
  167. def test_temperature_unit(self):
  168. self.dps[UNIT_DPS] = "c"
  169. self.assertEqual(self.subject.temperature_unit, TEMP_CELSIUS)
  170. self.dps[UNIT_DPS] = "f"
  171. self.assertEqual(self.subject.temperature_unit, TEMP_FAHRENHEIT)
  172. def test_target_temperature_f(self):
  173. self.dps[TEMPF_DPS] = 70
  174. self.dps[UNIT_DPS] = "f"
  175. self.assertEqual(self.subject.target_temperature, 70)
  176. def test_minimum_target_temperature_f(self):
  177. self.dps[UNIT_DPS] = "f"
  178. self.assertEqual(self.subject.min_temp, 41)
  179. def test_maximum_target_temperature_f(self):
  180. self.dps[UNIT_DPS] = "f"
  181. self.assertEqual(self.subject.max_temp, 99)
  182. async def test_legacy_set_temperature_with_preset_mode(self):
  183. async with assert_device_properties_set(
  184. self.subject._device, {PRESET_DPS: "holiday"}
  185. ):
  186. await self.subject.async_set_temperature(preset_mode="holiday")
  187. async def test_legacy_set_temperature_with_both_properties(self):
  188. async with assert_device_properties_set(
  189. self.subject._device,
  190. {
  191. TEMPERATURE_DPS: 25,
  192. PRESET_DPS: "program",
  193. },
  194. ):
  195. await self.subject.async_set_temperature(
  196. temperature=25, preset_mode="program"
  197. )
  198. async def test_set_target_temperature_fails_outside_valid_range_f(self):
  199. self.dps[UNIT_DPS] = "f"
  200. with self.assertRaisesRegex(
  201. ValueError, "temp_f \\(40\\) must be between 41 and 99"
  202. ):
  203. await self.subject.async_set_target_temperature(40)
  204. with self.assertRaisesRegex(
  205. ValueError, "temp_f \\(100\\) must be between 41 and 99"
  206. ):
  207. await self.subject.async_set_target_temperature(100)
  208. def test_current_temperature(self):
  209. self.dps[CURRENTTEMP_DPS] = 251
  210. self.dps[CURTEMPF_DPS] = 783
  211. self.dps[UNIT_DPS] = "c"
  212. self.assertEqual(self.subject.current_temperature, 25.1)
  213. self.dps[UNIT_DPS] = "f"
  214. self.assertEqual(self.subject.current_temperature, 78.3)
  215. def test_hvac_mode(self):
  216. self.dps[HVACMODE_DPS] = True
  217. self.dps[PRESET_DPS] = "manual"
  218. self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
  219. self.dps[PRESET_DPS] = "program"
  220. self.assertEqual(self.subject.hvac_mode, HVAC_MODE_AUTO)
  221. self.dps[PRESET_DPS] = "holiday"
  222. self.assertEqual(self.subject.hvac_mode, HVAC_MODE_AUTO)
  223. self.dps[HVACMODE_DPS] = False
  224. self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
  225. self.dps[HVACMODE_DPS] = None
  226. self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
  227. def test_hvac_modes(self):
  228. self.assertCountEqual(
  229. self.subject.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_AUTO]
  230. )
  231. async def test_set_hvac_heat(self):
  232. async with assert_device_properties_set(
  233. self.subject._device, {HVACMODE_DPS: True, PRESET_DPS: "manual"}
  234. ):
  235. await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
  236. async def test_set_hvac_auto(self):
  237. async with assert_device_properties_set(
  238. self.subject._device, {HVACMODE_DPS: True, PRESET_DPS: "program"}
  239. ):
  240. await self.subject.async_set_hvac_mode(HVAC_MODE_AUTO)
  241. async def test_turn_off(self):
  242. async with assert_device_properties_set(
  243. self.subject._device, {HVACMODE_DPS: False}
  244. ):
  245. await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
  246. def test_preset_mode(self):
  247. self.dps[PRESET_DPS] = "manual"
  248. self.assertEqual(self.subject.preset_mode, "manual")
  249. self.dps[PRESET_DPS] = "program"
  250. self.assertEqual(self.subject.preset_mode, "program")
  251. self.dps[PRESET_DPS] = "holiday"
  252. self.assertEqual(self.subject.preset_mode, "holiday")
  253. self.dps[PRESET_DPS] = None
  254. self.assertEqual(self.subject.preset_mode, None)
  255. def test_preset_modes(self):
  256. self.assertCountEqual(
  257. self.subject.preset_modes,
  258. ["manual", "program", "holiday"],
  259. )
  260. async def test_set_preset_mode_to_program(self):
  261. async with assert_device_properties_set(
  262. self.subject._device,
  263. {PRESET_DPS: "program"},
  264. ):
  265. await self.subject.async_set_preset_mode("program")
  266. async def test_set_preset_mode_to_manual(self):
  267. async with assert_device_properties_set(
  268. self.subject._device,
  269. {PRESET_DPS: "manual"},
  270. ):
  271. await self.subject.async_set_preset_mode("manual")
  272. async def test_set_preset_mode_to_holiday(self):
  273. async with assert_device_properties_set(
  274. self.subject._device,
  275. {PRESET_DPS: "holiday"},
  276. ):
  277. await self.subject.async_set_preset_mode("holiday")
  278. def test_hvac_action(self):
  279. self.dps[HVACMODE_DPS] = True
  280. self.dps[HVACACTION_DPS] = "start"
  281. self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
  282. self.dps[HVACACTION_DPS] = "stop"
  283. self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
  284. self.dps[HVACMODE_DPS] = False
  285. self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
  286. def test_extra_state_attributes(self):
  287. self.dps[UNKNOWN12_DPS] = False
  288. self.dps[UNKNOWN32_DPS] = 32
  289. self.dps[UNKNOWN45_DPS] = 45
  290. self.dps[UNKNOWN105_DPS] = "unknown 105"
  291. self.assertDictEqual(
  292. self.subject.extra_state_attributes,
  293. {
  294. "unknown_12": False,
  295. "unknown_32": 32,
  296. "unknown_45": 45,
  297. "unknown_105": "unknown 105",
  298. },
  299. )