1
+
2
+ /**
3
+ * MIT License
4
+ * Copyright 2023 Daniel Winks (daniel.winks@gmail.com)
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in all
14
+ * copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ * SOFTWARE.
23
+ **/
24
+
25
+ #include dwinks.UtilitiesAndLoggingLibrary
26
+
27
+ metadata {
28
+ definition (name : ' Rest Power Sensor' ,namespace : ' dwinks' , author : ' Daniel Winks' , importUrl :' ' ) {
29
+ command ' restartESP'
30
+ capability ' Refresh'
31
+ capability ' PowerMeter' // power - NUMBER, unit:W
32
+ capability ' EnergyMeter' // energy - NUMBER, unit:kWh
33
+
34
+ attribute ' status' , ' ENUM' , [' online' , ' offline' ]
35
+ attribute ' uptime' , ' NUMBER'
36
+ }
37
+
38
+ preferences {
39
+ section {
40
+ input ' ip' , ' string' , title :' IP Address' , description : ' ' , required : true , displayDuringSetup : true
41
+ input ' port' , ' string' , title :' Port' , description : ' ' , required : true , displayDuringSetup : true , defaultValue : ' 80'
42
+ input ' power' , ' string' , title :' Power Sensor Name' , description : ' ' , required : true , displayDuringSetup : true
43
+ input ' energy' , ' string' , title :' Total Daily Energy Sensor Name' , description : ' ' , required : true , displayDuringSetup : true
44
+ input ' autoUpdate' , ' bool' , title : " Refresh peridocially?" , required : true , defaultValue : true
45
+ input ' updateInterval' , ' enum' , title : ' Sensor Update Interval' , required : true , defaultValue : 10 , options :
46
+ [
47
+ 10 :' 10 Seconds' ,
48
+ 30 :' 30 Seconds' ,
49
+ 60 :' 1 Minute' ,
50
+ 120 :' 2 Minutes' ,
51
+ 180 :' 3 Minutes' ,
52
+ 240 :' 4 Minutes' ,
53
+ 300 :' 5 Minutes' ,
54
+ 600 :' 10 Minutes' ,
55
+ 900 :' 15 Minutes' ,
56
+ 1200 :' 20 Minutes' ,
57
+ 1800 :' 30 Minutes' ,
58
+ 3600 :' 60 Minutes'
59
+ ]
60
+ }
61
+ }
62
+ }
63
+
64
+ @Field static final String UPTIME_STATE = ' /sensor/uptime'
65
+ @Field static final String RESTART_ESP = ' /button/restart/press'
66
+ String powerState () { return " /sensor/${ power.toLowerCase().replace(' ','_')} " }
67
+ String energyState () { return " /sensor/${ energy.toLowerCase().replace(' ','_')} " }
68
+
69
+ void refresh () { refreshPowerMonitor() }
70
+ void refreshPowerMonitor () {
71
+ sendQueryAsync(powerState(), ' refreshCallback' , [sensor :' power' ])
72
+ sendQueryAsync(energyState(), ' refreshCallback' , [sensor :' energy' ])
73
+ }
74
+
75
+ void refreshCallback (AsyncResponse response , Map data = null ){
76
+ logDebug(" response.status = ${ response.status} " )
77
+ if (response. hasError()) {
78
+ logDebug(" ${ response.getErrorData()} " )
79
+ return
80
+ }
81
+ Map jsonBody = response. getJson()
82
+ logDebug(prettyJson(jsonBody))
83
+ if (data. sensor == ' power' ) { sendEvent(name :' power' , value :jsonBody?. value) }
84
+ if (data. sensor == ' energy' ) { sendEvent(name :' energy' , value :jsonBody?. value) }
85
+ }
86
+
87
+ void initialize () { configure() }
88
+ void configure () {
89
+ String newDni = getMACFromIP(ip)
90
+ device. setDeviceNetworkId(newDni)
91
+ refresh()
92
+ unschedule()
93
+ if (settings. autoUpdate != null && settings. autoUpdate == true ) {
94
+ logDebug(" Autoupdate every ${ settings?.updateInterval} seconds..." )
95
+ Integer interval = settings?. updateInterval as Integer
96
+ if (interval < 60 ) {
97
+ schedule(runEveryCustomSeconds(interval as Integer ), ' refresh' )
98
+ }
99
+ if (interval >= 60 && interval < 3600 ) {
100
+ String cron = runEveryCustomMinutes((interval/ 60 ) as Integer )
101
+ schedule(cron, ' refresh' )
102
+ }
103
+ if (interval == 3600 ) {
104
+ schedule(runEveryCustomHours((interval/ 3600 ) as Integer ), ' refresh' )
105
+ }
106
+ }
107
+ }
108
+
109
+ void restartESP () { sendCommandAsync(RESTART_ESP , null , null ) }
110
+
111
+ void sendCommandAsync (String path , String callbackMethod , Map data = null ) {
112
+ try {
113
+ Map params = [uri : " http://${ ip} :${ port}${ path} " ]
114
+ logDebug(" URI: ${ params.uri} " )
115
+ asynchttpPost(callbackMethod, params, data)
116
+ }
117
+ catch (Exception e){
118
+ if (e. message. toString() != ' OK' ) {
119
+ logError(e. message)
120
+ }
121
+ }
122
+ runInMillis(500 , ' refresh' )
123
+ }
124
+
125
+ void sendQueryAsync (String path , String callback , Map data = null ) {
126
+ Map params = [uri : " http://${ ip} :${ port}${ path} " ]
127
+ logDebug(" URI: ${ params.uri} " )
128
+ try {
129
+ asynchttpGet(callback, params, data)
130
+ } catch (Exception e) {
131
+ logDebug(" Call failed: ${ e.message} " )
132
+ return null
133
+ }
134
+ }
0 commit comments