-
Notifications
You must be signed in to change notification settings - Fork 1
/
radio_thermostat_zwave.groovy
1602 lines (1385 loc) · 73.2 KB
/
radio_thermostat_zwave.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* Radio Thermostat Zwave Hubitat driver
Hubitat driver for radio thermostat
Hubitat driver for Iris CT101 Thermostat
Radio Thermostat Company of America (RTC)
Building a better thermostat driver that just works.....
brand: Radio Thermostat
manufacturer: 152
model: CT30,CT32,CT50,CT80,CT100,CT101,CT110,CT200
Supports
poll chron, time set chron,humidity,heat or cool only,C-wire,Diff,Mans detection
Google Home
C/F notice your hub must match your thermostats settings no conversion is done.
Go to Hub Settings set C/F then go to thermostat and set C/F to match
______ _ _ _____ _ _ _
| ___ \ | (_) |_ _| | | | | |
| |_/ /__ _ __| |_ ___ | | | |__ ___ _ __ _ __ ___ ___ ___| |_ __ _| |_
| // _` |/ _` | |/ _ \ | | | '_ \ / _ \ '__| '_ ` _ \ / _ \/ __| __/ _` | __|
| |\ \ (_| | (_| | | (_) | | | | | | | __/ | | | | | | | (_) \__ \ || (_| | |_
\_| \_\__,_|\__,_|_|\___/ \_/ |_| |_|\___|_| |_| |_| |_|\___/|___/\__\__,_|\__|
No battery is needed on these thrmostats if using C Wire. The driver will restore settings on reboot.
Unneeded batteries cost money so you can stop using them. Set driver to ignore battery
Polling chron ends the need to use rouines to refreash the thermostat as some models just dont report
temp and setpoints to the hub unless polled.
Versions of the same model act diffrently depending on firmware. Some ct101 report some dont.
Heating Colling only supports using the thermostat only for heaters or ac units. Prevents the blocked mode
commans and removes blocked modes from the options in scripts.
Driver was written to fix the many problems with internal drivers not supporting fully the ct101
and the ct30 thermostats. The thermostats have bugs that need special programming.
Tested on....
USNAP Module RTZW-01 n
fingerprint mfr:0098 prod:6501 model:000C ct101 Iris version
fingerprint mfr:0098 prod:1E12 model:015C ct30e rev v1 C-wire report
If you have version that identifies as UNKNOWN please send me your fingerprint and the version on the thermostat.
If your version has a version # that doesnt match the fingerprints bellow please send me your fingerprint and version.
If any of the settings dont work on your thermostat please let me know.
CT30e [0098-0001-001E] USNAP Module RTZW-01 (tested) protocolVersion: 2.78 applicationVersion: 5.0
Has defective firmware
Displays REMOTE CONTROL box when paired.
False operating states. Claims its running all the time
never reports idle unless in OFF mode. Causes dashboard color to stay red or blue.
Doesnt support modes other CT30s do. Wont reply to bat request.
May report energySaveHeat:true, energySaveCool: true Then report False.
Firmware fix for ct30 ct32 units that dont report states corectaly
ZWAVE SPECIFIC_TYPE_THERMOSTAT_GENERAL_V2
===================================================================================================
v5.7.9 03/26/2023 New firmware version ident routine. Fix bad firmware dec order
v5.7.8 03/24/2023 Bug fix in scale in setpoint. Last update broke it
v5.7.7 03/24/2023 Bug in scale detection causing errors in the log
v5.7.6 03/17/2023 CT30 was corrupting modes. Mode setup rewritten with bug checking
v5.7.5 03/13/2023 get rid of nulls in database fields
v5.7.4 03/13/2023 error detection for c/f mismatch
v5.7.3 03/10/2023 Rewrote C/F routines.
v5.7.2 02/19/2023 Simulated ct30 state dupes removed.Better log. Event codes reordered
Google Home support added
Error checking to stop google from sending dec .5 values.
v5.7.1 02/18/2023 New simulated fan and operating states for CT30/CT32 units with bad firmware.
v5.7.0 02/16/2023 minor cleanup/logging changes. CT110 fingerprint added. 2 Stage Diff reporting fixed
New testing for supported functions. Non supported functions now hidden and never sent.
v5.6.9 02/11/2023 Fan Operating State now simulated when not sent from therm. Minor changes to improve reporting
v5.6.8 02/10/2023 Total Rewrite of MODE code and tracing logging, Last update broke things, fixed
v5.6.7 02/07/2023 Extra trace logging for sent commands
v5.6.6 02/06/2023 BUG FIX setpoints now wait for therm to report back before setting. Delays changed
v5.6.5 02/05/2023 2-stage diff reports not working, Config changes,Dashboard improvements
v5.6.4 12/26/2022 Bug fix supportedFanModes. Thermostat modes fix
v5.6.0 12/26/2022 Upgrade thermostat modes with double quotes to comply with new firmware 2.3.4.123 change
v5.5.6 12/14/2022 Ignore bat option for mains only. No bat is actualy needed
v5.5.5 12/05/2022 ManufacturerSpecificReport parsing added
v5.5.4 11/23/2022 Bug fix in recovery error counter getting reset/Bug in heat reset was resetting cool
v5.5.3 11/18/2022 extra polling times added
v5.5.2 11/12/2022 Logging module update. Autofix installed
v5.5.1 10/20/2022 Null on line 401. Error checking added/ Swing and DIff auto saved
v5.5.0 10/15/2022 Null detection added in event 11
v5.4.2 10/10/2022 Split info logs
v5.4.1 09/28/2022 Loging for chron human form
v5.4 09/19/2022 Rewrote logging routines.
v5.3.5 08/17/2022 Bug fix Last update broke the clock fixed
v5.3.4 08/16/2022 Added Recovery mode
v5.3.1 08/15/2022 Added Swing
v5.3 08/14/2022 Added 2 stage differential
v5.2.7 08/11/2022 Bug fixes. to many to list
v5.2 08/07/2022 mode bug fixed
v5.1 08/05/2022 Changes to manufacturerSpecificGet. Heat or Cool Only working
v4.8 08/04/2022 First major release out of beta working code.
v3.3 07/30/2022 Improvements and debuging code.
v3.1 07/30/2022 Total rewrite of event storage and Parsing.
v3.0 07/29/2022 Release - Major fixes and log conversion
----- Missing numbers are beta working local versions never released.
===================================================================================================
Notes
Paring. Bring hub to thermostat or thermostat to hub connect 24 volts AC between C and RC. (AC ONLY).
Be sure you get paired in c-wire mode.
CT101 will work in battery mode or c-wire mode. However I havent done much testing in battery mode.
Models with the Radio Thermostat Z-Wave USNAP Module RTZW-01 Require C-Wire or they will go to sleep
never to rewake. Some will take commands in sleep some wont. c-wire is required.
Do not even atempt to use battery mode.
Some models report C-Wire status some dont. Some models report Diff some take the command but report back 6
There are many diffrent versions of the ct30 some with bad firmware and some that dont support all commands.
======================================================================================================
Copyright [2022] [tmaster winnfreenet.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=======================================================================================================
Contains a lot of orginal code created by me
and some code from these drivers
None of these drivers work right on radio Thermostat they all have problems.
Orginal smartthings driver:
https://github.com/SmartThingsCommunity/SmartThingsPublic/blob/master/devicetypes/smartthings/ct100-thermostat.src/ct100-thermostat.groovy
These are all forks from the above.
https://github.com/MarioHudds/hubitat/blob/master/Enhanced%20Z-Wave%20Thermostat
https://community.hubitat.com/t/port-enhanced-z-wave-thermostat-ct-100-w-humidity-and-time-update/4743
https://github.com/motley74/SmartThingsPublic/blob/master/devicetypes/motley74/ct100-thermostat-custom.src/ct100-thermostat-custom.groovy
some google home code comes from
https://raw.githubusercontent.com/Botched1/Hubitat/master/Drivers/Vivint%20CT-200/vivint_ct200.groovy
May use some open source code from sources listed here.
https://raw.githubusercontent.com/tmastersmart/hubitat-code/main/opensource_links.txt
*/
def clientVersion() {
TheVersion="5.7.9"
if (state.version != TheVersion){
logging("Upgrading ! ${state.version} to ${TheVersion}", "warn")
state.version = TheVersion
runIn(10,configure)// Forces config on updates
}
}
metadata {
definition (name: "Radio Thermostat Zwave", namespace: "tmastersmart", author: "tmaster", importUrl: "https://raw.githubusercontent.com/tmastersmart/hubitat-code/main/radio_thermostat_zwave.groovy") {
capability "Actuator"
capability "Configuration"
capability "Polling"
capability "Sensor"
capability "Refresh"
capability "Battery"
capability "PowerSource"
capability "Thermostat"
capability "TemperatureMeasurement"
capability "ThermostatMode"
capability "ThermostatFanMode"
capability "ThermostatSetpoint"
capability "ThermostatCoolingSetpoint"
capability "ThermostatHeatingSetpoint"
capability "ThermostatOperatingState"
capability "RelativeHumidityMeasurement"
capability "HealthCheck"
attribute "thermostatFanState", "string"
attribute "SetClock", "string"
attribute "SetCool", "string"
attribute "SetHeat", "string"
attribute "temperatureSwing", "string"
attribute "recovery", "string"
attribute "recoveryTempDiffHeat", "string"
attribute "recoveryTempDiffCool", "string"
command "setDiff"
command "setSwing"
command "unschedule"
command "uninstall"
command "setClock"
command "setRecovery"
// command "saveSettings"
fingerprint deviceId: "0x08"
fingerprint inClusters: "0x43,0x40,0x44,0x31"
fingerprint inClusters: "0x20,0x87,0x72,0x31,0x40,0x42,0x44,0x43,0x86"// * ct-30e Z-Wave USNAP Module RTZW-01
fingerprint inClusters: "0x20,0x87,0x72,0x31,0x40,0x44,0x43,0x42,0x86,0x70,0x80,0x88" // * ct-30 private lable alarm
fingerprint inClusters: "0x20,0x81,0x87,0x72,0x31,0x40,0x44,0x43,0x42,0x86,0x70,0x80,0x88" //* ct-30e rev v1 Z-Wave USNAP Module RTZW-01
fingerprint inClusters: "0x20,0x81,0x87,0x72,0x31,0x40,0x42,0x44,0x45,0x43,0x86,0x70,0x80,0x85,0x60" // ct-100 & (ct-101 iris)
fingerprint inClusters: "0x20,0x81,0x87,0x72,0x31,0x40,0x42,0x44,0x45,0x43,0x86,0x70,0x80,0x85,0x5D,0x60"// ct-101
// hubitat ignores deviceJoinName only included for ref notes
// https://www.opensmarthouse.org/zwavedatabase/94
fingerprint type:"0806", mfr:"0098", prod:"1E10", model:"0158",manufacturer: "Radio Thermostat", deviceJoinName:"CT-30 Radio Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"0000", model:"0000",manufacturer: "Radio Thermostat", deviceJoinName:"CT-30 Radio Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"1E12", model:"015C",manufacturer: "Radio Thermostat", deviceJoinName:"CT-30e Radio Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"1E12", model:"015E",manufacturer: "Radio Thermostat", deviceJoinName:"CT-30 v1 Radio Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"0001", model:"001E",manufacturer: "Radio Thermostat", deviceJoinName:"CT-30e Radio Thermostat" //https://products.z-wavealliance.org/products/158?selectedFrequencyId=2
fingerprint type:"0806", mfr:"0098", prod:"0001", model:"0000",manufacturer: "Radio Thermostat", deviceJoinName:"CT-30 Z-Wave Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"0001", model:"00FF",manufacturer: "Radio Thermostat", deviceJoinName:"CT-30 Z-Wave Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"0001", model:"00FF",manufacturer: "Radio Thermostat", deviceJoinName:"CT-30 Z-Wave Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"2002", model:"0100",manufacturer: "Radio Thermostat", deviceJoinName:"CT-32 Z-Wave Thermostat" //https://products.z-wavealliance.org/products/1330?selectedFrequencyId=2 https://products.z-wavealliance.org/products/1046?selectedFrequencyId=2
fingerprint type:"0806", mfr:"0098", prod:"0002", model:"0100",manufacturer: "Radio Thermostat", deviceJoinName:"CT-32 Z-Wave Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"2002", model:"0102",manufacturer: "Radio Thermostat", deviceJoinName:"CT-32 Z-Wave Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"3200", model:"015E",manufacturer: "Radio Thermostat", deviceJoinName:"CT-50 Filtrete 3M-50 Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"5003", model:"0109",manufacturer: "Radio Thermostat", deviceJoinName:"CT-80 Radio Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"5003", model:"01FD",manufacturer: "Radio Thermostat", deviceJoinName:"CT-80 Radio Thermostat"
// There are 4 diffrent versions 8.4,8.7,9,9.1
fingerprint type:"0806", mfr:"0098", prod:"6401", model:"0015",manufacturer: "Radio Thermostat", deviceJoinName:"CT-100 v8.7 Radio Thermostat"// https://products.z-wavealliance.org/products/646?selectedFrequencyId=2
fingerprint type:"0806", mfr:"0098", prod:"6401", model:"0107",manufacturer: "Radio Thermostat", deviceJoinName:"CT-100 Radio Thermostat"//also 2gig
fingerprint type:"0806", mfr:"0098", prod:"6401", model:"0106",manufacturer: "Radio Thermostat", deviceJoinName:"CT-100 v9.1 Vivint Thermostat"// https://products.z-wavealliance.org/products/795?selectedFrequencyId=2
fingerprint type:"0806", mfr:"0098", prod:"6402", model:"0100",manufacturer: "Radio Thermostat", deviceJoinName:"CT-100 Plus Radio Thermostat"//https://products.z-wavealliance.org/products/1798?selectedFrequencyId=2
// https://www.opensmarthouse.org/zwavedatabase/98
fingerprint type:"0806", mfr:"0098", prod:"6501", model:"00FD",manufacturer: "Radio Thermostat", deviceJoinName:"CT-101 Radio Thermostat"//https://products.z-wavealliance.org/products/1301?selectedFrequencyId=2
fingerprint type:"0806", mfr:"0098", prod:"6501", model:"000B",manufacturer: "Radio Thermostat", deviceJoinName:"CT-101 Lowes Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"6501", model:"000C",manufacturer: "Radio Thermostat", deviceJoinName:"CT-101 Iris Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"6E01", model:"0000",manufacturer: "Radio Thermostat", deviceJoinName:"CT-110 Thermostat" //https://products.z-wavealliance.org/products/1333
fingerprint type:"0806", mfr:"0098", prod:"C801", model:"001D",manufacturer: "Radio Thermostat", deviceJoinName:"CT-200 Vivint Element Thermostat"
fingerprint type:"0806", mfr:"0098", prod:"C801", model:"0022",manufacturer: "Radio Thermostat", deviceJoinName:"CT-200X Vivint Element Thermostat"
// 6402:0100
// Tested on....
// fingerprint mfr:0098 prod:6501 model:000C ct101 Iris versio-Wave USNAP Module RTZW-01 n
// fingerprint mfr:0098 prod:1E12 model:015C ct30e rev v1 C-wire report
// fingerprint mfr:0098 prod:0001 model:001E ct30e Displays REMOTE CONTROL box when paired - No c-wire report
}
}
preferences {
updateParameters()
input name: "infoLogging", type: "bool", title: "Enable info logging", description: "Recomended info level" ,defaultValue: true,required: true
input name: "info2Logging", type: "bool", title: "Enable info Extra logging", description: "Recomended info2 level. Full info level." ,defaultValue: true,required: true
input name: "debugLogging", type: "bool", title: "Enable debug logging", description: "Programming Debug logs" ,defaultValue: false,required: true
input name: "traceLogging", type: "bool", title: "Enable trace logging", description: "Insane HIGH level", defaultValue: false,required: true
if (state.parameter[8]){
input( "heatDiff", "number", title: "2 Stage Heat differential", description: "Only for 2 stage ElectHeat or HeatPumps. 2nd stage engages when x above setpoint.(2 to 6)", defaultValue: 2,required: true)
input( "coolDiff", "number", title: "2 Stage Cool differential", description: "Only for 2 stage HeatPumps. (ignore if not using)(2 to 6)", defaultValue: 2,required: true)
}
if (state.parameter[7]){
input( "swing", "enum", title: "Temperature Swing", description: "Number of degrees above (for cooling) and below (for heating) the temp will fluctuate before cycling back on.", options: ["0.5","1.0","1.5","2.0","2.5","3.0","3.5","4.0"], defaultValue: "1.0", multiple: false, required: true)
}
if (state.parameter[9]){
input name: "recovery", type: "enum", title: "Recovery mode", description: "Fast or economy. ", options: ["fast", "economy"], defaultValue: "economy",required: true
}
input name: "onlyMode", type: "enum", title: "Mode Bypass", description: "Heat or Cool only mode", options: ["off", "heatonly","coolonly"], defaultValue: "off",required: true
input( "polling", "enum", title: "Polling minutes", description: "Polling Chron. Press Config after changing ", options: ["5","10","15","20","25","30","35","40","45","50","55",],defaultValue: 15,required: true)
input name: "autocorrect", type: "bool", title: "Auto Correct setpoints", description: "Keep thermostat settings matching hub (this will overide local changes)", defaultValue: false,required: true
input( "autocorrectNum", "number", title: "Auto Correct errors", description: "send auto corect after number of errors detected. ", defaultValue: 5,required: true)
if (state.parameter[19]){
input name: "FirmwareFix", type: "bool", title: "Simulate States", description: "Bad Firmware Fix. Simulates fan and operating states. Fixes dashboard staying red or blue when not running.", defaultValue: false,required: false
}
input name: "ignorebat", type: "bool", title: "Ignore Bat reports", description: "If no batteries inserted. Batteries are not needed if main powered.", defaultValue: false,required: true
}
def installed(){
logging("Radio Thermostat Paired!", "info")
cleanState()
configure()
}
// Runs on reboot
def initialize(){
logging("Radio Thermostat Initialize ", "debug")
randomSixty = Math.abs(new Random().nextInt() % 180)
runIn(randomSixty,refresh)
}
void cleanState(){
state.remove("paypal")
state.remove("pendingRefresh")
state.remove("precision")
state.remove("scale")
state.remove("size")
state.remove("version")
state.remove("supportedFanModes")
state.remove("supportedModes")
state.remove("lastbatt")
state.remove("LastTimeSet")
state.remove("lastTriedMode")
state.remove("lastTriedFanMode")
state.remove("lastClockSet")
state.remove("lastBattery")
state.remove("lastMode")
state.remove("lastBatteryGet")
state.remove("lastOpState")
state.remove("initialized")
state.remove("configUpdated")
state.remove("model")
state.remove("icon")
state.remove("donate")
state.remove("fingerprint")
state.remove("model")
state.remove("setCool")
state.remove("setHeat")
state.remove("cwire")
state.remove("error")
// no longer used
state.remove("lastClockSet")
state.remove("supportedFanModes")
state.remove("supportedModes")
state.remove("lastBatteryGet")
removeDataValue("thermostatSetpoint")
removeDataValue("SetCool")
removeDataValue("coolingSetpoint")
removeDataValue("SetHeat")
removeDataValue("supportedFanModes")
// Clear crap from other drivers
updateDataValue("hardwareVersion", "")
updateDataValue("protocolVersion", "")
updateDataValue("lastRunningMode", "")
updateDataValue("zwNNUR", "")
logging("Garbage Collection.", "info")
}
def uninstall() {
unschedule()
cleanState()
logging("Uninstalled", "info")
}
def configure() {
unschedule()
getIcons()
setClock()
updateParameters()
logging("Configure Driver v${state.version}", "info")
fanAuto() // set default
updated()
state.cwire =0
state.remove("lastBatteryGet")
logging("Sending >> configurationSet (parameterNumber: 4, size: 1, configurationValue: [2])", "trace")
logging("Sending >> configurationGet (4,7,8,9 = cwire,swing,diff,recovery) NodeID:${zwaveHubNodeId}", "trace")
logging("Sending >> get request (man,mode,FanMode) ", "trace")
delayBetween([
zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:1).format(), // get reports without polling
zwave.manufacturerSpecificV2.manufacturerSpecificGet().format(),// fingerprint
zwave.versionV1.versionGet().format(),
zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format(),
zwave.configurationV2.configurationSet(parameterNumber: 4, size: 1, configurationValue: [2]).format(), // cwire enabled
zwave.configurationV2.configurationGet(parameterNumber: 4).format(), // is cwire 1=true 2=false
zwave.configurationV2.configurationGet(parameterNumber: 7).format(), // swing
zwave.configurationV2.configurationGet(parameterNumber: 8).format(), // is diff
zwave.configurationV2.configurationGet(parameterNumber: 9).format(), // is fast recovery on ? 1on 0 off
], 3500)
}
def updated() {
updateParameters()
if (!polling){polling=15} // Poll the device every x min
// options: ["10","15","20","30","40","50"]
int checkEveryMinutes = Integer.parseInt(polling)
randomSixty = Math.abs(new Random().nextInt() % 60)
schedule("${randomSixty} 0/${checkEveryMinutes} * * * ? *", poll)
schedule("${randomSixty} 0 12 * * ? *", setTheClock)
logging("Setting Chron Poll: every ${checkEveryMinutes}mins Clock: 12:${randomSixty}", "info")
loggingUpdate()
logging("Sending >> get request (mode,temp,state) ", "trace")
saveSettings()
delayBetween([
zwave.thermostatModeV2.thermostatModeGet().format(),// get mode
zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format(),// get state
zwave.sensorMultilevelV3.sensorMultilevelGet().format(), // current temperature
zwave.batteryV1.batteryGet().format()
], 3500)
}
def ping() {
logging("Ping", "info")
logging("Sending >> get request (mode,temp,state) ", "trace")
updateParameters()
delayBetween([
zwave.thermostatModeV2.thermostatModeGet().format(),// get mode
zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format(),// get state
zwave.sensorMultilevelV3.sensorMultilevelGet().format(), // current temperature
zwave.batteryV1.batteryGet().format()
], 3500)
}
def pollDevice() {
logging("pollDevice", "info")
poll()
}
def refresh() {
logging("refresh", "info")
poll()
}
def poll() {
updateParameters()
def nowCal = Calendar.getInstance(location.timeZone)
Timecheck = "${nowCal.getTime().format("EEE MMM dd", location.timeZone)}"
logging("Poll E=Event# ${Timecheck} v${state.version}", "info")
//zwave.sensorMultilevelV5.sensorMultilevelGet().format(), // testing
//zwave.batteryV1.batteryGet().format(),
//zwave.commands.versionv2.VersionReport
//zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
//zwave.manufacturerSpecificV2.manufacturerSpecificGet().format(),
logging("Sending >> get request (temp,Hum,Setpoint 1&2,mode,FanMode,state,battery) ", "trace")
logging("Sending >> configurationGet (4,7,8,9 = cwire,swing,diff,recovery", "trace")
delayBetween([
zwave.sensorMultilevelV3.sensorMultilevelGet().format(),// current temperature
zwave.multiInstanceV1.multiInstanceCmdEncap(instance: 2).encapsulate(zwave.sensorMultilevelV2.sensorMultilevelGet()).format(), // CT-100/101 Humidity
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format(),
zwave.thermostatModeV2.thermostatModeGet().format(),
zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format(),
zwave.thermostatFanModeV3.thermostatFanModeGet().format(),
zwave.configurationV2.configurationGet(parameterNumber: 1).format(),// get Temperature Reporting Threshold
zwave.configurationV2.configurationGet(parameterNumber: 2).format(), // HVAC Settings
zwave.configurationV2.configurationGet(parameterNumber: 4).format(),// get cwire
zwave.configurationV2.configurationGet(parameterNumber: 5).format(), // Humidity Reporting Threshold
zwave.configurationV2.configurationGet(parameterNumber: 6).format(),// get emergency aux
zwave.configurationV2.configurationGet(parameterNumber: 7).format(),// temp swing
zwave.configurationV2.configurationGet(parameterNumber: 8).format(),// is temp diff
zwave.configurationV2.configurationGet(parameterNumber: 9).format(),// is fast recovery
zwave.batteryV1.batteryGet().format()
// zwave.configurationV2.configurationGet(parameterNumber: 11).format(),// Get UI mode
], 3500)// delay increased to allow therm to respond.
// zwave.configurationV2.configurationGet(parameterNumber: 10).format(),// reports data what is it
// These are documented
// zwave.configurationV2.configurationGet(parameterNumber: 3).format(), // Utility Lock
// zwave.configurationV2.configurationGet(parameterNumber: 11).format(),// get UI mode
// zwave.configurationV2.configurationSet(parameterNumber: 11, size: 1, configurationValue: 1) // simple UI enabled 1 on 2 off
// zwave.configurationV1.configurationSet(scaledConfigurationValue: value, parameterNumber: 15, size: 1), //fan timmer CT200
// zwave.configurationV1.configurationSet(scaledConfigurationValue: value, parameterNumber: 17, size: 1), //sensor cal CT200
// zwave.configurationV1.configurationSet(parameterNumber: 18, size: 1, scaledConfigurationValue: paramValue)// display units
}
def updateParameters(){// set the info line
text =""
// build the database
if(!state.parameter) {state.parameter=[]}
if(!state.parameter[1]) {state.parameter[1]=0}
if(!state.parameter[2]) {state.parameter[2]=0}
if(!state.parameter[3]) {state.parameter[3]=0}
if(!state.parameter[4]) {state.parameter[4]=0}
if(!state.parameter[5]) {state.parameter[5]=0}
if(!state.parameter[6]) {state.parameter[6]=0}
if(!state.parameter[7]) {state.parameter[7]=0}
if(!state.parameter[8]) {state.parameter[8]=0}
if(!state.parameter[7]) {state.parameter[7]=0}
if(!state.parameter[8]) {state.parameter[8]=0}
if(!state.parameter[9]) {state.parameter[9]=0}
if(!state.parameter[10]) {state.parameter[10]=0}
if(!state.parameter[11]) {state.parameter[11]=0}
if(!state.parameter[12]) {state.parameter[12]=0}
if(!state.parameter[13]) {state.parameter[13]=0}
if(!state.parameter[14]) {state.parameter[14]=0}
if(!state.parameter[15]) {state.parameter[15]=0}
if(!state.parameter[16]) {state.parameter[16]=0}
if(!state.parameter[17]) {state.parameter[17]=0}
if(!state.parameter[18]) {state.parameter[18]=0}
if(!state.parameter[19]) {state.parameter[19]=0}
// build the info line from the database
if (state.parameter[1]){text +="TempReportThreshold,"}
if (state.parameter[2]){text +="HVAC,"}
if (state.parameter[3]){text +="Lock,"}
if (state.parameter[4]){text +="CWIRE,"}
if (state.parameter[5]){text +="HumReportThreshold,"}
if (state.parameter[6]){text +="AuxHeat,"}
if (state.parameter[7]){text +="Swing,"}
if (state.parameter[8]){text +="Diff,"}
if (state.parameter[9]){text +="Recovery,"}
// if (state.parameter[10]){text +="unknown,"}
if (state.parameter[11]){text +="UI,"}
if (state.parameter[12]){text +="Temp,"}
if (state.parameter[13]){text +="Hum,"}
if (state.parameter[14]){text +="Battery,"}
if (state.parameter[15]){text +="Clock,"}
if (state.parameter[16]){text +="FanState,"}
if (state.parameter[17]){text +="energySaveHeat,"}
if (state.parameter[18]){text +="energySaveCool"}
if (state.parameter[19]){text +="Firmwarefix"}
state.info ="Supported Parameters: ${text}"
}
def parse(String description)
{
// 0x20:1
// 0x31:3 Sensor Multilevel <--
// 0x40:2 Mode
// 0x42:1 Operating State <--
// 0x43:2 Setpoint <--
// 0x44:3 Fan Mode <--
// 0x45:1 Fan State
// 0x59:1
// 0x5A:1
// 0x5D:1
// 0x5E:2
// 0x60:3 Multi channel
// 0x70:2 Config
// 0x72:2 Manufacturer Specific
// 0x80:1 Battery
// 0x81:1 Clock
// 0x85:1 Association
// 0x86:1 Version
// 0x87:1 Indicator
// 0x8F:3
// 0x98:1 Security
clientVersion()
CommandClassCapabilities = [0x31:3,0x40:2,0x42:1,0x43:2,0x44:3,0x45:1,0x60:3,0x70:2,0x72:2,0x80:1,0x81:1,0x85:1,0x86:1,0x87:1,0x98:1]
hubitat.zwave.Command map = zwave.parse(description, CommandClassCapabilities)
if (!map) {
logging("Unable to Parse ${description}", "error")
return
}
def result = [map]
logging("Raw:${description}", "trace")
logging("Parse ${map}", "debug")
zwaveEvent(map)
}
// Event Generation
// event E1
// Termostat setpoints -------------------------------------------------------
def zwaveEvent(hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointReport cmd)
{
if (!cmd){
logging("E1 Received NULL", "warn")
return
}
logging("E1 Received ${cmd}", "debug")
state.scale = cmd.scale // Device scale
if (cmd.scale == 1){scale="F"}
else {scale="C"}
logging("E1 Received setpointType:${cmd.setpointType} Value:${cmd.scaledValue} Precision:${cmd.precision} Scale:${scale} /${cmd.scale} ","trace")
// def cmdScale = cmd.scale == 1 ? "F" : "C"
// map.value = convertTemperatureIfNeeded(cmd.scaledValue, cmdScale, cmd.precision)
// map.unit = getTemperatureScale()
switch (cmd.setpointType) {
case 1:
name = "heatingSetpoint"
tempCheck = state.SetHeat
break;
case 2:
if(heatonly == true){return}
name = "coolingSetpoint"
tempCheck = state.SetCool
break;
default:
logging("error Unknown SetpointType:${cmd.setpointType}", "warn")
return [:]
}
logging("E1 ${name} ${cmd.scaledValue} ${scale}", "info")
sendEvent(name: name , value: cmd.scaledValue ,unit: scale,descriptionText:"${name} ${cmd.scaledValue} ${scale} ${state.version}", isStateChange:true)
tempCheck2 = cmd.scaledValue.toDouble()
if(tempCheck){ // needed in case of no last setpoints set
if(tempCheck == tempCheck2){
logging("E1 ${name} Set Points Match Last:${tempCheck}=Current:${tempCheck2}", "debug") //moved to debug
//state.error = 0
}
if(tempCheck != tempCheck2 & autocorrect == true){
if(!state.error){state.error=0}
state.error = state.error + 1
logging("E1 ${map.name} Last Point does not match Last:${tempCheck}<>Current:${tempCheck2} error:${state.error} fixOn:${autocorrectNum}", "warn")
if (state.error >= autocorrectNum ){
runIn(1,FixHeat)
runIn(5,FixCool)
logging("Resetting cool:${state.SetCool}/Heat:${state.SetHeat}", "info")
state.error = 0
}
}
}// end if not null
// set the current setpoint
OpeTest = device.currentValue("thermostatOperatingState")
modeTest = device.currentValue("thermostatMode")
setpoint = 0
if (OpeTest == "heating" || modeTest =="heat" || modeTest=="emergency heat") {setpoint= state.SetHeat}
if (OpeTest == "cooling" || modeTest =="cool") {setpoint= state.SetCool}
if (setpoint!=0){
updateDataValue("thermostatSetpoint", setpoint.toString())
logging("E1.1 Update thermostatSetpoint:${setpoint} for Google Home", "debug")
sendEvent([name: "thermostatSetpoint", value: setpoint, unit: scale, descriptionText:"thermostatSetpoint ${setpoint} ${scale}${state.version}",isStateChange:true])
}
// stored so we can use on send
state.size = cmd.size
state.scale = cmd.scale
state.precision = cmd.precision
if (FirmwareFix){ct30OperatingFix()}
}
// E2
def zwaveEvent(hubitat.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
{
logging("E2 Received sensorMultilevelv2", "debug")
logging("E2 Received sensorType:${cmd.sensorType} scaledSensorValue:${cmd.scaledSensorValue} scale:${cmd.scale}","trace")
if (cmd.sensorType == 0) {return } // ct30 (fixed in rev1)
if (cmd.sensorType == 1) {
if (cmd.scale == 1){scale="F"}
else {scale="C"}
state.scale = cmd.scale
logging("E2 Device Scale is ${scale}/${state.scale}", "info2")
value = cmd.scaledSensorValue
name = "temperature"
state.parameter[12]=1
logging("E2 ${name} ${value} ${scale}", "info")
sendEvent(name:name ,value:value ,unit: scale, descriptionText:"${name} ${value} ${scale} ${state.version}", isStateChange: true)
return
} else if (cmd.sensorType == 5) {
value = cmd.scaledSensorValue
unit = "%"
name = "humidity"
state.parameter[13]=1
logging("E2 ${name} ${value} ${unit}", "info")
sendEvent(name:name ,value:value ,unit: unit, descriptionText:"${name} ${value} ${unit} ${state.version}", isStateChange: true)
return
}
logging("E2 Unknown data ${cmd}", "warn")
if (FirmwareFix){ct30OperatingFix()}
}
// E3
def zwaveEvent(hubitat.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport cmd)
{
logging("E3 Received Operating State ${cmd.operatingState}", "debug")
if (FirmwareFix){
ct30OperatingFix()
return
}
value = "idle"
switch (cmd.operatingState) {
case hubitat.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_IDLE:
value = "idle"
break
case hubitat.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_HEATING:
value = "heating"
break
case hubitat.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_COOLING:
value = "cooling"
break
case hubitat.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_FAN_ONLY:
value = "fan only"
break
case hubitat.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_HEAT:
value = "pending heat"
break
case hubitat.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_COOL:
value = "pending cool"
break
case hubitat.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_VENT_ECONOMIZER:
value = "vent economizer"
break
}
logging("E3 Operating State - ${value} ", "info2")
sendEvent(name: "thermostatOperatingState", value: value,descriptionText: "Operating State ${value} ${state.version}", isStateChange:true)
GoogleHome()
fanStateFix()
}
// Google Home support.
private GoogleHome(){
OpeTest = device.currentValue("thermostatOperatingState")
value="idle"
name ="lastRunningMode"
if (state.scale == 1){scale="F"}
else {scale="C"}
if (OpeTest == "heating") { value="heat" }
if (OpeTest == "cooling") { value="cool" }
if (value !="idle"){
updateDataValue("lastRunningMode", value)
sendEvent(name:name ,value:value ,unit: scale, descriptionText:"${name} ${value} ${scale} ${state.version}", isStateChange: true)
logging("E3.2 Update LastRunningMode:${value} for Google Home", "debug")
}
}
// --------------simulate fan state for ct sending bad data--------------------
private fanStateFix(){
fanTest = device.currentValue("thermostatFanMode")
fanSTest = device.currentValue("thermostatFanState")
OpeTest = device.currentValue("thermostatOperatingState")
if(fanTest == "fanAuto"){ // fan should follow operating state if in auto
if (OpeTest == "idle"){ value = "idle"}
else {value = "running"}
}
else if (fanTest == "fanOn"){value = "running"}
if (fanSTest == value){return}// all is ok just exit
logging("E4.2 Fan State Simulated: ${value} ", "info2")
sendEvent(name: "thermostatFanState", value: value,descriptionText: "Simulated Fan State ${value} ${state.version}", isStateChange:true)
}
private ct30OperatingFix(){
fanTest = device.currentValue("thermostatFanMode")
fanSTest = device.currentValue("thermostatFanState")
modeTest = device.currentValue("thermostatMode")
tempTest = device.currentValue("temperature")
OpeTest = device.currentValue("thermostatOperatingState")
// set the operating state
value="idle"
if (modeTest =="heat"){
if (tempTest < state.SetHeat){value="heating"}
}
if (modeTest =="cool"){
if (tempTest > state.SetCool){value="cooling"}
}
if(OpeTest != value){
logging("E3.1 Operating State Simulated: ${value} ", "info2")
sendEvent(name: "thermostatOperatingState", value: value,descriptionText: "Simulated Operating State ${value} ${state.version}", isStateChange:true)
GoogleHome()
}
// set the fan operating state
valueF="idle"
if(fanTest == "fanOn" || value == "heating" || value=="cooling"){ valueF="running"}
if ( fanSTest != valueF){
logging("E4.1 Fan State Simulated: ${valueF} ", "info2")
sendEvent(name: "thermostatFanState", valueF: value,descriptionText: "Simulated Fan State ${valueF} ${state.version}", isStateChange:true)
}
logging("E3.1 Syncing Simulated States. fanState:${valueF} OperatingState:${value}", "debug")
}
// Fan State Report
def zwaveEvent(hubitat.zwave.commands.thermostatfanstatev1.ThermostatFanStateReport cmd) {
logging("E4 Received Fan State ${cmd.fanOperatingState}", "debug")
state.parameter[16]=1
if(cmd.fanOperatingState ==0){value = "idle"}
else if(cmd.fanOperatingState ==1){value = "running"}
else if(cmd.fanOperatingState ==2){value = "running high"}
else {
logging("E4 Received Unknown Fan State :${cmd.fanOperatingState} ", "warn")
return
}
logging("E4 Received Fan State :${value} ", "info2")
sendEvent(name: "thermostatFanState", value: value,descriptionText: "Fan State ${value} ${state.version}", isStateChange:true)
}
//off, heat, cool, auto, auxiliaryemergencyHeat, resume, fanOnly, furnace, energySaveHeat, energySaveCool, away
def zwaveEvent(hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport cmd) {
def map = [:]
logging("E5 Received Mode:${cmd.mode}", "debug")
map.name = "thermostatMode"
map.value = "unknown"
switch (cmd.mode) {
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_OFF:
map.value = "off"
break
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_HEAT:
map.value = "heat"
break
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUXILIARY_HEAT:
map.value = "emergency heat"
break
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_COOL:
map.value = "cool"
break
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUTO:
map.value = "auto"
break
}
logging("E5 ${map.name} - ${map.value} ", "info")
sendEvent(name: map.name, value: map.value,descriptionText: "${map.name} ${map.value} ${state.version}", isStateChange:true)
}
// auto, low, autoHigh, high, autoMedium, medium, circulation, humidityCirculation
def zwaveEvent(hubitat.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport cmd) {
def map = [:]
logging("E6 Received FanMode:${cmd.fanMode}", "debug")
map.name = "thermostatFanMode"
map.value = "unknown"
switch (cmd.fanMode) {
case hubitat.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_AUTO_LOW:// =0
map.value = "fanAuto"
break
case hubitat.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_AUTO_HIGH:
map.value = "fanAuto"
break
case hubitat.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_LOW: // =1
map.value = "fanOn"
break
case hubitat.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_HIGH:
map.value = "fanOn"
break
case hubitat.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_CIRCULATION:// Dont thinmk rT supports this
map.value = "fanCirculate"
break
}
logging("E6 ${map.name} - ${map.value} ", "info2")
sendEvent(name: map.name, value: map.value,descriptionText: "${map.name} ${map.value} ${state.version}", isStateChange:true)
fanStateFix()
}
// --------read the MODES from Thermostat ----------
// off:true, heat:true, cool:true, auto:true, auxiliaryemergencyHeat:true, resume:false, fanOnly:false, furnace:false, energySaveHeat:false, energySaveCool: false, away:false
// autoChangeover dryAir moistAir resume
// new firmware update requires quotes ["off", "heat", "cool", "auto", "emergency heat"]
// Bug fix for CT30 bad reports energySaveHeat & energySaveCool then reports it doesnt have them?
// Ignore energySave and treat it as cool heat
def zwaveEvent(hubitat.zwave.commands.thermostatmodev2.ThermostatModeSupportedReport cmd) {
def supportedModes = '"off"'// force off as the first mode
logging("E7 Received ${cmd}", "debug")
if(cmd.energySaveHeat) { state.parameter[17]=1 }
if(cmd.energySaveCool) { state.parameter[18]=1 }
// if(cmd.off) { supportedModes += '"off"' }
if(cmd.heat || cmd.energySaveHeat) { supportedModes += ',"heat"'
if(cmd.auxiliaryemergencyHeat) { supportedModes += ',"emergency heat"' }
}
if(cmd.cool || cmd.energySaveCool) { supportedModes += ',"cool"' }
if(cmd.auto) { supportedModes += ',"auto"' }
if(onlyMode == "coolonly"){supportedModes = '"off","cool"'}// custom setup for AC only
if(onlyMode == "heatonly"){supportedModes = '"off","heat"' // custom setup for HEAT only
if(cmd.auxiliaryemergencyHeat) { supportedModes += ',"emergency heat"' }
}
logging("E7 supportedModes [${supportedModes}]", "info2")
sendEvent(name: "supportedThermostatModes", value: "[${supportedModes}]",descriptionText: "${supportedModes} ${state.version}", isStateChange:true)
}
// auto:true, low: true, autoHigh: false, high: false autoMedium:false, medium:false circulation:false, humidityCirculation:false
def zwaveEvent(hubitat.zwave.commands.thermostatfanmodev3.ThermostatFanModeSupportedReport cmd) {
def supportedFanModes = '' // ["Auto","On"]
logging("E8 Received ${cmd}", "debug")
if(cmd.auto) { supportedFanModes += '"Auto",' }
if(cmd.low) { supportedFanModes += '"On"' }
if(cmd.circulation) { supportedFanModes += ',"Circulate",' } // not used
if(cmd.humidityCirculation){supportedFanModes += "HumCirculate, " } // not used
if(cmd.high) { supportedFanModes += "High," } // not used
logging("E8 supportedFanModes[${supportedFanModes}]", "info2")
sendEvent(name: "supportedThermostatFanModes", value: "[${supportedFanModes}]",descriptionText: "${supportedFanModes} ${state.version}", isStateChange:true)
//supportedThermostatFanModes/
}
// these are untrapped log them...
def zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) {
logging("E9 Received ${cmd}", "debug")
}
def zwaveEvent(hubitat.zwave.commands.configurationv2.ConfigurationReport cmd) {
logging("E10 Received ${cmd}", "debug")
if(!state.parameter){state.parameter=[]}
if (cmd.parameterNumber== 1){//0 to 4 This is not working on my ct101
state.parameter[1]=1
def value = cmd.scaledConfigurationValue
// def test = cmd2Integer(cmd.configurationValue)
if (value <=5 && value >=0){logging("E10-1 Temp Report Threshold ${value}", "info2")}
else {
if (debugLogging){logging("E10-1 ERROR Temp Report Threshold must be 0-4 value:${cmd.configurationValue} Scaled:${cmd.scaledConfigurationValue} Not a valid value", "warn")}
}
return
}
//2 4 HVAC Settings 1 to 2147483647 Byte 1: normal (1) or heat pump (2). Byte 2, Bits 7-4: Gas (1) or Electric (2). Byte 2, Bits 3-0: # of Auxiliary Stages.
// Byte 3: # of Heat Pump Stages. Byte 4: # of Cool Stages. value:[1, 34, 0, 1] Scaled:19005441
else if (cmd.parameterNumber== 2){
state.parameter[2]=1
if(cmd.size == 4){
mode = cmd.configurationValue[0]
gas = cmd.configurationValue[1] // dont yet know how to seperate bits 7-4 and 3-0 need help...(34= electric and 2 stages.)
pump = cmd.configurationValue[2]
cool = cmd.configurationValue[3]
modet="Normal"
gasT=""
if (mode == 2){modet="Heat Pump"}
if (gas == 34){gasT= "2 Stage Electric"}
if (gas == 33){gasT= "Backup Electric"}
logging("E10-2 HVAC Settings mode:${modet} ${gasT} HeatPumpStages:${pump} CoolStages:${cool}", "info2")
}
else {// size 3 is not in the spec but I get 1,1,1 from a ct30
mode = cmd.configurationValue[0]
modet="Normal"
if (mode == 2){modet="Heat Pump"}
logging("E10-2 HVAC Settings mode:${modet}", "info2")
}
logging("E10-2 HVAC Settings value:${cmd.configurationValue} Scaled:${cmd.scaledConfigurationValue}", "debug")
}
// ConfigurationReport(parameterNumber: 4, size: 1, configurationValue: [1], scaledConfigurationValue: 1)
else if (cmd.parameterNumber== 4){
state.parameter[4]=1
// state.cwire = cmd.configurationValue[0]
state.cwire = cmd.scaledConfigurationValue
if (state.cwire == 1){
logging("E10-4 C-Wire :TRUE PowerSouce :mains", "info2")
sendEvent(name: "powerSource", value: "mains",descriptionText: "Power Mains ${state.version}", isStateChange: true)
}
if (state.cwire == 2){
logging("E10-4 C-Wire :FALSE PowerSouce :battery", "info2")
sendEvent(name: "powerSource", value: "battery",descriptionText: "Power Battery ${state.version}", isStateChange: true)
}
}
// Humidity Reporting Threshold 0 to 3 0 = Disabled, 1 = 3% RH, 2 = 5% RH, 3 = 10% RH
// E10 Received ConfigurationReport(parameterNumber: 5, size: 1, configurationValue: [2], scaledConfigurationValue: 2)
else if (cmd.parameterNumber== 5){
state.parameter[5]=1
if (cmd.scaledConfigurationValue == 0){report="Disabled"}
if (cmd.scaledConfigurationValue == 1){report="3% RH"}
if (cmd.scaledConfigurationValue == 2){report="5% RH"}
if (cmd.scaledConfigurationValue == 3){report="10% RH"}
logging(" E10-5 Humidity Reporting Threshold :${report} ", "info2")
}
// Auxiliary/Emergency Mode 0 = Disabled, 1 = Enabled
else if (cmd.parameterNumber== 6){
state.parameter[6]=1
if (cmd.configurationValue == 1){logging("E10-6 Auxiliary/Emergency TRUE", "info2")}
else { logging("E10-6 Auxiliary/Emergency FALSE", "info2")}
}
// ConfigurationReport(parameterNumber: 7, size: 1, configurationValue:
else if (cmd.parameterNumber== 7){
state.parameter[7]=1
def test = cmd.scaledConfigurationValue
def value = 2
def locationScale = getTemperatureScale()
if (test == 1){value = "0.5"}
if (test == 2){value = "1.0"}
if (test == 3){value = "1.5"}
if (test == 4){value = "2.0"}
if (test == 5){value = "2.5"}
if (test == 6){value = "3.0"}
if (test == 7){value = "3.5"}
if (test == 8){value = "4.0"}
state.swing = value
logging("E10-7 Temp Swing :${state.swing} ${locationScale} - #${test}", "info2")
sendEvent(name: "temperatureSwing", value: state.swing, descriptionText: "${state.swing}${locationScale} - #${test} ${state.version}",displayed: true, isStateChange:true)
}
// 2 to 6(Default) The thermostat differential temperature is in units of 0.5 degrees Fahrenheit.
else if (cmd.parameterNumber== 8){
state.parameter[8]=1
def testHeat = cmd.configurationValue[0] * 0.5
def testCool = cmd.configurationValue[1] * 0.5
logging("E10-8 DiffReport Heat:${testCool}° Cool:${testHeat}° [RawHeat:${cmd.configurationValue[1]} RawCool:${cmd.configurationValue[1]}] ", "debug")
// -------------heat
if (state.heatDiff == testHeat) {
logging("E10-8-0 (2 stage Heat Differential) :${testHeat} °", "info2")
sendEvent(name: "recoveryTempDiffHeat", value: "${testHeat}",descriptionText: "heat ${testHeat}° ${state.version}",displayed: true, isStateChange:true)
}
else {
if (debugLogging){
logging("E10-8-0 Report ERROR (2 stage Differential) Heat:${testHeat} [should be ${state.heatDiff}]", "warn")
}
}
// ------------cool
if (state.coolDiff == testCool) {
logging("E10-8-1 (2 stage Cool Differential) :${testCool} °", "info2")
sendEvent(name: "recoveryTempDiffCool", value: "${testCool}", descriptionText: "cool ${testCool} ${state.version}",displayed: true, isStateChange:true)
}
else {