I have this running on the gateway as a timer script (600 000ms), it seems if you poll it too often you get issues.
print "Eskom Loadshedding Script executed"
#Scrape loadshedding value from Eskom's site
#Eskom uses 1 for not loadshedding, 2 for Stage 1, etc
Stage = -1
try:
HTTPString = system.net.httpGet("https://loadshedding.eskom.co.za/LoadShedding/GetStatus")
Stage = int(HTTPString)
print "- Status Updated"
system.tag.writeBlocking(["[default]Global/Loadshedding_LastUpdate"],[system.date.now()])
except:
print "- Update failed"
print "- Reason:" + str(sys.exc_info())
print "- Status last updated at: " + system.date.format(system.tag.readBlocking(["[default]Global/Loadshedding_LastUpdate"]), "yyyy-MM-dd HH:mm:ss")
#if value is incorrectly read it will be 0, convert this to null on the tag
#Sometimes the response is a negative number, assuming this means a faulty read, ignore this
if Stage < 0:
Dummy = 1
elif Stage == 0:
system.tag.write("[default]Global/Loadshedding_Stage",null)
else:
system.tag.write("[default]Global/Loadshedding_Stage",Stage-1)
Not sure if this is the best way to do it, but it works for me
value = int(system.net.httpGet("https://loadshedding.eskom.co.za/LoadShedding/GetStatus"))
system.tag.writeBlocking(['[Power Monitoring]Load Shedding/Eskom LS Stage'], [value])
Have you been able to get the schedule? And convert it into something useful?
The schedule API only works for Eskom direct suburbs.
I programmed the entire schedule by hand based on day of month and the stage (get that through the API you mentioned). The only problem is the shifting stages, but it works well enough for me.
If this is a legit commercial application, Eskom se Push have a very good API, but it is exorbitantly expensive in my opinion. Cheapest tier of R18k/month is rough
Zip file is Beautiful soup
Unzip and put all folders in the gateway's /user-lib/pylib/site-packages folder. bs4.zip (468.4 KB)
from bs4 import BeautifulSoup
# replace with your httpGet of httpClient response
response = system.file.readFileAsString('c:/test/702.html')
# Parse html with bs4
dataIn = BeautifulSoup(response)
# Get all of the scheduleDay classes
days = dataIn.findAll('div', {'class':'scheduleDay'})
headers = ['day', 'start', 'end']
data = []
# Get today's date
today = system.date.midnight(system.date.now())
# Extract year and subtract 1900 for use in setYear()
currentYear = system.date.getYear(system.date.now())-1900
for day in days:
dateString = day.find('div', {'class':'dayMonth'}).contents[0].strip()
date = system.date.parse(dateString, 'E, dd MMM')
date.setYear(currentYear)
#if date < today:
#date = system.date.addYears(date, 1)
data.extend([[date] + time.contents[0].split(' - ') for time in day.findAll('a')])
dataset = system.dataset.toDataSet(headers, data)
util.printDataSet(dataset)
Output
row | day | start | end
--------------------------------------------------
0 | Mon Mar 06 00:00:00 EST 2023 | 05:00 | 07:30
1 | Mon Mar 06 00:00:00 EST 2023 | 13:00 | 15:30
2 | Mon Mar 06 00:00:00 EST 2023 | 21:00 | 23:30
3 | Tue Mar 07 00:00:00 EST 2023 | 05:00 | 07:30
4 | Tue Mar 07 00:00:00 EST 2023 | 13:00 | 15:30
5 | Tue Mar 07 00:00:00 EST 2023 | 21:00 | 23:30
6 | Wed Mar 08 00:00:00 EST 2023 | 05:00 | 07:30
7 | Wed Mar 08 00:00:00 EST 2023 | 13:00 | 15:30
8 | Wed Mar 08 00:00:00 EST 2023 | 21:00 | 23:30
9 | Thu Mar 09 00:00:00 EST 2023 | 03:00 | 05:30
10 | Thu Mar 09 00:00:00 EST 2023 | 11:00 | 13:30
11 | Thu Mar 09 00:00:00 EST 2023 | 19:00 | 21:30
12 | Fri Mar 10 00:00:00 EST 2023 | 03:00 | 05:30
13 | Fri Mar 10 00:00:00 EST 2023 | 11:00 | 13:30
14 | Fri Mar 10 00:00:00 EST 2023 | 19:00 | 21:30
15 | Sat Mar 11 00:00:00 EST 2023 | 03:00 | 05:30
16 | Sat Mar 11 00:00:00 EST 2023 | 11:00 | 13:30
17 | Sat Mar 11 00:00:00 EST 2023 | 19:00 | 21:30
18 | Sun Mar 12 00:00:00 EST 2023 | 03:00 | 05:30
19 | Sun Mar 12 00:00:00 EST 2023 | 11:00 | 13:30
20 | Sun Mar 12 00:00:00 EST 2023 | 19:00 | 21:30
21 | Mon Mar 13 00:00:00 EDT 2023 | 01:00 | 03:30
22 | Mon Mar 13 00:00:00 EDT 2023 | 09:00 | 11:30
23 | Mon Mar 13 00:00:00 EDT 2023 | 17:00 | 19:30
24 | Tue Mar 14 00:00:00 EDT 2023 | 01:00 | 03:30
25 | Tue Mar 14 00:00:00 EDT 2023 | 09:00 | 11:30
26 | Tue Mar 14 00:00:00 EDT 2023 | 17:00 | 19:30
27 | Wed Mar 15 00:00:00 EDT 2023 | 01:00 | 03:30
28 | Wed Mar 15 00:00:00 EDT 2023 | 09:00 | 11:30
29 | Wed Mar 15 00:00:00 EDT 2023 | 17:00 | 19:30
30 | Thu Mar 16 00:00:00 EDT 2023 | 01:00 | 03:30
31 | Thu Mar 16 00:00:00 EDT 2023 | 09:00 | 11:30
32 | Thu Mar 16 00:00:00 EDT 2023 | 17:00 | 19:30
33 | Fri Mar 17 00:00:00 EDT 2023 | 07:00 | 09:30
34 | Fri Mar 17 00:00:00 EDT 2023 | 15:00 | 17:30
35 | Fri Mar 17 00:00:00 EDT 2023 | 23:00 | 01:30
36 | Sat Mar 18 00:00:00 EDT 2023 | 07:00 | 09:30
37 | Sat Mar 18 00:00:00 EDT 2023 | 15:00 | 17:30
38 | Sat Mar 18 00:00:00 EDT 2023 | 23:00 | 01:30
39 | Sun Mar 19 00:00:00 EDT 2023 | 07:00 | 09:30
40 | Sun Mar 19 00:00:00 EDT 2023 | 15:00 | 17:30
41 | Sun Mar 19 00:00:00 EDT 2023 | 23:00 | 01:30
42 | Mon Mar 20 00:00:00 EDT 2023 | 07:00 | 09:30
43 | Mon Mar 20 00:00:00 EDT 2023 | 15:00 | 17:30
44 | Mon Mar 20 00:00:00 EDT 2023 | 23:00 | 01:30
45 | Tue Mar 21 00:00:00 EDT 2023 | 05:00 | 07:30
46 | Tue Mar 21 00:00:00 EDT 2023 | 13:00 | 15:30
47 | Tue Mar 21 00:00:00 EDT 2023 | 21:00 | 23:30
48 | Wed Mar 22 00:00:00 EDT 2023 | 05:00 | 07:30
49 | Wed Mar 22 00:00:00 EDT 2023 | 13:00 | 15:30
50 | Wed Mar 22 00:00:00 EDT 2023 | 21:00 | 23:30
51 | Thu Mar 23 00:00:00 EDT 2023 | 05:00 | 07:30
52 | Thu Mar 23 00:00:00 EDT 2023 | 13:00 | 15:30
53 | Thu Mar 23 00:00:00 EDT 2023 | 21:00 | 23:30
54 | Fri Mar 24 00:00:00 EDT 2023 | 05:00 | 07:30
55 | Fri Mar 24 00:00:00 EDT 2023 | 13:00 | 15:30
56 | Fri Mar 24 00:00:00 EDT 2023 | 21:00 | 23:30
57 | Sat Mar 25 00:00:00 EDT 2023 | 03:00 | 05:30
58 | Sat Mar 25 00:00:00 EDT 2023 | 11:00 | 13:30
59 | Sat Mar 25 00:00:00 EDT 2023 | 19:00 | 21:30
60 | Sun Mar 26 00:00:00 EDT 2023 | 03:00 | 05:30
61 | Sun Mar 26 00:00:00 EDT 2023 | 11:00 | 13:30
62 | Sun Mar 26 00:00:00 EDT 2023 | 19:00 | 21:30
63 | Mon Mar 27 00:00:00 EDT 2023 | 03:00 | 05:30
64 | Mon Mar 27 00:00:00 EDT 2023 | 11:00 | 13:30
65 | Mon Mar 27 00:00:00 EDT 2023 | 19:00 | 21:30
66 | Tue Mar 28 00:00:00 EDT 2023 | 03:00 | 05:30
67 | Tue Mar 28 00:00:00 EDT 2023 | 11:00 | 13:30
68 | Tue Mar 28 00:00:00 EDT 2023 | 19:00 | 21:30
69 | Wed Mar 29 00:00:00 EDT 2023 | 01:00 | 03:30
70 | Wed Mar 29 00:00:00 EDT 2023 | 09:00 | 11:30
71 | Wed Mar 29 00:00:00 EDT 2023 | 17:00 | 19:30
72 | Thu Mar 30 00:00:00 EDT 2023 | 01:00 | 03:30
73 | Thu Mar 30 00:00:00 EDT 2023 | 09:00 | 11:30
74 | Thu Mar 30 00:00:00 EDT 2023 | 17:00 | 19:30
75 | Fri Mar 31 00:00:00 EDT 2023 | 01:00 | 03:30
76 | Fri Mar 31 00:00:00 EDT 2023 | 09:00 | 11:30
77 | Fri Mar 31 00:00:00 EDT 2023 | 17:00 | 19:30
78 | Sat Apr 01 00:00:00 EDT 2023 | 07:00 | 09:30
79 | Sat Apr 01 00:00:00 EDT 2023 | 15:00 | 17:30
80 | Sat Apr 01 00:00:00 EDT 2023 | 23:00 | 01:30
81 | Sun Apr 02 00:00:00 EDT 2023 | 07:00 | 09:30
82 | Sun Apr 02 00:00:00 EDT 2023 | 15:00 | 17:30
83 | Sun Apr 02 00:00:00 EDT 2023 | 23:00 | 01:30
84 | Mon Apr 03 00:00:00 EDT 2023 | 07:00 | 09:30
85 | Mon Apr 03 00:00:00 EDT 2023 | 15:00 | 17:30
86 | Mon Apr 03 00:00:00 EDT 2023 | 23:00 | 01:30
Thank You. I feel like it's Christmas.
I did get this error.
Traceback (most recent call last): File "<input>", line 35, in <module> NameError: name 'util' is not defined
What would be the best way in insert that data into Microsoft SQL?
Only overwriting the most resent date from data to future.
I think you can remove the last line, that's just to show you the output. your schedule information is in 'dataset' already. You'd take that data stored in 'dataset'. Loop through it and write it into SQL. I don't have an example on hand, but maybe have a look at this. There seems to be many examples of writing a dataset into SQL on the forums
This one may be a bit more useful, to have the start and end times as dates. Since the information changes fairly often, I'd keep it in a dataset tag.
EDIT: modified to handle transitions over midnight.
from bs4 import BeautifulSoup
def hhmmToMinutes(timeIn):
'''helper function to return an offset in minutes.
example: hhmmToMinutes('15:30') returns 930
'''
hours, minutes = [int(unit) for unit in timeIn.split(':')]
return hours*60 + minutes
# replace with your httpGet of httpClient response
response = system.file.readFileAsString('c:/test/702.html')
# Parse html with bs4
dataIn = BeautifulSoup(response)
# Get all of the scheduleDay classes
days = dataIn.findAll('div', {'class':'scheduleDay'})
headers = ['start', 'end']
data = []
# Get today's date
today = system.date.midnight(system.date.now())
# Extract year and subtract 1900 for use in setYear() of the Date class.
currentYear = system.date.getYear(system.date.now())-1900
for day in days:
# find the day in the schedule and convert to a Date
dateString = day.find('div', {'class':'dayMonth'}).contents[0].strip()
date = system.date.parse(dateString, 'E, dd MMM')
# set the year to the current year.
date.setYear(currentYear)
# If the date is before today, assume it's for next year.
# Useful for December to January boundaries
if date < today:
date = system.date.addYears(date, 1)
# fint the shed times and add them to the date.
for shedTime in day.findAll('a'):
timeOffsets = [system.date.addMinutes(date, hhmmToMinutes(time)) for time in shedTime.contents[0].split(' - ')]
# Check if the end time is before the start time. if yes, add 1 day.
if system.date.isBefore(timeOffsets[1], timeOffsets[0]):
timeOffsets[1] = system.date.addDays(timeOffsets[1], 1)
data.append(timeOffsets)
dataset = system.dataset.toDataSet(headers, data)
system.tag.writeBlocking(['[Test]Result'], [dataset])
Dataset. Note that I had added a test so that if a date is before the current date, it adds a year. This would take care of the transitions from December to January. Since I'm using 'old' data, the first few rows are in 2024.
row | start | end
-----------------------------------------------------------------
0 | Wed Mar 06 05:00:00 EST 2024 | Wed Mar 06 07:30:00 EST 2024
1 | Wed Mar 06 13:00:00 EST 2024 | Wed Mar 06 15:30:00 EST 2024
2 | Wed Mar 06 21:00:00 EST 2024 | Wed Mar 06 23:30:00 EST 2024
3 | Thu Mar 07 05:00:00 EST 2024 | Thu Mar 07 07:30:00 EST 2024
4 | Thu Mar 07 13:00:00 EST 2024 | Thu Mar 07 15:30:00 EST 2024
5 | Thu Mar 07 21:00:00 EST 2024 | Thu Mar 07 23:30:00 EST 2024
6 | Wed Mar 08 05:00:00 EST 2023 | Wed Mar 08 07:30:00 EST 2023
7 | Wed Mar 08 13:00:00 EST 2023 | Wed Mar 08 15:30:00 EST 2023
8 | Wed Mar 08 21:00:00 EST 2023 | Wed Mar 08 23:30:00 EST 2023
9 | Thu Mar 09 03:00:00 EST 2023 | Thu Mar 09 05:30:00 EST 2023
10 | Thu Mar 09 11:00:00 EST 2023 | Thu Mar 09 13:30:00 EST 2023
11 | Thu Mar 09 19:00:00 EST 2023 | Thu Mar 09 21:30:00 EST 2023
12 | Fri Mar 10 03:00:00 EST 2023 | Fri Mar 10 05:30:00 EST 2023
13 | Fri Mar 10 11:00:00 EST 2023 | Fri Mar 10 13:30:00 EST 2023
14 | Fri Mar 10 19:00:00 EST 2023 | Fri Mar 10 21:30:00 EST 2023
15 | Sat Mar 11 03:00:00 EST 2023 | Sat Mar 11 05:30:00 EST 2023
16 | Sat Mar 11 11:00:00 EST 2023 | Sat Mar 11 13:30:00 EST 2023
17 | Sat Mar 11 19:00:00 EST 2023 | Sat Mar 11 21:30:00 EST 2023
18 | Sun Mar 12 04:00:00 EDT 2023 | Sun Mar 12 06:30:00 EDT 2023
19 | Sun Mar 12 12:00:00 EDT 2023 | Sun Mar 12 14:30:00 EDT 2023
20 | Sun Mar 12 20:00:00 EDT 2023 | Sun Mar 12 22:30:00 EDT 2023
21 | Mon Mar 13 01:00:00 EDT 2023 | Mon Mar 13 03:30:00 EDT 2023
22 | Mon Mar 13 09:00:00 EDT 2023 | Mon Mar 13 11:30:00 EDT 2023
23 | Mon Mar 13 17:00:00 EDT 2023 | Mon Mar 13 19:30:00 EDT 2023
24 | Tue Mar 14 01:00:00 EDT 2023 | Tue Mar 14 03:30:00 EDT 2023
25 | Tue Mar 14 09:00:00 EDT 2023 | Tue Mar 14 11:30:00 EDT 2023
26 | Tue Mar 14 17:00:00 EDT 2023 | Tue Mar 14 19:30:00 EDT 2023
27 | Wed Mar 15 01:00:00 EDT 2023 | Wed Mar 15 03:30:00 EDT 2023
28 | Wed Mar 15 09:00:00 EDT 2023 | Wed Mar 15 11:30:00 EDT 2023
29 | Wed Mar 15 17:00:00 EDT 2023 | Wed Mar 15 19:30:00 EDT 2023
30 | Thu Mar 16 01:00:00 EDT 2023 | Thu Mar 16 03:30:00 EDT 2023
31 | Thu Mar 16 09:00:00 EDT 2023 | Thu Mar 16 11:30:00 EDT 2023
32 | Thu Mar 16 17:00:00 EDT 2023 | Thu Mar 16 19:30:00 EDT 2023
33 | Fri Mar 17 07:00:00 EDT 2023 | Fri Mar 17 09:30:00 EDT 2023
34 | Fri Mar 17 15:00:00 EDT 2023 | Fri Mar 17 17:30:00 EDT 2023
35 | Fri Mar 17 23:00:00 EDT 2023 | Fri Mar 17 01:30:00 EDT 2023
36 | Sat Mar 18 07:00:00 EDT 2023 | Sat Mar 18 09:30:00 EDT 2023
37 | Sat Mar 18 15:00:00 EDT 2023 | Sat Mar 18 17:30:00 EDT 2023
38 | Sat Mar 18 23:00:00 EDT 2023 | Sat Mar 18 01:30:00 EDT 2023
39 | Sun Mar 19 07:00:00 EDT 2023 | Sun Mar 19 09:30:00 EDT 2023
40 | Sun Mar 19 15:00:00 EDT 2023 | Sun Mar 19 17:30:00 EDT 2023
41 | Sun Mar 19 23:00:00 EDT 2023 | Sun Mar 19 01:30:00 EDT 2023
42 | Mon Mar 20 07:00:00 EDT 2023 | Mon Mar 20 09:30:00 EDT 2023
43 | Mon Mar 20 15:00:00 EDT 2023 | Mon Mar 20 17:30:00 EDT 2023
44 | Mon Mar 20 23:00:00 EDT 2023 | Mon Mar 20 01:30:00 EDT 2023
45 | Tue Mar 21 05:00:00 EDT 2023 | Tue Mar 21 07:30:00 EDT 2023
46 | Tue Mar 21 13:00:00 EDT 2023 | Tue Mar 21 15:30:00 EDT 2023
47 | Tue Mar 21 21:00:00 EDT 2023 | Tue Mar 21 23:30:00 EDT 2023
48 | Wed Mar 22 05:00:00 EDT 2023 | Wed Mar 22 07:30:00 EDT 2023
49 | Wed Mar 22 13:00:00 EDT 2023 | Wed Mar 22 15:30:00 EDT 2023
50 | Wed Mar 22 21:00:00 EDT 2023 | Wed Mar 22 23:30:00 EDT 2023
51 | Thu Mar 23 05:00:00 EDT 2023 | Thu Mar 23 07:30:00 EDT 2023
52 | Thu Mar 23 13:00:00 EDT 2023 | Thu Mar 23 15:30:00 EDT 2023
53 | Thu Mar 23 21:00:00 EDT 2023 | Thu Mar 23 23:30:00 EDT 2023
54 | Fri Mar 24 05:00:00 EDT 2023 | Fri Mar 24 07:30:00 EDT 2023
55 | Fri Mar 24 13:00:00 EDT 2023 | Fri Mar 24 15:30:00 EDT 2023
56 | Fri Mar 24 21:00:00 EDT 2023 | Fri Mar 24 23:30:00 EDT 2023
57 | Sat Mar 25 03:00:00 EDT 2023 | Sat Mar 25 05:30:00 EDT 2023
58 | Sat Mar 25 11:00:00 EDT 2023 | Sat Mar 25 13:30:00 EDT 2023
59 | Sat Mar 25 19:00:00 EDT 2023 | Sat Mar 25 21:30:00 EDT 2023
60 | Sun Mar 26 03:00:00 EDT 2023 | Sun Mar 26 05:30:00 EDT 2023
61 | Sun Mar 26 11:00:00 EDT 2023 | Sun Mar 26 13:30:00 EDT 2023
62 | Sun Mar 26 19:00:00 EDT 2023 | Sun Mar 26 21:30:00 EDT 2023
63 | Mon Mar 27 03:00:00 EDT 2023 | Mon Mar 27 05:30:00 EDT 2023
64 | Mon Mar 27 11:00:00 EDT 2023 | Mon Mar 27 13:30:00 EDT 2023
65 | Mon Mar 27 19:00:00 EDT 2023 | Mon Mar 27 21:30:00 EDT 2023
66 | Tue Mar 28 03:00:00 EDT 2023 | Tue Mar 28 05:30:00 EDT 2023
67 | Tue Mar 28 11:00:00 EDT 2023 | Tue Mar 28 13:30:00 EDT 2023
68 | Tue Mar 28 19:00:00 EDT 2023 | Tue Mar 28 21:30:00 EDT 2023
69 | Wed Mar 29 01:00:00 EDT 2023 | Wed Mar 29 03:30:00 EDT 2023
70 | Wed Mar 29 09:00:00 EDT 2023 | Wed Mar 29 11:30:00 EDT 2023
71 | Wed Mar 29 17:00:00 EDT 2023 | Wed Mar 29 19:30:00 EDT 2023
72 | Thu Mar 30 01:00:00 EDT 2023 | Thu Mar 30 03:30:00 EDT 2023
73 | Thu Mar 30 09:00:00 EDT 2023 | Thu Mar 30 11:30:00 EDT 2023
74 | Thu Mar 30 17:00:00 EDT 2023 | Thu Mar 30 19:30:00 EDT 2023
75 | Fri Mar 31 01:00:00 EDT 2023 | Fri Mar 31 03:30:00 EDT 2023
76 | Fri Mar 31 09:00:00 EDT 2023 | Fri Mar 31 11:30:00 EDT 2023
77 | Fri Mar 31 17:00:00 EDT 2023 | Fri Mar 31 19:30:00 EDT 2023
78 | Sat Apr 01 07:00:00 EDT 2023 | Sat Apr 01 09:30:00 EDT 2023
79 | Sat Apr 01 15:00:00 EDT 2023 | Sat Apr 01 17:30:00 EDT 2023
80 | Sat Apr 01 23:00:00 EDT 2023 | Sat Apr 01 01:30:00 EDT 2023
81 | Sun Apr 02 07:00:00 EDT 2023 | Sun Apr 02 09:30:00 EDT 2023
82 | Sun Apr 02 15:00:00 EDT 2023 | Sun Apr 02 17:30:00 EDT 2023
83 | Sun Apr 02 23:00:00 EDT 2023 | Sun Apr 02 01:30:00 EDT 2023
84 | Mon Apr 03 07:00:00 EDT 2023 | Mon Apr 03 09:30:00 EDT 2023
85 | Mon Apr 03 15:00:00 EDT 2023 | Mon Apr 03 17:30:00 EDT 2023
86 | Mon Apr 03 23:00:00 EDT 2023 | Mon Apr 03 01:30:00 EDT 2023
Then, to test:
datesIn = system.dataset.toPyDataSet(system.tag.readBlocking(['[Test]Result'])[0].value)
now = system.date.now()
print any([system.date.isBetween(now, row['start'], row['end']) for row in datesIn])
Thank You very much. It works very well. We just had one at now at 13:00 with pre warning.
In the data row 86 it goes over midnight. The load shedding normally last 2.5 hours.
Even if they overlap it would be 13:00-15:30 then 15:00-16:30. (Stage 5 the over lapping starts)
Could it be possible just to add 2.5 hours to the start time for the end time.