@TrystanLea
The EV charged overnight and, as usual this am, the Demand Shaper webpage showed SMART highlighted but no schedule bars for a future charge.
I then ran a test script incorporating yr suggested lines for which many thx:
import requests, json, os, time
# Emoncms server configuration ...
emoncms_apikey = "xxxxxxxxxxxxxxxxxx" # use appropriate key
emoncms_server = "http://127.0.0.1"
# Get the Demand Shaper data ...
params = (
('device', 'openevse'),
('apikey', emoncms_apikey)
)
reply = requests.get(emoncms_server+"/demandshaper/get", params=params)
jsonstr = reply.text.rstrip()
ds_data = json.loads(jsonstr)
print(reply.status_code) # Debugging only
print (ds_data) # Debugging only
# Extract relevant data from the json
# The following section for debugging only ...
data1 = ds_data['schedule']['settings']['ctrlmode']
data2 = ds_data['schedule']['settings']['on_completion']
data3 = ds_data['schedule']['settings']['target_soc']
data4 = ds_data['schedule']['settings']['divert_mode']
data5 = ds_data['schedule']['settings']['period']
data6 = ds_data['schedule']['runtime']['timeleft']
print (data1)
print (data2)
print (data3)
print (data4)
print (data5)
print (data6)
# End of above debugging section
# Demand Shaper modes ...
# divert_mode = 1 = ECO mode ON
# divert_mode = 2 = ECO mode OFF
# Other modes: 'smart' 'off' 'on' 'timer'
## FIXED DEMAND SHAPER PARAMETERS HERE ...
ds_data['schedule']['settings']['ctrlmode'] = 'smart'
ds_data['schedule']['settings']['on_completion'] = 'smart'
ds_data['schedule']['settings']['divert_mode'] = 1 # ECO mode ON
ds_data['schedule']['settings']['battery_capacity'] = 75 # kWh ... depends on EV
ds_data['schedule']['settings']['charge_rate'] = 6.9 # A ... for a single phase openEVSE charger
# ===================================================================
## SEASON VARIABLE PARAMETER ...
# Dependent on the Season and the need to leave 'space' in the EV battery for next days ANTICIPATED charge from excess solar gen
# Max is 0.9 - recognises the limit set to conserve battery life
# WINTER season = 0.9
# MID season = ???
# POOL season = ???
ds_data['schedule']['settings']['target_soc'] = 0.9
# ===================================================================
## CHANGES TO ENSURE SMART CHARGING DOES OCCUR - per @TrystanLea REF: https://community.openenergymonitor.org/t/emoncms-demand-shaper-module/9097/164
kwh_required = (ds_data['schedule']['settings']['target_soc']-ds_data['schedule']['settings']['current_soc'])*ds_data['schedule']['settings']['battery_capacity']
ds_data['schedule']['settings']['period'] = kwh_required/ds_data['schedule']['settings']['charge_rate']
if ds_data['schedule']['settings']['balpercentage'] < ds_data['schedule']['settings']['target_soc']:
ds_data['schedule']['settings']['period'] += ds_data['schedule']['settings']['baltime']
ds_data['schedule']['runtime']['timeleft'] = ds_data['schedule']['settings']['period'] * 3600;
# ===================================================================
# Now save all the changed parameters ...
reply = requests.post(emoncms_server+"/demandshaper/save", params=params, data={'schedule':json.dumps(ds_data['schedule'])})
print (data1) # Debugging only
print (data2) # Debugging only
print (data3) # Debugging only
print (data4) # Debugging only
print (data5) # Debugging only
print (data6) # Debugging only
print (ds_data) # Debugging only
print(reply.status_code) # Debugging only
print(reply.text) # Debugging only
The script ran without error with following result:
200
{'schedule': {'settings': {'device': 'openevse', 'device_type': 'openevse', 'device_name': 'openevse', 'ctrlmode': 'smart', 'period': 0.5434782608695657, 'end': 8, 'end_timestamp': 1610697600, 'interruptible': 0, 'runone': 0, 'on_completion': 'smart', 'forecast_config': [{'name': 'octopusagile', 'weight': 1, 'gsp_id': 'H'}], 'forecast_units': 'generic', 'timer': [{'start': 0, 'end': 0}, {'start': 0, 'end': 0}], 'ip': '', 'soc_source': 'input', 'battery_capacity': 75, 'charge_rate': 6.9, 'target_soc': 0.9, 'current_soc': 0.85, 'balpercentage': 0.9, 'baltime': 2, 'car_economy': 3.4, 'charge_energy': 3.75, 'charge_distance': 12.8, 'distance_units': 'miles', 'ovms_vehicleid': '', 'ovms_carpass': '', 'divert_mode': 1}, 'runtime': {'started': True, 'periods': [], 'timeleft': 0}}}
smart
smart
0.9
1
0.5434782608695657
0
smart
smart
0.9
1
0.5434782608695657
0
{'schedule': {'settings': {'device': 'openevse', 'device_type': 'openevse', 'device_name': 'openevse', 'ctrlmode': 'smart', 'period': 0.5434782608695657, 'end': 8, 'end_timestamp': 1610697600, 'interruptible': 0, 'runone': 0, 'on_completion': 'smart', 'forecast_config': [{'name': 'octopusagile', 'weight': 1, 'gsp_id': 'H'}], 'forecast_units': 'generic', 'timer': [{'start': 0, 'end': 0}, {'start': 0, 'end': 0}], 'ip': '', 'soc_source': 'input', 'battery_capacity': 75, 'charge_rate': 6.9, 'target_soc': 0.9, 'current_soc': 0.85, 'balpercentage': 0.9, 'baltime': 2, 'car_economy': 3.4, 'charge_energy': 3.75, 'charge_distance': 12.8, 'distance_units': 'miles', 'ovms_vehicleid': '', 'ovms_carpass': '', 'divert_mode': 1}, 'runtime': {'started': True, 'periods': [], 'timeleft': 1956.5217391304366}}}
200
{"success":true,"message":"Saved to redis only"}
pi@emonpi-node-15:~/ev-charging-scripts
timeleft is now showing in the json but still not periods
I restarted demandshaper.service to no avail. The schedule bars for the future charge were still not showing.
However per the screenshot, the Time left and future charge amount were showing – which is certainly on the way to a solution:
Finally I did a text search on file: main.js for periods, start & end:
Search for: periods, start & end
pi@emonpi-node-15:/opt/emoncms/modules/demandshaper/demandshaper-module/js $ grep -n 'periods\|start\|end' /opt/emoncms/modules/demandshaper/demandshaper-module/js/main.js
47: // Convert hour into end timestamp
48: schedule.settings.end_timestamp = hour_to_timestamp(schedule.settings.end)
54: data: "config="+JSON.stringify(schedule.settings.forecast_config)+"&interruptible="+schedule.settings.interruptible+"&period="+schedule.runtime.timeleft+"&end="+schedule.settings.end_timestamp,
59: schedule.runtime.periods = result;
60: $("#schedule_json").html(JSON.stringify(schedule.runtime.periods));
69: data: "config="+JSON.stringify(schedule.settings.timer)+"&forecast_start="+forecast.start+"&forecast_end="+forecast.end,
74: schedule.runtime.periods = result;
75: $("#schedule_json").html(JSON.stringify(schedule.runtime.periods));
80: schedule.runtime.periods = [];
121: $("#end input[type=time]").val(timestr(schedule.settings.end,false));
125: $("#timer_start1 input[type=time]").val(timestr(schedule.settings.timer[0].start,false));
126: $("#timer_stop1 input[type=time]").val(timestr(schedule.settings.timer[0].end,false));
127: $("#timer_start2 input[type=time]").val(timestr(schedule.settings.timer[1].start,false));
128: $("#timer_stop2 input[type=time]").val(timestr(schedule.settings.timer[1].end,false));
153: // Output schedule periods
154: var periods = [];
155: for (var z in schedule.runtime.periods) {
157: date = (new Date(schedule.runtime.periods[z].start[0]*1000));
161: date = (new Date(schedule.runtime.periods[z].end[0]*1000));
165: periods.push(timestr(h1+m1,true)+" to "+timestr(h2+m2,true));
168: if (periods.length && schedule.settings.ctrlmode=="smart") {
169: out = jsUcfirst(schedule.settings.device_name)+" scheduled to run: <b>"+periods.join(", ")+"</b><br>";
186: for (var time=forecast.start; time<forecast.end; time+=forecast.interval) {
193: for (var p in schedule.runtime.periods) {
194: if (time>=schedule.runtime.periods[p].start[0] && time<schedule.runtime.periods[p].end[0]) active = true;
251: // Shade out time after end of schedule
254: if (schedule.runtime.periods.length) markings.push({ color: "rgba(0,0,0,0.1)", xaxis: { from: schedule.settings.end_timestamp*1000 } });
320: if (name=="period" || name=="end") {
325: else if (name=="timer_start1") schedule.settings.timer[0].start = hour;
326: else if (name=="timer_stop1") schedule.settings.timer[0].end = hour;
327: else if (name=="timer_start2") schedule.settings.timer[1].start = hour;
328: else if (name=="timer_stop2") schedule.settings.timer[1].end = hour;
436: }).appendTo("body").fadeIn(200);
471: // Convert hour into end timestamp
pi@emonpi-node-15:/opt/emoncms/modules/demandshaper/demandshaper-module/js $
This may be useful.
Thx for yr help till now.