Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
26.09.2025, 12:53
(This post was last modified: 26.09.2025, 12:55 by gjniewenhuijse.)
I like to control a Nefit boiler that has an EMS protocol. Its not possible to control it directly so i inserted an EMS-ESP into my system.
Now i can get data from my system with this script
Code: --[[
Nefit heat pump ems bus
https://bbqkees-electronics.nl/wiki/gateway/restful-api.html
https://docs.emsesp.org/Commands/
ems-esp/boiler {"cmd":"heatingactivated", "data":"on"} turn on heatingactivated in boiler
ems-esp/boiler/heatingactivated {"data":"on"} turn on heatingactivated in boiler (equivalent to command above)
ems-esp/boiler {"cmd":"dhw.disinfecting", "data":"on"} turn on DHW disinfecting in boiler
--]]
https = require('ssl.https')
json = require('json')
ltn12 = require('ltn12')
iDebug = true
devIp = '192.168.x.xx' -- ems-esp.local
devUrl = 'http://'..devIp..'/api/'
function getData(iFunction)
if iDebug then log(devUrl..iFunction) end
res, code = https.request({
url = devUrl..iFunction,
method = 'GET'
})
if iDebug then
log(code, res)
end
return code, res
end
function setData(iFunction, iData)
if iDebug then log(devUrl..iFunction) end
res, code = https.request({
url = devUrl..iFunction,
method = 'POST',
headers = {["content-type"] = "application/json"},
data = iData
})
if iDebug then
log(code, res)
end
return code, res
end
-- get system info
--getData('system')
-- get boiler info - GET outputs current EMS device information in verbose
--getData('boiler/info')
-- get boiler values - GET outputs current EMS device information in short format
--getData('boiler/values')
-- get boiler - GET same as values above
--getData('boiler')
-- get boiler commands - GET lists the available command entities to call
--getData('boiler/commands')
-- get boiler entities - GET lists all enabled entities
--getData('boiler/entities')
-- get boiler dhw info
--getData('boiler/dhw/info')
-- get boiler entity heatingactive
--getData('boiler/heatingactive')
-- thermostaat streeftemperatuur
--getData('thermostat/seltemp')
-- dhw Laden
--getData('thermostat/dhw/charge')
setData('thermostat/dhw/charge', '{"value": true}') --curl -X POST http:///api/system/dhw/charge -H "Content-Type: application/json" -d '{"value": true}'
I also like to control the data with the setData function (last line). But i received an error 400. Whats wrong with my code?
Documentation can be found here: https://docs.emsesp.org/Commands/
Posts: 8397
Threads: 45
Joined: Jun 2015
Reputation:
481
You are missing Content-Length header for the POST request.
Code: ["Content-Length"] = #iData,
You should use json.encode instead of writing JSON manually to avoid potential errors.
Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
(26.09.2025, 12:58)admin Wrote: You are missing Content-Length header for the POST request.
Code: ["Content-Length"] = #iData,
You should use json.encode instead of writing JSON manually to avoid potential errors.
Like this (but with same error)?
Code: setData('thermostat/dhw/charge', {value = true})
function setData(iFunction, iData)
if iDebug then log(devUrl..iFunction) end
res, code = https.request({
url = devUrl..iFunction,
method = 'POST',
headers = {["Content-Type"] = "application/json",
["Content-Length"] = #iData
},
data = json.encode(iData)
})
if iDebug then
log(code, res)
end
return code, res
end
Posts: 8397
Threads: 45
Joined: Jun 2015
Reputation:
481
Try this:
Code: setData('thermostat/dhw/charge', {value = true})
function setData(iFunction, iData)
local data = json.encode(iData)
if iDebug then log(devUrl..iFunction) end
res, code = https.request({
url = devUrl..iFunction,
method = 'POST',
headers = {
["Content-Type"] = "application/json",
["Content-Length"] = #data
},
data = data
})
if iDebug then log(code, res) end
return code, res
end
Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
(26.09.2025, 13:13)admin Wrote: Try this:
Code: setData('thermostat/dhw/charge', {value = true})
function setData(iFunction, iData)
local data = json.encode(iData)
if iDebug then log(devUrl..iFunction) end
res, code = https.request({
url = devUrl..iFunction,
method = 'POST',
headers = {
["Content-Type"] = "application/json",
["Content-Length"] = #data
},
data = data
})
if iDebug then log(code, res) end
return code, res
end
Other error:
* arg: 1
* string: closed
* arg: 2
* nil
Posts: 8397
Threads: 45
Joined: Jun 2015
Reputation:
481
Are you sure that URL endpoint and parameters are correct?
Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
(26.09.2025, 13:27)admin Wrote: Are you sure that URL endpoint and parameters are correct?
getData for that endpoint works and the result is:
* arg: 1
* number: 200
* arg: 2
* string: {"name":"charge","fullname":"dhw Laden","circuit":"dhw","bool":false,"index":0,"value":"uit","type":"boolean","readable":true,"writeable":true,"visible":true}
Posts: 8397
Threads: 45
Joined: Jun 2015
Reputation:
481
Send a request to http://<hostname>/api/<device>/commands to get a list of available commands. Do you have access token enabled in Security->Manage Users?
Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
26.09.2025, 13:49
(This post was last modified: 26.09.2025, 13:50 by gjniewenhuijse.)
(26.09.2025, 13:39)admin Wrote: Send a request to http://<hostname>/api/<device>/commands to get a list of available commands. Do you have access token enabled in Security->Manage Users?
Access token is disabled
In the output i need the command: ,"dhw[n].charge":"Laden"
Output:
{"info":"lijst van alle waardes","values":"list all values","commands":"lijst van alle commando's","entities":"lijst van alle entiteiten","[hc<n>.]boost":"boost mode","[hc<n>.]boosttime":"boost time","[hc<n>.]comforttemp":"Comforttemperatuur","[hc<n>.]control":"Afstandsbedieding","[hc<n>.]controlmode":"Comtrolemodus","[hc<n>.]cooloffdelay":"cooling off delay","[hc<n>.]coolondelay":"cooling on delay","[hc<n>.]coolstart":"cooling starttemp","[hc<n>.]cooltemp":"Temperatuur koelbedrijf","[hc<n>.]designtemp":"Ontwerptemperatuur","[hc<n>.]dewoffset":"Offset dauwpunt","[hc<n>.]dhwprio":"Prioriteit warm water","[hc<n>.]ecotemp":"Temperatuur eco","[hc<n>.]fastheatup":"Snel opwarmen","[hc<n>.]heatingtype":"Verwarmingstype","[hc<n>.]heatoffdelay":"heat-off delay","[hc<n>.]heatondelay":"heat-on delay","[hc<n>.]hpcooling":"WP koelbedrijf","[hc<n>.]hpminflowtemp":"Minimale aanvoertemperatuur WP","[hc<n>.]hpmode":"Modus warmtepomp","[hc<n>.]hpoperatingmode":"Bedrijfsmodus warmtepomp","[hc<n>.]instantstart":"instant start","[hc<n>.]intoffset":"Offset interne temperatuur","[hc<n>.]manualtemp":"Temperatuur handmatig","[hc<n>.]maxflowtemp":"Maximale aanvoertemperatuur","[hc<n>.]minflowtemp":"Minimale aanvoertemperatuur","[hc<n>.]mode":"Modus","[hc<n>.]nofrostmode":"Vorstbeveiligingsmodus","[hc<n>.]nofrosttemp":"Temperatuur vorstbeveiliging","[hc<n>.]noreducetemp":"Reduceermodus onderbreken onder","[hc<n>.]offsettemp":"Temperatuur offset","[hc<n>.]program":"Programma","[hc<n>.]redthreshold":"reduction threshold","[hc<n>.]reducemode":"Gereduceerde modus","[hc<n>.]reducetemp":"Onderste afschakeltemperatuur","[hc<n>.]remotehum":"room humidity from remote","[hc<n>.]remotetemp":"Ruimtetemperatuur van afstandsbediening","[hc<n>.]roominflfactor":"Factor ruimteinvloed","[hc<n>.]roominfluence":"Ruimteinvloed","[hc<n>.]roomtempdiff":"Verschiltemperatuur kamertemp","[hc<n>.]seltemp":"Streeftemperatuur kamer","[hc<n>.]solarinfl":"solar influence","[hc<n>.]summersetmode":"Instelling zomerbedrijf","[hc<n>.]summertemp":"Zomertemperatuur","[hc<n>.]switchonoptimization":"Inschakeloptimalisering","[hc<n>.]switchprogmode":"switch program mode","[hc<n>.]tempautotemp":"Streeftemperatuur automodus tijdelijk","absent":"absent","building":"Type gebouw","damping":"Demping buitentemperatuur","datetime":"Datum/Tijd","delayboiler":"Vertragingsoptie","dhw[n].charge":"Laden","dhw[n].chargeduration":"Laadtijd","dhw[n].circmode":"Modus circulatiepomp","dhw[n].dailyheating":"Dagelijks opwarmen","dhw[n].dailyheattime":"Tijd dagelijkse opwarming","dhw[n].disinfectday":"Desinfectiedag","dhw[n].disinfecting":"Desinfectie","dhw[n].disinfecttime":"Desinfectietijd","dhw[n].mode":"Modus","dhw[n].settemp":"Streeftemperatuut","dhw[n].settemplow":"Onderste streeftemperatuur","electricfactor":"Energiefactor electrisch","energycostratio":"Energiekostenratio","fossilefactor":"Energiefactor fossiele brandstof","hybridstrategy":"Hybride strategie","intoffset":"Offset interne temperatuur","minexttemp":"Min. buitentemperatuur","pvenabledhw":"Verhoging WW activeren","pvlowercool":"Verlagen koeling met PV activeren","pvraiseheat":"Verwarmen met PV activeren","solar":"solar","switchovertemp":"Schakeltemperatuur buitentemperatuur","tempdiffboiler":"Verschiltemperatuuroptie"}
Posts: 8397
Threads: 45
Joined: Jun 2015
Reputation:
481
Try sending true instead of {value = true}. If this does not help then you should ask this question here: https://github.com/emsesp/EMS-ESP32/discussions
Posts: 6
Threads: 2
Joined: Mar 2024
Reputation:
1
Fyi: Theben has an Opentherm to KNX gateway and there is an Opentherm to EMS converter. I have this setup and it works very well.
Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
(26.09.2025, 21:00)maxmp Wrote: Fyi: Theben has an Opentherm to KNX gateway and there is an Opentherm to EMS converter. I have this setup and it works very well.
Which Openterm to EMS converter do you use?
And can you control the DHW charge? (Extra warm water function)
Posts: 6
Threads: 2
Joined: Mar 2024
Reputation:
1
(29.09.2025, 08:58)gjniewenhuijse Wrote: (26.09.2025, 21:00)maxmp Wrote: Fyi: Theben has an Opentherm to KNX gateway and there is an Opentherm to EMS converter. I have this setup and it works very well.
Which Openterm to EMS converter do you use?
And can you control the DHW charge? (Extra warm water function)
Hi.
I have this gateway: https://www.robbshop.nl/nefit-ems-opentherm-converter
Regarding the DHW, i don't use this function, but i see its status.
Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
(06.10.2025, 06:52)maxmp Wrote: (29.09.2025, 08:58)gjniewenhuijse Wrote: (26.09.2025, 21:00)maxmp Wrote: Fyi: Theben has an Opentherm to KNX gateway and there is an Opentherm to EMS converter. I have this setup and it works very well.
Which Openterm to EMS converter do you use?
And can you control the DHW charge? (Extra warm water function)
Hi.
I have this gateway: https://www.robbshop.nl/nefit-ems-opentherm-converter
Regarding the DHW, i don't use this function, but i see its status.
Thanks, and is it also possible to control this status?
Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
(26.09.2025, 14:05)admin Wrote: Try sending true instead of {value = true}. If this does not help then you should ask this question here: https://github.com/emsesp/EMS-ESP32/discussions
If i try the same with Postman it works great, so why it doesnt work from the LM?
POST /api/thermostat/dhw/charge HTTP/1.1
Host: 192.168.x.x
Content-Type: application/json
Content-Length: 16
{"value": false}
Posts: 8397
Threads: 45
Joined: Jun 2015
Reputation:
481
Replace data = data with body = data in https.request({...}).
Posts: 477
Threads: 100
Joined: Jun 2015
Reputation:
6
|