node-red-contrib-eskomsepush 0.0.14 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/nodes/eskomsepush.html +8 -1
- package/src/nodes/eskomsepush.js +69 -41
package/package.json
CHANGED
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
area: {value:""},
|
|
38
38
|
statusselect: {value:"", validate: RED.validators.regex(/^(eskom|capetown)$/)},
|
|
39
39
|
test: { value: false },
|
|
40
|
-
verbose: {value: false}
|
|
40
|
+
verbose: {value: false},
|
|
41
|
+
api_allowance_buffer: {value: 0, validate: RED.validators.regex(/^[0-9]+$/)}
|
|
41
42
|
},
|
|
42
43
|
inputs:1,
|
|
43
44
|
outputs:2,
|
|
@@ -110,6 +111,10 @@
|
|
|
110
111
|
<option value="capetown">Cape Town</option>
|
|
111
112
|
</select>
|
|
112
113
|
</div>
|
|
114
|
+
<div class="form-row">
|
|
115
|
+
<label for="node-input-api_allowance_buffer"><i class="fa fa-shopping-bag"></i> API allowance buffer</label>
|
|
116
|
+
<input type="text" id="node-input-api_allowance_buffer" placeholder="0">
|
|
117
|
+
</div>
|
|
113
118
|
<div class="form-row">
|
|
114
119
|
<label style="min-width:190px" for="node-input-test"><i class="fa fa-volume-up"></i> Use test data</label>
|
|
115
120
|
<input type="checkbox" checked id="node-input-test" style="max-width:30px">
|
|
@@ -130,6 +135,7 @@
|
|
|
130
135
|
<input type="text" id="searchAreaText" placeholder="Area" disabled />
|
|
131
136
|
<button id="searchAreaId">Search</button><br />
|
|
132
137
|
</p>
|
|
138
|
+
|
|
133
139
|
</div>
|
|
134
140
|
<div class="form-row" style="margin-bottom:0px;">
|
|
135
141
|
<input type="checkbox" checked id="node-input-verbose" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
|
|
@@ -158,6 +164,7 @@ see how many queries you have left.</p>
|
|
|
158
164
|
<p>First you will need a <em>licence key</em>. You can get one from <a href="https://eskomsepush.gumroad.com/l/api">here</a>, by subsribing to the Free model. Note that this is for personal use only.</p>
|
|
159
165
|
<p>Next you need to insert the correct area. Once a valid license is filled out, the API can be used for searching the correct area id. Do note that this will cost some of the daily queries. If you don't want that and you already know the id of the area, fill out the area id manually.</p>
|
|
160
166
|
<p>Then you need to fill out which status to follow. This can be either <em>National</em> (eskom) or <em>Capetown</em>.</p>
|
|
167
|
+
<p>The <i>API allowance buffer</i> allows you to reserve some daily unused API calls (so you can use your API key for other integrations too). If you don't use that, set this to _0_ (zero).</p>
|
|
161
168
|
<p>If the <em>test</em> checkbox has been selected, test data for the area will be fetched instead of the actual schedule. This is useful when debugging.</p>
|
|
162
169
|
<p>The <em>verbose</em> checkbox will give some additional <tt>node.warn()</tt> messages, appearing in the debug tab. This is also useful when debugging.</p>
|
|
163
170
|
|
package/src/nodes/eskomsepush.js
CHANGED
|
@@ -20,11 +20,11 @@ module.exports = function (RED) {
|
|
|
20
20
|
|
|
21
21
|
function getMinutesToAPIReset () {
|
|
22
22
|
const now = new Date()
|
|
23
|
-
const targetTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 2, 0, 0)
|
|
23
|
+
const targetTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 2, 0, 0)
|
|
24
24
|
if (now > targetTime) {
|
|
25
|
-
targetTime.setDate(targetTime.getDate() + 1)
|
|
25
|
+
targetTime.setDate(targetTime.getDate() + 1)
|
|
26
26
|
}
|
|
27
|
-
const timeDiff = targetTime - now
|
|
27
|
+
const timeDiff = targetTime - now
|
|
28
28
|
const minutesLeft = Math.floor(timeDiff / (1000 * 60))
|
|
29
29
|
|
|
30
30
|
return minutesLeft
|
|
@@ -109,7 +109,7 @@ module.exports = function (RED) {
|
|
|
109
109
|
const now = new Date()
|
|
110
110
|
|
|
111
111
|
// Check allowance every ten minutes
|
|
112
|
-
if ((msg && msg.payload === 'allowance'
|
|
112
|
+
if ((msg && msg.payload === 'allowance') || EskomSePushInfo.api.lastUpdate === null || (now.getTime() - EskomSePushInfo.api.lastUpdate.getTime()) > 600000) {
|
|
113
113
|
checkAllowance(node)
|
|
114
114
|
}
|
|
115
115
|
|
|
@@ -126,19 +126,38 @@ module.exports = function (RED) {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// Fetching actual information takes 2 calls, so calculate how long until the next API count
|
|
129
|
-
// reset and divide the calls over the day. Wait at least
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
// reset and divide the calls over the day. Wait at least 60 minutes between calls
|
|
130
|
+
// reduce limit by api_allowance_buffer to cater for units consumed by other API calls
|
|
131
|
+
if (node.config.verbose === true) {
|
|
132
|
+
node.warn('Minutes to API Reset: ' + getMinutesToAPIReset())
|
|
133
|
+
}
|
|
134
|
+
const allowanceRemaining = EskomSePushInfo.api.info.allowance.limit - node.config.api_allowance_buffer - EskomSePushInfo.api.info.allowance.count
|
|
135
|
+
|
|
136
|
+
if (allowanceRemaining > 0) {
|
|
137
|
+
EskomSePushInfo.calc.sleeptime = Math.round(getMinutesToAPIReset() / Math.ceil(allowanceRemaining / 2))
|
|
138
|
+
if (node.config.verbose === true) {
|
|
139
|
+
node.warn('API allowance limit: ' + EskomSePushInfo.api.info.allowance.limit)
|
|
140
|
+
node.warn('API allowance count: ' + EskomSePushInfo.api.info.allowance.count)
|
|
141
|
+
node.warn('Calculated sleeptime: ' + EskomSePushInfo.calc.sleeptime)
|
|
142
|
+
}
|
|
143
|
+
if (EskomSePushInfo.calc.sleeptime < 10) {
|
|
144
|
+
EskomSePushInfo.calc.sleeptime = 10
|
|
145
|
+
if (node.config.verbose === true) {
|
|
146
|
+
node.warn('Calculated sleeptime was less than 10. Set it to 10: ' + EskomSePushInfo.calc.sleeptime)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
133
149
|
} else {
|
|
134
|
-
EskomSePushInfo.calc.sleeptime =
|
|
150
|
+
EskomSePushInfo.calc.sleeptime = 60
|
|
151
|
+
if (node.config.verbose === true) {
|
|
152
|
+
node.warn('Set sleeptime to 60 since allowance count is low: ' + EskomSePushInfo.calc.sleeptime)
|
|
153
|
+
}
|
|
135
154
|
}
|
|
136
155
|
|
|
137
|
-
if ((
|
|
156
|
+
if ((msg && msg.payload === 'stage') || EskomSePushInfo.status.lastUpdate === null || (now.getTime() - EskomSePushInfo.status.lastUpdate) > (EskomSePushInfo.calc.sleeptime * 60000)) {
|
|
138
157
|
checkStage(node)
|
|
139
158
|
}
|
|
140
159
|
|
|
141
|
-
if ((
|
|
160
|
+
if ((msg && msg.payload === 'area') || EskomSePushInfo.area.lastUpdate === null || (now.getTime() - EskomSePushInfo.area.lastUpdate) > (EskomSePushInfo.calc.sleeptime * 60000)) {
|
|
142
161
|
checkArea(node)
|
|
143
162
|
}
|
|
144
163
|
|
|
@@ -187,30 +206,39 @@ module.exports = function (RED) {
|
|
|
187
206
|
// So not just like events, where they are in UTC with an offset
|
|
188
207
|
let BreakLoop = false
|
|
189
208
|
for (const dates of EskomSePushInfo.area.info.schedule.days) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// This schedule is either active or will be next
|
|
199
|
-
if (now >= ScheduleStart) {
|
|
200
|
-
EskomSePushInfo.calc.active = true
|
|
201
|
-
EskomSePushInfo.calc.type = 'schedule'
|
|
202
|
-
EskomSePushInfo.calc.start = ScheduleStart
|
|
203
|
-
EskomSePushInfo.calc.end = ScheduleEnd
|
|
204
|
-
} else {
|
|
205
|
-
EskomSePushInfo.calc.next = {
|
|
206
|
-
type: 'schedule',
|
|
207
|
-
start: ScheduleStart,
|
|
208
|
-
end: ScheduleEnd,
|
|
209
|
-
stage: EskomSePushInfo.calc.stage
|
|
209
|
+
const stageIndex = EskomSePushInfo.calc.stage - 1
|
|
210
|
+
if (stageIndex >= 0 && stageIndex < dates.stages.length) {
|
|
211
|
+
if (Array.isArray(dates.stages[stageIndex])) {
|
|
212
|
+
for (const schedule of dates.stages[stageIndex]) {
|
|
213
|
+
const ScheduleStart = Date.parse(dates.date + ' ' + schedule.split('-')[0])
|
|
214
|
+
let ScheduleEnd = Date.parse(dates.date + ' ' + schedule.split('-')[1])
|
|
215
|
+
if (ScheduleEnd < ScheduleStart) {
|
|
216
|
+
ScheduleEnd += (24 * 60 * 60 * 1000)
|
|
210
217
|
}
|
|
218
|
+
if (now < ScheduleEnd) {
|
|
219
|
+
BreakLoop = true
|
|
220
|
+
// This schedule is either active or will be next
|
|
221
|
+
if (now >= ScheduleStart) {
|
|
222
|
+
EskomSePushInfo.calc.active = true
|
|
223
|
+
EskomSePushInfo.calc.type = 'schedule'
|
|
224
|
+
EskomSePushInfo.calc.start = ScheduleStart
|
|
225
|
+
EskomSePushInfo.calc.end = ScheduleEnd
|
|
226
|
+
} else {
|
|
227
|
+
EskomSePushInfo.calc.next = {
|
|
228
|
+
type: 'schedule',
|
|
229
|
+
start: ScheduleStart,
|
|
230
|
+
end: ScheduleEnd,
|
|
231
|
+
stage: EskomSePushInfo.calc.stage
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (BreakLoop) { break }
|
|
211
236
|
}
|
|
237
|
+
} else {
|
|
238
|
+
console.warn('Not an array:', dates.stages[stageIndex]) // Warning if not an array
|
|
212
239
|
}
|
|
213
|
-
|
|
240
|
+
} else {
|
|
241
|
+
console.warn('Invalid stage index:', stageIndex) // Warning if stage index is out of bounds
|
|
214
242
|
}
|
|
215
243
|
if (BreakLoop) { break }
|
|
216
244
|
}
|
|
@@ -219,7 +247,7 @@ module.exports = function (RED) {
|
|
|
219
247
|
EskomSePushInfo.calc.next.duration = (EskomSePushInfo.calc.next.end - EskomSePushInfo.calc.next.start) / 1000
|
|
220
248
|
EskomSePushInfo.calc.next.islong = EskomSePushInfo.calc.next.duration >= (4 * 3600)
|
|
221
249
|
EskomSePushInfo.calc.secondstostatechange = parseInt((EskomSePushInfo.calc.next.start - now) / 1000)
|
|
222
|
-
EskomSePushInfo.calc.next.isHigherStage = EskomSePushInfo.calc.next.stage > EskomSePushInfo.calc.
|
|
250
|
+
EskomSePushInfo.calc.next.isHigherStage = EskomSePushInfo.calc.next.stage > EskomSePushInfo.calc.stage
|
|
223
251
|
}
|
|
224
252
|
|
|
225
253
|
if (EskomSePushInfo.calc.active) {
|
|
@@ -257,16 +285,16 @@ module.exports = function (RED) {
|
|
|
257
285
|
if (EskomSePushInfo.calc.type === 'event') {
|
|
258
286
|
shape = 'dot'
|
|
259
287
|
}
|
|
260
|
-
if (
|
|
261
|
-
statusText += new Date(EskomSePushInfo.calc.start).toLocaleTimeString([], {timeStyle: 'short'})
|
|
262
|
-
statusText += ' - ' + new Date(EskomSePushInfo.calc.end).toLocaleTimeString([], {timeStyle: 'short'})
|
|
288
|
+
if (EskomSePushInfo.calc.start) {
|
|
289
|
+
statusText += new Date(EskomSePushInfo.calc.start).toLocaleTimeString([], { timeStyle: 'short' })
|
|
290
|
+
statusText += ' - ' + new Date(EskomSePushInfo.calc.end).toLocaleTimeString([], { timeStyle: 'short' })
|
|
263
291
|
}
|
|
264
292
|
} else {
|
|
265
|
-
if (new Date(EskomSePushInfo.calc.next.start).getUTCDay() !==
|
|
266
|
-
statusText += new Date(EskomSePushInfo.calc.next.start).toLocaleString([], {weekday: 'short'}) + ' '
|
|
293
|
+
if (new Date(EskomSePushInfo.calc.next.start).getUTCDay() !== now.getUTCDate) {
|
|
294
|
+
statusText += new Date(EskomSePushInfo.calc.next.start).toLocaleString([], { weekday: 'short' }) + ' '
|
|
267
295
|
}
|
|
268
|
-
statusText += new Date(EskomSePushInfo.calc.next.start).toLocaleTimeString([], {timeStyle: 'short'})
|
|
269
|
-
statusText += ' - ' + new Date(EskomSePushInfo.calc.next.end).toLocaleTimeString([], {timeStyle: 'short'})
|
|
296
|
+
statusText += new Date(EskomSePushInfo.calc.next.start).toLocaleTimeString([], { timeStyle: 'short' })
|
|
297
|
+
statusText += ' - ' + new Date(EskomSePushInfo.calc.next.end).toLocaleTimeString([], { timeStyle: 'short' })
|
|
270
298
|
}
|
|
271
299
|
|
|
272
300
|
statusText += ' (API: ' + EskomSePushInfo.api.info.allowance.count + '/' + EskomSePushInfo.api.info.allowance.limit + ')'
|
|
@@ -286,7 +314,7 @@ module.exports = function (RED) {
|
|
|
286
314
|
updateSheddingStatus(node)
|
|
287
315
|
}, 60000)
|
|
288
316
|
|
|
289
|
-
node.on('input', function(msg) {
|
|
317
|
+
node.on('input', function (msg) {
|
|
290
318
|
updateSheddingStatus(node, msg)
|
|
291
319
|
})
|
|
292
320
|
|