test_saswell_c16_thermostat.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. from homeassistant.components.climate.const import (
  2. ClimateEntityFeature,
  3. HVACAction,
  4. HVACMode,
  5. PRESET_AWAY,
  6. PRESET_HOME,
  7. )
  8. from homeassistant.components.sensor import SensorDeviceClass
  9. from homeassistant.const import POWER_WATT, TEMP_CELSIUS
  10. from ..const import SASWELL_C16_THERMOSTAT_PAYLOAD
  11. from ..helpers import assert_device_properties_set
  12. from ..mixins.climate import TargetTemperatureTests
  13. from ..mixins.lock import BasicLockTests
  14. from ..mixins.number import MultiNumberTests
  15. from ..mixins.select import MultiSelectTests
  16. from ..mixins.sensor import BasicSensorTests
  17. from ..mixins.switch import BasicSwitchTests
  18. from .base_device_tests import TuyaDeviceTestCase
  19. TEMPERATURE_DPS = "2"
  20. PRESET_DPS = "3"
  21. UNKNOWN4_DPS = "4"
  22. CURRENTTEMP_DPS = "5"
  23. FLOORTEMPLIMIT_DPS = "6"
  24. INSTALL_DPS = "7"
  25. FLOORTEMP_DPS = "8"
  26. HVACMODE_DPS = "9"
  27. ADAPTIVE_DPS = "10"
  28. LOCK_DPS = "11"
  29. SCHED_DPS = "12"
  30. UNKNOWN14_DPS = "14"
  31. UNKNOWN15_DPS = "15"
  32. UNKNOWN17_DPS = "17"
  33. UNKNOWN21_DPS = "21"
  34. POWERRATING_DPS = "22"
  35. UNKNOWN23_DPS = "23"
  36. HVACACTION_DPS = "24"
  37. UNKNOWN26_DPS = "26"
  38. class TestSaswellC16Thermostat(
  39. BasicLockTests,
  40. BasicSensorTests,
  41. BasicSwitchTests,
  42. MultiNumberTests,
  43. MultiSelectTests,
  44. TargetTemperatureTests,
  45. TuyaDeviceTestCase,
  46. ):
  47. __test__ = True
  48. def setUp(self):
  49. self.setUpForConfig(
  50. "saswell_c16_thermostat.yaml", SASWELL_C16_THERMOSTAT_PAYLOAD
  51. )
  52. self.subject = self.entities.get("climate")
  53. self.setUpTargetTemperature(
  54. TEMPERATURE_DPS,
  55. self.subject,
  56. min=5.0,
  57. max=40.0,
  58. scale=10,
  59. step=5,
  60. )
  61. self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
  62. self.setUpBasicSensor(
  63. FLOORTEMP_DPS,
  64. self.entities.get("sensor_floor_temperature"),
  65. device_class=SensorDeviceClass.TEMPERATURE,
  66. state_class="measurement",
  67. unit=TEMP_CELSIUS,
  68. testdata=(218, 21.8),
  69. )
  70. self.setUpBasicSwitch(ADAPTIVE_DPS, self.entities.get("switch_adaptive"))
  71. self.setUpMultiNumber(
  72. [
  73. {
  74. "name": "number_floor_temperature_limit",
  75. "dps": FLOORTEMPLIMIT_DPS,
  76. "min": 20.0,
  77. "max": 50.0,
  78. "scale": 10,
  79. "step": 0.5,
  80. "unit": TEMP_CELSIUS,
  81. },
  82. {
  83. "name": "number_power_rating",
  84. "dps": POWERRATING_DPS,
  85. "max": 3500,
  86. "unit": POWER_WATT,
  87. },
  88. ]
  89. )
  90. self.setUpMultiSelect(
  91. [
  92. {
  93. "name": "select_installation",
  94. "dps": INSTALL_DPS,
  95. "options": {
  96. True: "Office",
  97. False: "Home",
  98. },
  99. },
  100. {
  101. "name": "select_schedule",
  102. "dps": SCHED_DPS,
  103. "options": {
  104. "5_1_1": "Weekdays+Sat+Sun",
  105. "7": "Daily",
  106. },
  107. },
  108. ]
  109. )
  110. self.mark_secondary(
  111. [
  112. "lock_child_lock",
  113. "sensor_floor_temperature",
  114. "switch_adaptive",
  115. "number_floor_temperature_limit",
  116. "number_power_rating",
  117. "select_installation",
  118. "select_schedule",
  119. ]
  120. )
  121. def test_supported_features(self):
  122. self.assertEqual(
  123. self.subject.supported_features,
  124. (
  125. ClimateEntityFeature.TARGET_TEMPERATURE
  126. | ClimateEntityFeature.PRESET_MODE
  127. ),
  128. )
  129. def test_icon(self):
  130. self.dps[PRESET_DPS] = "Smart"
  131. self.assertEqual(self.subject.icon, "mdi:home-thermometer")
  132. self.dps[PRESET_DPS] = "Manual"
  133. self.assertEqual(self.subject.icon, "mdi:cursor-pointer")
  134. self.dps[PRESET_DPS] = "Anti_frozen"
  135. self.assertEqual(self.subject.icon, "mdi:snowflake-melt")
  136. self.dps[LOCK_DPS] = True
  137. self.assertEqual(self.basicLock.icon, "mdi:hand-back-right-off")
  138. self.dps[LOCK_DPS] = False
  139. self.assertEqual(self.basicLock.icon, "mdi:hand-back-right")
  140. def test_temperature_unit(self):
  141. self.assertEqual(
  142. self.subject.temperature_unit,
  143. self.subject._device.temperature_unit,
  144. )
  145. def test_current_temperature(self):
  146. self.dps[CURRENTTEMP_DPS] = 250
  147. self.assertEqual(self.subject.current_temperature, 25.0)
  148. def test_hvac_mode(self):
  149. self.dps[HVACMODE_DPS] = True
  150. self.assertEqual(self.subject.hvac_mode, HVACMode.COOL)
  151. self.dps[HVACMODE_DPS] = False
  152. self.assertEqual(self.subject.hvac_mode, HVACMode.HEAT)
  153. def test_hvac_modes(self):
  154. self.assertCountEqual(
  155. self.subject.hvac_modes,
  156. [HVACMode.COOL, HVACMode.HEAT],
  157. )
  158. async def test_set_hvac_mode_cool(self):
  159. with self.assertRaises(TypeError):
  160. await self.subject.async_set_hvac_mode(HVACMode.COOL)
  161. async def test_set_hvac_mode_heat(self):
  162. with self.assertRaises(TypeError):
  163. await self.subject.async_set_hvac_mode(HVACMode.HEAT)
  164. def test_hvac_action(self):
  165. self.dps[HVACACTION_DPS] = "Cooling"
  166. self.assertEqual(self.subject.hvac_action, HVACAction.COOLING)
  167. self.dps[HVACACTION_DPS] = "Heating"
  168. self.assertEqual(self.subject.hvac_action, HVACAction.HEATING)
  169. self.dps[HVACACTION_DPS] = "Standby"
  170. self.assertEqual(self.subject.hvac_action, HVACAction.IDLE)
  171. def test_preset_mode(self):
  172. self.dps[PRESET_DPS] = "Smart"
  173. self.assertEqual(self.subject.preset_mode, PRESET_HOME)
  174. self.dps[PRESET_DPS] = "Manual"
  175. self.assertEqual(self.subject.preset_mode, "manual")
  176. self.dps[PRESET_DPS] = "Anti_frozen"
  177. self.assertEqual(self.subject.preset_mode, PRESET_AWAY)
  178. def test_preset_modes(self):
  179. self.assertCountEqual(
  180. self.subject.preset_modes,
  181. [PRESET_HOME, PRESET_AWAY, "manual"],
  182. )
  183. async def test_set_preset_to_away(self):
  184. async with assert_device_properties_set(
  185. self.subject._device,
  186. {PRESET_DPS: "Anti_frozen"},
  187. ):
  188. await self.subject.async_set_preset_mode(PRESET_AWAY)
  189. async def test_set_preset_to_home(self):
  190. async with assert_device_properties_set(
  191. self.subject._device,
  192. {PRESET_DPS: "Smart"},
  193. ):
  194. await self.subject.async_set_preset_mode(PRESET_HOME)
  195. async def test_set_preset_to_manual(self):
  196. async with assert_device_properties_set(
  197. self.subject._device,
  198. {PRESET_DPS: "Manual"},
  199. ):
  200. await self.subject.async_set_preset_mode("manual")
  201. def test_extra_state_attributes(self):
  202. self.dps[UNKNOWN4_DPS] = 4
  203. self.dps[FLOORTEMPLIMIT_DPS] = 355
  204. self.dps[INSTALL_DPS] = True
  205. self.dps[FLOORTEMP_DPS] = 251
  206. self.dps[ADAPTIVE_DPS] = False
  207. self.dps[SCHED_DPS] = "5_1_1"
  208. self.dps[UNKNOWN14_DPS] = 14
  209. self.dps[UNKNOWN15_DPS] = 15
  210. self.dps[UNKNOWN17_DPS] = 17
  211. self.dps[UNKNOWN21_DPS] = True
  212. self.dps[POWERRATING_DPS] = 2000
  213. self.dps[UNKNOWN23_DPS] = 23
  214. self.dps[UNKNOWN26_DPS] = 26
  215. self.assertDictEqual(
  216. self.subject.extra_state_attributes,
  217. {
  218. "unknown_4": 4,
  219. "floor_temp_limit": 35.5,
  220. "installation": "Office",
  221. "floor_temperature": 25.1,
  222. "adaptive": False,
  223. "schedule": "5_1_1",
  224. "unknown_14": 14,
  225. "unknown_15": 15,
  226. "unknown_17": 17,
  227. "unknown_21": True,
  228. "power_rating": 2000,
  229. "unknown_23": 23,
  230. "unknown_26": 26,
  231. },
  232. )