@willieee802/zigbee-herdsman-converters 15.0.8-4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -0
  3. package/converters/fromZigbee.js +8439 -0
  4. package/converters/toZigbee.js +7162 -0
  5. package/devices/ITCommander.js +37 -0
  6. package/devices/RMC002.js +20 -0
  7. package/devices/acova.js +101 -0
  8. package/devices/acuity_brands_lighting.js +11 -0
  9. package/devices/adeo.js +256 -0
  10. package/devices/adurosmart.js +130 -0
  11. package/devices/aeotec.js +13 -0
  12. package/devices/airam.js +59 -0
  13. package/devices/ajax_online.js +49 -0
  14. package/devices/akuvox.js +28 -0
  15. package/devices/alchemy.js +18 -0
  16. package/devices/aldi.js +53 -0
  17. package/devices/alecto.js +98 -0
  18. package/devices/anchor.js +17 -0
  19. package/devices/atlantic.js +110 -0
  20. package/devices/atsmart.js +28 -0
  21. package/devices/aubess.js +21 -0
  22. package/devices/aurora_lighting.js +292 -0
  23. package/devices/automaton.js +44 -0
  24. package/devices/awox.js +184 -0
  25. package/devices/axis.js +22 -0
  26. package/devices/bankamp.js +11 -0
  27. package/devices/bega.js +22 -0
  28. package/devices/belkin.js +11 -0
  29. package/devices/bitron.js +334 -0
  30. package/devices/blaupunkt.js +27 -0
  31. package/devices/blitzwolf.js +47 -0
  32. package/devices/bosch.js +702 -0
  33. package/devices/brimate.js +15 -0
  34. package/devices/bseed.js +17 -0
  35. package/devices/bticino.js +118 -0
  36. package/devices/busch-jaeger.js +140 -0
  37. package/devices/byun.js +24 -0
  38. package/devices/calex.js +37 -0
  39. package/devices/candeo.js +49 -0
  40. package/devices/casaia.js +52 -0
  41. package/devices/centralite.js +359 -0
  42. package/devices/cleode.js +20 -0
  43. package/devices/cleverio.js +36 -0
  44. package/devices/climax.js +138 -0
  45. package/devices/commercial_electric.js +16 -0
  46. package/devices/connecte.js +46 -0
  47. package/devices/cree.js +11 -0
  48. package/devices/ctm.js +999 -0
  49. package/devices/current_products_corp.js +24 -0
  50. package/devices/custom_devices_diy.js +850 -0
  51. package/devices/cy-lighting.js +11 -0
  52. package/devices/danalock.js +26 -0
  53. package/devices/danfoss.js +340 -0
  54. package/devices/databyte.ch.js +55 -0
  55. package/devices/datek.js +246 -0
  56. package/devices/dawon_dns.js +338 -0
  57. package/devices/develco.js +868 -0
  58. package/devices/digi.js +14 -0
  59. package/devices/diyruz.js +305 -0
  60. package/devices/dlink.js +37 -0
  61. package/devices/dnake.js +11 -0
  62. package/devices/dresden_elektronik.js +47 -0
  63. package/devices/easyaccess.js +27 -0
  64. package/devices/eatonhalo_led.js +11 -0
  65. package/devices/echostar.js +25 -0
  66. package/devices/ecodim.js +145 -0
  67. package/devices/ecolink.js +21 -0
  68. package/devices/ecosmart.js +64 -0
  69. package/devices/ecozy.js +31 -0
  70. package/devices/edp.js +39 -0
  71. package/devices/eglo.js +25 -0
  72. package/devices/elko.js +176 -0
  73. package/devices/enbrighten.js +163 -0
  74. package/devices/enocean.js +52 -0
  75. package/devices/envilar.js +73 -0
  76. package/devices/essentialb.js +87 -0
  77. package/devices/eurotronic.js +48 -0
  78. package/devices/evanell.js +29 -0
  79. package/devices/evn.js +31 -0
  80. package/devices/evology.js +24 -0
  81. package/devices/evvr.js +17 -0
  82. package/devices/ewelink.js +184 -0
  83. package/devices/ezex.js +24 -0
  84. package/devices/fantem.js +77 -0
  85. package/devices/feibit.js +172 -0
  86. package/devices/fireangel.js +15 -0
  87. package/devices/frankever.js +23 -0
  88. package/devices/garza.js +11 -0
  89. package/devices/ge.js +111 -0
  90. package/devices/gewiss.js +48 -0
  91. package/devices/gidealed.js +11 -0
  92. package/devices/giderwel.js +11 -0
  93. package/devices/giex.js +222 -0
  94. package/devices/girier.js +19 -0
  95. package/devices/gledopto.js +756 -0
  96. package/devices/gmy.js +11 -0
  97. package/devices/gs.js +29 -0
  98. package/devices/halemeier.js +18 -0
  99. package/devices/hampton_bay.js +37 -0
  100. package/devices/heiman.js +805 -0
  101. package/devices/hej.js +107 -0
  102. package/devices/hfh.js +11 -0
  103. package/devices/hgkg.js +54 -0
  104. package/devices/hilux.js +11 -0
  105. package/devices/hive.js +524 -0
  106. package/devices/home_control_as.js +27 -0
  107. package/devices/hommyn.js +24 -0
  108. package/devices/honyar.js +29 -0
  109. package/devices/hornbach.js +53 -0
  110. package/devices/hzc.js +21 -0
  111. package/devices/hzc_electric.js +42 -0
  112. package/devices/icasa.js +121 -0
  113. package/devices/idinio.js +19 -0
  114. package/devices/ihorn.js +61 -0
  115. package/devices/ikea.js +1168 -0
  116. package/devices/ilightsin.js +11 -0
  117. package/devices/iluminize.js +262 -0
  118. package/devices/ilux.js +11 -0
  119. package/devices/immax.js +203 -0
  120. package/devices/innr.js +705 -0
  121. package/devices/inovelli.js +1315 -0
  122. package/devices/insta.js +110 -0
  123. package/devices/iolloi.js +20 -0
  124. package/devices/iotperfect.js +20 -0
  125. package/devices/iris.js +180 -0
  126. package/devices/istar.js +20 -0
  127. package/devices/jasco.js +55 -0
  128. package/devices/javis.js +37 -0
  129. package/devices/jethome.js +48 -0
  130. package/devices/jiawen.js +18 -0
  131. package/devices/jumitech.js +18 -0
  132. package/devices/jxuan.js +49 -0
  133. package/devices/kami.js +15 -0
  134. package/devices/keen_home.js +80 -0
  135. package/devices/klikaanklikuit.js +17 -0
  136. package/devices/kmpcil.js +148 -0
  137. package/devices/konke.js +141 -0
  138. package/devices/ksentry.js +17 -0
  139. package/devices/kurvia.js +17 -0
  140. package/devices/kwikset.js +120 -0
  141. package/devices/lanesto.js +11 -0
  142. package/devices/lds.js +11 -0
  143. package/devices/led_trading.js +69 -0
  144. package/devices/ledvance.js +353 -0
  145. package/devices/leedarson.js +130 -0
  146. package/devices/legrand.js +554 -0
  147. package/devices/lellki.js +146 -0
  148. package/devices/letsled.js +11 -0
  149. package/devices/letv.js +18 -0
  150. package/devices/leviton.js +142 -0
  151. package/devices/lg.js +18 -0
  152. package/devices/lidl.js +1000 -0
  153. package/devices/lifecontrol.js +92 -0
  154. package/devices/lightsolutions.js +37 -0
  155. package/devices/linkind.js +205 -0
  156. package/devices/livingwise.js +59 -0
  157. package/devices/livolo.js +286 -0
  158. package/devices/lixee.js +779 -0
  159. package/devices/lonsonho.js +218 -0
  160. package/devices/lubeez.js +18 -0
  161. package/devices/lupus.js +74 -0
  162. package/devices/lutron.js +32 -0
  163. package/devices/lux.js +40 -0
  164. package/devices/m-elec.js +18 -0
  165. package/devices/makegood.js +51 -0
  166. package/devices/matcall_bv.js +18 -0
  167. package/devices/meazon.js +47 -0
  168. package/devices/mercator.js +225 -0
  169. package/devices/miboxer.js +72 -0
  170. package/devices/micromatic.js +29 -0
  171. package/devices/moes.js +400 -0
  172. package/devices/mycket.js +11 -0
  173. package/devices/m/303/274ller_licht.js +220 -0
  174. package/devices/namron.js +774 -0
  175. package/devices/nanoleaf.js +11 -0
  176. package/devices/neo.js +86 -0
  177. package/devices/net2grid.js +29 -0
  178. package/devices/netvox.js +35 -0
  179. package/devices/niko.js +314 -0
  180. package/devices/ninja_blocks.js +24 -0
  181. package/devices/niviss.js +11 -0
  182. package/devices/nodon.js +109 -0
  183. package/devices/nordtronic.js +30 -0
  184. package/devices/nous.js +88 -0
  185. package/devices/novo.js +17 -0
  186. package/devices/nue_3a.js +417 -0
  187. package/devices/nyce.js +67 -0
  188. package/devices/onesti.js +59 -0
  189. package/devices/openlumi.js +22 -0
  190. package/devices/orvibo.js +515 -0
  191. package/devices/osram.js +519 -0
  192. package/devices/oujiabao.js +15 -0
  193. package/devices/owon.js +352 -0
  194. package/devices/ozsmartthings.js +11 -0
  195. package/devices/paul_neuhaus.js +96 -0
  196. package/devices/paulmann.js +158 -0
  197. package/devices/peq.js +24 -0
  198. package/devices/perenio.js +413 -0
  199. package/devices/philips.js +3118 -0
  200. package/devices/plaid.js +25 -0
  201. package/devices/plugwise.js +173 -0
  202. package/devices/popp.js +10 -0
  203. package/devices/profalux.js +47 -0
  204. package/devices/prolight.js +54 -0
  205. package/devices/qmotion.js +33 -0
  206. package/devices/qoto.js +113 -0
  207. package/devices/quotra.js +18 -0
  208. package/devices/rademacher.js +18 -0
  209. package/devices/rgb_genie.js +119 -0
  210. package/devices/robb.js +335 -0
  211. package/devices/roome.js +15 -0
  212. package/devices/rtx.js +90 -0
  213. package/devices/salus_controls.js +137 -0
  214. package/devices/samotech.js +93 -0
  215. package/devices/saswell.js +58 -0
  216. package/devices/scanproducts.js +32 -0
  217. package/devices/schlage.js +24 -0
  218. package/devices/schneider_electric.js +1039 -0
  219. package/devices/schwaiger.js +62 -0
  220. package/devices/seastar_intelligence.js +16 -0
  221. package/devices/securifi.js +39 -0
  222. package/devices/sengled.js +332 -0
  223. package/devices/sercomm.js +140 -0
  224. package/devices/shenzhen_homa.js +53 -0
  225. package/devices/shinasystem.js +686 -0
  226. package/devices/siglis.js +440 -0
  227. package/devices/sinope.js +1257 -0
  228. package/devices/siterwell.js +46 -0
  229. package/devices/skydance.js +112 -0
  230. package/devices/slv.js +27 -0
  231. package/devices/smart9.js +27 -0
  232. package/devices/smart_home_pty.js +18 -0
  233. package/devices/smartenit.js +42 -0
  234. package/devices/smartthings.js +495 -0
  235. package/devices/smartwings.js +24 -0
  236. package/devices/sohan_electric.js +13 -0
  237. package/devices/solaredge.js +11 -0
  238. package/devices/somgoms.js +47 -0
  239. package/devices/sonoff.js +262 -0
  240. package/devices/spotmau.js +36 -0
  241. package/devices/sprut.js +317 -0
  242. package/devices/stelpro.js +216 -0
  243. package/devices/sunricher.js +625 -0
  244. package/devices/swann.js +33 -0
  245. package/devices/sylvania.js +200 -0
  246. package/devices/tci.js +25 -0
  247. package/devices/technicolor.js +47 -0
  248. package/devices/terncy.js +64 -0
  249. package/devices/the_light_group.js +70 -0
  250. package/devices/third_reality.js +195 -0
  251. package/devices/titan_products.js +22 -0
  252. package/devices/tplink.js +42 -0
  253. package/devices/trust.js +114 -0
  254. package/devices/tubeszb.js +20 -0
  255. package/devices/tuya.js +4215 -0
  256. package/devices/ubisys.js +938 -0
  257. package/devices/uhome.js +25 -0
  258. package/devices/universal_electronics_inc.js +119 -0
  259. package/devices/urlighting.js +12 -0
  260. package/devices/useelink.js +52 -0
  261. package/devices/vbled.js +18 -0
  262. package/devices/vesternet.js +188 -0
  263. package/devices/viessmann.js +51 -0
  264. package/devices/villeroy_boch.js +18 -0
  265. package/devices/vimar.js +78 -0
  266. package/devices/visonic.js +80 -0
  267. package/devices/vrey.js +18 -0
  268. package/devices/wally.js +25 -0
  269. package/devices/waxman.js +45 -0
  270. package/devices/weiser.js +67 -0
  271. package/devices/weten.js +13 -0
  272. package/devices/wisdom.js +11 -0
  273. package/devices/woox.js +177 -0
  274. package/devices/wyze.js +23 -0
  275. package/devices/xiaomi.js +3223 -0
  276. package/devices/xinghuoyuan.js +11 -0
  277. package/devices/yale.js +227 -0
  278. package/devices/ynoa.js +68 -0
  279. package/devices/yookee.js +23 -0
  280. package/devices/ysrsai.js +26 -0
  281. package/devices/zemismart.js +254 -0
  282. package/devices/zen.js +34 -0
  283. package/devices/zipato.js +11 -0
  284. package/index.js +242 -0
  285. package/lib/color.js +784 -0
  286. package/lib/configureKey.js +944 -0
  287. package/lib/constants.js +316 -0
  288. package/lib/exposes.js +677 -0
  289. package/lib/extend.js +180 -0
  290. package/lib/kelvinToXy.js +1912 -0
  291. package/lib/legacy.js +2223 -0
  292. package/lib/light.js +111 -0
  293. package/lib/ota/OTA_URLs.md +119 -0
  294. package/lib/ota/common.js +476 -0
  295. package/lib/ota/index.js +10 -0
  296. package/lib/ota/inovelli.js +72 -0
  297. package/lib/ota/ledvance.js +52 -0
  298. package/lib/ota/lixee.js +57 -0
  299. package/lib/ota/salus.js +82 -0
  300. package/lib/ota/securifi.js +25 -0
  301. package/lib/ota/tradfri.js +45 -0
  302. package/lib/ota/ubisys.js +61 -0
  303. package/lib/ota/zigbeeOTA.js +161 -0
  304. package/lib/philips.js +667 -0
  305. package/lib/reporting.js +234 -0
  306. package/lib/store.js +57 -0
  307. package/lib/tuya.js +2027 -0
  308. package/lib/utils.js +527 -0
  309. package/lib/xiaomi.d.ts +11 -0
  310. package/lib/xiaomi.js +1288 -0
  311. package/lib/zosung.js +243 -0
  312. package/package.json +39 -0
@@ -0,0 +1,1000 @@
1
+ const exposes = require('../lib/exposes');
2
+ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
+ const tz = require('../converters/toZigbee');
4
+ const reporting = require('../lib/reporting');
5
+ const e = exposes.presets;
6
+ const ea = exposes.access;
7
+ const tuya = require('../lib/tuya');
8
+ const globalStore = require('../lib/store');
9
+ const ota = require('../lib/ota');
10
+ const utils = require('../lib/utils');
11
+ const {ColorMode, colorModeLookup} = require('../lib/constants');
12
+ const libColor = require('../lib/color');
13
+
14
+ const tuyaLocal = {
15
+ dataPoints: {
16
+ zsHeatingSetpoint: 16,
17
+ zsChildLock: 40,
18
+ zsTempCalibration: 104,
19
+ zsLocalTemp: 24,
20
+ zsBatteryVoltage: 35,
21
+ zsComfortTemp: 101,
22
+ zsEcoTemp: 102,
23
+ zsHeatingSetpointAuto: 105,
24
+ zsOpenwindowTemp: 116,
25
+ zsOpenwindowTime: 117,
26
+ zsErrorStatus: 45,
27
+ zsMode: 2,
28
+ zsAwaySetting: 103,
29
+ zsBinaryOne: 106,
30
+ zsBinaryTwo: 107,
31
+ zsScheduleMonday: 109,
32
+ zsScheduleTuesday: 110,
33
+ zsScheduleWednesday: 111,
34
+ zsScheduleThursday: 112,
35
+ zsScheduleFriday: 113,
36
+ zsScheduleSaturday: 114,
37
+ zsScheduleSunday: 115,
38
+ },
39
+ };
40
+
41
+ const fzLocal = {
42
+ zs_thermostat: {
43
+ cluster: 'manuSpecificTuya',
44
+ type: ['commandDataResponse', 'commandDataReport'],
45
+ convert: (model, msg, publish, options, meta) => {
46
+ const dpValue = tuya.firstDpValue(msg, meta, 'zs_thermostat');
47
+ const dp = dpValue.dp;
48
+ const value = tuya.getDataValue(dpValue);
49
+ const ret = {};
50
+ const daysMap = {1: 'monday', 2: 'tuesday', 3: 'wednesday', 4: 'thursday', 5: 'friday', 6: 'saturday', 7: 'sunday'};
51
+ const day = daysMap[value[0]];
52
+
53
+ switch (dp) {
54
+ case tuyaLocal.dataPoints.zsChildLock:
55
+ return {child_lock: value ? 'LOCK' : 'UNLOCK'};
56
+
57
+ case tuyaLocal.dataPoints.zsHeatingSetpoint:
58
+ if (value==0) ret.system_mode='off';
59
+ if (value==60) {
60
+ ret.system_mode='heat';
61
+ ret.preset = 'boost';
62
+ }
63
+
64
+ ret.current_heating_setpoint= (value / 2).toFixed(1);
65
+ if (value>0 && value<60) globalStore.putValue(msg.endpoint, 'current_heating_setpoint', ret.current_heating_setpoint);
66
+ return ret;
67
+ case tuyaLocal.dataPoints.zsHeatingSetpointAuto:
68
+ return {current_heating_setpoint_auto: (value / 2).toFixed(1)};
69
+
70
+ case tuyaLocal.dataPoints.zsOpenwindowTemp:
71
+ return {detectwindow_temperature: (value / 2).toFixed(1)};
72
+
73
+ case tuyaLocal.dataPoints.zsOpenwindowTime:
74
+ return {detectwindow_timeminute: value};
75
+
76
+ case tuyaLocal.dataPoints.zsLocalTemp:
77
+ return {local_temperature: (value / 10).toFixed(1)};
78
+
79
+ case tuyaLocal.dataPoints.zsBatteryVoltage:
80
+ return {voltage: Math.round(value * 10)};
81
+
82
+ case tuyaLocal.dataPoints.zsTempCalibration:
83
+ return {local_temperature_calibration: value > 55 ?
84
+ ((value - 0x100000000)/10).toFixed(1): (value/ 10).toFixed(1)};
85
+
86
+ case tuyaLocal.dataPoints.zsBinaryOne:
87
+ return {binary_one: value ? 'ON' : 'OFF'};
88
+
89
+ case tuyaLocal.dataPoints.zsBinaryTwo:
90
+ return {binary_two: value ? 'ON' : 'OFF'};
91
+
92
+ case tuyaLocal.dataPoints.zsComfortTemp:
93
+ return {comfort_temperature: (value / 2).toFixed(1)};
94
+
95
+ case tuyaLocal.dataPoints.zsEcoTemp:
96
+ return {eco_temperature: (value / 2).toFixed(1)};
97
+
98
+ case tuyaLocal.dataPoints.zsAwayTemp:
99
+ return {away_preset_temperature: (value / 2).toFixed(1)};
100
+
101
+ case tuyaLocal.dataPoints.zsMode:
102
+ switch (value) {
103
+ case 1: // manual
104
+ return {system_mode: 'heat', away_mode: 'OFF', preset: 'manual'};
105
+ case 2: // away
106
+ return {system_mode: 'auto', away_mode: 'ON', preset: 'holiday'};
107
+ case 0: // auto
108
+ return {system_mode: 'auto', away_mode: 'OFF', preset: 'schedule'};
109
+ default:
110
+ meta.logger.warn('zigbee-herdsman-converters:zsThermostat: ' +
111
+ `preset ${value} is not recognized.`);
112
+ break;
113
+ }
114
+ break;
115
+ case tuyaLocal.dataPoints.zsScheduleMonday:
116
+ case tuyaLocal.dataPoints.zsScheduleTuesday:
117
+ case tuyaLocal.dataPoints.zsScheduleWednesday:
118
+ case tuyaLocal.dataPoints.zsScheduleThursday:
119
+ case tuyaLocal.dataPoints.zsScheduleFriday:
120
+ case tuyaLocal.dataPoints.zsScheduleSaturday:
121
+ case tuyaLocal.dataPoints.zsScheduleSunday:
122
+ for (let i = 1; i <= 9; i++) {
123
+ const tempId = ((i-1) * 2) +1;
124
+ const timeId = ((i-1) * 2) +2;
125
+ ret[`${day}_temp_${i}`] = (value[tempId] / 2).toFixed(1);
126
+ if (i!=9) {
127
+ ret[`${day}_hour_${i}`] = Math.floor(value[timeId] / 4).toString().padStart(2, '0');
128
+ ret[`${day}_minute_${i}`] = ((value[timeId] % 4) *15).toString().padStart(2, '0');
129
+ }
130
+ }
131
+ return ret;
132
+ case tuyaLocal.dataPoints.zsAwaySetting:
133
+ ret.away_preset_year = value[0];
134
+ ret.away_preset_month = value[1];
135
+ ret.away_preset_day = value[2];
136
+ ret.away_preset_hour = value[3];
137
+ ret.away_preset_minute = value[4];
138
+ ret.away_preset_temperature = (value[5] / 2).toFixed(1);
139
+ ret.away_preset_days = (value[6]<<8)+value[7];
140
+ return ret;
141
+ default:
142
+ meta.logger.warn(`zigbee-herdsman-converters:zsThermostat: Unrecognized DP #${dp} with data ${JSON.stringify(dpValue)}`);
143
+ }
144
+ },
145
+ },
146
+ };
147
+ const tzLocal = {
148
+ led_control: {
149
+ key: ['brightness', 'color', 'color_temp', 'transition'],
150
+ options: [exposes.options.color_sync()],
151
+ convertSet: async (entity, _key, _value, meta) => {
152
+ const newState = {};
153
+
154
+ // The color mode encodes whether the light is using its white LEDs or its color LEDs
155
+ let colorMode = meta.state.color_mode ?? colorModeLookup[ColorMode.ColorTemp];
156
+
157
+ // Color mode switching is done by setting color temperature (switch to white LEDs) or setting color (switch
158
+ // to color LEDs)
159
+ if ('color_temp' in meta.message) colorMode = colorModeLookup[ColorMode.ColorTemp];
160
+ if ('color' in meta.message) colorMode = colorModeLookup[ColorMode.HS];
161
+
162
+ if (colorMode != meta.state.color_mode) {
163
+ newState.color_mode = colorMode;
164
+
165
+ // To switch between white mode and color mode, we have to send a special command:
166
+ const rgbMode = (colorMode == colorModeLookup[ColorMode.HS]);
167
+ await entity.command('lightingColorCtrl', 'tuyaRgbMode', {enable: rgbMode}, {}, {disableDefaultResponse: true});
168
+ }
169
+
170
+ // A transition time of 0 would be treated as about 1 second, probably some kind of fallback/default
171
+ // transition time, so for "no transition" we use 1 (tenth of a second).
172
+ const transtime = 'transition' in meta.message ? meta.message.transition * 10 : 1;
173
+
174
+ if (colorMode == colorModeLookup[ColorMode.ColorTemp]) {
175
+ if ('brightness' in meta.message) {
176
+ const zclData = {level: Number(meta.message.brightness), transtime};
177
+ await entity.command('genLevelCtrl', 'moveToLevel', zclData, utils.getOptions(meta.mapped, entity));
178
+ newState.brightness = meta.message.brightness;
179
+ }
180
+
181
+ if ('color_temp' in meta.message) {
182
+ const zclData = {colortemp: meta.message.color_temp, transtime: transtime};
183
+ await entity.command('lightingColorCtrl', 'moveToColorTemp', zclData, utils.getOptions(meta.mapped, entity));
184
+ newState.color_temp = meta.message.color_temp;
185
+ }
186
+ } else if (colorMode == colorModeLookup[ColorMode.HS]) {
187
+ if ('brightness' in meta.message || 'color' in meta.message) {
188
+ // We ignore the brightness of the color and instead use the overall brightness setting of the lamp
189
+ // for the brightness because I think that's the expected behavior and also because the color
190
+ // conversion below always returns 100 as brightness ("value") even for very dark colors, except
191
+ // when the color is completely black/zero.
192
+
193
+ // Load current state or defaults
194
+ const newSettings = {
195
+ brightness: meta.state.brightness ?? 254, // full brightness
196
+ hue: (meta.state.color ?? {}).hue ?? 0, // red
197
+ saturation: (meta.state.color ?? {}).saturation ?? 100, // full saturation
198
+ };
199
+
200
+ // Apply changes
201
+ if ('brightness' in meta.message) {
202
+ newSettings.brightness = meta.message.brightness;
203
+ newState.brightness = meta.message.brightness;
204
+ }
205
+ if ('color' in meta.message) {
206
+ // The Z2M UI sends `{ hex:'#xxxxxx' }`.
207
+ // Home Assistant sends `{ h: xxx, s: xxx }`.
208
+ // We convert the former into the latter.
209
+ const c = libColor.Color.fromConverterArg(meta.message.color);
210
+ if (c.isRGB()) {
211
+ // https://github.com/Koenkk/zigbee2mqtt/issues/13421#issuecomment-1426044963
212
+ c.hsv = c.rgb.gammaCorrected().toXY().toHSV();
213
+ }
214
+ const color = c.hsv;
215
+
216
+ newSettings.hue = color.hue;
217
+ newSettings.saturation = color.saturation;
218
+
219
+ newState.color = {
220
+ hue: color.hue,
221
+ saturation: color.saturation,
222
+ };
223
+ }
224
+
225
+ // Convert to device specific format and send
226
+ const zclData = {
227
+ brightness: utils.mapNumberRange(newSettings.brightness, 0, 254, 0, 1000),
228
+ hue: newSettings.hue,
229
+ saturation: utils.mapNumberRange(newSettings.saturation, 0, 100, 0, 1000),
230
+ };
231
+ // This command doesn't support a transition time
232
+ await entity.command('lightingColorCtrl', 'tuyaMoveToHueAndSaturationBrightness2', zclData,
233
+ utils.getOptions(meta.mapped, entity));
234
+ }
235
+ }
236
+
237
+ // If we're in white mode, calculate a matching display color for the set color temperature. This also kind
238
+ // of works in the other direction.
239
+ Object.assign(newState, libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger));
240
+
241
+ return {state: newState};
242
+ },
243
+ convertGet: async (entity, key, meta) => {
244
+ await entity.read('lightingColorCtrl', ['currentHue', 'currentSaturation', 'currentLevel', 'tuyaRgbMode', 'colorTemperature']);
245
+ },
246
+ },
247
+ zs_thermostat_child_lock: {
248
+ key: ['child_lock'],
249
+ convertSet: async (entity, key, value, meta) => {
250
+ await tuya.sendDataPointBool(entity, tuyaLocal.dataPoints.zsChildLock, value === 'LOCK');
251
+ },
252
+ },
253
+ zs_thermostat_binary_one: {
254
+ key: ['binary_one'],
255
+ convertSet: async (entity, key, value, meta) => {
256
+ await tuya.sendDataPointBool(entity, tuyaLocal.dataPoints.zsBinaryOne, value === 'ON');
257
+ },
258
+ },
259
+ zs_thermostat_binary_two: {
260
+ key: ['binary_two'],
261
+ convertSet: async (entity, key, value, meta) => {
262
+ await tuya.sendDataPointBool(entity, tuyaLocal.dataPoints.zsBinaryTwo, value === 'ON');
263
+ },
264
+ },
265
+ zs_thermostat_current_heating_setpoint: {
266
+ key: ['current_heating_setpoint'],
267
+ convertSet: async (entity, key, value, meta) => {
268
+ let temp = Math.round(value * 2);
269
+ if (temp<=0) temp = 1;
270
+ if (temp>=60) temp = 59;
271
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, temp);
272
+ },
273
+ },
274
+ zs_thermostat_current_heating_setpoint_auto: {
275
+ key: ['current_heating_setpoint_auto'],
276
+ convertSet: async (entity, key, value, meta) => {
277
+ let temp = Math.round(value * 2);
278
+ if (temp<=0) temp = 1;
279
+ if (temp>=60) temp = 59;
280
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpointAuto, temp);
281
+ },
282
+ },
283
+ zs_thermostat_comfort_temp: {
284
+ key: ['comfort_temperature'],
285
+ convertSet: async (entity, key, value, meta) => {
286
+ meta.logger.debug(JSON.stringify(entity));
287
+ const temp = Math.round(value * 2);
288
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsComfortTemp, temp);
289
+ },
290
+ },
291
+ zs_thermostat_openwindow_temp: {
292
+ key: ['detectwindow_temperature'],
293
+ convertSet: async (entity, key, value, meta) => {
294
+ let temp = Math.round(value * 2);
295
+ if (temp<=0) temp = 1;
296
+ if (temp>=60) temp = 59;
297
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsOpenwindowTemp, temp);
298
+ },
299
+ },
300
+ zs_thermostat_openwindow_time: {
301
+ key: ['detectwindow_timeminute'],
302
+ convertSet: async (entity, key, value, meta) => {
303
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsOpenwindowTime, value);
304
+ },
305
+ },
306
+ zs_thermostat_eco_temp: {
307
+ key: ['eco_temperature'],
308
+ convertSet: async (entity, key, value, meta) => {
309
+ const temp = Math.round(value * 2);
310
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsEcoTemp, temp);
311
+ },
312
+ },
313
+ zs_thermostat_preset_mode: {
314
+ key: ['preset'],
315
+ convertSet: async (entity, key, value, meta) => {
316
+ const lookup = {'schedule': 0, 'manual': 1, 'holiday': 2};
317
+ if (value == 'boost') {
318
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, lookup['manual']);
319
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, 60);
320
+ } else {
321
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, lookup[value]);
322
+ if (value == 'manual') {
323
+ const temp = globalStore.getValue(entity, 'current_heating_setpoint');
324
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, temp ? Math.round(temp * 2) : 43 );
325
+ }
326
+ }
327
+ },
328
+ },
329
+ zs_thermostat_system_mode: {
330
+ key: ['system_mode'],
331
+ convertSet: async (entity, key, value, meta) => {
332
+ if (value == 'off') {
333
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, 1);
334
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, 0);
335
+ } else if (value == 'auto') {
336
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, 0);
337
+ } else if (value == 'heat') {
338
+ // manual
339
+ const temp = globalStore.getValue(entity, 'current_heating_setpoint');
340
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, 1);
341
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, temp ? Math.round(temp * 2) : 43 );
342
+ }
343
+ },
344
+ },
345
+ zs_thermostat_local_temperature_calibration: {
346
+ key: ['local_temperature_calibration'],
347
+ convertSet: async (entity, key, value, meta) => {
348
+ if (value > 0) value = value*10;
349
+ if (value < 0) value = value*10 + 0x100000000;
350
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsTempCalibration, value);
351
+ },
352
+ },
353
+ zs_thermostat_away_setting: {
354
+ key: ['away_setting'],
355
+ convertSet: async (entity, key, value, meta) => {
356
+ const result = [];
357
+ const daysInMonth = new Date(2000+result[0], result[1], 0).getDate();
358
+
359
+ for (const attrName of ['away_preset_year',
360
+ 'away_preset_month',
361
+ 'away_preset_day',
362
+ 'away_preset_hour',
363
+ 'away_preset_minute',
364
+ 'away_preset_temperature',
365
+ 'away_preset_days']) {
366
+ let v = 0;
367
+ if (value.hasOwnProperty(attrName)) {
368
+ v = value[attrName];
369
+ } else if (meta.state.hasOwnProperty(attrName)) {
370
+ v = meta.state[attrName];
371
+ }
372
+ switch (attrName) {
373
+ case 'away_preset_year':
374
+ if (v<17 || v>99) v = 17;
375
+ result.push(Math.round(v));
376
+ break;
377
+ case 'away_preset_month':
378
+ if (v<1 || v>12) v = 1;
379
+ result.push(Math.round(v));
380
+ break;
381
+ case 'away_preset_day':
382
+ if (v<1) {
383
+ v = 1;
384
+ } else if (v>daysInMonth) {
385
+ v = daysInMonth;
386
+ }
387
+ result.push(Math.round(v));
388
+ break;
389
+ case 'away_preset_hour':
390
+ if (v<0 || v>23) v = 0;
391
+ result.push(Math.round(v));
392
+ break;
393
+ case 'away_preset_minute':
394
+ if (v<0 || v>59) v = 0;
395
+ result.push(Math.round(v));
396
+ break;
397
+ case 'away_preset_temperature':
398
+ if (v<0.5 || v>29.5) v = 17;
399
+ result.push(Math.round(v * 2));
400
+ break;
401
+ case 'away_preset_days':
402
+ if (v<1 || v>9999) v = 1;
403
+ result.push((v & 0xff00)>>8);
404
+ result.push((v & 0x00ff));
405
+ break;
406
+ }
407
+ }
408
+
409
+ await tuya.sendDataPointRaw(entity, tuyaLocal.dataPoints.zsAwaySetting, result);
410
+ },
411
+ },
412
+ zs_thermostat_local_schedule: {
413
+ key: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'],
414
+ convertSet: async (entity, key, value, meta) => {
415
+ const daysMap = {'monday': 1, 'tuesday': 2, 'wednesday': 3, 'thursday': 4, 'friday': 5, 'saturday': 6, 'sunday': 7};
416
+ const day = daysMap[key];
417
+ const results = [];
418
+ results.push(day);
419
+ for (let i = 1; i <= 9; i++) {
420
+ // temperature
421
+ const attrName = `${key}_temp_${i}`;
422
+ let v = 17;
423
+ if (value.hasOwnProperty(attrName)) {
424
+ v = value[attrName];
425
+ } else if (meta.state.hasOwnProperty(attrName)) {
426
+ v = meta.state[attrName];
427
+ }
428
+ if (v<0.5 || v>29.5) v = 17;
429
+ results.push(Math.round(v * 2));
430
+ if (i!=9) {
431
+ // hour
432
+ let attrName = `${key}_hour_${i}`;
433
+ let h = 0;
434
+ if (value.hasOwnProperty(attrName)) {
435
+ h = value[attrName];
436
+ } else if (meta.state.hasOwnProperty(attrName)) {
437
+ h = meta.state[attrName];
438
+ }
439
+ // minute
440
+ attrName = `${key}_minute_${i}`;
441
+ let m = 0;
442
+ if (value.hasOwnProperty(attrName)) {
443
+ m = value[attrName];
444
+ } else if (meta.state.hasOwnProperty(attrName)) {
445
+ m = meta.state[attrName];
446
+ }
447
+ let rt = h*4 + m/15;
448
+ if (rt<1) {
449
+ rt =1;
450
+ } else if (rt>96) {
451
+ rt = 96;
452
+ }
453
+ results.push(Math.round(rt));
454
+ }
455
+ }
456
+ if (value > 0) value = value*10;
457
+ if (value < 0) value = value*10 + 0x100000000;
458
+ await tuya.sendDataPointRaw(entity, (109+day-1), results);
459
+ },
460
+ },
461
+ };
462
+
463
+ module.exports = [
464
+ {
465
+ fingerprint: [
466
+ {manufacturerName: '_TZ3000_kdi2o9m6'}, // EU
467
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_plyvnuf5'}, // CH
468
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_wamqdr3f'}, // FR
469
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_00mk2xzy'}, // BS
470
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_upjrsxh1'}, // DK
471
+ {manufacturerName: '_TZ3000_00mk2xzy'}, // BS
472
+ ],
473
+ model: 'HG06337',
474
+ vendor: 'Lidl',
475
+ description: 'Silvercrest smart plug (EU, CH, FR, BS, DK)',
476
+ extend: tuya.extend.switch(),
477
+ configure: async (device, coordinatorEndpoint, logger) => {
478
+ const endpoint = device.getEndpoint(11);
479
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
480
+ await reporting.onOff(endpoint);
481
+ },
482
+ },
483
+ {
484
+ fingerprint: [
485
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_j1v25l17'}, // EU
486
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_ynmowqk2'}, // FR
487
+ ],
488
+ model: 'HG08673',
489
+ vendor: 'Lidl',
490
+ description: 'Silvercrest smart plug with power monitoring (EU, FR)',
491
+ ota: ota.zigbeeOTA,
492
+ extend: tuya.extend.switch({electricalMeasurements: true, powerOutageMemory: true, indicatorMode: true, childLock: true}),
493
+ configure: async (device, coordinatorEndpoint, logger) => {
494
+ const endpoint = device.getEndpoint(1);
495
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
496
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement']);
497
+ await reporting.rmsVoltage(endpoint, {change: 5});
498
+ await reporting.rmsCurrent(endpoint, {change: 50});
499
+ await reporting.activePower(endpoint, {change: 10});
500
+ // Energy reporting (currentSummDelivered) doesn't work; requires polling: https://github.com/Koenkk/zigbee2mqtt/issues/14356
501
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
502
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
503
+ device.save();
504
+ },
505
+ options: [exposes.options.measurement_poll_interval().withDescription('Only the energy value is polled for this device.')],
506
+ onEvent: (type, data, device, options) => tuya.onEventMeasurementPoll(type, data, device, options, false, true),
507
+ },
508
+ {
509
+ fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_rco1yzb1'}],
510
+ model: 'HG08164',
511
+ vendor: 'Lidl',
512
+ description: 'Silvercrest smart button',
513
+ fromZigbee: [fz.command_on, fz.command_off, fz.command_step, fz.command_stop, fz.battery, fz.tuya_on_off_action],
514
+ toZigbee: [],
515
+ configure: async (device, coordinatorEndpoint, logger) => {
516
+ const endpoint = device.getEndpoint(1);
517
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
518
+ await reporting.batteryPercentageRemaining(endpoint);
519
+ },
520
+ exposes: [e.action(
521
+ ['on', 'off', 'brightness_stop', 'brightness_step_up', 'brightness_step_down', 'single', 'double']), e.battery()],
522
+ },
523
+ {
524
+ fingerprint: [{modelID: 'TS0211', manufacturerName: '_TZ1800_ladpngdx'}],
525
+ model: 'HG06668',
526
+ vendor: 'Lidl',
527
+ description: 'Silvercrest smart wireless door bell button',
528
+ fromZigbee: [fz.battery, fz.tuya_doorbell_button, fz.ignore_basic_report],
529
+ toZigbee: [],
530
+ configure: async (device, coordinatorEndpoint, logger) => {
531
+ const endpoint = device.getEndpoint(1);
532
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
533
+ await reporting.batteryPercentageRemaining(endpoint);
534
+ },
535
+ exposes: [e.battery(), e.action(['pressed']), e.battery_low(), e.tamper()],
536
+ },
537
+ {
538
+ fingerprint: [{modelID: 'TY0202', manufacturerName: '_TZ1800_fcdjzz3s'}],
539
+ model: 'HG06335/HG07310',
540
+ vendor: 'Lidl',
541
+ description: 'Silvercrest smart motion sensor',
542
+ fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery],
543
+ toZigbee: [],
544
+ exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery()],
545
+ configure: async (device, coordinatorEndpoint, logger) => {
546
+ const endpoint = device.getEndpoint(1);
547
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
548
+ await reporting.batteryVoltage(endpoint);
549
+ await reporting.batteryPercentageRemaining(endpoint);
550
+ },
551
+ },
552
+ {
553
+ fingerprint: [{modelID: 'TY0203', manufacturerName: '_TZ1800_ejwkn2h2'}],
554
+ model: 'HG06336',
555
+ vendor: 'Lidl',
556
+ description: 'Silvercrest smart window and door sensor',
557
+ fromZigbee: [fz.ias_contact_alarm_1, fz.ias_contact_alarm_1_report, fz.battery],
558
+ toZigbee: [],
559
+ exposes: [e.contact(), e.battery_low(), e.tamper(), e.battery()],
560
+ configure: async (device, coordinatorEndpoint, logger) => {
561
+ const endpoint = device.getEndpoint(1);
562
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
563
+ await reporting.batteryPercentageRemaining(endpoint);
564
+ },
565
+ },
566
+ {
567
+ fingerprint: [{modelID: 'TS1001', manufacturerName: '_TYZB01_bngwdjsr'}],
568
+ model: 'FB20-002',
569
+ vendor: 'Lidl',
570
+ description: 'Livarno Lux switch and dimming light remote control',
571
+ exposes: [e.action(['on', 'off', 'brightness_stop', 'brightness_step_up', 'brightness_step_down', 'brightness_move_up',
572
+ 'brightness_move_down'])],
573
+ fromZigbee: [fz.command_on, fz.command_off, fz.command_step, fz.command_move, fz.command_stop],
574
+ toZigbee: [],
575
+ },
576
+ {
577
+ fingerprint: [{modelID: 'TS1001', manufacturerName: '_TYZB01_hww2py6b'}],
578
+ model: 'FB21-001',
579
+ vendor: 'Lidl',
580
+ description: 'Livarno Lux switch and dimming light remote control',
581
+ exposes: [e.action(['on', 'off', 'brightness_stop', 'brightness_step_up', 'brightness_step_down', 'brightness_move_up',
582
+ 'brightness_move_down', 'switch_scene'])],
583
+ fromZigbee: [fz.command_on, fz.command_off, fz.command_step, fz.command_move, fz.command_stop, fz.tuya_switch_scene],
584
+ toZigbee: [],
585
+ },
586
+ {
587
+ fingerprint: [
588
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_wzauvbcs'}, // EU
589
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_oznonj5q'},
590
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_1obwwnmq'},
591
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_4uf3d0ax'}, // FR
592
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_vzopcetz'}, // CZ
593
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_vmpbygs5'}, // BS
594
+ ],
595
+ model: 'HG06338',
596
+ vendor: 'Lidl',
597
+ description: 'Silvercrest 3 gang switch, with 4 USB (EU, FR, CZ, BS)',
598
+ extend: tuya.extend.switch({endpoints: ['l1', 'l2', 'l3']}),
599
+ meta: {multiEndpoint: true},
600
+ configure: async (device, coordinatorEndpoint, logger) => {
601
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
602
+ for (const ID of [1, 2, 3]) {
603
+ await reporting.bind(device.getEndpoint(ID), coordinatorEndpoint, ['genOnOff']);
604
+ }
605
+ },
606
+ endpoint: (device) => {
607
+ return {'l1': 1, 'l2': 2, 'l3': 3};
608
+ },
609
+ },
610
+ {
611
+ fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_riwp3k79'}, {manufacturerName: '_TZ3000_riwp3k79'}],
612
+ model: 'HG06104A',
613
+ vendor: 'Lidl',
614
+ description: 'Livarno Lux smart LED light strip 2.5m',
615
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({noConfigure: true}),
616
+ configure: async (device, coordinatorEndpoint, logger) => {
617
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
618
+ },
619
+ },
620
+ {
621
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_s8gkrkxk'}],
622
+ model: 'HG06467',
623
+ vendor: 'Lidl',
624
+ description: 'Melinera smart LED string lights',
625
+ toZigbee: [tz.on_off, tz.silvercrest_smart_led_string],
626
+ fromZigbee: [fz.on_off, fz.silvercrest_smart_led_string],
627
+ exposes: [e.light_brightness_colorhs().setAccess('brightness', ea.STATE_SET).setAccess('color_hs', ea.STATE_SET)],
628
+ },
629
+ {
630
+ fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_odygigth'}],
631
+ model: 'HG06106B',
632
+ vendor: 'Lidl',
633
+ description: 'Livarno Lux E14 candle RGB',
634
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({noConfigure: true}),
635
+ configure: async (device, coordinatorEndpoint, logger) => {
636
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
637
+ },
638
+ },
639
+ {
640
+ fingerprint: [{modelID: 'TS0504B', manufacturerName: '_TZ3210_sroezl0s'}],
641
+ model: '14153806L',
642
+ vendor: 'Lidl',
643
+ description: 'Livarno smart LED ceiling light',
644
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
645
+ configure: async (device, coordinatorEndpoint, logger) => {
646
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
647
+ },
648
+ },
649
+ {
650
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_r0xgkft5'}],
651
+ model: '14156506L',
652
+ vendor: 'Lidl',
653
+ description: 'Livarno Lux smart LED mood light',
654
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
655
+ configure: async (device, coordinatorEndpoint, logger) => {
656
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
657
+ },
658
+ },
659
+ {
660
+ fingerprint: [{modelID: 'TS0502B', manufacturerName: '_TZ3210_c2iwpxf1'}],
661
+ model: '14156408L',
662
+ vendor: 'Lidl',
663
+ description: 'Livarno Lux smart LED ceiling light',
664
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
665
+ configure: async (device, coordinatorEndpoint, logger) => {
666
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 16});
667
+ },
668
+ },
669
+ {
670
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_umi6vbsz'}],
671
+ model: 'HG08010',
672
+ vendor: 'Lidl',
673
+ description: 'Livarno Home outdoor spotlight',
674
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
675
+ configure: async (device, coordinatorEndpoint, logger) => {
676
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
677
+ },
678
+ },
679
+ {
680
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_p9ao60da'}],
681
+ model: 'HG08008',
682
+ vendor: 'Lidl',
683
+ description: 'Livarno Home LED ceiling light',
684
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
685
+ configure: async (device, coordinatorEndpoint, logger) => {
686
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
687
+ },
688
+ },
689
+ {
690
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_zbabx9wh'}],
691
+ model: 'HG08007',
692
+ vendor: 'TuYa',
693
+ description: 'Livarno Home outdoor LED band',
694
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
695
+ },
696
+ {
697
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_z1vlyufu'}],
698
+ model: '14158704L',
699
+ vendor: 'Lidl',
700
+ description: 'Livarno Home LED floor lamp, RGBW',
701
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
702
+ configure: async (device, coordinatorEndpoint, logger) => {
703
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
704
+ },
705
+ },
706
+ {
707
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_hxtfthp5'}],
708
+ model: '14158804L',
709
+ vendor: 'Lidl',
710
+ description: 'Livarno Home LED desk lamp RGBW',
711
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
712
+ configure: async (device, coordinatorEndpoint, logger) => {
713
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
714
+ },
715
+ },
716
+ {
717
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_quqaeew6'}],
718
+ model: 'HG07834A',
719
+ vendor: 'Lidl',
720
+ description: 'Livarno Lux GU10 spot RGB',
721
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
722
+ configure: async (device, coordinatorEndpoint, logger) => {
723
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
724
+ },
725
+ },
726
+ {
727
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_th6zqqy6'},
728
+ {modelID: 'TS0505B', manufacturerName: '_TZ3000_wr6g6olr'}],
729
+ model: 'HG07834B',
730
+ vendor: 'Lidl',
731
+ description: 'Livarno Lux E14 candle RGB',
732
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
733
+ configure: async (device, coordinatorEndpoint, logger) => {
734
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
735
+ },
736
+ },
737
+ {
738
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_q50zhdsc'}],
739
+ model: 'HG08131C',
740
+ vendor: 'Lidl',
741
+ description: 'Livarno Home outdoor E27 bulb in set with flare',
742
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
743
+ configure: async (device, coordinatorEndpoint, logger) => {
744
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
745
+ },
746
+ },
747
+ {
748
+ fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_kdpxju99'}],
749
+ model: 'HG06106A',
750
+ vendor: 'Lidl',
751
+ description: 'Livarno Lux GU10 spot RGB',
752
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({noConfigure: true}),
753
+ configure: async (device, coordinatorEndpoint, logger) => {
754
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
755
+ },
756
+ },
757
+ {
758
+ fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_dbou1ap4'}],
759
+ model: 'HG06106C',
760
+ vendor: 'Lidl',
761
+ description: 'Livarno Lux E27 bulb RGB',
762
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({noConfigure: true}),
763
+ configure: async (device, coordinatorEndpoint, logger) => {
764
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
765
+ },
766
+ },
767
+ {
768
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_qd7hej8u'}],
769
+ model: 'HG07834C',
770
+ vendor: 'Lidl',
771
+ description: 'Livarno Lux E27 bulb RGB',
772
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], noConfigure: true}),
773
+ configure: async (device, coordinatorEndpoint, logger) => {
774
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
775
+ },
776
+ },
777
+ {
778
+ fingerprint: [{modelID: 'TS0502A', manufacturerName: '_TZ3000_el5kt5im'}],
779
+ model: 'HG06492A',
780
+ vendor: 'Lidl',
781
+ description: 'Livarno Lux GU10 spot CCT',
782
+ extend: tuya.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500], noConfigure: true}),
783
+ configure: async (device, coordinatorEndpoint, logger) => {
784
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 16});
785
+ },
786
+ },
787
+ {
788
+ fingerprint: [{modelID: 'TS0502A', manufacturerName: '_TZ3000_oborybow'}],
789
+ model: 'HG06492B',
790
+ vendor: 'Lidl',
791
+ description: 'Livarno Lux E14 candle CCT',
792
+ extend: tuya.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500], noConfigure: true}),
793
+ configure: async (device, coordinatorEndpoint, logger) => {
794
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 16});
795
+ },
796
+ },
797
+ {
798
+ fingerprint: [{modelID: 'TS0502A', manufacturerName: '_TZ3000_49qchf10'}],
799
+ model: 'HG06492C',
800
+ vendor: 'Lidl',
801
+ description: 'Livarno Lux E27 bulb CCT',
802
+ extend: tuya.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500], noConfigure: true}),
803
+ configure: async (device, coordinatorEndpoint, logger) => {
804
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 16});
805
+ },
806
+ },
807
+ {
808
+ fingerprint: [{modelID: 'TS0502A', manufacturerName: '_TZ3000_rylaozuc'},
809
+ {modelID: 'TS0502A', manufacturerName: '_TZ3000_5fkufhn1'}],
810
+ model: '14147206L',
811
+ vendor: 'Lidl',
812
+ description: 'Livarno Lux ceiling light',
813
+ extend: tuya.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500], noConfigure: true}),
814
+ configure: async (device, coordinatorEndpoint, logger) => {
815
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 16});
816
+ },
817
+ },
818
+ {
819
+ fingerprint: [{modelID: 'TS0502A', manufacturerName: '_TZ3000_8uaoilu9'}],
820
+ model: '14153905L',
821
+ vendor: 'Lidl',
822
+ description: 'Livarno Home LED floor lamp',
823
+ extend: tuya.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500], noConfigure: true}),
824
+ configure: async (device, coordinatorEndpoint, logger) => {
825
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 16});
826
+ },
827
+ },
828
+ {
829
+ fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_9cpuaca6'}],
830
+ model: '14148906L',
831
+ vendor: 'Lidl',
832
+ description: 'Livarno Lux mood light RGB+CCT',
833
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({noConfigure: true}),
834
+ configure: async (device, coordinatorEndpoint, logger) => {
835
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
836
+ },
837
+ },
838
+ {
839
+ fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_gek6snaj'}],
840
+ model: '14149505L/14149506L_1',
841
+ vendor: 'Lidl',
842
+ description: 'Livarno Lux light bar RGB+CCT (black/white)',
843
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({noConfigure: true}),
844
+ configure: async (device, coordinatorEndpoint, logger) => {
845
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
846
+ },
847
+ },
848
+ {
849
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_iystcadi'}],
850
+ model: '14149505L/14149506L_2',
851
+ vendor: 'Lidl',
852
+ description: 'Livarno Lux light bar RGB+CCT (black/white)',
853
+ toZigbee: [tz.on_off, tzLocal.led_control],
854
+ fromZigbee: [fz.on_off, fz.tuya_led_controller, fz.brightness, fz.ignore_basic_report],
855
+ exposes: [e.light_brightness_colortemp_colorhs([153, 500]).removeFeature('color_temp_startup')],
856
+ configure: async (device, coordinatorEndpoint, logger) => {
857
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
858
+ },
859
+ },
860
+ {
861
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_htnnfasr'}],
862
+ model: 'PSBZS A1',
863
+ vendor: 'Lidl',
864
+ description: 'Parkside smart watering timer',
865
+ fromZigbee: [fz.ignore_basic_report],
866
+ toZigbee: [tz.on_off, tz.lidl_watering_timer],
867
+ onEvent: tuya.onEventSetTime,
868
+ configure: async (device, coordinatorEndpoint, logger) => {},
869
+ exposes: [e.switch(), exposes.numeric('timer', ea.SET).withValueMin(1).withValueMax(10000)
870
+ .withUnit('min').withDescription('Auto off after specific time.')],
871
+ },
872
+ {
873
+ fingerprint: [{modelID: 'TS0501A', manufacturerName: '_TZ3000_j2w1dw29'}],
874
+ model: 'HG06463A',
875
+ vendor: 'Lidl',
876
+ description: 'Livarno Lux E27 ST64 filament bulb',
877
+ extend: tuya.extend.light_onoff_brightness(),
878
+ meta: {turnsOffAtBrightness1: false},
879
+ },
880
+ {
881
+ fingerprint: [{modelID: 'TS0501A', manufacturerName: '_TZ3000_nosnx7im'}],
882
+ model: 'HG06463B',
883
+ vendor: 'Lidl',
884
+ description: 'Livarno Lux E27 G95 filament bulb',
885
+ extend: tuya.extend.light_onoff_brightness(),
886
+ meta: {turnsOffAtBrightness1: false},
887
+ },
888
+ {
889
+ fingerprint: [{modelID: 'TS0101', manufacturerName: '_TZ3000_br3laukf'}],
890
+ model: 'HG06620',
891
+ vendor: 'Lidl',
892
+ description: 'Silvercrest garden spike with 2 sockets',
893
+ extend: tuya.extend.switch(),
894
+ configure: async (device, coordinatorEndpoint, logger) => {
895
+ const endpoint = device.getEndpoint(1);
896
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
897
+ await reporting.onOff(endpoint);
898
+ },
899
+ },
900
+ {
901
+ fingerprint: [
902
+ {modelID: 'TS0501A', manufacturerName: '_TZ3000_7dcddnye'},
903
+ {modelID: 'TS0501A', manufacturerName: '_TZ3000_nbnmw9nc'}, // UK
904
+ ],
905
+ model: 'HG06462A',
906
+ vendor: 'Lidl',
907
+ description: 'Livarno Lux E27 A60 filament bulb',
908
+ extend: tuya.extend.light_onoff_brightness(),
909
+ meta: {turnsOffAtBrightness1: false},
910
+ },
911
+ {
912
+ fingerprint: [{modelID: 'TS0101', manufacturerName: '_TZ3000_pnzfdr9y'}],
913
+ model: 'HG06619',
914
+ vendor: 'Lidl',
915
+ description: 'Silvercrest outdoor plug',
916
+ extend: tuya.extend.switch(),
917
+ configure: async (device, coordinatorEndpoint, logger) => {
918
+ const endpoint = device.getEndpoint(1);
919
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
920
+ await reporting.onOff(endpoint);
921
+ },
922
+ },
923
+ {
924
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_lxw3zcdk'}],
925
+ model: 'HG08633',
926
+ vendor: 'Lidl',
927
+ description: 'Livarno gardenspot RGB',
928
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({supportsHS: true, preferHS: true, colorTempRange: [153, 500]}),
929
+ },
930
+ {
931
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_bwlvyjwk'}],
932
+ model: 'HG08383B',
933
+ vendor: 'Lidl',
934
+ description: 'Livarno outdoor LED light chain',
935
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
936
+ },
937
+ {
938
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_chyvmhay'}],
939
+ model: '368308_2010',
940
+ vendor: 'Lidl',
941
+ description: 'Silvercrest radiator valve with thermostat',
942
+ fromZigbee: [fz.ignore_tuya_set_time, fzLocal.zs_thermostat],
943
+ toZigbee: [tzLocal.zs_thermostat_current_heating_setpoint, tzLocal.zs_thermostat_child_lock,
944
+ tzLocal.zs_thermostat_comfort_temp, tzLocal.zs_thermostat_eco_temp, tzLocal.zs_thermostat_preset_mode,
945
+ tzLocal.zs_thermostat_system_mode, tzLocal.zs_thermostat_local_temperature_calibration,
946
+ tzLocal.zs_thermostat_current_heating_setpoint_auto, tzLocal.zs_thermostat_openwindow_time,
947
+ tzLocal.zs_thermostat_openwindow_temp, tzLocal.zs_thermostat_binary_one, tzLocal.zs_thermostat_binary_two,
948
+ tzLocal.zs_thermostat_away_setting, tzLocal.zs_thermostat_local_schedule],
949
+ onEvent: tuya.onEventSetLocalTime,
950
+ configure: async (device, coordinatorEndpoint, logger) => {
951
+ const endpoint = device.getEndpoint(1);
952
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
953
+ },
954
+ exposes: [
955
+ e.child_lock(), e.comfort_temperature(), e.eco_temperature(), e.battery_voltage(),
956
+ exposes.numeric('current_heating_setpoint_auto', ea.STATE_SET).withValueMin(0.5).withValueMax(29.5)
957
+ .withValueStep(0.5).withUnit('°C').withDescription('Temperature setpoint automatic'),
958
+ exposes.climate().withSetpoint('current_heating_setpoint', 0.5, 29.5, 0.5, ea.STATE_SET)
959
+ .withLocalTemperature(ea.STATE).withLocalTemperatureCalibration(-12.5, 5.5, 0.1, ea.STATE_SET)
960
+ .withSystemMode(['off', 'heat', 'auto'], ea.STATE_SET)
961
+ .withPreset(['schedule', 'manual', 'holiday', 'boost']),
962
+ exposes.numeric('detectwindow_temperature', ea.STATE_SET).withUnit('°C').withDescription('Open window detection temperature')
963
+ .withValueMin(-10).withValueMax(35),
964
+ exposes.numeric('detectwindow_timeminute', ea.STATE_SET).withUnit('min').withDescription('Open window time in minute')
965
+ .withValueMin(0).withValueMax(1000),
966
+ exposes.binary('binary_one', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown binary one'),
967
+ exposes.binary('binary_two', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown binary two'),
968
+ exposes.binary('away_mode', ea.STATE, 'ON', 'OFF').withDescription('Away mode'),
969
+ exposes.composite('away_setting', 'away_setting', ea.STATE_SET)
970
+ .withFeature(e.away_preset_days()).setAccess('away_preset_days', ea.ALL)
971
+ .withFeature(e.away_preset_temperature()).setAccess('away_preset_temperature', ea.ALL)
972
+ .withFeature(exposes.numeric('away_preset_year', ea.ALL).withUnit('year').withDescription('Start away year 20xx'))
973
+ .withFeature(exposes.numeric('away_preset_month', ea.ALL).withUnit('month').withDescription('Start away month'))
974
+ .withFeature(exposes.numeric('away_preset_day', ea.ALL).withUnit('day').withDescription('Start away day'))
975
+ .withFeature(exposes.numeric('away_preset_hour', ea.ALL).withUnit('hour').withDescription('Start away hours'))
976
+ .withFeature(exposes.numeric('away_preset_minute', ea.ALL).withUnit('min').withDescription('Start away minutes')),
977
+ ...['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].map((day) => {
978
+ const expose = exposes.composite(day, day, ea.STATE_SET);
979
+ [1, 2, 3, 4, 5, 6, 7, 8, 9].forEach((i) => {
980
+ expose.withFeature(exposes.numeric(`${day}_temp_${i}`, ea.ALL).withValueMin(0.5)
981
+ .withValueMax(29.5).withValueStep(0.5).withUnit('°C').withDescription(`Temperature ${i}`));
982
+ expose.withFeature(exposes.enum(`${day}_hour_${i}`, ea.STATE_SET,
983
+ ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
984
+ '10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
985
+ '20', '21', '22', '23', '24']).withDescription(`Hour TO for temp ${i}`));
986
+ expose.withFeature(exposes.enum(`${day}_minute_${i}`, ea.STATE_SET, ['00', '15', '30', '45'])
987
+ .withDescription(`Minute TO for temp ${i}`));
988
+ });
989
+ return expose;
990
+ }),
991
+ ],
992
+ },
993
+ {
994
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_taspddvq'}],
995
+ model: 'HG08383A',
996
+ vendor: 'Lidl',
997
+ description: 'Livarno outdoor LED light chain',
998
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
999
+ },
1000
+ ];