forked from DaveGut/HubitatActive
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSamsung_HVAC.groovy
804 lines (739 loc) · 36.5 KB
/
Samsung_HVAC.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
/* Samsung HVAC using SmartThings Interface
Copyright Dave Gutheinz
License Information:
https://github.com/DaveGut/HubitatActive/blob/master/KasaDevices/License.md
===== Description
This driver is for SmartThings-installed Samsung HVAC for import of control
and status of defined functions into Hubitat Environment.
===== Library Use
This driver uses libraries for the functions common to SmartThings devices.
Library code is at the bottom of the distributed single-file driver.
===== Installation Instructions Link =====
https://github.com/DaveGut/HubitatActive/blob/master/SamsungAppliances/Install_Samsung_Appliance.pdf
===== Version B0.5
Beta release for further user testiong
a. Update major commands, as follows:
1. setThermostatMode now has all Samsung HVAC modes plus mode samsungAuto. samsungAuto mode
is different than auto. auto mode emulates standard hubitat auto mode where the mode is auto
controlled by temperature as it goes above "coolingSetpoint" and below "heatingSetpoint".
samsungAuto uses the native HVAC auto mode with a single setpoint (samsungAutoSetpoint).
2. setCoolingSetpoint and setHeatingSetpoint. When setting a calculation will be made to assue
that colling setpoint > heatingSetpoint plus the preference "min Heating/Cooling delta".
This precludes unsuccessful operation while in auto mode.
3. setSamsungAutoSetpoint. Sets the single setpoint when you set the mode to the HVAC-
internal auto mode.
4. setLight: new command to set the panel light on or off.
b. Developed standard thermostat auto mode emulation.
c. Developed methods to track and control the resultant thermostat modes and operating states.
==============================================================================*/
def driverVer() { return "1.1" }
metadata {
definition (name: "Samsung HVAC",
namespace: "davegut",
author: "David Gutheinz",
importUrl: "https://raw.githubusercontent.com/DaveGut/HubitatActive/master/SamsungAppliances/Samsung_HVAC.groovy"
){
capability "Refresh"
capability "Thermostat"
command "setThermostatMode", [[
name: "Thermostat Mode",
constraints: ["off", "auto", "cool", , "heat", "dry", "wind", "samsungAuto"],
type: "ENUM"]]
command "emergencyHeat", [[name: "NOT IMPLEMENTED"]]
command "samsungAuto"
command "wind"
command "dry"
command "setThermostatFanMode", [[
name: "Thermostat Fan Mode",
constraints: ["auto", "low", "medium", "high"],
type: "ENUM"]]
command "fanLow"
command "fanMedium"
command "fanHigh"
command "setSamsungAutoSetpoint", ["number"]
attribute "samsungAutoSetpoint", "number"
// Set the light on the remote control.
command "togglePanelLight"
attribute "lightStatus", "string"
command "setLevel", ["number"] // To set samsungAutoSetpoint via slider
attribute "level", "number" // Reflects samsungAutoSetpoint
// command "setTemperature", ["number"]
}
preferences {
input ("stApiKey", "string", title: "SmartThings API Key", defaultValue: "")
if (stApiKey) {
input ("stDeviceId", "string", title: "SmartThings Device ID", defaultValue: "")
}
input ("tempOffset", "number", title: "Min Heat/Cool temperature delta",
defaultValue: 4)
input ("pollInterval", "enum", title: "Poll Interval (minutes)",
options: ["1", "5", "10", "30"], defaultValue: "1")
input ("debugLog", "bool",
title: "Enable debug logging for 30 minutes", defaultValue: false)
}
}
def installed() { }
def updated() {
def commonStatus = commonUpdate()
if (commonStatus.status == "FAILED") {
logWarn("updated: ${commonStatus}")
} else {
logInfo("updated: ${commonStatus}")
}
deviceSetup()
}
def auto() { setThermostatMode("auto") }
def cool() { setThermostatMode("cool") }
def heat() { setThermostatMode("heat") }
def wind() { setThermostatMode("wind") }
def dry() { setThermostatMode("dry") }
def samsungAuto() { setThermostatMode("samsungAuto") }
def emergencyHeat() { logInfo("emergencyHeat: Not Available on this device") }
def off() { setThermostatMode("off") }
def setOff() {
def cmdData = [
component: "main",
capability: "switch",
command: "off",
arguments: []]
def cmdStatus = deviceCommand(cmdData)
return cmdStatus
}
def setThermostatMode(thermostatMode) {
def cmdStatus
def prevMode = device.currentValue("thermostatMode")
if (thermostatMode == "auto") {
state.autoMode = true
cmdStatus = [status: "OK", mode: "Auto Emulation"]
poll()
} else if (thermostatMode == "off") {
state.autoMode = false
cmdStatus = setOff()
} else {
state.autoMode = false
if (thermostatMode == "samsungAuto") {
thermostatMode = "auto"
}
cmdStatus = sendModeCommand(thermostatMode)
}
logInfo("setThermostatMode: [cmd: ${thermostatMode}, ${cmdStatus}]")
}
def sendModeCommand(thermostatMode) {
def cmdData = [
component: "main",
capability: "airConditionerMode",
command: "setAirConditionerMode",
arguments: [thermostatMode]]
cmdStatus = deviceCommand(cmdData)
return cmdStatus
}
def fanAuto() { setThermostatFanMode("auto") }
def fanCirculate() { setThermostatFanMode("medium") }
def fanOn() { setThermostatFanMode("medium") }
def fanLow() { setThermostatFanMode("low") }
def fanMedium() { setThermostatFanMode("medium") }
def fanHigh() { setThermostatFanMode("high") }
def setThermostatFanMode(fanMode) {
def cmdData = [
component: "main",
capability: "airConditionerFanMode",
command: "setFanMode",
arguments: [fanMode]]
def cmdStatus = deviceCommand(cmdData)
logInfo("setThermostatFanMode: [cmd: ${fanMode}, ${cmdStatus}]")
}
def setHeatingSetpoint(setpoint) {
if (setpoint < state.minSetpoint || setpoint > state.maxSetpoint) {
logWarn("setHeatingSetpoint: Setpoint out of range")
return
}
def logData = [:]
def offset = tempOffset
if (offset < 0) { offset = -offset }
if (state.tempUnit == "°F") {
setpoint = setpoint.toInteger()
offset = offset.toInteger()
}
if (device.currentValue("heatingSetpoint") != setpoint) {
sendEvent(name: "heatingSetpoint", value: setpoint, unit: state.tempUnit)
logData << [heatingSetpoint: setpoint]
}
def minSetpoint = setpoint + offset
if (minSetpoint > device.currentValue("coolingSetpoint")) {
sendEvent(name: "coolingSetpoint", value: minSetpoint, unit: state.tempUnit)
logData << [coolingSetpoint: minSetpoint]
}
runIn(1, updateOperation)
if (logData != [:]) {
logInfo("setHeatingSetpoint: ${logData}")
}
}
def setCoolingSetpoint(setpoint) {
if (setpoint < state.minSetpoint || setpoint > state.maxSetpoint) {
logWarn("setCoolingSetpoint: Setpoint out of range")
return
}
def logData = [:]
def offset = tempOffset
if (offset < 0) { offset = -offset }
if (state.tempUnit == "°F") {
setpoint = setpoint.toInteger()
offset = offset.toInteger()
}
if (device.currentValue("coolingSetpoint") != setpoint) {
sendEvent(name: "coolingSetpoint", value: setpoint, unit: state.tempUnit)
logData << [coolingSetpoint: setpoint]
}
def maxSetpoint = setpoint - 4
if (maxSetpoint < device.currentValue("heatingSetpoint")) {
sendEvent(name: "heatingSetpoint", value: maxSetpoint, unit: state.tempUnit)
logData << [heatingSetpoint: maxSetpoint]
}
runIn(1, updateOperation)
if (logData != [:]) {
logInfo("setCoolingSetpoint: ${logData}")
}
}
def setSamsungAutoSetpoint(setpoint) {
if (setpoint < state.minSetpoint || setpoint > state.maxSetpoint) {
logWarn("setSamsungAutoSetpoint: Setpoint out of range")
return
}
if (state.tempUnit == "°F") {
setpoint = setpoint.toInteger()
}
def logData = [:]
if (device.currentValue("samsungAutoSetpoint") != setpoint) {
sendEvent(name: "samsungAutoSetpoint", value: setpoint, unit: state.tempUnit)
sendEvent(name: "level", value: setpoint)
logData << [samsungAutoSetpoint: setpoint]
if (samsungAuto && device.currentValue("thermostatMode") == "auto") {
setThermostatSetpoint(setpoint)
}
}
runIn(1, updateOperation)
if (logData != [:]) {
logInfo("setSamsungAutoSetpoint: ${logData}")
}
}
def setLevel(level) { setSamsungAutoSetpoint(level) }
def setThermostatSetpoint(setpoint) {
def cmdData = [
component: "main",
capability: "thermostatCoolingSetpoint",
command: "setCoolingSetpoint",
arguments: [setpoint]]
def cmdStatus = deviceCommand(cmdData)
logInfo("setThermostatSetpoint: [cmd: ${setpoint}, ${cmdStatus}]")
}
def togglePanelLight() {
def newOnOff = "on"
if (device.currentValue("lightStatus") == "on") {
newOnOff = "off"
}
def lightCmd = "Light_Off"
if (newOnOff == "off") {
lightCmd = "Light_On"
}
def arguments = [
"mode/vs/0",
["x.com.samsung.da.options":[lightCmd]]
]
def cmdData = [
component: "main",
capability: "execute",
command: "execute",
arguments: arguments]
def cmdStatus = deviceCommand(cmdData)
logInfo("setThermostatSetpoint: [cmd: ${setpoint}, ${cmdStatus}]")
}
def stringPostHttp(cmdString) {
def respData = [:]
def sendCmdParams = [
uri: "https://api.smartthings.com/v1",
path: "/devices/${stDeviceId.trim()}/commands",
headers: ['Authorization': 'Bearer ' + stApiKey.trim()],
body : cmdString]
try {
httpPost(sendCmdParams) {resp ->
if (resp.status == 200 && resp.data != null) {
respData << [status: "OK", results: resp.data.results]
refresh()
} else {
respData << [status: "FAILED",
httpCode: resp.status,
errorMsg: resp.errorMessage]
}
}
} catch (error) {
respData << [status: "FAILED",
httpCode: "Timeout",
errorMsg: error]
}
return respData
}
def distResp(resp, data) {
def respLog = [:]
if (resp.status == 200) {
try {
def respData = new JsonSlurper().parseText(resp.data)
if (data.reason == "deviceSetup") {
deviceSetupParse(respData.components.main)
}
statusParse(respData.components.main)
} catch (err) {
respLog << [status: "ERROR",
errorMsg: err,
respData: resp.data]
}
} else {
respLog << [status: "ERROR",
httpCode: resp.status,
errorMsg: resp.errorMessage]
}
if (respLog != [:]) {
// logWarn("distResp: ${respLog}")
}
}
def deviceSetupParse(parseData) {
def logData = [:]
tempUnit = parseData.temperatureMeasurement.temperature.unit
state.tempUnit = "°${tempUnit}"
logData << [tempUnit: tempUnit]
def supportedThermostatModes = parseData.airConditionerMode.supportedAcModes.value
supportedThermostatModes << "samsungAuto"
supportedThermostatModes << "off"
sendEvent(name: "supportedThermostatModes", value: supportedThermostatModes)
logData << [supportedThermostatModes: supportedThermostatModes]
def supportedThermostatFanModes = parseData.airConditionerFanMode.supportedAcFanModes.value
sendEvent(name: "supportedThermostatFanModes", value: supportedThermostatFanModes)
logData << [supportedThermostatFanModes: supportedThermostatFanModes]
state.minSetpoint = parseData["custom.thermostatSetpointControl"].minimumSetpoint.value
state.maxSetpoint = parseData["custom.thermostatSetpointControl"].maximumSetpoint.value
// Initialize setpoints if required.
def coolSetpoint = 76
def heatSetpoint = 68
def samsungAutoSetpoint = 72
if (state.tempUnit == "°C") {
coolSetpoint = 24
heatSetpoint = 20
samsungAutoSetpoint = 22
}
if (!device.currentValue("coolingSetpoint")) {
sendEvent(name: "coolingSetpoint", value: coolSetpoint, unit: state.tempUnit)
}
if (!device.currentValue("heatingSetpoint")) {
sendEvent(name: "heatingSetpoint", value: heatSetpoint, unit: state.tempUnit)
}
if (!device.currentValue("samsungAutoSetpoint")) {
sendEvent(name: "samsungAutoSetpoint", value: samsungAutoSetpoint, unit: state.tempUnit)
}
logInfo("deviceSetupParse: ${logData}")
}
def statusParse(parseData) {
def logData = [:]
def temperature = parseData.temperatureMeasurement.temperature.value
if (device.currentValue("temperature") != temperature) {
sendEvent(name: "temperature", value: temperature, unit: tempUnit)
logData << [temperature: temperature]
}
def thermostatSetpoint = parseData.thermostatCoolingSetpoint.coolingSetpoint.value
if (device.currentValue("thermostatSetpoint") != thermostatSetpoint) {
sendEvent(name: "thermostatSetpoint", value: thermostatSetpoint, unit: tempUnit)
logData << [thermostatSetpoint: thermostatSetpoint]
}
def onOff = parseData.switch.switch.value
def thermostatMode = parseData.airConditionerMode.airConditionerMode.value
state.rawMode = thermostatMode
if (state.autoMode) {
thermostatMode = "auto"
} else if (onOff == "off") {
thermostatMode = "off"
} else if (thermostatMode != "cool" && thermostatMode != "heat" &&
thermostatMode != "wind" && thermostatMode != "dry" &&
thermostatMode != "off") {
thermostatMode = "samsungAuto"
}
if (device.currentValue("thermostatMode") != thermostatMode) {
sendEvent(name: "thermostatMode", value: thermostatMode)
logData << [thermostatMode: thermostatMode]
}
def thermostatFanMode = parseData.airConditionerFanMode.fanMode.value
if (device.currentValue("thermostatFanMode") != thermostatFanMode) {
sendEvent(name: "thermostatFanMode", value: thermostatFanMode)
logData << [thermostatFanMode: thermostatFanMode]
}
def execStatus = parseData.execute.data.value.payload["x.com.samsung.da.options"]
def lightStatus = "on"
if (execStatus.contains("Light_On")) { lightStatus = "off" }
if (device.currentValue("lightStatus") != lightStatus) {
sendEvent(name: "lightStatus", value: lightStatus)
logData << [lightStatus: lightStatus]
}
runIn(2, updateOperation)
if (logData != [:]) { logInfo("statusParse: ${logData}") }
runIn(4, listAttributes)
}
def updateOperation() {
def respData = [:]
def setpoint = device.currentValue("thermostatSetpoint")
def temperature = device.currentValue("temperature")
def heatPoint = device.currentValue("heatingSetpoint")
def coolPoint = device.currentValue("coolingSetpoint")
def samsungPoint = device.currentValue("samsungAutoSetpoint")
def mode = device.currentValue("thermostatMode")
def rawMode = state.rawMode
def autoMode = state.autoMode
if (state.autoMode) {
def opMode
if (temperature <= heatPoint) {
opMode = "heat"
} else if (temperature >= coolSetpoint) {
opMode = "cool"
}
if (rawMode != opMode) {
def cmdStatus = sendModeCommand(opMode)
respData << [sendModeCommand: opMode]
logInfo("updateOperation: ${respData}")
return
}
}
def newSetpoint = setpoint
if (rawMode == "cool") {
newSetpoint = coolPoint
} else if (rawMode == "heat") {
newSetpoint = heatPoint
} else if (mode == "samsungAuto") {
newSetpoint = samsungPoint
}
if (newSetpoint != setpoint) {
setThermostatSetpoint(newSetpoint)
respData << [thermostatSetpoint: newSetpoint]
logInfo("updateOperation: ${respData}")
return
}
def opState = "idle"
if (mode == "off" || mode == "wind" || mode == "dry") {
opState = mode
} else if (mode == "samsungAuto") {
if (temperature - setpoint > 1.5) {
opState = "cooling"
} else if (setpoint - temperature > 1.5) {
opState = "heating"
}
} else if (rawMode == "cool") {
if (temperature - setpoint > 0) {
opState = "cooling"
}
} else if (rawMode == "heat") {
if (setpoint - temperature > 0) {
opState = "heating"
}
}
if (device.currentValue("thermostatOperatingState") != opState) {
sendEvent(name: "thermostatOperatingState", value: opState)
respData << [thermostatOperatingState: opState]
logInfo("updateOperation: ${respData}")
}
}
// ===== Library Integration =====
def simulate() { return false}
//#include davegut.Samsung-HVAC-Sim
// ~~~~~ start include (1072) davegut.Logging ~~~~~
library ( // library marker davegut.Logging, line 1
name: "Logging", // library marker davegut.Logging, line 2
namespace: "davegut", // library marker davegut.Logging, line 3
author: "Dave Gutheinz", // library marker davegut.Logging, line 4
description: "Common Logging Methods", // library marker davegut.Logging, line 5
category: "utilities", // library marker davegut.Logging, line 6
documentationLink: "" // library marker davegut.Logging, line 7
) // library marker davegut.Logging, line 8
// Logging during development // library marker davegut.Logging, line 10
def listAttributes(trace = false) { // library marker davegut.Logging, line 11
def attrs = device.getSupportedAttributes() // library marker davegut.Logging, line 12
def attrList = [:] // library marker davegut.Logging, line 13
attrs.each { // library marker davegut.Logging, line 14
def val = device.currentValue("${it}") // library marker davegut.Logging, line 15
attrList << ["${it}": val] // library marker davegut.Logging, line 16
} // library marker davegut.Logging, line 17
if (trace == true) { // library marker davegut.Logging, line 18
logTrace("Attributes: ${attrList}") // library marker davegut.Logging, line 19
} else { // library marker davegut.Logging, line 20
logDebug("Attributes: ${attrList}") // library marker davegut.Logging, line 21
} // library marker davegut.Logging, line 22
} // library marker davegut.Logging, line 23
def logTrace(msg){ // library marker davegut.Logging, line 25
log.trace "${device.displayName} ${driverVer()}: ${msg}" // library marker davegut.Logging, line 26
} // library marker davegut.Logging, line 27
def logInfo(msg) { // library marker davegut.Logging, line 29
if (infoLog == true) { // library marker davegut.Logging, line 30
log.info "${device.displayName} ${driverVer()}: ${msg}" // library marker davegut.Logging, line 31
} // library marker davegut.Logging, line 32
} // library marker davegut.Logging, line 33
def debugLogOff() { // library marker davegut.Logging, line 35
if (debug == true) { // library marker davegut.Logging, line 36
device.updateSetting("debug", [type:"bool", value: false]) // library marker davegut.Logging, line 37
} else if (debugLog == true) { // library marker davegut.Logging, line 38
device.updateSetting("debugLog", [type:"bool", value: false]) // library marker davegut.Logging, line 39
} // library marker davegut.Logging, line 40
logInfo("Debug logging is false.") // library marker davegut.Logging, line 41
} // library marker davegut.Logging, line 42
def logDebug(msg) { // library marker davegut.Logging, line 44
if (debug == true || debugLog == true) { // library marker davegut.Logging, line 45
log.debug "${device.displayName} ${driverVer()}: ${msg}" // library marker davegut.Logging, line 46
} // library marker davegut.Logging, line 47
} // library marker davegut.Logging, line 48
def logWarn(msg) { log.warn "${device.displayName} ${driverVer()}: ${msg}" } // library marker davegut.Logging, line 50
// ~~~~~ end include (1072) davegut.Logging ~~~~~
// ~~~~~ start include (1091) davegut.ST-Communications ~~~~~
library ( // library marker davegut.ST-Communications, line 1
name: "ST-Communications", // library marker davegut.ST-Communications, line 2
namespace: "davegut", // library marker davegut.ST-Communications, line 3
author: "Dave Gutheinz", // library marker davegut.ST-Communications, line 4
description: "ST Communications Methods", // library marker davegut.ST-Communications, line 5
category: "utilities", // library marker davegut.ST-Communications, line 6
documentationLink: "" // library marker davegut.ST-Communications, line 7
) // library marker davegut.ST-Communications, line 8
import groovy.json.JsonSlurper // library marker davegut.ST-Communications, line 9
private asyncGet(sendData, passData = "none") { // library marker davegut.ST-Communications, line 11
if (!stApiKey || stApiKey.trim() == "") { // library marker davegut.ST-Communications, line 12
logWarn("asyncGet: [status: ERROR, errorMsg: no stApiKey]") // library marker davegut.ST-Communications, line 13
} else { // library marker davegut.ST-Communications, line 14
logDebug("asyncGet: ${sendData}, ${passData}") // library marker davegut.ST-Communications, line 15
def sendCmdParams = [ // library marker davegut.ST-Communications, line 16
uri: "https://api.smartthings.com/v1", // library marker davegut.ST-Communications, line 17
path: sendData.path, // library marker davegut.ST-Communications, line 18
headers: ['Authorization': 'Bearer ' + stApiKey.trim()]] // library marker davegut.ST-Communications, line 19
try { // library marker davegut.ST-Communications, line 20
asynchttpGet(sendData.parse, sendCmdParams, [reason: passData]) // library marker davegut.ST-Communications, line 21
} catch (error) { // library marker davegut.ST-Communications, line 22
logWarn("asyncGet: [status: FAILED, errorMsg: ${error}]") // library marker davegut.ST-Communications, line 23
} // library marker davegut.ST-Communications, line 24
} // library marker davegut.ST-Communications, line 25
} // library marker davegut.ST-Communications, line 26
private syncGet(path){ // library marker davegut.ST-Communications, line 28
def respData = [:] // library marker davegut.ST-Communications, line 29
if (!stApiKey || stApiKey.trim() == "") { // library marker davegut.ST-Communications, line 30
respData << [status: "FAILED", // library marker davegut.ST-Communications, line 31
errorMsg: "No stApiKey"] // library marker davegut.ST-Communications, line 32
} else { // library marker davegut.ST-Communications, line 33
logDebug("syncGet: ${sendData}") // library marker davegut.ST-Communications, line 34
def sendCmdParams = [ // library marker davegut.ST-Communications, line 35
uri: "https://api.smartthings.com/v1", // library marker davegut.ST-Communications, line 36
path: path, // library marker davegut.ST-Communications, line 37
headers: ['Authorization': 'Bearer ' + stApiKey.trim()] // library marker davegut.ST-Communications, line 38
] // library marker davegut.ST-Communications, line 39
try { // library marker davegut.ST-Communications, line 40
httpGet(sendCmdParams) {resp -> // library marker davegut.ST-Communications, line 41
if (resp.status == 200 && resp.data != null) { // library marker davegut.ST-Communications, line 42
respData << [status: "OK", results: resp.data] // library marker davegut.ST-Communications, line 43
} else { // library marker davegut.ST-Communications, line 44
respData << [status: "FAILED", // library marker davegut.ST-Communications, line 45
httpCode: resp.status, // library marker davegut.ST-Communications, line 46
errorMsg: resp.errorMessage] // library marker davegut.ST-Communications, line 47
} // library marker davegut.ST-Communications, line 48
} // library marker davegut.ST-Communications, line 49
} catch (error) { // library marker davegut.ST-Communications, line 50
respData << [status: "FAILED", // library marker davegut.ST-Communications, line 51
httpCode: "Timeout", // library marker davegut.ST-Communications, line 52
errorMsg: error] // library marker davegut.ST-Communications, line 53
} // library marker davegut.ST-Communications, line 54
} // library marker davegut.ST-Communications, line 55
return respData // library marker davegut.ST-Communications, line 56
} // library marker davegut.ST-Communications, line 57
private syncPost(sendData){ // library marker davegut.ST-Communications, line 59
def respData = [:] // library marker davegut.ST-Communications, line 60
if (!stApiKey || stApiKey.trim() == "") { // library marker davegut.ST-Communications, line 61
respData << [status: "FAILED", // library marker davegut.ST-Communications, line 62
errorMsg: "No stApiKey"] // library marker davegut.ST-Communications, line 63
} else { // library marker davegut.ST-Communications, line 64
logDebug("syncPost: ${sendData}") // library marker davegut.ST-Communications, line 65
def cmdBody = [commands: [sendData.cmdData]] // library marker davegut.ST-Communications, line 67
def sendCmdParams = [ // library marker davegut.ST-Communications, line 68
uri: "https://api.smartthings.com/v1", // library marker davegut.ST-Communications, line 69
path: sendData.path, // library marker davegut.ST-Communications, line 70
headers: ['Authorization': 'Bearer ' + stApiKey.trim()], // library marker davegut.ST-Communications, line 71
body : new groovy.json.JsonBuilder(cmdBody).toString() // library marker davegut.ST-Communications, line 72
] // library marker davegut.ST-Communications, line 73
try { // library marker davegut.ST-Communications, line 74
httpPost(sendCmdParams) {resp -> // library marker davegut.ST-Communications, line 75
if (resp.status == 200 && resp.data != null) { // library marker davegut.ST-Communications, line 76
respData << [status: "OK", results: resp.data.results] // library marker davegut.ST-Communications, line 77
} else { // library marker davegut.ST-Communications, line 78
respData << [status: "FAILED", // library marker davegut.ST-Communications, line 79
httpCode: resp.status, // library marker davegut.ST-Communications, line 80
errorMsg: resp.errorMessage] // library marker davegut.ST-Communications, line 81
} // library marker davegut.ST-Communications, line 82
} // library marker davegut.ST-Communications, line 83
} catch (error) { // library marker davegut.ST-Communications, line 84
respData << [status: "FAILED", // library marker davegut.ST-Communications, line 85
httpCode: "Timeout", // library marker davegut.ST-Communications, line 86
errorMsg: error] // library marker davegut.ST-Communications, line 87
} // library marker davegut.ST-Communications, line 88
} // library marker davegut.ST-Communications, line 89
return respData // library marker davegut.ST-Communications, line 90
} // library marker davegut.ST-Communications, line 91
// ~~~~~ end include (1091) davegut.ST-Communications ~~~~~
// ~~~~~ start include (1090) davegut.ST-Common ~~~~~
library ( // library marker davegut.ST-Common, line 1
name: "ST-Common", // library marker davegut.ST-Common, line 2
namespace: "davegut", // library marker davegut.ST-Common, line 3
author: "Dave Gutheinz", // library marker davegut.ST-Common, line 4
description: "ST Wash/Dryer Common Methods", // library marker davegut.ST-Common, line 5
category: "utilities", // library marker davegut.ST-Common, line 6
documentationLink: "" // library marker davegut.ST-Common, line 7
) // library marker davegut.ST-Common, line 8
def commonUpdate() { // library marker davegut.ST-Common, line 10
if (!stApiKey || stApiKey == "") { // library marker davegut.ST-Common, line 11
return [status: "FAILED", reason: "No stApiKey"] // library marker davegut.ST-Common, line 12
} // library marker davegut.ST-Common, line 13
if (!stDeviceId || stDeviceId == "") { // library marker davegut.ST-Common, line 14
getDeviceList() // library marker davegut.ST-Common, line 15
return [status: "FAILED", reason: "No stDeviceId"] // library marker davegut.ST-Common, line 16
} // library marker davegut.ST-Common, line 17
unschedule() // library marker davegut.ST-Common, line 19
def updateData = [:] // library marker davegut.ST-Common, line 20
updateData << [status: "OK"] // library marker davegut.ST-Common, line 21
if (debugLog) { runIn(1800, debugLogOff) } // library marker davegut.ST-Common, line 22
updateData << [stDeviceId: stDeviceId] // library marker davegut.ST-Common, line 23
updateData << [debugLog: debugLog, infoLog: infoLog] // library marker davegut.ST-Common, line 24
if (!getDataValue("driverVersion") || // library marker davegut.ST-Common, line 25
getDataValue("driverVersion") != driverVer()) { // library marker davegut.ST-Common, line 26
updateDataValue("driverVersion", driverVer()) // library marker davegut.ST-Common, line 27
updateData << [driverVer: driverVer()] // library marker davegut.ST-Common, line 28
} // library marker davegut.ST-Common, line 29
setPollInterval(pollInterval) // library marker davegut.ST-Common, line 30
updateData << [pollInterval: pollInterval] // library marker davegut.ST-Common, line 31
runIn(5, refresh) // library marker davegut.ST-Common, line 33
return updateData // library marker davegut.ST-Common, line 34
} // library marker davegut.ST-Common, line 35
def setPollInterval(pollInterval) { // library marker davegut.ST-Common, line 37
logDebug("setPollInterval: ${pollInterval}") // library marker davegut.ST-Common, line 38
state.pollInterval = pollInterval // library marker davegut.ST-Common, line 39
switch(pollInterval) { // library marker davegut.ST-Common, line 40
case "10sec": // library marker davegut.ST-Common, line 41
schedule("*/10 * * * * ?", "poll") // library marker davegut.ST-Common, line 42
break // library marker davegut.ST-Common, line 43
case "20sec": // library marker davegut.ST-Common, line 44
schedule("*/20 * * * * ?", "poll") // library marker davegut.ST-Common, line 45
break // library marker davegut.ST-Common, line 46
case "30sec": // library marker davegut.ST-Common, line 47
schedule("*/30 * * * * ?", "poll") // library marker davegut.ST-Common, line 48
break // library marker davegut.ST-Common, line 49
case "1" : runEvery1Minute(poll); break // library marker davegut.ST-Common, line 50
case "5" : runEvery5Minutes(poll); break // library marker davegut.ST-Common, line 51
case "10" : runEvery10Minutes(poll); break // library marker davegut.ST-Common, line 52
case "30" : runEvery30Minutes(poll); break // library marker davegut.ST-Common, line 53
default: runEvery10Minutes(poll) // library marker davegut.ST-Common, line 54
} // library marker davegut.ST-Common, line 55
} // library marker davegut.ST-Common, line 56
def deviceCommand(cmdData) { // library marker davegut.ST-Common, line 58
def respData = [:] // library marker davegut.ST-Common, line 59
if (simulate() == true) { // library marker davegut.ST-Common, line 60
respData = testResp(cmdData) // library marker davegut.ST-Common, line 61
} else if (!stDeviceId || stDeviceId.trim() == "") { // library marker davegut.ST-Common, line 62
respData << [status: "FAILED", data: "no stDeviceId"] // library marker davegut.ST-Common, line 63
} else { // library marker davegut.ST-Common, line 64
def sendData = [ // library marker davegut.ST-Common, line 65
path: "/devices/${stDeviceId.trim()}/commands", // library marker davegut.ST-Common, line 66
cmdData: cmdData // library marker davegut.ST-Common, line 67
] // library marker davegut.ST-Common, line 68
respData = syncPost(sendData) // library marker davegut.ST-Common, line 69
} // library marker davegut.ST-Common, line 70
if (cmdData.capability && cmdData.capability != "refresh") { // library marker davegut.ST-Common, line 71
refresh() // library marker davegut.ST-Common, line 72
} else { // library marker davegut.ST-Common, line 73
poll() // library marker davegut.ST-Common, line 74
} // library marker davegut.ST-Common, line 75
return respData // library marker davegut.ST-Common, line 76
} // library marker davegut.ST-Common, line 77
def refresh() { // library marker davegut.ST-Common, line 79
if (stApiKey!= null) { // library marker davegut.ST-Common, line 80
def cmdData = [ // library marker davegut.ST-Common, line 81
component: "main", // library marker davegut.ST-Common, line 82
capability: "refresh", // library marker davegut.ST-Common, line 83
command: "refresh", // library marker davegut.ST-Common, line 84
arguments: []] // library marker davegut.ST-Common, line 85
deviceCommand(cmdData) // library marker davegut.ST-Common, line 86
} // library marker davegut.ST-Common, line 87
} // library marker davegut.ST-Common, line 88
def poll() { // library marker davegut.ST-Common, line 90
if (simulate() == true) { // library marker davegut.ST-Common, line 91
def children = getChildDevices() // library marker davegut.ST-Common, line 92
if (children) { // library marker davegut.ST-Common, line 93
children.each { // library marker davegut.ST-Common, line 94
it.statusParse(testData()) // library marker davegut.ST-Common, line 95
} // library marker davegut.ST-Common, line 96
} // library marker davegut.ST-Common, line 97
statusParse(testData()) // library marker davegut.ST-Common, line 98
} else if (!stDeviceId || stDeviceId.trim() == "") { // library marker davegut.ST-Common, line 99
respData = "[status: FAILED, data: no stDeviceId]" // library marker davegut.ST-Common, line 100
logWarn("poll: [status: ERROR, errorMsg: no stDeviceId]") // library marker davegut.ST-Common, line 101
} else { // library marker davegut.ST-Common, line 102
def sendData = [ // library marker davegut.ST-Common, line 103
path: "/devices/${stDeviceId.trim()}/status", // library marker davegut.ST-Common, line 104
parse: "distResp" // library marker davegut.ST-Common, line 105
] // library marker davegut.ST-Common, line 106
asyncGet(sendData, "statusParse") // library marker davegut.ST-Common, line 107
} // library marker davegut.ST-Common, line 108
} // library marker davegut.ST-Common, line 109
def deviceSetup() { // library marker davegut.ST-Common, line 111
if (simulate() == true) { // library marker davegut.ST-Common, line 112
def children = getChildDevices() // library marker davegut.ST-Common, line 113
deviceSetupParse(testData()) // library marker davegut.ST-Common, line 114
} else if (!stDeviceId || stDeviceId.trim() == "") { // library marker davegut.ST-Common, line 115
respData = "[status: FAILED, data: no stDeviceId]" // library marker davegut.ST-Common, line 116
logWarn("poll: [status: ERROR, errorMsg: no stDeviceId]") // library marker davegut.ST-Common, line 117
} else { // library marker davegut.ST-Common, line 118
def sendData = [ // library marker davegut.ST-Common, line 119
path: "/devices/${stDeviceId.trim()}/status", // library marker davegut.ST-Common, line 120
parse: "distResp" // library marker davegut.ST-Common, line 121
] // library marker davegut.ST-Common, line 122
asyncGet(sendData, "deviceSetup") // library marker davegut.ST-Common, line 123
} // library marker davegut.ST-Common, line 124
} // library marker davegut.ST-Common, line 125
def getDeviceList() { // library marker davegut.ST-Common, line 127
def sendData = [ // library marker davegut.ST-Common, line 128
path: "/devices", // library marker davegut.ST-Common, line 129
parse: "getDeviceListParse" // library marker davegut.ST-Common, line 130
] // library marker davegut.ST-Common, line 131
asyncGet(sendData) // library marker davegut.ST-Common, line 132
} // library marker davegut.ST-Common, line 133
def getDeviceListParse(resp, data) { // library marker davegut.ST-Common, line 135
def respData // library marker davegut.ST-Common, line 136
if (resp.status != 200) { // library marker davegut.ST-Common, line 137
respData = [status: "ERROR", // library marker davegut.ST-Common, line 138
httpCode: resp.status, // library marker davegut.ST-Common, line 139
errorMsg: resp.errorMessage] // library marker davegut.ST-Common, line 140
} else { // library marker davegut.ST-Common, line 141
try { // library marker davegut.ST-Common, line 142
respData = new JsonSlurper().parseText(resp.data) // library marker davegut.ST-Common, line 143
} catch (err) { // library marker davegut.ST-Common, line 144
respData = [status: "ERROR", // library marker davegut.ST-Common, line 145
errorMsg: err, // library marker davegut.ST-Common, line 146
respData: resp.data] // library marker davegut.ST-Common, line 147
} // library marker davegut.ST-Common, line 148
} // library marker davegut.ST-Common, line 149
if (respData.status == "ERROR") { // library marker davegut.ST-Common, line 150
logWarn("getDeviceListParse: ${respData}") // library marker davegut.ST-Common, line 151
} else { // library marker davegut.ST-Common, line 152
log.info "" // library marker davegut.ST-Common, line 153
respData.items.each { // library marker davegut.ST-Common, line 154
log.trace "${it.label}: ${it.deviceId}" // library marker davegut.ST-Common, line 155
} // library marker davegut.ST-Common, line 156
log.trace "<b>Copy your device's deviceId value and enter into the device Preferences.</b>" // library marker davegut.ST-Common, line 157
} // library marker davegut.ST-Common, line 158
} // library marker davegut.ST-Common, line 159
def calcTimeRemaining(completionTime) { // library marker davegut.ST-Common, line 161
Integer currTime = now() // library marker davegut.ST-Common, line 162
Integer compTime // library marker davegut.ST-Common, line 163
try { // library marker davegut.ST-Common, line 164
compTime = Date.parse("yyyy-MM-dd'T'HH:mm:ss'Z'", completionTime,TimeZone.getTimeZone('UTC')).getTime() // library marker davegut.ST-Common, line 165
} catch (e) { // library marker davegut.ST-Common, line 166
compTime = Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", completionTime,TimeZone.getTimeZone('UTC')).getTime() // library marker davegut.ST-Common, line 167
} // library marker davegut.ST-Common, line 168
Integer timeRemaining = ((compTime-currTime) /1000).toInteger() // library marker davegut.ST-Common, line 169
if (timeRemaining < 0) { timeRemaining = 0 } // library marker davegut.ST-Common, line 170
return timeRemaining // library marker davegut.ST-Common, line 171
} // library marker davegut.ST-Common, line 172
// ~~~~~ end include (1090) davegut.ST-Common ~~~~~