node-red-contrib-eskomsepush 0.0.14 → 0.0.15

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-eskomsepush",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "description": "Node-RED interface for the Eskomsepush API",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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&#39;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
 
@@ -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' ) || EskomSePushInfo.api.lastUpdate === null || (now.getTime() - EskomSePushInfo.api.lastUpdate.getTime()) > 600000) {
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 10 minutes between calls
130
- if ((EskomSePushInfo.api.info.allowance.limit - EskomSePushInfo.api.info.allowance.count) > 0) {
131
- EskomSePushInfo.calc.sleeptime = (getMinutesToAPIReset() / ((EskomSePushInfo.api.info.allowance.limit - EskomSePushInfo.api.info.allowance.count) / 2)).toFixed(0)
132
- if (EskomSePushInfo.calc.sleeptime < 10) { EskomSePushInfo.calc.sleeptime = 10 }
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 < 60) {
144
+ EskomSePushInfo.calc.sleeptime = 60
145
+ if (node.config.verbose === true) {
146
+ node.warn('Calculated sleeptime was less than 60. Set it to 60: ' + EskomSePushInfo.calc.sleeptime)
147
+ }
148
+ }
133
149
  } else {
134
- EskomSePushInfo.calc.sleeptime = 30
150
+ EskomSePushInfo.calc.sleeptime = 120
151
+ if (node.config.verbose === true) {
152
+ node.warn('Set sleeptime to 120 since allowance count is low: ' + EskomSePushInfo.calc.sleeptime)
153
+ }
135
154
  }
136
155
 
137
- if (( msg && msg.payload === 'stage' ) || EskomSePushInfo.status.lastUpdate === null || (now.getTime() - EskomSePushInfo.status.lastUpdate) > (EskomSePushInfo.calc.sleeptime * 60000)) {
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 (( msg && msg.payload === 'area' ) || EskomSePushInfo.area.lastUpdate === null || (now.getTime() - EskomSePushInfo.area.lastUpdate) > (EskomSePushInfo.calc.sleeptime * 60000)) {
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
- for (const schedule of dates.stages[EskomSePushInfo.calc.stage-1]) {
191
- const ScheduleStart = Date.parse(dates.date + ' ' + schedule.split('-')[0])
192
- let ScheduleEnd = Date.parse(dates.date + ' ' + schedule.split('-')[1])
193
- if (ScheduleEnd < ScheduleStart) {
194
- ScheduleEnd += (24 * 60 * 60 * 1000)
195
- }
196
- if (now < ScheduleEnd) {
197
- BreakLoop = true
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
- if (BreakLoop) { break }
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.next.stage
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 ( EskomSePushInfo.calc.start ) {
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() !== now.getUTCDate) {
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