Advertisement
Guest User

Untitled

a guest
Nov 21st, 2023
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.60 KB | None | 0 0
  1.  
  2. """Beca TRV devices support."""
  3. import logging
  4. from typing import Optional, Union
  5.  
  6. import zigpy.types as t
  7. from zhaquirks import Bus, LocalDataCluster
  8. from zhaquirks.const import (
  9. DEVICE_TYPE,
  10. ENDPOINTS,
  11. INPUT_CLUSTERS,
  12. MODELS_INFO,
  13. OUTPUT_CLUSTERS,
  14. PROFILE_ID,
  15. )
  16. from zhaquirks.tuya import (
  17. TuyaManufClusterAttributes,
  18. TuyaPowerConfigurationCluster,
  19. TuyaThermostat,
  20. TuyaThermostatCluster,
  21. TuyaUserInterfaceCluster,
  22. )
  23. from zigpy.profiles import zha
  24. from zigpy.zcl import foundation
  25. from zigpy.zcl.clusters.general import (
  26. AnalogOutput,
  27. Basic,
  28. BinaryInput,
  29. Groups,
  30. OnOff,
  31. Ota,
  32. Scenes,
  33. Time,
  34. )
  35. from zigpy.zcl.clusters.hvac import Thermostat
  36.  
  37. _LOGGER = logging.getLogger(__name__)
  38.  
  39. BECA_TARGET_TEMP_ATTR = 0x0202 # target room temp (degree)
  40. BECA_TEMPERATURE_ATTR = 0x0203 # current room temp (decidegree)
  41. BECA_MODE_ATTR = 0x0401 # [0] schedule [1] manual [2] temporary manual [3] away
  42. BECA_CHILD_LOCK_ATTR = 0x010D # [0] unlocked [1] locked
  43. BECA_TEMP_CALIBRATION_ATTR = 0x0269 # temperature calibration (degree)
  44. BECA_MIN_TEMPERATURE_ATTR = 0x026D # minimum limit of temperature setting (degree)
  45. BECA_MAX_TEMPERATURE_ATTR = 0x026C # maximum limit of temperature setting (degree)
  46. BECA_WINDOW_DETECT_ATTR = 0x0409 # [1] alarm not active [0] alarm active
  47. BECA_WINDOW_DETECT_A2_ATTR = 0x0108 # [0] function disactive [1] function active
  48. BECA_BOOST_TIME_ATTR = 0x0267 # BOOST mode operating time in (sec)
  49. BECA_BOOST_ATTR = 0x0104 # [0] off [1] on
  50. BECA_BOOST_COUNTDOWN_ATTR = 0x0205 # (seconds)
  51. BECA_ECO_TEMP_ATTR = 0x026B # eco mode temperature (degree)
  52. BECA_ECO_MODE_ATTR = 0x016A # [0] off [1] on
  53. BECA_VALVE_STATE_ATTR = 0x0268 # opening percentage
  54. BECA_VALVE_STATE_ONOFF_ATTR = 0x0407 # [0] closed [1] opened
  55. BECA_BATTERY_ATTR = 0x020E # battery percentage remaining 0-100%
  56. BECA_SCHEDULE = 0x0065 # schedule
  57. # [6, 0, 40, 11, 30, 42, 13, 30, 44, 17, 30, 46, 6, 0, 48, 12, 0, 46, 14, 30, 44, 17, 30, 42, 6, 0, 38, 12, 30, 40, 14, 30, 42, 18, 30, 40] for :
  58. # Monday to friday : 06:00 20°C / 11:30 21°C / 13:30 22°C / 17:30 23°C
  59. # Saturday : 06:00 24°C / 12:00 23°C / 14:30 22°C / 17:30 21°C
  60. # Sunday : 06:00 19°C / 12:30 20°C / 14:30 21°C / 18:30 20°C )
  61. BecaManufClusterSelf = {}
  62.  
  63.  
  64. class data288(t.FixedList, item_type=t.uint8_t, length=36):
  65. """General data, Discrete, 288 bit."""
  66.  
  67. pass
  68.  
  69.  
  70. class BecaManufCluster(TuyaManufClusterAttributes):
  71. """Manufacturer Specific Cluster of thermostatic valves."""
  72.  
  73. def __init__(self, *args, **kwargs):
  74. """Init."""
  75. super().__init__(*args, **kwargs)
  76. global BecaManufClusterSelf
  77. BecaManufClusterSelf[self.endpoint.device.ieee] = self
  78.  
  79. set_time_offset = 1970
  80.  
  81. attributes = TuyaManufClusterAttributes.attributes.copy()
  82. attributes.update(
  83. {
  84. BECA_TEMPERATURE_ATTR: ("temperature", t.uint32_t),
  85. BECA_TARGET_TEMP_ATTR: ("target_temperature", t.uint32_t),
  86. BECA_MODE_ATTR: ("mode", t.uint8_t),
  87. BECA_CHILD_LOCK_ATTR: ("child_lock", t.uint8_t),
  88. BECA_TEMP_CALIBRATION_ATTR: ("temperature_calibration", t.int32s),
  89. BECA_MIN_TEMPERATURE_ATTR: ("min_temperature", t.uint32_t),
  90. BECA_MAX_TEMPERATURE_ATTR: ("max_temperature", t.uint32_t),
  91. BECA_WINDOW_DETECT_ATTR: ("window_detection", t.uint8_t),
  92. BECA_WINDOW_DETECT_A2_ATTR: ("window_detection_A2_function", t.uint8_t),
  93. BECA_BOOST_TIME_ATTR: ("boost_duration_seconds", t.uint32_t),
  94. BECA_BOOST_ATTR: ("boost_enabled", t.uint8_t),
  95. BECA_BOOST_COUNTDOWN_ATTR: ("boost_duration_countdown_seconds", t.uint32_t),
  96. #BECA_BOOST_COUNTDOWN_ATTR: ("boost_duration_seconds", t.uint32_t),
  97. BECA_ECO_TEMP_ATTR: ("eco_mode_temperature", t.uint32_t),
  98. BECA_ECO_MODE_ATTR: ("eco_mode_enabled", t.uint8_t),
  99. BECA_VALVE_STATE_ATTR: ("valve_state", t.uint32_t),
  100. BECA_VALVE_STATE_ONOFF_ATTR: ("valve_state_onoff", t.uint8_t),
  101. BECA_BATTERY_ATTR: ("battery", t.uint32_t),
  102. BECA_SCHEDULE: ("schedule", data288),
  103. }
  104. )
  105.  
  106. DIRECT_MAPPED_ATTRS = {
  107. BECA_TEMPERATURE_ATTR: ("local_temperature", lambda value: value * 10),
  108. BECA_TARGET_TEMP_ATTR: ("occupied_heating_setpoint", lambda value: value * 100),
  109. BECA_TEMP_CALIBRATION_ATTR: ("local_temperature_calibration", None),
  110. BECA_MIN_TEMPERATURE_ATTR: (
  111. "min_heat_setpoint_limit",
  112. lambda value: value * 100,
  113. ),
  114. BECA_MAX_TEMPERATURE_ATTR: (
  115. "max_heat_setpoint_limit",
  116. lambda value: value * 100,
  117. ),
  118. }
  119.  
  120. def _update_attribute(self, attrid, value):
  121. """Override default _update_attribute."""
  122. super()._update_attribute(attrid, value)
  123. if attrid in self.DIRECT_MAPPED_ATTRS:
  124. self.endpoint.device.thermostat_bus.listener_event(
  125. "temperature_change",
  126. self.DIRECT_MAPPED_ATTRS[attrid][0],
  127. value
  128. if self.DIRECT_MAPPED_ATTRS[attrid][1] is None
  129. else self.DIRECT_MAPPED_ATTRS[attrid][1](value),
  130. )
  131.  
  132. if attrid == BECA_WINDOW_DETECT_ATTR:
  133. self.endpoint.device.BecaWindowDetection_bus.listener_event(
  134. "set_value", value
  135. )
  136. if attrid == BECA_WINDOW_DETECT_A2_ATTR:
  137. self.endpoint.device.BecaWindowDetection_A2_bus.listener_event(
  138. "switch_change", value
  139. )
  140. elif attrid == BECA_CHILD_LOCK_ATTR:
  141. mode = 1 if value else 0
  142. self.endpoint.device.ui_bus.listener_event("child_lock_change", mode)
  143. self.endpoint.device.BecaChildLock_bus.listener_event("switch_change", mode)
  144. elif attrid in (BECA_MODE_ATTR, BECA_BOOST_ATTR, BECA_ECO_MODE_ATTR):
  145. if attrid == BECA_BOOST_ATTR and value == 1:
  146. self.endpoint.device.thermostat_bus.listener_event("mode_change", 5)
  147. elif attrid == BECA_ECO_MODE_ATTR and value == 1:
  148. self.endpoint.device.thermostat_bus.listener_event("mode_change", 4)
  149. elif attrid == BECA_MODE_ATTR:
  150. self.endpoint.device.thermostat_bus.listener_event("mode_change", value)
  151. elif attrid == BECA_VALVE_STATE_ATTR:
  152. self.endpoint.device.BecaValveState_bus.listener_event("set_value", value)
  153. elif attrid == BECA_TEMP_CALIBRATION_ATTR:
  154. self.endpoint.device.BecaTempCalibration_bus.listener_event(
  155. "set_value", value
  156. )
  157. elif attrid == BECA_BOOST_TIME_ATTR:
  158. self.endpoint.device.BecaBoostTime_bus.listener_event("set_value", value)
  159. elif attrid == BECA_BOOST_COUNTDOWN_ATTR:
  160. self.endpoint.device.BecaBoostCountdown_bus.listener_event(
  161. "set_value", value
  162. )
  163. elif attrid == BECA_ECO_TEMP_ATTR:
  164. self.endpoint.device.BecaEcoTemp_bus.listener_event("set_value", value)
  165. elif attrid == BECA_BATTERY_ATTR:
  166. self.endpoint.device.battery_bus.listener_event("battery_change", value)
  167. elif attrid == BECA_MIN_TEMPERATURE_ATTR:
  168. self.endpoint.device.BecaMinTemp_bus.listener_event("set_value", value)
  169. elif attrid == BECA_MAX_TEMPERATURE_ATTR:
  170. self.endpoint.device.BecaMaxTemp_bus.listener_event("set_value", value)
  171. elif attrid == BECA_SCHEDULE:
  172. self.endpoint.device.thermostat_bus.listener_event("schedule_change", value)
  173. # elif attrid in (BECA_TEMPERATURE_ATTR, BECA_TARGET_TEMP_ATTR):
  174. # self.endpoint.device.thermostat_bus.listener_event(
  175. # "hass_climate_state_change", attrid, value
  176. # )
  177. elif attrid == BECA_VALVE_STATE_ONOFF_ATTR:
  178. self.endpoint.device.thermostat_bus.listener_event(
  179. "state_change", not value
  180. )
  181.  
  182.  
  183. class BecaThermostat(TuyaThermostatCluster):
  184. """Thermostat cluster for thermostatic valves."""
  185.  
  186. class Preset(t.enum8):
  187. """Working modes of the thermostat."""
  188.  
  189. Away = 0x00
  190. Schedule = 0x01
  191. Manual = 0x02
  192. Comfort = 0x03
  193. Eco = 0x04
  194. Boost = 0x05
  195. Complex = 0x06
  196. TempManual = 0x07
  197.  
  198. class WorkDays(t.enum8):
  199. """Workday configuration for scheduler operation mode."""
  200.  
  201. MonToFri = 0x00
  202. MonToSat = 0x01
  203. MonToSun = 0x02
  204.  
  205. class ForceValveState(t.enum8):
  206. """Force valve state option."""
  207.  
  208. Normal = 0x00
  209. Open = 0x01
  210. Close = 0x02
  211.  
  212. _CONSTANT_ATTRIBUTES = {
  213. 0x001B: Thermostat.ControlSequenceOfOperation.Heating_Only,
  214. 0x001C: Thermostat.SystemMode.Heat,
  215. }
  216.  
  217. attributes = TuyaThermostatCluster.attributes.copy()
  218. attributes.update(
  219. {
  220. 0x4002: ("operation_preset", Preset),
  221. 0x4110: ("schedule_workday_1_hour", t.uint8_t),
  222. 0x4111: ("schedule_workday_1_minute", t.uint8_t),
  223. 0x4112: ("schedule_workday_1_temperature", t.uint8_t),
  224. 0x4113: ("schedule_workday_2_hour", t.uint8_t),
  225. 0x4114: ("schedule_workday_2_minute", t.uint8_t),
  226. 0x4115: ("schedule_workday_2_temperature", t.uint8_t),
  227. 0x4116: ("schedule_workday_3_hour", t.uint8_t),
  228. 0x4117: ("schedule_workday_3_minute", t.uint8_t),
  229. 0x4118: ("schedule_workday_3_temperature", t.uint8_t),
  230. 0x4119: ("schedule_workday_4_hour", t.uint8_t),
  231. 0x4120: ("schedule_workday_4_minute", t.uint8_t),
  232. 0x4121: ("schedule_workday_4_temperature", t.uint8_t),
  233. 0x4122: ("schedule_saturday_1_hour", t.uint8_t),
  234. 0x4123: ("schedule_saturday_1_minute", t.uint8_t),
  235. 0x4124: ("schedule_saturday_1_temperature", t.uint8_t),
  236. 0x4125: ("schedule_saturday_2_hour", t.uint8_t),
  237. 0x4126: ("schedule_saturday_2_minute", t.uint8_t),
  238. 0x4127: ("schedule_saturday_2_temperature", t.uint8_t),
  239. 0x4128: ("schedule_saturday_3_hour", t.uint8_t),
  240. 0x4129: ("schedule_saturday_3_minute", t.uint8_t),
  241. 0x4130: ("schedule_saturday_3_temperature", t.uint8_t),
  242. 0x4131: ("schedule_saturday_4_hour", t.uint8_t),
  243. 0x4132: ("schedule_saturday_4_minute", t.uint8_t),
  244. 0x4133: ("schedule_saturday_4_temperature", t.uint8_t),
  245. 0x4134: ("schedule_sunday_1_hour", t.uint8_t),
  246. 0x4135: ("schedule_sunday_1_minute", t.uint8_t),
  247. 0x4136: ("schedule_sunday_1_temperature", t.uint8_t),
  248. 0x4137: ("schedule_sunday_2_hour", t.uint8_t),
  249. 0x4138: ("schedule_sunday_2_minute", t.uint8_t),
  250. 0x4139: ("schedule_sunday_2_temperature", t.uint8_t),
  251. 0x4140: ("schedule_sunday_3_hour", t.uint8_t),
  252. 0x4141: ("schedule_sunday_3_minute", t.uint8_t),
  253. 0x4142: ("schedule_sunday_3_temperature", t.uint8_t),
  254. 0x4143: ("schedule_sunday_4_hour", t.uint8_t),
  255. 0x4144: ("schedule_sunday_4_minute", t.uint8_t),
  256. 0x4145: ("schedule_sunday_4_temperature", t.uint8_t),
  257. }
  258. )
  259.  
  260. DIRECT_MAPPING_ATTRS = {
  261. "min_heat_setpoint_limit": (
  262. BECA_MIN_TEMPERATURE_ATTR,
  263. lambda value: round(value / 100),
  264. ),
  265. "max_heat_setpoint_limit": (
  266. BECA_MAX_TEMPERATURE_ATTR,
  267. lambda value: round(value / 100),
  268. ),
  269. "local_temperature_calibration": (
  270. BECA_TEMP_CALIBRATION_ATTR,
  271. lambda value: value,
  272. ),
  273. }
  274.  
  275. SCHEDULE_ATTRS = {
  276. "schedule_sunday_4_temperature": 20,
  277. "schedule_sunday_4_minute": 30,
  278. "schedule_sunday_4_hour": 18,
  279. "schedule_sunday_3_temperature": 21,
  280. "schedule_sunday_3_minute": 30,
  281. "schedule_sunday_3_hour": 14,
  282. "schedule_sunday_2_temperature": 20,
  283. "schedule_sunday_2_minute": 30,
  284. "schedule_sunday_2_hour": 12,
  285. "schedule_sunday_1_temperature": 19,
  286. "schedule_sunday_1_minute": 0,
  287. "schedule_sunday_1_hour": 6,
  288. "schedule_saturday_4_temperature": 21,
  289. "schedule_saturday_4_minute": 30,
  290. "schedule_saturday_4_hour": 17,
  291. "schedule_saturday_3_temperature": 22,
  292. "schedule_saturday_3_minute": 30,
  293. "schedule_saturday_3_hour": 14,
  294. "schedule_saturday_2_temperature": 23,
  295. "schedule_saturday_2_minute": 00,
  296. "schedule_saturday_2_hour": 12,
  297. "schedule_saturday_1_temperature": 24,
  298. "schedule_saturday_1_minute": 0,
  299. "schedule_saturday_1_hour": 6,
  300. "schedule_workday_4_temperature": 23,
  301. "schedule_workday_4_minute": 30,
  302. "schedule_workday_4_hour": 17,
  303. "schedule_workday_3_temperature": 22,
  304. "schedule_workday_3_minute": 30,
  305. "schedule_workday_3_hour": 13,
  306. "schedule_workday_2_temperature": 21,
  307. "schedule_workday_2_minute": 30,
  308. "schedule_workday_2_hour": 11,
  309. "schedule_workday_1_temperature": 20,
  310. "schedule_workday_1_minute": 0,
  311. "schedule_workday_1_hour": 6,
  312. }
  313.  
  314. def map_attribute(self, attribute, value):
  315. """Map standardized attribute value to dict of manufacturer values."""
  316.  
  317. if attribute in self.DIRECT_MAPPING_ATTRS:
  318. return {
  319. self.DIRECT_MAPPING_ATTRS[attribute][0]: value
  320. if self.DIRECT_MAPPING_ATTRS[attribute][1] is None
  321. else self.DIRECT_MAPPING_ATTRS[attribute][1](value)
  322. }
  323.  
  324. if attribute == "occupied_heating_setpoint":
  325. mode = self._attr_cache.get(self.attributes_by_name["operation_preset"].id)
  326. if mode == self.Preset.Schedule:
  327. return {BECA_MODE_ATTR: 2, BECA_TARGET_TEMP_ATTR: value / 100}
  328. else:
  329. return {BECA_TARGET_TEMP_ATTR: value / 100}
  330.  
  331. if attribute == "operation_preset":
  332. if value == 0:
  333. return {BECA_MODE_ATTR: 3, BECA_BOOST_ATTR: 0, BECA_ECO_MODE_ATTR: 0}
  334. if value == 1:
  335. return {BECA_MODE_ATTR: 0, BECA_BOOST_ATTR: 0, BECA_ECO_MODE_ATTR: 0}
  336. if value == 2:
  337. return {BECA_MODE_ATTR: 1, BECA_BOOST_ATTR: 0, BECA_ECO_MODE_ATTR: 0}
  338. if value == 4:
  339. return {BECA_BOOST_ATTR: 0, BECA_ECO_MODE_ATTR: 1}
  340. if value == 5:
  341. return {BECA_BOOST_ATTR: 1, BECA_ECO_MODE_ATTR: 0}
  342. if value == 7:
  343. return {BECA_MODE_ATTR: 2, BECA_BOOST_ATTR: 0, BECA_ECO_MODE_ATTR: 0}
  344.  
  345. if attribute in ("programing_oper_mode", "occupancy"):
  346. if attribute == "occupancy":
  347. occupancy = value
  348. oper_mode = self._attr_cache.get(
  349. self.attributes_by_name["programing_oper_mode"].id,
  350. self.ProgrammingOperationMode.Simple,
  351. )
  352. else:
  353. occupancy = self._attr_cache.get(
  354. self.attributes_by_name["occupancy"].id, self.Occupancy.Occupied
  355. )
  356. oper_mode = value
  357. if occupancy == self.Occupancy.Unoccupied:
  358. return {BECA_MODE_ATTR: 3}
  359. if occupancy == self.Occupancy.Occupied:
  360. if oper_mode == self.ProgrammingOperationMode.Schedule_programming_mode:
  361. return {BECA_MODE_ATTR: 0}
  362. if oper_mode == self.ProgrammingOperationMode.Simple:
  363. return {BECA_MODE_ATTR: 1}
  364. self.error("Unsupported value for ProgrammingOperationMode")
  365. else:
  366. self.error("Unsupported value for Occupancy")
  367.  
  368. if attribute in self.SCHEDULE_ATTRS:
  369. data = data288()
  370. for num, (attr, default) in enumerate(self.SCHEDULE_ATTRS.items()):
  371. if num % 3 == 0:
  372. if attr == attribute:
  373. val = round(value * 2)
  374. else:
  375. val = round(
  376. self._attr_cache.get(
  377. self.attributes_by_name[attr].id, default
  378. )
  379. * 2
  380. )
  381. else:
  382. if attr == attribute:
  383. val = value
  384. else:
  385. val = self._attr_cache.get(
  386. self.attributes_by_name[attr].id, default
  387. )
  388.  
  389. data.append(val)
  390. return {BECA_SCHEDULE: data}
  391.  
  392. def hass_climate_state_change(self, attrid, value):
  393. """Update of the HASS Climate gui state according to temp difference."""
  394. if attrid == BECA_TEMPERATURE_ATTR:
  395. temp_current = value * 10
  396. temp_set = self._attr_cache.get(
  397. self.attributes_by_name["occupied_heating_setpoint"].id
  398. )
  399. else:
  400. temp_set = value * 100
  401. temp_current = self._attr_cache.get(
  402. self.attributes_by_name["local_temperature"].id
  403. )
  404.  
  405. state = 0 if (int(temp_current) >= int(temp_set)) else 1
  406. self.endpoint.device.thermostat_bus.listener_event("state_change", state)
  407.  
  408. def mode_change(self, value):
  409. """System Mode change."""
  410. if value == 1:
  411. operation_preset = self.Preset.Manual
  412. prog_mode = self.ProgrammingOperationMode.Simple
  413. occupancy = self.Occupancy.Occupied
  414. elif value == 2:
  415. operation_preset = self.Preset.TempManual
  416. prog_mode = self.ProgrammingOperationMode.Simple
  417. occupancy = self.Occupancy.Occupied
  418. elif value == 3:
  419. operation_preset = self.Preset.Away
  420. prog_mode = self.ProgrammingOperationMode.Simple
  421. occupancy = self.Occupancy.Unoccupied
  422. elif value == 4:
  423. operation_preset = self.Preset.Eco
  424. prog_mode = self.ProgrammingOperationMode.Economy_mode
  425. occupancy = self.Occupancy.Occupied
  426. elif value == 5:
  427. operation_preset = self.Preset.Boost
  428. prog_mode = self.ProgrammingOperationMode.Simple
  429. occupancy = self.Occupancy.Occupied
  430. else:
  431. operation_preset = self.Preset.Schedule
  432. prog_mode = self.ProgrammingOperationMode.Schedule_programming_mode
  433. occupancy = self.Occupancy.Occupied
  434.  
  435. self._update_attribute(
  436. self.attributes_by_name["programing_oper_mode"].id, prog_mode
  437. )
  438. self._update_attribute(self.attributes_by_name["occupancy"].id, occupancy)
  439. self._update_attribute(
  440. self.attributes_by_name["operation_preset"].id, operation_preset
  441. )
  442.  
  443. def schedule_change(self, value):
  444. """Scheduler attribute change."""
  445. self._update_attribute(
  446. self.attributes_by_name["schedule_workday_1_hour"].id, value[35]
  447. )
  448. self._update_attribute(
  449. self.attributes_by_name["schedule_workday_1_minute"].id, value[34]
  450. )
  451. self._update_attribute(
  452. self.attributes_by_name["schedule_workday_1_temperature"].id, value[33] / 2
  453. )
  454. self._update_attribute(
  455. self.attributes_by_name["schedule_workday_2_hour"].id, value[32]
  456. )
  457. self._update_attribute(
  458. self.attributes_by_name["schedule_workday_2_minute"].id, value[31]
  459. )
  460. self._update_attribute(
  461. self.attributes_by_name["schedule_workday_2_temperature"].id, value[30] / 2
  462. )
  463. self._update_attribute(
  464. self.attributes_by_name["schedule_workday_3_hour"].id, value[29]
  465. )
  466. self._update_attribute(
  467. self.attributes_by_name["schedule_workday_3_minute"].id, value[28]
  468. )
  469. self._update_attribute(
  470. self.attributes_by_name["schedule_workday_3_temperature"].id, value[27] / 2
  471. )
  472. self._update_attribute(
  473. self.attributes_by_name["schedule_workday_4_hour"].id, value[26]
  474. )
  475. self._update_attribute(
  476. self.attributes_by_name["schedule_workday_4_minute"].id, value[25]
  477. )
  478. self._update_attribute(
  479. self.attributes_by_name["schedule_workday_4_temperature"].id, value[24] / 2
  480. )
  481. self._update_attribute(
  482. self.attributes_by_name["schedule_saturday_1_hour"].id, value[23]
  483. )
  484. self._update_attribute(
  485. self.attributes_by_name["schedule_saturday_1_minute"].id, value[22]
  486. )
  487. self._update_attribute(
  488. self.attributes_by_name["schedule_saturday_1_temperature"].id, value[21] / 2
  489. )
  490. self._update_attribute(
  491. self.attributes_by_name["schedule_saturday_2_hour"].id, value[20]
  492. )
  493. self._update_attribute(
  494. self.attributes_by_name["schedule_saturday_2_minute"].id, value[19]
  495. )
  496. self._update_attribute(
  497. self.attributes_by_name["schedule_saturday_2_temperature"].id, value[18] / 2
  498. )
  499. self._update_attribute(
  500. self.attributes_by_name["schedule_saturday_3_hour"].id, value[17]
  501. )
  502. self._update_attribute(
  503. self.attributes_by_name["schedule_saturday_3_minute"].id, value[16]
  504. )
  505. self._update_attribute(
  506. self.attributes_by_name["schedule_saturday_3_temperature"].id, value[15] / 2
  507. )
  508. self._update_attribute(
  509. self.attributes_by_name["schedule_saturday_4_hour"].id, value[14]
  510. )
  511. self._update_attribute(
  512. self.attributes_by_name["schedule_saturday_4_minute"].id, value[13]
  513. )
  514. self._update_attribute(
  515. self.attributes_by_name["schedule_saturday_4_temperature"].id, value[12] / 2
  516. )
  517. self._update_attribute(
  518. self.attributes_by_name["schedule_sunday_1_hour"].id, value[11]
  519. )
  520. self._update_attribute(
  521. self.attributes_by_name["schedule_sunday_1_minute"].id, value[10]
  522. )
  523. self._update_attribute(
  524. self.attributes_by_name["schedule_sunday_1_temperature"].id, value[9] / 2
  525. )
  526. self._update_attribute(
  527. self.attributes_by_name["schedule_sunday_2_hour"].id, value[8]
  528. )
  529. self._update_attribute(
  530. self.attributes_by_name["schedule_sunday_2_minute"].id, value[7]
  531. )
  532. self._update_attribute(
  533. self.attributes_by_name["schedule_sunday_2_temperature"].id, value[6] / 2
  534. )
  535. self._update_attribute(
  536. self.attributes_by_name["schedule_sunday_3_hour"].id, value[5]
  537. )
  538. self._update_attribute(
  539. self.attributes_by_name["schedule_sunday_3_minute"].id, value[4]
  540. )
  541. self._update_attribute(
  542. self.attributes_by_name["schedule_sunday_3_temperature"].id, value[3] / 2
  543. )
  544. self._update_attribute(
  545. self.attributes_by_name["schedule_sunday_4_hour"].id, value[2]
  546. )
  547. self._update_attribute(
  548. self.attributes_by_name["schedule_sunday_4_minute"].id, value[1]
  549. )
  550. self._update_attribute(
  551. self.attributes_by_name["schedule_sunday_4_temperature"].id, value[0] / 2
  552. )
  553.  
  554.  
  555. class BecaUserInterface(TuyaUserInterfaceCluster):
  556. """HVAC User interface cluster for tuya electric heating thermostats."""
  557.  
  558. _CHILD_LOCK_ATTR = BECA_CHILD_LOCK_ATTR
  559.  
  560.  
  561. class BecaWindowDetection(LocalDataCluster, BinaryInput):
  562. """On/Off cluster for the window detect function of the electric heating thermostats."""
  563.  
  564. def __init__(self, *args, **kwargs):
  565. """Init."""
  566. super().__init__(*args, **kwargs)
  567. self.endpoint.device.BecaWindowDetection_bus.add_listener(self)
  568.  
  569. def set_value(self, value):
  570. """Set value."""
  571. self._update_attribute(self.attributes_by_name["present_value"].id, value)
  572.  
  573.  
  574. class BecaWindowDetection_A2(LocalDataCluster, OnOff):
  575. """On/Off cluster for the window detect A2 function of the electric heating thermostats."""
  576.  
  577. def __init__(self, *args, **kwargs):
  578. """Init."""
  579. super().__init__(*args, **kwargs)
  580. self.endpoint.device.BecaWindowDetection_A2_bus.add_listener(self)
  581.  
  582. def switch_change(self, value):
  583. """Window detect A2 change."""
  584. self._update_attribute(self.attributes_by_name["on_off"].id, value)
  585.  
  586. async def write_attributes(self, attributes, manufacturer=None):
  587. """Defer attributes writing to the set_data tuya command."""
  588. records = self._write_attr_records(attributes)
  589. if not records:
  590. return [[foundation.WriteAttributesStatusRecord(foundation.Status.SUCCESS)]]
  591.  
  592. has_change = False
  593. for record in records:
  594. attr_name = self.attributes[record.attrid].name
  595. #attr_name = self.attributes[record.attrid][0]
  596. if attr_name == "on_off":
  597. value = record.value.value
  598. has_change = True
  599.  
  600. if has_change:
  601. return await BecaManufClusterSelf[
  602. self.endpoint.device.ieee
  603. ].endpoint.tuya_manufacturer.write_attributes(
  604. {BECA_WINDOW_DETECT_A2_ATTR: value}, manufacturer=manufacturer
  605. )
  606.  
  607. return [
  608. [
  609. foundation.WriteAttributesStatusRecord(
  610. foundation.Status.FAILURE, r.attrid
  611. )
  612. for r in records
  613. ]
  614. ]
  615.  
  616. async def command(
  617. self,
  618. command_id: Union[foundation.GeneralCommand, int, t.uint8_t],
  619. *args,
  620. manufacturer: Optional[Union[int, t.uint16_t]] = None,
  621. expect_reply: bool = True,
  622. tsn: Optional[Union[int, t.uint8_t]] = None,
  623. ):
  624. """Override the default Cluster command."""
  625.  
  626. if command_id in (0x0000, 0x0001, 0x0002):
  627. if command_id == 0x0000:
  628. value = False
  629. elif command_id == 0x0001:
  630. value = True
  631. else:
  632. attrid = self.attributes_by_name["on_off"].id
  633. success, _ = await self.read_attributes(
  634. (attrid,), manufacturer=manufacturer
  635. )
  636. try:
  637. value = success[attrid]
  638. except KeyError:
  639. return foundation.Status.FAILURE
  640. value = not value
  641.  
  642. (res,) = await self.write_attributes(
  643. {"on_off": value}, manufacturer=manufacturer
  644. )
  645.  
  646. return [command_id, res]
  647.  
  648. return [command_id, foundation.Status.UNSUP_CLUSTER_COMMAND]
  649.  
  650.  
  651. class BecaChildLock(LocalDataCluster, OnOff):
  652. """On/Off cluster for the child lock function of the electric heating thermostats."""
  653.  
  654. def __init__(self, *args, **kwargs):
  655. """Init."""
  656. super().__init__(*args, **kwargs)
  657. self.endpoint.device.BecaChildLock_bus.add_listener(self)
  658.  
  659. def switch_change(self, value):
  660. """Child lock change."""
  661. self._update_attribute(self.attributes_by_name["on_off"].id, value)
  662.  
  663. async def write_attributes(self, attributes, manufacturer=None):
  664. """Defer attributes writing to the set_data tuya command."""
  665. records = self._write_attr_records(attributes)
  666. if not records:
  667. return [[foundation.WriteAttributesStatusRecord(foundation.Status.SUCCESS)]]
  668.  
  669. has_change = False
  670. for record in records:
  671. attr_name = self.attributes[record.attrid].name
  672. #attr_name = self.attributes[record.attrid][0]
  673. if attr_name == "on_off":
  674. value = record.value.value
  675. has_change = True
  676.  
  677. if has_change:
  678. return await BecaManufClusterSelf[
  679. self.endpoint.device.ieee
  680. ].endpoint.tuya_manufacturer.write_attributes(
  681. {BECA_CHILD_LOCK_ATTR: value}, manufacturer=manufacturer
  682. )
  683.  
  684. return [
  685. [
  686. foundation.WriteAttributesStatusRecord(
  687. foundation.Status.FAILURE, r.attrid
  688. )
  689. for r in records
  690. ]
  691. ]
  692.  
  693. async def command(
  694. self,
  695. command_id: Union[foundation.GeneralCommand, int, t.uint8_t],
  696. *args,
  697. manufacturer: Optional[Union[int, t.uint16_t]] = None,
  698. expect_reply: bool = True,
  699. tsn: Optional[Union[int, t.uint8_t]] = None,
  700. ):
  701. """Override the default Cluster command."""
  702.  
  703. if command_id in (0x0000, 0x0001, 0x0002):
  704. if command_id == 0x0000:
  705. value = False
  706. elif command_id == 0x0001:
  707. value = True
  708. else:
  709. attrid = self.attributes_by_name["on_off"].id
  710. success, _ = await self.read_attributes(
  711. (attrid,), manufacturer=manufacturer
  712. )
  713. try:
  714. value = success[attrid]
  715. except KeyError:
  716. return foundation.Status.FAILURE
  717. value = not value
  718.  
  719. (res,) = await self.write_attributes(
  720. {"on_off": value}, manufacturer=manufacturer
  721. )
  722.  
  723. return [command_id, res]
  724.  
  725. return [command_id, foundation.Status.UNSUP_CLUSTER_COMMAND]
  726.  
  727.  
  728. class BecaValveState(LocalDataCluster, AnalogOutput):
  729. """Analog output for Valve State."""
  730.  
  731. def __init__(self, *args, **kwargs):
  732. """Init."""
  733. super().__init__(*args, **kwargs)
  734. self.endpoint.device.BecaValveState_bus.add_listener(self)
  735. self._update_attribute(self.attributes_by_name["description"].id, "Valve State")
  736. self._update_attribute(self.attributes_by_name["max_present_value"].id, 100)
  737. self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
  738. self._update_attribute(self.attributes_by_name["resolution"].id, 1)
  739. self._update_attribute(self.attributes_by_name["application_type"].id, 4 << 16)
  740. self._update_attribute(self.attributes_by_name["engineering_units"].id, 98)
  741.  
  742. def set_value(self, value):
  743. """Set value."""
  744. self._update_attribute(self.attributes_by_name["present_value"].id, value)
  745.  
  746.  
  747. class BecaTempCalibration(LocalDataCluster, AnalogOutput):
  748. """Analog output for Temp Calibration."""
  749.  
  750. def __init__(self, *args, **kwargs):
  751. """Init."""
  752. super().__init__(*args, **kwargs)
  753. self.endpoint.device.BecaTempCalibration_bus.add_listener(self)
  754. self._update_attribute(
  755. self.attributes_by_name["description"].id, "Temperature Calibration"
  756. )
  757. self._update_attribute(self.attributes_by_name["max_present_value"].id, 9)
  758. self._update_attribute(self.attributes_by_name["min_present_value"].id, -9)
  759. self._update_attribute(self.attributes_by_name["resolution"].id, 1)
  760. self._update_attribute(self.attributes_by_name["application_type"].id, 13 << 16)
  761. self._update_attribute(self.attributes_by_name["engineering_units"].id, 62)
  762.  
  763. def set_value(self, value):
  764. """Set value."""
  765. self._update_attribute(self.attributes_by_name["present_value"].id, value)
  766.  
  767. def get_value(self):
  768. """Get value."""
  769. return self._attr_cache.get(self.attributes_by_name["present_value"].id)
  770.  
  771. async def write_attributes(self, attributes, manufacturer=None):
  772. """Override the default Cluster write_attributes."""
  773. for attrid, value in attributes.items():
  774. if isinstance(attrid, str):
  775. attrid = self.attributes_by_name[attrid].id
  776. if attrid not in self.attributes:
  777. self.error("%d is not a valid attribute id", attrid)
  778. continue
  779. self._update_attribute(attrid, value)
  780.  
  781. await BecaManufClusterSelf[
  782. self.endpoint.device.ieee
  783. ].endpoint.tuya_manufacturer.write_attributes(
  784. {BECA_TEMP_CALIBRATION_ATTR: value},
  785. manufacturer=None,
  786. )
  787. return ([foundation.WriteAttributesStatusRecord(foundation.Status.SUCCESS)],)
  788.  
  789.  
  790. class BecaBoostTime(LocalDataCluster, AnalogOutput):
  791. """Analog output for Boost Time."""
  792.  
  793. def __init__(self, *args, **kwargs):
  794. """Init."""
  795. super().__init__(*args, **kwargs)
  796. self.endpoint.device.BecaBoostTime_bus.add_listener(self)
  797. self._update_attribute(self.attributes_by_name["description"].id, "Boost Time")
  798. self._update_attribute(self.attributes_by_name["max_present_value"].id, 9999)
  799. self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
  800. self._update_attribute(self.attributes_by_name["resolution"].id, 1)
  801. self._update_attribute(self.attributes_by_name["application_type"].id, 14 << 16)
  802. self._update_attribute(self.attributes_by_name["engineering_units"].id, 73)
  803.  
  804. def set_value(self, value):
  805. """Set value."""
  806. self._update_attribute(self.attributes_by_name["present_value"].id, value)
  807.  
  808. def get_value(self):
  809. """Get value."""
  810. return self._attr_cache.get(self.attributes_by_name["present_value"].id)
  811.  
  812. async def write_attributes(self, attributes, manufacturer=None):
  813. """Override the default Cluster write_attributes."""
  814. for attrid, value in attributes.items():
  815. if isinstance(attrid, str):
  816. attrid = self.attributes_by_name[attrid].id
  817. if attrid not in self.attributes:
  818. self.error("%d is not a valid attribute id", attrid)
  819. continue
  820. self._update_attribute(attrid, value)
  821.  
  822. await BecaManufClusterSelf[
  823. self.endpoint.device.ieee
  824. ].endpoint.tuya_manufacturer.write_attributes(
  825. {BECA_BOOST_TIME_ATTR: value},
  826. manufacturer=None,
  827. )
  828. return ([foundation.WriteAttributesStatusRecord(foundation.Status.SUCCESS)],)
  829.  
  830.  
  831. class BecaBoostCountdown(LocalDataCluster, AnalogOutput):
  832. """Analog output for Boost Countdown time."""
  833.  
  834. def __init__(self, *args, **kwargs):
  835. """Init."""
  836. super().__init__(*args, **kwargs)
  837. self.endpoint.device.BecaBoostCountdown_bus.add_listener(self)
  838. self._update_attribute(
  839. self.attributes_by_name["description"].id, "Boost Countdown"
  840. )
  841. self._update_attribute(self.attributes_by_name["max_present_value"].id, 9999)
  842. self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
  843. self._update_attribute(self.attributes_by_name["resolution"].id, 1)
  844. self._update_attribute(self.attributes_by_name["application_type"].id, 12 << 16)
  845. self._update_attribute(self.attributes_by_name["engineering_units"].id, 72)
  846.  
  847. def set_value(self, value):
  848. """Set value."""
  849. self._update_attribute(self.attributes_by_name["present_value"].id, value)
  850.  
  851.  
  852. class BecaEcoTemp(LocalDataCluster, AnalogOutput):
  853. """Analog output for Eco Temperature."""
  854.  
  855. def __init__(self, *args, **kwargs):
  856. """Init."""
  857. super().__init__(*args, **kwargs)
  858. self.endpoint.device.BecaEcoTemp_bus.add_listener(self)
  859. self._update_attribute(
  860. self.attributes_by_name["description"].id, "Eco Temperature"
  861. )
  862. self._update_attribute(self.attributes_by_name["max_present_value"].id, 35)
  863. self._update_attribute(self.attributes_by_name["min_present_value"].id, 5)
  864. self._update_attribute(self.attributes_by_name["resolution"].id, 1)
  865. self._update_attribute(self.attributes_by_name["application_type"].id, 13 << 16)
  866. self._update_attribute(self.attributes_by_name["engineering_units"].id, 62)
  867.  
  868. def set_value(self, value):
  869. """Set value."""
  870. self._update_attribute(self.attributes_by_name["present_value"].id, value)
  871.  
  872. def get_value(self):
  873. """Get value."""
  874. return self._attr_cache.get(self.attributes_by_name["present_value"].id)
  875.  
  876. async def write_attributes(self, attributes, manufacturer=None):
  877. """Override the default Cluster write_attributes."""
  878. for attrid, value in attributes.items():
  879. if isinstance(attrid, str):
  880. attrid = self.attributes_by_name[attrid].id
  881. if attrid not in self.attributes:
  882. self.error("%d is not a valid attribute id", attrid)
  883. continue
  884. self._update_attribute(attrid, value)
  885.  
  886. await BecaManufClusterSelf[
  887. self.endpoint.device.ieee
  888. ].endpoint.tuya_manufacturer.write_attributes(
  889. {BECA_ECO_TEMP_ATTR: value},
  890. manufacturer=None,
  891. )
  892. return ([foundation.WriteAttributesStatusRecord(foundation.Status.SUCCESS)],)
  893.  
  894.  
  895. class BecaMinTemp(LocalDataCluster, AnalogOutput):
  896. """Analog output for Min Temperature."""
  897.  
  898. def __init__(self, *args, **kwargs):
  899. """Init."""
  900. super().__init__(*args, **kwargs)
  901. self.endpoint.device.BecaMinTemp_bus.add_listener(self)
  902. self._update_attribute(
  903. self.attributes_by_name["description"].id, "Min Temperature"
  904. )
  905. self._update_attribute(self.attributes_by_name["max_present_value"].id, 15)
  906. self._update_attribute(self.attributes_by_name["min_present_value"].id, 5)
  907. self._update_attribute(self.attributes_by_name["resolution"].id, 1)
  908. self._update_attribute(self.attributes_by_name["application_type"].id, 13 << 16)
  909. self._update_attribute(self.attributes_by_name["engineering_units"].id, 62)
  910.  
  911. def set_value(self, value):
  912. """Set value."""
  913. self._update_attribute(self.attributes_by_name["present_value"].id, value)
  914.  
  915. def get_value(self):
  916. """Get value."""
  917. return self._attr_cache.get(self.attributes_by_name["present_value"].id)
  918.  
  919. async def write_attributes(self, attributes, manufacturer=None):
  920. """Override the default Cluster write_attributes."""
  921. for attrid, value in attributes.items():
  922. if isinstance(attrid, str):
  923. attrid = self.attributes_by_name[attrid].id
  924. if attrid not in self.attributes:
  925. self.error("%d is not a valid attribute id", attrid)
  926. continue
  927. self._update_attribute(attrid, value)
  928.  
  929. await BecaManufClusterSelf[
  930. self.endpoint.device.ieee
  931. ].endpoint.tuya_manufacturer.write_attributes(
  932. {BECA_MIN_TEMPERATURE_ATTR: value},
  933. manufacturer=None,
  934. )
  935. return ([foundation.WriteAttributesStatusRecord(foundation.Status.SUCCESS)],)
  936.  
  937.  
  938. class BecaMaxTemp(LocalDataCluster, AnalogOutput):
  939. """Analog output for Max Temperature."""
  940.  
  941. def __init__(self, *args, **kwargs):
  942. """Init."""
  943. super().__init__(*args, **kwargs)
  944. self.endpoint.device.BecaMaxTemp_bus.add_listener(self)
  945. self._update_attribute(
  946. self.attributes_by_name["description"].id, "Max Temperature"
  947. )
  948. self._update_attribute(self.attributes_by_name["max_present_value"].id, 45)
  949. self._update_attribute(self.attributes_by_name["min_present_value"].id, 15)
  950. self._update_attribute(self.attributes_by_name["resolution"].id, 1)
  951. self._update_attribute(self.attributes_by_name["application_type"].id, 13 << 16)
  952. self._update_attribute(self.attributes_by_name["engineering_units"].id, 62)
  953.  
  954. def set_value(self, value):
  955. """Set value."""
  956. self._update_attribute(self.attributes_by_name["present_value"].id, value)
  957.  
  958. def get_value(self):
  959. """Get value."""
  960. return self._attr_cache.get(self.attributes_by_name["present_value"].id)
  961.  
  962. async def write_attributes(self, attributes, manufacturer=None):
  963. """Override the default Cluster write_attributes."""
  964. for attrid, value in attributes.items():
  965. if isinstance(attrid, str):
  966. attrid = self.attributes_by_name[attrid].id
  967. if attrid not in self.attributes:
  968. self.error("%d is not a valid attribute id", attrid)
  969. continue
  970. self._update_attribute(attrid, value)
  971.  
  972. await BecaManufClusterSelf[
  973. self.endpoint.device.ieee
  974. ].endpoint.tuya_manufacturer.write_attributes(
  975. {BECA_MAX_TEMPERATURE_ATTR: value},
  976. manufacturer=None,
  977. )
  978. return ([foundation.WriteAttributesStatusRecord(foundation.Status.SUCCESS)],)
  979.  
  980.  
  981. class Beca(TuyaThermostat):
  982. """BECA Thermostatic radiator valve."""
  983.  
  984. def __init__(self, *args, **kwargs):
  985. """Init device."""
  986. self.BecaWindowDetection_bus = Bus()
  987. self.BecaWindowDetection_A2_bus = Bus()
  988. self.BecaChildLock_bus = Bus()
  989. self.BecaValveState_bus = Bus()
  990. self.BecaTempCalibration_bus = Bus()
  991. self.BecaBoostTime_bus = Bus()
  992. self.BecaBoostCountdown_bus = Bus()
  993. self.BecaEcoTemp_bus = Bus()
  994. self.BecaMinTemp_bus = Bus()
  995. self.BecaMaxTemp_bus = Bus()
  996. super().__init__(*args, **kwargs)
  997.  
  998. signature = {
  999. # endpoint=1 profile=260 device_type=81 device_version=0 input_clusters=[0, 4, 5, 61184]
  1000. # output_clusters=[10, 25]>
  1001. MODELS_INFO: [
  1002. ("_TZE200_b6wax7g0", "TS0601"),
  1003. ],
  1004. ENDPOINTS: {
  1005. 1: {
  1006. PROFILE_ID: zha.PROFILE_ID,
  1007. DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
  1008. INPUT_CLUSTERS: [
  1009. Basic.cluster_id,
  1010. Groups.cluster_id,
  1011. Scenes.cluster_id,
  1012. TuyaManufClusterAttributes.cluster_id,
  1013. ],
  1014. OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
  1015. }
  1016. },
  1017. }
  1018.  
  1019. replacement = {
  1020. ENDPOINTS: {
  1021. 1: {
  1022. PROFILE_ID: zha.PROFILE_ID,
  1023. DEVICE_TYPE: zha.DeviceType.THERMOSTAT,
  1024. INPUT_CLUSTERS: [
  1025. Basic.cluster_id,
  1026. Groups.cluster_id,
  1027. Scenes.cluster_id,
  1028. BecaManufCluster,
  1029. BecaThermostat,
  1030. BecaUserInterface,
  1031. BecaWindowDetection,
  1032. TuyaPowerConfigurationCluster,
  1033. ],
  1034. OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
  1035. },
  1036. 2: {
  1037. PROFILE_ID: zha.PROFILE_ID,
  1038. DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
  1039. INPUT_CLUSTERS: [BecaChildLock],
  1040. OUTPUT_CLUSTERS: [],
  1041. },
  1042. 3: {
  1043. PROFILE_ID: zha.PROFILE_ID,
  1044. DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
  1045. INPUT_CLUSTERS: [BecaValveState],
  1046. OUTPUT_CLUSTERS: [],
  1047. },
  1048. 4: {
  1049. PROFILE_ID: zha.PROFILE_ID,
  1050. DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
  1051. INPUT_CLUSTERS: [BecaWindowDetection_A2],
  1052. OUTPUT_CLUSTERS: [],
  1053. },
  1054. 5: {
  1055. PROFILE_ID: zha.PROFILE_ID,
  1056. DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
  1057. INPUT_CLUSTERS: [BecaTempCalibration],
  1058. OUTPUT_CLUSTERS: [],
  1059. },
  1060. 6: {
  1061. PROFILE_ID: zha.PROFILE_ID,
  1062. DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
  1063. INPUT_CLUSTERS: [BecaBoostTime],
  1064. OUTPUT_CLUSTERS: [],
  1065. },
  1066. 7: {
  1067. PROFILE_ID: zha.PROFILE_ID,
  1068. DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
  1069. INPUT_CLUSTERS: [BecaBoostCountdown],
  1070. OUTPUT_CLUSTERS: [],
  1071. },
  1072. 8: {
  1073. PROFILE_ID: zha.PROFILE_ID,
  1074. DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
  1075. INPUT_CLUSTERS: [BecaEcoTemp],
  1076. OUTPUT_CLUSTERS: [],
  1077. },
  1078. 9: {
  1079. PROFILE_ID: zha.PROFILE_ID,
  1080. DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
  1081. INPUT_CLUSTERS: [BecaMinTemp],
  1082. OUTPUT_CLUSTERS: [],
  1083. },
  1084. 10: {
  1085. PROFILE_ID: zha.PROFILE_ID,
  1086. DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
  1087. INPUT_CLUSTERS: [BecaMaxTemp],
  1088. OUTPUT_CLUSTERS: [],
  1089. },
  1090. }
  1091. }
  1092.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement