OpenEnergyMonitor Community

DemandShaper/openEVSE – help please

I want to use a Python script to set DemandShaper & openEVSE parameters rather than having to use the webpages to do this.

Of particular interest is the target_soc which currently must be set by dragging the light green bar on the DemandShaper webpage.

The following script is a work-in-progress which works OK until the last line …



# ---------------------------------------------

import requests, json

from requests.structures import CaseInsensitiveDict

# Emoncms server configuration ...

emoncms_apikey = "18f634838244c193b816f51aabe048da" # For Node 15 - use appropriate key

emoncms_server = ""

username = "emonpi"

password = "emonpimqtt2016"

# Get the Demand Shaper data ...

headers = CaseInsensitiveDict()

headers["Accept"] = "application/json"

headers["Authorization"] = "Bearer APIKEY"

headers["Content-Type"] = "application/json"

params = (

('device', 'openevse'),

('apikey', emoncms_apikey),

{'username', username},

{'password', password}


reply = requests.get(emoncms_server+"/demandshaper/get", params=params)

jsonstr = reply.text.rstrip()

ds_data = json.loads(jsonstr)


print (ds_data)

# Extract relevant data from the json

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']

print (data1)

print (data2)

print (data3)

print (data4)

# Do tests and make any changes here ...

# First test ...

di3 = 0.8

ds_data['schedule']['settings']['target_soc'] = di3

print (ds_data) # IT WORKS UPTO & INCL THIS LINE ... target_soc has been modified to 0.8

# Script fails at this point - Status Code = 406

reply ="/demandshaper/post", headers=headers, params=params, data=json.dumps(ds_data))


Here’s the output …

[email protected]:~/ev-charging-scripts $ python3


{'schedule': {'settings': {'device': 'openevse', 'device_type': 'openevse', 'device_name': 'openevse', 'ctrlmode': 'smart', 'period': 5.108695652173913, 'end': 8, 'end_timestamp': 1608451200, '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.43, 'balpercentage': 0.9, 'baltime': 2, 'car_economy': 3.4, 'charge_energy': 35.25, 'charge_distance': 119.8, 'distance_units': 'miles', 'ovms_vehicleid': '', 'ovms_carpass': '', 'divert_mode': 1}, 'runtime': {'started': True, 'periods': [{'start': [1608427800, 1.5], 'end': [1608446191, 6.6]}], 'timeleft': 18391.304347826088}}}





{'schedule': {'settings': {'device': 'openevse', 'device_type': 'openevse', 'device_name': 'openevse', 'ctrlmode': 'smart', 'period': 5.108695652173913, 'end': 8, 'end_timestamp': 1608451200, '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.8,** 'current_soc': 0.43, 'balpercentage': 0.9, 'baltime': 2, 'car_economy': 3.4, 'charge_energy': 35.25, 'charge_distance': 119.8, 'distance_units': 'miles', 'ovms_vehicleid': '', 'ovms_carpass': '', 'divert_mode': 1}, 'runtime': {'started': True, 'periods': [{'start': [1608427800, 1.5], 'end': [1608446191, 6.6]}], 'timeleft': 18391.304347826088}}}


The target_soc has clearly been changed 0.9 > 0.8 but this has not been written back to the OS.

Apparently exit code 406 is unusual and covers diverse problems – which is not very helpful info.

Is my approach flawed?

Suggestions most welcome.

Hello @johnbanks

There is already a built in demandshaper feature to read the SOC from an emoncms input, did you see that?

The input needs to be called ‘soc’ and under node name: ‘openevse’

You can then perhaps more easily set the input from a script?


Apologies - I did not make myself entirely clear.

I’m successfully using the soc feature you have mentioned. It’s the current soc of the EV and so a fact that should not be altered.
In my json download, it appears as current_soc.

What I’m trying to achieve is to set the target_soc by script rather having to use the DemandShaper webpage to drag the light green bar to the desired target_soc.
target_soc is the level which DemandShaper will charge the EV to overnight at cheap rates.

My frustration is that whilst I can make my desired change to the DemandShaper json, I cannot write this change to target_soc back to the OS so that DemandShaper acts accordingly.


Hello @johnbanks

I think the following is working ok:

import requests, json

emoncms_apikey = "18f634838244c193b816f51aabe048da"
emoncms_server = ""

reply = requests.get(emoncms_server+"/demandshaper/get", params={'device':'openevse','apikey':emoncms_apikey})
ds_data = json.loads(reply.text)

ds_data['schedule']['settings']['target_soc'] = 0.6

reply ="/demandshaper/save", params={'apikey':emoncms_apikey}, data={'schedule':json.dumps(ds_data['schedule'])})


It may take until the next SOC auto update for the changes to take effect, up to 10 mins.


It works! Brilliant! Many thx

PS - I remotely monitor a system at my son’s place. He has a Tesla EV.
A script runs at 8pm each evening and checks the EV soc. If it’s below a certain level and the EV is not connected, he’s sent an text suggesting he does connect to take advantage of cheap Agile overnight rates.
He may connect at any time between 8pm and midnight.
I’m still working on this bit of the script - to stop charging happening the moment a connection is made and to set Demand Shaper and openEVSE correctly so Demand Shaper controls the optimum time for charging during the early hours.

1 Like