-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathESv4.6Rooms
4113 lines (3925 loc) · 217 KB
/
ESv4.6Rooms
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
/*
* EchoSistant Rooms Profile - EchoSistant Add-on
*
* 11/25/2018 Version:4.6 R.0.1.5 Bug fix for individual lights feedback
* 11/24/2018 Version:4.6 R.0.1.4 Completed code for compound devices and compound groups commands
* 11/23/2018 Version:4.6 R.0.1.3 Code Cleanup prep for release with Version Change
* 11/21/2018 Version:4.5 R.0.1.2 Improved performance and outputs
* 11/19/2018 Version:4.5 R.0.1.1 Add in cancel of delay/timers
* 11/19/2018 Version:4.5 R.0.1.0 Add in delay timers, improved logic
* 11/18/2018 Version:4.5 R.0.0.9 Added individual device controls
* 11/16/2018 Version:4.5 R.0.0.8 Updates to the way things look in the app.
* 11/16/2018 Version:4.5 R.0.0.7 Complete overhaul of the freespeech engine. Compound commands added
* 11/09/2018 Version:4.5 R.0.0.6 Control update: added ability to set volume to a precise number
* 11/08/2018 Version:4.5 R.0.0.5 Feedback update: added Alexa Device capabilities, power meters
* 11/07/2018 Version:4.5 R.0.0.4 Feedback update: added ability to ask "Is the alarm on/off" also "Is the garage door open/closed"
* 10/26/2018 Version:4.5 R.0.0.3 Re-release
* 9/12/2018 Version:4.5 R.0.0.2 Rework for streamlining and added Echo Device selection
* 6/12/2017 Version:4.5 R.0.0.1 Alpha Release
* 2/17/2017 Version:4.0 R.0.0.1 Public Release
*
* Copyright 2016 Jason Headley & Bobby Dobrescu
*
* 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.
*
/**********************************************************************************************************************************************/
import groovy.json.*
import java.text.SimpleDateFormat
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import java.security.InvalidKeyException
import java.security.MessageDigest
include 'asynchttp_v1'
definition(
name : "EchoSistant Rooms",
namespace : "Echo",
author : "JH/BD",
description : "EchoSistant Rooms - Custom rooms and Custom Control",
category : "",
parent : "Echo:EchoSistant",
iconUrl : "https://raw.githubusercontent.com/BamaRayne/Echosistant/master/smartapps/bamarayne/echosistant.src/app-Echosistant.png",
iconX2Url : "https://raw.githubusercontent.com/BamaRayne/Echosistant/master/smartapps/bamarayne/echosistant.src/[email protected]",
iconX3Url : "https://raw.githubusercontent.com/BamaRayne/Echosistant/master/smartapps/bamarayne/echosistant.src/[email protected]")
/**********************************************************************************************************************************************/
private release() {
def text = "R.0.4.6"
}
private revision(text) {
text = "Version 4.6, Revision 0.1.5"
return text
}
/**********************************************************************************************************************************************/
preferences {
page name: "mainProfilePage"
page name: "pSend"
page name: "pActions"
page name: "pGroups"
page name: "pRestrict"
page name: "pDeviceControl"
page name: "pPerson"
page name: "pVirPerAction"
page name: "renamePage"
}
// MAIN PROFILE - HOME PAGE
def mainProfilePage() {
dynamicPage(name: "mainProfilePage", title:"", install: true, uninstall: installed) {
section ("") {
label title:"Name this Room", required:true,
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/Name.jpg"
}
section("") {
href "messaging", title: "Outgoing Messages", description: pSendComplete(), state: pSendSettings(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/Messages.png"
}
section("") {
href "feedback", title: "Devices & Device Groups Control and Feedback", description: mIntentD(), state: mIntentS(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/control panel.ico"
}
section("") {
href "Shortcuts", title: "Shortcuts", description: mRoomsD(), state: mRoomsS(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/shortcut.png"
}
section ("") {
href "pTrackers", title: "Task Trackers", description: pTrackComplete(), state: pTrackSettings(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/Taskers.png"
}
section ("") {
href "pRestrict", title: "Action Restrictions", description: pRestrictComplete(), state: pRestrictSettings(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/Restrictions.png"
}
}
}
// OUTPUT MESSAGES HOME PAGE
page name: "messaging"
def messaging(){
dynamicPage(name: "messaging", title: "Messaging Configuration", uninstall: false){
section("") {
href "pSend", title: "Audio and Text Message Settings", description: pMsgComplete(), state: pMsgSettings(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/Speakers.jpg"
}
section ("") {
href "pConfig", title: "Message Output Settings", description: pConfigComplete(), state: pConfigSettings(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/Settings.jpg"
}
}
}
// SHORTCUT PHRASES
page name: "Shortcuts"
def Shortcuts(){
dynamicPage(name: "Shortcuts", title: "Create shortcut phrases and custom Alexa responses", uninstall: false){
if (childApps?.size()>0) {
section("", uninstall: false){
app(name: "EchoSistant Rooms Shortcuts", appName: "EchoSistant Rooms Shortcuts", namespace: "Echo", title: "Create a New ShortCut", displayChildApps: false, multiple: true, uninstall: false)
}
}
else {
section("", uninstall: false){
paragraph "NOTE: Looks like you haven't created any Rooms yet.\n \nPlease make sure you have installed the EchoSistant Shortcuts Add-on before creating a new Profile!"
app(name: "EchoSistant Rooms Shortcuts", appName: "EchoSistant Rooms Shortcuts", namespace: "Echo", title: "Create a New Shortcut", multiple: true, uninstall: false)
}
}
}
}
// FEEDBACK CONFIGURATION HOME PAGE
page name: "feedback"
def feedback(){
dynamicPage(name: "feedback", title: "Device Groups Control and Feedback Configuration", uninstall: false){
section("") {
href "pGroups", title: "Individual Devices & Device Groups Control", description: pGroupComplete(), state: pGroupSettings(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/control panel.ico"
}
section("") {
href "fDevices", title: "Individual Devices Feedback", description: fDeviceComplete(), state: fDeviceSettings(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/Feedback.png"
}
section("") {
href "pActions", title: "Location and Profile Actions (to execute when Profile runs)", description: pActionsComplete(), state: pActionsSettings(),
image: "https://raw.githubusercontent.com/BamaRayne/SmartSuite/master/Icons/Action.png"
}
}
}
// FEEDBACK DEVICE GROUPS SELECTION
page name: "fDevices"
def fDevices(){
dynamicPage(name: "fDevices", title: "Select devices physically in this room for Feedback", uninstall: false){
section("Netatmo Weather Station") {
input "NetatmoTrue", "bool", title: "Do you have any of the Netatmo Weather Station Modules?", required: false, default: false, submitOnChange: true
if (NetatmoTrue) {
input "fWind", "capability.sensor", title: "Wind Speed", multiple: false, required: false, submitOnChange: true
input "fRain", "capability.sensor", title: "Rain Accumulation", multiple: false, required: false, submitOnChange: true
input "fOutDoor", "capability.sensor", title: "Outdoor Module", multiple: false, required: false, submitOnChange: true
input "fBase", "capability.sensor", title: "Base Station", multiple: false, required: false, submitOnChange: true
input "fIndoor", "capability.sensor", title: "Indoor Modules", multiple: true, required: false, submitOnChange: true
}
}
section("Lights, Bulbs, and Switches") {
input "fSwitches", "capability.switch", title: "Lights, Bulbs, and Switches...", multiple: true, required: false
}
section("Doors and Windows") {
input "fGarage", "capability.garageDoorControl", title: "Garage Doors....", multiple: true, required: false
input "fDoors", "capability.contactSensor", title: "Contacts only on Doors...", multiple: true, required: false
input "fWindows", "capability.contactSensor", title: "Contacts only on Windows...", multiple: true, required: false
input "fShades", "capability.windowShade", title: "Curtains, Blinds, Shades...", multiple: true, required: false
}
section("Environmental Controls") {
input "fFans", "capability.switch", title: "Ceiling Fans...", multiple: true, required: false
input "fVents", "capability.switchLevel", title: "Smart Vents...", multiple: true, required: false
input "fTemp", "capability.temperatureMeasurement", title: "Devices that Report Temperature...", multiple: true, required: false
input "fHum", "capability.relativeHumidityMeasurement", title: "Devices that Report Humidity...", multiple: true, required: false
}
section("Locks, Motion, and Presence") {
input "fLock", "capability.lock", title: "Smart Locks...", multiple: true, required: false
input "fPresence", "capability.presenceSensor", title: "Presence Sensors...", required: false, multiple: true
input "fMotion", "capability.motionSensor", title: "Motion Sensors...", required: false, multiple: true
}
section("Power Meters") {
input "fPower", "capability.powerMeter", title: "Aeon Power Meters...", multiple: true, required: false
input "ofPower", "capability.powerMeter", title: "Iris Smart Plugs...", multiple: true, required: false
if (fPower || ofPower) {
input "fCosts", "string", title: "What is your cost per kilowatt hour?", required: false, defaultValue: 0.000, submitOnChange: true
}
}
}
}
// TASK TRACKERS CONFIGURATION
page name: "pTrackers"
def pTrackers(){
dynamicPage(name: "pTrackers", title: "", uninstall: false) {
section ("Tell me about the Task Trackers", hideable: true, hidden: true) {
paragraph "Your Task Trackers are now active for ${app.label}. \n" +
"\n" +
"Task trackers are designed as a quick way for you to keep track of important events or tasks. " +
"Do you have trouble remembering when you gave your pet their medicine? Or, when you changed the " +
"oil in your vehicles? Or, when the last time you called your Mom was? Well, now you can just tell " +
"Alexa that you've done something and she will record the date and time. Then when you want to find " +
"out when it was last done, you just ask! \n" +
" \n" +
"Configuring a Task Tracker is fairly simple. This example is using a pets daily medicine. " +
"My cat is name Calliope and she is diabetic. She recieves an insulin shot twice daily. There are a lot " +
"of people in my home, so to ensure we do not over medicate, we use this Task Tracker ~~ \n" +
"\n" +
"First, I created a profile named Calliope and configured the Task Tracker in that profile " +
"I want to say this, 'Alexa, tell Calliope that she got her shot' \n" +
"I also want anyone in the home to be able to know right away when she was last medicated. So, using the " +
"Task Tracker, anyone can say, 'Alexa, ask Calliope when she was shot', and they are given the date and time \n" +
" \n" +
"Decide what phrase you want to say to record the Task, and then pull out the key words. In my " +
"example the key words are 'Got' 'Her' 'Shot'. \n" +
" \n" +
"Put those key words into the Tracker in that order and you're done. Now give it a try! \n"
}
section ("Task Tracker One", hideable: true, hidden: false) {
input "trackerOne2", "text", title: "1st Tracker Key Word #1", required: false, default: "", submitOnChange: true
input "trackerOne3", "text", title: "1st Tracker Key Word #2", required: false, default: "", submitOnChange: true
input "trackerOne1", "text", title: "1st Tracker Key Word #3", required: false, default: "", submitOnChange: true
input "t1notify", "bool", title: "Do you want to set a reminder?", required: false, default: false, submitOnChange: true
if (t1notify) {
def title1
if (reminderTitle != null) title1 = "${reminderTitle}"
else {
title1 = "A Reminder has not been created for this Task Tracker" }
paragraph "You can create a reminder that will be scheduled for a future time based on the execution of this " +
"Task Tracker. Example: Reminder is configured to run every 12 hours, it will be scheduled for a ONE TIME execution " +
"12 hours AFTER this Task Tracker executes. "
href "reminderPage1", title: "Create a Reminder for this Task Tracker", description: "${title1}"
}
}
section ("Task Tracker Two", hideable: true, hidden: false) {
input "trackerTwo2", "text", title: "2nd Tracker Key Word #1", required: false, default: "", submitOnChange: true
input "trackerTwo3", "text", title: "2nd Tracker Key Word #2", required: false, default: "", submitOnChange: true
input "trackerTwo1", "text", title: "2nd Tracker Key Word #3", required: false, default: "", submitOnChange: true
input "t2notify", "bool", title: "Do you want to set a reminder?", required: false, default: false, submitOnChange: true
if (t2notify) {
def title2
if (reminderTitle2 != null) { title2 = "${reminderTitle2}" }
else {
title2 = "A Reminder has not been created for this Task Tracker" }
paragraph "You can create a reminder that will be scheduled for a future time based on the execution of this " +
"Task Tracker. Example: Reminder is configured to run every 12 hours, it will be scheduled for a ONE TIME execution " +
"12 hours AFTER this Task Tracker executes. "
href "reminderPage2", title: "Create a Reminder for this Task Tracker", description: "${title2}"
}
}
section ("Task Tracker Three", hideable: true, hidden: false) {
input "trackerThree2", "text", title: "3rd Tracker Key Word #1", required: false, default: false, submitOnChange: true
input "trackerThree3", "text", title: "3rd Tracker Key Word #2", required: false, default: false, submitOnChange: true
input "trackerThree1", "text", title: "3rd Tracker Key Word #3", required: false, default: false, submitOnChange: true
input "t3notify", "bool", title: "Do you want to set a reminder?", required: false, default: false, submitOnChange: true
if (t3notify) {
def title3
if (remindertitle3 != null) { title3 = "${reminderTitle3}" }
else {
title3 = "A Reminder has not been created for this Task Tracker" }
paragraph "You can create a reminder that will be scheduled for a future time based on the execution of this " +
"Task Tracker. Example: Reminder is configured to run every 12 hours, it will be scheduled for a ONE TIME execution " +
"12 hours AFTER this Task Tracker executes. "
href "reminderPage3", title: "Create a Reminder for this Task Tracker", description: "${title3}"
}
}
section ("Task Tracker Four", hideable: true, hidden: false) {
input "trackerFour2", "text", title: "4th Tracker Key Word #1", required: false, default: false, submitOnChange: true
input "trackerFour3", "text", title: "4th Tracker Key Word #2", required: false, default: false, submitOnChange: true
input "trackerFour1", "text", title: "4th Tracker Key Word #3", required: false, default: false, submitOnChange: true
input "t4notify", "bool", title: "Do you want to set a reminder?", required: false, default: false, submitOnChange: true
if (t4notify) {
def title4
if (remindertitle4 != null) { title4 = "${reminderTitle4}" }
else {
title4 = "A Reminder has not been created for this Task Tracker" }
paragraph "You can create a reminder that will be scheduled for a future time based on the execution of this " +
"Task Tracker. Example: Reminder is configured to run every 12 hours, it will be scheduled for a ONE TIME execution " +
"12 hours AFTER this Task Tracker executes. "
href "t4Reminder", title: "Create a Reminder for this Task Tracker", description: "${title4}"
}
}
section ("Configure Notifications for $app.label", hideable: true, hidden: true) {
paragraph "\n" +
"Send a text message when a tracker is updated. Separate multiple numbers with a comma and " +
"use this format: +19045554444,+19045554433 "
input name: "psms", type: "phone", title: "Send text notification to (optional):", required: false
input "pPush", "bool", title: "Do you want to send a Push message when Trackers are updated?", required: false, defaultValue: false, submitOnChange: true
}
}
}
// VIRTUAL PERSON NOTIFICATIONS (SENDS WHEN VP CHECKS IN/OUT)
page name: "pVPNotifyPage"
def pVPNotifyPage() {
dynamicPage(name: "pVPNotifyPage", title: "Notification Settings") {
section {
input "vpPhone", "phone", title: "Text This Number", description: "Phone number", required: false, submitOnChange: true
paragraph "For multiple SMS recipients, separate phone numbers with a comma"
input "vpNotification", "bool", title: "Send A Push Notification", description: "Notification", required: false, submitOnChange: true
}
}
}
// VIRTUAL PERSON CONFIG HOME PAGE
page name: "pPerson"
def pPerson(){
dynamicPage(name: "pPerson", title: "", uninstall: false){
def deviceId = "${app.label}"
def d = getChildDevice("${app.label}")
section("Configure the Virtual Person Device") {
if(d==null) {
href "pPersonCreate", title: "Create Virtual Person Device"
}
if(d) {
href "pPersonDelete", title: "Delete Virtual Person Device"
input "notifyVPArrive", "bool", title: "Notify when Virtual Person Arrives", required: false, submitOnChange: true
input "notifyVPDepart", "bool", title: "Notify when Virtual Person Departs", required: false, submitOnChange: true
if (notifyVPArrive || notifyVPDepart) {
href "pVPNotifyPage", title: "Virtual Person Notification Settings", description: VPNotifyComplete(), state: VPNotifySettings()
}
}
}
}
}
// VIRTUAL PERSON SENSOR DELETE
page name: "pPersonDelete"
def pPersonDelete(){
dynamicPage(name: "pPersonDelete", title: "", uninstall: false) {
section ("") {
paragraph "You have deleted a virtual presence sensor device. You will no longer see this device in your " +
"SmartThings Environment. "
}
removeChildDevices(getAllChildDevices())
}
}
// VIRTUAL PERSON SENSOR CREATE
page name: "pPersonCreate"
def pPersonCreate(){
dynamicPage(name: "pPersonCreate", title: "", uninstall: false) {
section ("") {
paragraph "You have created a virtual presence sensor device named ($app.label). !!!DO NOT RENAME THIS DEVICE!!!. " +
"You will now see this device in your 'Devices' list in the Smartthings IDE and SmartApp."
}
virtualPerson()
}
}
// OUTPUT MESSAGES CONFIGURATION PAGE
page name: "pSend"
def pSend(){
dynamicPage(name: "pSend", title: "Audio and Text Message Settings", uninstall: false){
section ("") {
input "echoDevice", "device.echoSpeaksDevice", title: "Amazon Alexa Devices", multiple: true, required: false
input "eVolume", "number", title: "Set the volume", description: "0-100 (default value = 30)", required: false, defaultValue: 30
if (eVolume) {
input "svr", "bool", title: "Do you want to restore the volume to preannouncement levels?", required: false, default:faluse, submitOnChange: true
if (svr == true) paragraph "The volume in the $app.label will be restored to " + sSpeaker.currentState("level")?.stringValue + " percent"
}
}
section (""){
input "synthDevice", "capability.speechSynthesis", title: "Speech Synthesis Devices", multiple: true, required: false
}
section ("") {
input "sonosDevice", "capability.musicPlayer", title: "Music Player Devices", required: false, multiple: true, submitOnChange: true
if (sonosDevice) {
input "volume", "number", title: "Temporarily change volume", description: "0-100% (default value = 30%)", required: false
}
}
section ("") {
input "smc", "bool", title: "Send the message to Smart Message Control", default: false, submitOnChange: true
}
section ("" ) {
input "sendText", "bool", title: "Enable Text Notifications", required: false, submitOnChange: true
if (sendText){
paragraph "You may enter multiple phone numbers separated by comma to deliver the Alexa message. E.g. +18045551122,+18046663344"
input name: "sms", title: "Send text notification to (optional):", type: "phone", required: false
}
}
section ("Push Messages") {
input "push", "bool", title: "Send Push Notification (optional)", required: false, defaultValue: false
}
}
}
// ALEXA RESPONSES PAGE
page name: "pConfig"
def pConfig(){
dynamicPage(name: "pConfig", title: "Message Output Settings", uninstall: false) {
section ("Configure Alexa Responses for Voice Messaging") {
input "pDisableAlexaProfile", "bool", title: "Disable Alexa Feedback Responses (silence Alexa - overrides all other Alexa Options)?", defaultValue: false
input "pAlexaCustResp", "text", title: "Custom Response from Alexa...", required: false, defaultValue: none
input "pAlexaRepeat", "bool", title: "Alexa repeats the message to the sender as the response...", defaultValue: false, submitOnChange: true
if (pAlexaRepeat) {
if (pAlexaRepeat && pAlexaCustResp){
paragraph "NOTE: only one custom Alexa response can"+
" be delivered at once. Please only enable Custom Response OR Repeat Message"
}
}
input "pContCmdsProfile", "bool", title: "Disable Conversation? (Alexa no longer prompts for additional commands, after a message is sent to a remote speaker, except for 'try again' if an error ocurs)", defaultValue: false
}
section ("Remote Speaker Settings") {
input "pRunMsg", "Text", title: "Play this predetermined message when this profile executes...", required: false
input "pPreMsg", "text", title: "Play this message before your spoken message...", defaultValue: none, required: false
input "pDisableALLProfile", "bool", title: "Disable Audio Output on the Remote Speaker(s)?", required: false
}
section ("Text Notifications") {
input "pRunTextMsg", "Text", title: "Send this predetermined text when this profile executes...", required: false
input "pPreTextMsg", "text", title: "Append this text before the text message...", defaultValue: none, required: false
}
}
}
// PROFILE ACTIONS ARE EXECUTED EACH TIME THE PROFILE RUNS
page name: "pActions"
def pActions() {
dynamicPage(name: "pActions", uninstall: false) {
section ("Trigger these lights and actions when the Profile runs...") {
href "pDeviceControl", title: "Select Devices...", description: pDevicesComplete() , state: pDevicesSettings()
input "pMode", "enum", title: "Choose Mode to change to...", options: location.modes.name.sort(), multiple: false, required: false
input "shmState", "enum", title: "Set Smart Home Monitor to...", options:["stay":"Armed Stay","away":"Armed Away","off":"Disarmed"], multiple: false, required: false, submitOnChange: true
if (shmState) {
input "shmStateKeypads", "capability.lockCodes", title: "Send status change to these keypads...", multiple: true, required: false, submitOnChange: true
}
input "pVirPer", "bool", title: "Toggle the Virtual Person State Automatically when this Profile Runs", default: false, submitOnChange: true, required: false
if (pVirPer) {
href "pPerson", title: "Configure the Virtual Person for ${app.label}", description: VPCreateComplete(), state: VPCreateSettings()
}
}
}
}
// DEVICE CONTROL SELECTION PAGE
page name: "pDeviceControl"
def pDeviceControl() {
dynamicPage(name: "pDeviceControl", title: "",install: false, uninstall: false) {
section ("Trigger these lights and actions when the Profile runs..."){
input "gDoor1", "capability.garageDoorControl", title: "Select Garage Doors...", multiple: true, required: false, submitOnChange: true
}
section (""){
input "sSwitches", "capability.switch", title: "Select Lights and Switches...", multiple: true, required: false, submitOnChange: true
if (sSwitches) {
input "sSwitchCmd", "enum", title: "Command To Send",
options:["on":"Turn on","off":"Turn off","toggle":"Toggle"], multiple: false, required: false, submitOnChange:true
input "delaySwitches", "bool", title: "Delay Actions?", required: false, defaultValue: false, submitOnChange:true
if (delaySwitches) {
input "sSecondsOn", "number", title: "Turn on in Seconds?", defaultValue: none, required: false
input "sSecondsOff", "number", title: "Turn off in Seconds?", defaultValue: none, required: false
}
if (sSwitchCmd) input "sOtherSwitch", "capability.switch", title: "...and these other switches?", multiple: true, required: false, submitOnChange: true
if (sOtherSwitch) input "sOtherSwitchCmd", "enum", title: "Command To Send to these other switches",
options: ["on1":"Turn on","off1":"Turn off","toggle1":"Toggle"], multiple: false, required: false, submitOnChange: true
if (sOtherSwitchCmd) input "delayOtherSwitches", "bool", title: "Delay Actions?", required: false, defaultValue: false, submitOnChange:true
if (delayOtherSwitches) {
input "sOtherSecondsOn", "number", title: "Turn on in Seconds?", defaultValue: none, required: false
input "sOtherSecondsOff", "number", title: "Turn off in Seconds?", defaultValue: none, required: false
}
}
}
section (""){
input "sDimmers", "capability.switchLevel", title: "Select Dimmers...", multiple: true, required: false , submitOnChange:true
if (sDimmers) { input "sDimmersCmd", "enum", title: "Command To Send",
options:["on":"Turn on","off":"Turn off", "set":"Set level"], multiple: false, required: false, submitOnChange:true
}
if (sDimmersCmd) {
input "sDimmersLVL", "number", title: "Dimmers Level", description: "Set dimmer level", required: false, submitOnChange: true
input "delayDimmers", "bool", title: "Delay Actions?", required: false, defaultValue: false, submitOnChange:true
if (delayDimmers) {
input "sSecondsDimmers", "number", title: "Turn on in Seconds?", defaultValue: none, required: false
input "sSecondsDimmersOff", "number", title: "Turn off in Seconds?", defaultValue: none, required: false
}
input "sOtherDimmers", "capability.switchLevel", title: "...and these other Dimmers...", multiple: true, required: false , submitOnChange:true
if (sOtherDimmers) {
input "sOtherDimmersCmd", "enum", title: "Command To Send to these other Dimmers",
options:["on":"Turn on","off":"Turn off","set":"Set level"], multiple: false, required: false, submitOnChange:true
}
if (sOtherDimmersCmd) {
input "sOtherDimmersLVL", "number", title: "Dimmers Level", description: "Set dimmer level", required: false, submitOnChange: true
input "delayOtherDimmers", "bool", title: "Delay Actions?", required: false, defaultValue: false, submitOnChange: true
if (delayOtherDimmers) {
input "sSecondsOtherDimmers", "number", title: "Turn on in Seconds?", defaultValue: none, required: false
input "sSecondsOtherDimmersOff", "number", title: "Turn off in Seconds?", defaultValue: none, required: false
}
}
}
}
section (""){
input "sHues", "capability.colorControl", title: "Select These Colored Lights...", multiple: true, required: false, submitOnChange:true
if (sHues) {
input "sHuesCmd", "enum", title: "Command To Send ",
options:["on":"Turn on","off":"Turn off","setColor":"Set Color"], multiple: false, required: false, submitOnChange:true
if(sHuesCmd == "setColor") {
input "sHuesColor", "enum", title: "Hue Color?", required: false, multiple:false, options: fillColorSettings().name
}
if(sHuesCmd == "setColor" || sHuesCmd == "on") {
input "sHuesLevel", "enum", title: "Light Level?", required: false, options: [[10:"10%"],[20:"20%"],[30:"30%"],[40:"40%"],[50:"50%"],[60:"60%"],[70:"70%"],[80:"80%"],[90:"90%"],[100:"100%"]], submitOnChange:true
}
}
if (sHuesLevel) input "sHuesOther", "capability.colorControl", title: "...and these other Colored Lights?", multiple: true, required: false, submitOnChange:true
if (sHuesOther) {
input "sHuesOtherCmd", "enum", title: "Command To Send to these other Colored Lights", options:["on":"Turn on","off":"Turn off","setColor":"Set Color"], multiple: false, required: false, submitOnChange:true
if(sHuesOtherCmd == "setColor") {
input "sHuesOtherColor", "enum", title: "Which Color?", required: false, multiple:false, options: fillColorSettings().name
}
if(sHuesOtherCmd == "on" || sHuesOtherCmd == "setColor") {
input "sHuesOtherLevel", "enum", title: "Light Level?", required: false, options: [[10:"10%"],[20:"20%"],[30:"30%"],[40:"40%"],[50:"50%"],[60:"60%"],[70:"70%"],[80:"80%"],[90:"90%"],[100:"100%"]]
}
}
}
section ("") {
input "sFlash", "capability.switch", title: "Flash Switch(es)", multiple: true, required: false, submitOnChange:true
if (sFlash) {
input "numFlashes", "number", title: "This number of times (default 3)", required: false, submitOnChange:true
input "onFor", "number", title: "On for (default 1 second)", required: false, submitOnChange:true
input "offFor", "number", title: "Off for (default 1 second)", required: false, submitOnChange:true
}
}
}
}
// DEVICE GROUPS PAGE
page name: "pGroups"
def pGroups() {
dynamicPage(name: "pGroups", title: "", install: false, uninstall: false) {
section (""){
paragraph "~~Control all groups by saying, 'Alexa, turn on/off the ~group name~ in the $app.label'"
paragraph "~~Control all devices by saying, 'Alexa, turn on/off the ~device name~ in the $app.label'"
paragraph "~~All devices CAN be selected in multiple sections"
paragraph "~~Compound Commands are available for Individual Devices ONLY! 'Alexa, turn on the corner light and turn on the ceiling fan in the $app.label'"
}
section ("Individual Control Devices"){
input "cSwitches", "capability.switch", title: "Select Devices individual control (select everything)", multiple: true, required: false
}
section ("Location Modes"){
input "mMode", "enum", title: "Choose Modes to be used by this Room...", options: location.modes.name.sort(), multiple: true, required: false
}
section ("Garage Doors"){
input "gGarage", "capability.garageDoorControl", title: "Garage Door(s)...", multiple:true, required: false
}
section ("Vents and Window Coverings Groups"){
input "gVents", "capability.switchLevel", title: "Group Smart Vent(s)...", multiple: true, required: false
input "gShades", "capability.windowShade", title: "Group These Window Covering Devices...", multiple: true, required: false
}
section ("Media"){
input "sMedia", "capability.mediaController", title: "Use This Media Controller", multiple: false, required: false
input "sSpeaker", "capability.musicPlayer", title: "Use This Media Player Device For Volume Control (Select your Alexa Devices)", required: false, multiple: false
input "sSynth", "capability.speechSynthesis", title: "Use This Speech Synthesis Capable Device", multiple: false, required: false
}
section ("Lights and Switches Groups"){
input "gSwitches", "capability.switch", title: "Group Lights and Switches...", multiple: true, required: false
}
section ("Ceiling Fans and Automations Groups"){
input "gDisable", "capability.switch", title: "Group Automation & Disable Switches (disable = off, enable = on)", multiple: true, required: false
input "gFans", "capability.switch", title: "Fans and Ceiling Fans...", multiple: true, required: false
}
section ("Create Custom Groups") {
input "gCustom1N", "text", label: "Name this Group...", multiple: false, required: false, defaultLabel: "Custom Group 1"
input "gCustom1", "capability.switch", title: "Select Switches for $gCustom1N...", multiple: true, required: false
if (gCustom1) {
input "gCustom2N", "text", label: "Name this Group...", multiple: false, required: false, defaultLabel: "Custom Group 2"
input "gCustom2", "capability.switch", title: "Select Switches for $gCustom2N...", multiple: true, required: false
}
if (gCustom2) {
input "gCustom3N", "text", label: "Name this Group...", multiple: false, required: false, defaultLabel: "Custom Group 3"
input "gCustom3", "capability.switch", title: "Select Switches for $gCustom3N...", multiple: true, required: false
}
if (gCustom3) {
input "gCustom4N", "text", label: "Name this Group...", multiple: false, required: false, defaultLabel: "Custom Group 4"
input "gCustom4", "capability.switch", title: "Select Switches for $gCustom4N...", multiple: true, required: false
}
if (gCustom4) {
input "gCustom5N", "text", label: "Name this Group...", multiple: false, required: false, defaultLabel: "Custom Group 5"
input "gCustom5", "capability.switch", title: "Select Switches for $gCustom5N...", multiple: true, required: false
}
}
}
}
// RESTRICTIONS HOME PAGE
page name: "pRestrict"
def pRestrict(){
dynamicPage(name: "pRestrict", title: "Profile Restrictions", uninstall: false) {
section ("") {
input "modes", "mode", title: "Audio only when mode is", multiple: true, required: false
}
section (""){
input "days", title: "Audio only on these days of the week", multiple: true, required: false,
"enum", options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
}
section (""){
href "certainTime", title: "Audio only during a certain time", description: pTimeComplete(), state: pTimeSettings()
}
}
}
// RESTRICTION PAGE - TIME SELECTIONS
page name: "certainTime"
def certainTime() {
dynamicPage(name:"certainTime",title: "Only during a certain time", uninstall: false) {
section("Beginning at....") {
input "startingX", "enum", title: "Starting at...", options: ["A specific time", "Sunrise", "Sunset"], required: false , submitOnChange: true
if(startingX in [null, "A specific time"]) input "starting", "time", title: "Start time", required: false, submitOnChange: true
else {
if(startingX == "Sunrise") input "startSunriseOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false, submitOnChange: true
else if(startingX == "Sunset") input "startSunsetOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false, submitOnChange: true
}
}
section("Ending at....") {
input "endingX", "enum", title: "Ending at...", options: ["A specific time", "Sunrise", "Sunset"], required: false, submitOnChange: true
if(endingX in [null, "A specific time"]) input "ending", "time", title: "End time", required: false, submitOnChange: true
else {
if(endingX == "Sunrise") input "endSunriseOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false, submitOnChange: true
else if(endingX == "Sunset") input "endSunsetOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false, submitOnChange: true
}
}
}
}
/************************************************************************************************************
**** HANDLERS FOLLOW
************************************************************************************************************/
// VIRTUAL PERSON CREATE HANDLER
def virtualPerson() {
log.trace "Creating Voice Companion Virtual Person Device"
def deviceId = "${app.label}"
def d = getChildDevice("${app.label}")
if(!d) {
d = addChildDevice("Assistant", "Voice Companion Simulated Presence Sensor", deviceId, null, [label:"${app.label}"])
log.trace "Voice Companion Virtual Person Device - Created ${app.label} "
}
else {
log.trace "NOTICE!!! Found that the EVPD ${d.displayName} already exists. Only one device per profile permitted"
}
}
// VIRTUAL PERSON DELETE HANDLER
private removeChildDevices(delete) {
log.debug "The Virtual Person Device '${app.label}' has been deleted from your SmartThings environment"
delete.each {
deleteChildDevice(it.deviceNetworkId)
}
}
// VIRTUAL PERSON CHECK IN/OUT TOGGLE HANDLER
private pVirToggle() {
def vp = getChildDevice("${app.label}")
if(vp) {
if (vp?.currentValue('presence')?.contains('not')) {
log.info "${app.label} has arrived"
vp.arrived()
}
else if (vp?.currentValue('presence')?.contains('present')) {
log.info "${app.label} has departed"
vp.departed()
}
}
}
/************************************************************************************************************
SECURITY CONTROL HANDLER
************************************************************************************************************/
def securityHandler(tts) {
def outputTxt
def currentSHM = location.currentState("alarmSystemStatus")?.value
if (tts.contains("turn on the alarm")){
sendLocationEvent(name: "alarmSystemStatus", value: "stay")
tts = "I changed the Smart Home Monitor to armed stay"
log.info "securityHandler On says: $tts"
return tts
}
if (tts.contains("turn off the alarm")){
sendLocationEvent(name: "alarmSystemStatus", value: "off")
tts = "I have disarmed Smart Home Monitor"
log.info "securityHandler Off says: $tts"
return tts
}
return tts
}
/************************************************************************************************************
Base Process
************************************************************************************************************/
def installed() {
log.debug "Installed with settings: ${settings}, current app version: ${release()}"
state.ProfileRelease ="Profile: " + release()
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}, current app version: ${release()}"
state.ProfileRelease = "Profile: " + release()
unsubscribe()
initialize()
if(!atomicState?.isInstalled) { atomicState?.isInstalled = true }
}
def initialize() {
state.tts
state.lastMessage
state.lastTime
state.lastAction = null
state.lastActivity
//Sound Cancellation
state.pMuteAlexa = settings.pDisableAlexaProfile ?: false
state.pMuteAll = settings.pDisableALLProfile ?: false
// Turn OFF the Color Loop
unschedule("startLoop")
unschedule("continueLoop")
//SHM status change and keypad initialize
subscribe(location, locationHandler)
state.responseTxt = null
state.lambdaReleaseTxt = "Not Set"
state.lambdaReleaseDt = "Not Set"
state.lambdatextVersion = "Not Set"
//Alexa Responses
state.pTryAgain = false
state.pContCmds = settings.pContCmdsProfile == false ? true : settings.pContCmdsProfile == true ? false : false
state.pMuteAlexa = settings.pEnableMuteAlexa
state.pShort = settings.pUseShort
state.pContCmdsR = "init"
//OTHER
state.sched
state.sched2
state.sched3
state.sched4
state.date
if (fMinutes1) { state.fSched1 = "1" }
else { state.fSched1 = "0" }
log.info "fSched1 = $state.fSched1"
def String deviceType = (String) null
def String outputTxt = (String) null
def String result = (String) null
def String deviceM = (String) null
def currState
def stateDate
def stateTime
def data = [:]
if (fDevice != null) {
fDevice = fDevice.replaceAll("[^a-zA-Z0-9 ]", "") }
def fProcess = true
state.pTryAgain = false
if (taskTrackers) {
log.info "Initializing Task Tracker variable for '${app.label}'"
if (state.trackerOne == null) {state.trackerOne = "I'm sorry, I have not been told when the ${trackerOne1} was ${trackerOne2}" }
if (state.trackerTwo == null) {state.trackerTwo = "I'm sorry, I have not been told when the ${trackerTwo1} was ${trackerTwo2}" }
if (state.trackerThree == null) {state.trackerThree = "I'm sorry, I have not been told when the ${trackerThree1} was ${trackerThree2}" }
if (state.trackerFour == null) {state.trackerFour = "I'm sorry, I have not been told when the ${trackerFour1} was ${trackerFour1}" }
}
}
def uninstalled() {
revokeAccessToken()
LogAction("${app?.getLabel()} has been Uninstalled...", "warn", true)
}
private stripBrackets(str) {
str = str.replace("[", "")
return str.replace("]", "")
}
/******************************************************************************************************
PARENT STATUS CHECKS
******************************************************************************************************/
def checkState() {
return state.pMuteAlexa
}
def checkRelease() {
return state.ProfileRelease
}
/******************************************************************************************************
SPEECH AND TEXT PROCESSING INTERNAL - FEEDBACK
******************************************************************************************************/
def profileFeedbackEvaluate(params) {
log.info "profileFeedbackEvaluate has been activated with params: $params"
def tts = params.ptts
def intent = params.pintentName
def childName = app.label
def data = [:]
//Output Variables
def pTryAgain = false
def pPIN = false
def pShort = state.pShort
def String pContCmdsR = (String) "tts"
def String outputTxt = (String) null
def String scheduler = (String) null
def String ttsR = (String) null
def String command = (String) null
def String deviceType = (String) null
def String colorMatch = (String) null
def fbDoors = fDoors
def fbWindows = fWindows
def fbLights = fSwitches
def fbFans = fFans
if (tts != null) {
tts = tts.replaceAll("[^a-zA-Z0-9 ]", "") }
if (debug) log.debug "Messaging Profile Data: (ptts) = '${ptts}', (pintentName) = '${pintentName}'"
if (command == "undefined") {
outputTxt = "Sorry, I didn't get that, "
state.pTryAgain = false
state.pContCmdsR = "clear"
state.lastAction = null
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
if (intent == childName){
if (test){
outputTxt = "Congratulations! Your EchoSistant is now setup properly, good job"
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
if(parent.debug) log.debug "I have received a feedback command: ${command}, deviceType: ${deviceType}, with this text: ${tts}"
if (tts.contains("current revision")) {
def roomsRev = revision(text)
def parentRev = parent.release()
// def shortRev = childApps.find.release()
outputTxt = "The current Echosistant Parent app Revision is, $parentRev. The Rooms Revision is, $roomsRev" //, and the ShortCuts Revision is $shortRev"
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
//// LIGHTS INDIVIDUAL FEEDBACK
fbLights.each { s ->
def lMatch = s.label.toLowerCase()
if(tts.contains("TV")) {
lMatch = lMatch.toUpperCase()
}
if (tts.contains("$lMatch")) {
def fbLightsStatus = s?.latestValue("switch")
log.debug "light status is: $fbLightsStatus"
if (tts.contains("on")) {
if (fbLightsStatus == "on") {
outputTxt = "Yes, the $lMatch is $fbLightsStatus"
}
if (fbLightsStatus == "off") {
outputTxt = "No, the $lMatch is $fbLightsStatus"
}
}
else {
if (fbLightsStatus == "off") {
outputTxt = "Yes, the $lMatch is $fbLightsStatus"
}
if (fbLightsStatus == "on") {
outputTxt = "No, the $lMatch is $fbLightsStatus"
}
}
}
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
//// DOORS INDIVIDUAL FEEDBACK
fbDoors.each { c ->
def cMatch = c.label.toLowerCase()
if (tts.contains("$cMatch")) {
def fbDoorsStatus = c?.latestValue("contact")
log.info "fbDoorsStatus is: $fbDoorsStatus"
if (tts.contains("open")) {
if (fbDoorsStatus.contains("open")) {
outputTxt = "Yes, the $cMatch is $fbDoorsStatus"
}
if (fbDoorsStatus.contains("closed")) {
outputTxt = "No, the $cMatch is $fbDoorsStatus"
}
}
if (tts.contains("closed")) {
if (fbDoorsStatus.contains("closed")) {
outputTxt = "Yes, the $cMatch is $fbDoorsStatus"
}
if (fbDoorsStatus.contains("open")) {
outputTxt = "No, the $cMatch is $fbDoorsStatus"
}
}
}
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
// FEEDBACK HANDLER
def fDevice = tts.contains("power") ? fPower: tts.contains("garage") ? fGarage : tts.contains("vent") ? fVents : tts.contains("light") ? fSwitches : tts.contains("door") ? fDoors : tts.contains("window") ? fWindows : tts.contains("fan") ? fFans :
tts.contains("TV") ? fSwitches : tts.contains("motion") ? fMotion : tts.contains("lock") ? fLocks : tts.contains("shade") ? fShades : tts.contains("curtains") ? fShades : tts.contains("blinds") ? fShades : tts.startsWith("who") ? fPresence : tts.contains("batteries") ? fBattery : null
def fValue = tts.contains("power") ? "powerMeter" : tts.contains("garage") ? "contact" : tts.contains("vent") ? "switch" : tts.contains("light") ? "switch" : tts.contains("door") ? "contact" : tts.contains("window") ? "contact" : tts.contains("fan") ? "switch" :
tts.contains("TV") ? "switch" : tts.contains("lock") ? "lock" : tts.contains("shade") ? "windowShade" : tts.contains("blind") ? "windowShade" : tts.contains("who") ? "presence" : tts.contains("curtains") ? "windowShade" : null
def fName = tts.contains("motion") ? "motion sensors" : tts.contains("vent") ? "vent" : tts.contains("lock") ? "lock" : tts.contains("door") ? "door" : tts.contains("window") ? "window" : tts.contains("fan") ? "fan" :
tts.contains("light") ? "light" : tts.contains("shade") ? "shade" : tts.contains("blind") ? "blind" : tts.contains("curtains") ? "curtain" : null
def fCommand = tts=="who is at home" ? "present" : tts=="who is home" ? "present" : tts=="who is not home" ? "not present" : tts=="who is not at home" ? "not present" : tts.contains("open") ? "open" :
tts.contains("closed") ? "closed" : tts.contains("on") ? "on" : tts.contains("off") ? "off" : null
if (tts.contains("check") && tts.contains("light")) { fCommand = "on" }
if (tts.contains("motion")) { fCommand = "active" }
if (tts.contains("check")) {
if (tts.contains("lock") || tts.contains("door") || tts.contains("window") || tts.contains("vent") || tts.contains("shades") || tts.contains("blind") || tts.contains("curtain")) {
fCommand = "open" }}
// ALEXA DEVICES - LAST THING SPOKEN
if (tts.contains("last thing said")) {
def result = "The last thing spoken on the " + "${sSpeaker}" + " was, " + sSpeaker.currentState("lastSpeakCmd")?.stringValue
log.info "Alexa Device: Last speak cmd was --> $result"
outputTxt = stripBrackets(result ? " $result " : "")
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
// ALEXA DEVICE - WAKE WORD
if (tts.contains("wake word")) {
def result = "The wake word for the " + "${sSpeaker}" + " is, " + sSpeaker.currentState("alexaWakeWord")?.stringValue
log.info "Alexa Device: Wake Word is --> $result"
outputTxt = stripBrackets(result ? " $result " : "")
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
// ALEXA DEVICE - VOLUME
if (tts.contains("what is the volume")) {
def result = "The volume in the $app.label is set to " + sSpeaker.currentState("level")?.stringValue + " percent"
log.info "$app.label: Volume Level is --> $result"
outputTxt = stripBrackets(result ? " $result " : "")
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
// ALEXA DEVICE - WHATS PLAYING
if (tts.contains("what is playing") || tts.contains("what was the last song")) {
outputTxt = "The song " + sSpeaker.currentState("currentStation")?.stringValue + " by " + sSpeaker.currentState("currentAlbum")?.stringValue + " was the last thing played in the $app.label"
log.info "Ask this: $tts, and receive this answer: $outputTxt"
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
// TEMPERATURE //
if (tts == "what is the temperature" || tts == "whats the temperature" || tts == "whats the temp"){
if(fTemp){
def sensors = fTemp?.size()
def tempAVG = fTemp ? getAverage(fTemp, "temperature") : "undefined device"
def currentTemp = tempAVG
outputTxt = "The current temperature in the $app.label is $currentTemp degrees."
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
else {
outputTxt = "There are no temperature sensors selected, go to the Voice Companion Smart App and select one or more sensors"
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
}
// HUMIDITY //
if (tts == "what is the humidity" || tts == "whats the humidity" || tts == "how humid is it"){
if(fHum){
def sensors = fHum?.size()
def humidAVG = fHum ? getAverage(fHum, "humidity") : "undefined device"
def currentHum = humidAVG
outputTxt = "The current humidity in the $app.label is $currentHum percent."
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
else {
outputTxt = "There are no humidity sensors selected, go to the Voice Companion Smart App and select one or more sensors"
return ["outputTxt":outputTxt, "pContCmds":state.pContCmds, "pShort":state.pShort, "pContCmdsR":state.pContCmdsR, "pTryAgain":state.pTryAgain, "pPIN":pPIN]
}
}
// POWER CONSUMPTION AEON SWITCHES
/* if (tts.contains("how much power") || tts.contains("power usage")) {
def result
def devList = []
def currWatts = []
def wattsUsed = []
if (fPower) {
devices.each { deviceName ->
String device = (String) deviceName
devList += device
def sensor = fPower?.size()
def powerAVG = deviceName ? getAverage(fPower, "power") : "undefined device"
def longWatts = "(Consumed: ${fPower?.currentState('energy')?.value}kWh))\nMaximum of ${devices?.currentState('powerTwo')?.value}"
currWatts = (deviceName?.currentState('power'))?.value// IRIS SMART PLUG
wattsUsed = (deviceName?.currentState('power'))?.value// IRIS SMART PLUG
currWatts = (deviceName?.currentState('powerDisp'))?.value // AEON POWER METER
wattsUsed = (deviceName?.currentState('energy'))?.value // AEON POWER METER
def watts = "${wattsUsed}"?.replaceAll("\\D", "") as double // AEON POWER METER
def costs = "${fCosts}" as double
def resetDate = (fPower?.currentState('powerOne'))?.value
def total = ((watts*costs)/1000).round(2)
log.info "devList = $devList"
log.info "currWatts = $currWatts & the costs = $costs for a total cost of " + total + " using a total of " + wattsUsed + " watts"
if (devList?.size() > 1) {
result = "There is currently an average of $powerAVG watts being used in the $app.label."// The total watts used has been $wattsUsed Kilowatts, for a total cost of ${total} U.S. dollars"
}
else {