Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
Hi.
I have a floorheat brand that has an REST API that I want to implement into a buildings KNX installation.
is it possible to make this with some script or is it someone that has done this already? I want to control and see status och the floorheating.
Attach the link to its api information if that’s explains my goal better.
https://www.ebeco.se/support/ebeco-open-api
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
470
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
Hi.
I ran this in Postman where I got the accessToken with success.
Code:
1 2 3 4 5 6 7 8
curl
"userNameOrEmailAddress" :
"xxxxx@xxxxx.com" ,
"password" :
"xxxxx"
}
'
But in my script I don´t get the response of the connected devices, in fact I dopnt get much at all in response, what is wrong here?
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
require (
'json' )
require (
'ssl.https' )
require (
'ltn12' )
userNameOrEmailAddress =
"xxxxx@xxxxx.com"
password =
"xxxxx"
function GetToken ()
request_token_url =
'https://ebecoconnect.com/api/TokenAuth/Authenticate'
local response_body = {}
local request_body =
"grant_type=password&username=" ..
userNameOrEmailAddress ..
"&password=" ..
password
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
request_token_url ;
method =
"POST" ;
headers =
{
[
"Content-Type" ] =
"application/x-www-form-urlencoded" ;
[
"Content-Length" ] = #
request_body ;
[
"Abp.TenantId" ] =
1 ;
};
source =
ltn12.source.string (
request_body );
sink =
ltn12.sink.table (
response_body );
}
if code ==
200 then
ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
log (
ret )
return ret.access_token
end
end
if not API_Token then
API_Token =
GetToken ()
end
function RequestFromEbeco (
request )
request_url =
'https://api/services/app/Devices/GetUserDevices' ..
request
local response_body = {}
local request_body =
""
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
request_url ;
method =
"GET" ;
headers =
{
[
"Content-Type" ] =
"application/json" ;
[
"Authorization" ] =
"Bearer " ..
API_Token ;
};
source =
ltn12.source.string (
request_body );
sink =
ltn12.sink.table (
response_body );
}
if code ==
200 then
ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
return ret
else
API_Token =
GetToken ()
end
end
products =
RequestFromEbeco (
'products' )
log (
products )
Ebecos API documentation here
https://www.ebeco.se/radgivning/guider/ebeco-oppet-api
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
470
Use this:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
function GetToken ()
local response_body = {}
local request_body =
json.encode ({
userNameOrEmailAddress =
userNameOrEmailAddress ,
password =
password ,
})
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
'https://ebecoconnect.com/api/TokenAuth/Authenticate' ,
method =
'POST' ,
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Content-Length' ] = #
request_body ,
[
'Abp.TenantId' ] =
1 ,
},
source =
ltn12.source.string (
request_body ),
sink =
ltn12.sink.table (
response_body ),
}
if code ==
200 then
ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
log (
ret )
return ret.access_token
else
log (
'request failed' ,
body ,
code ,
hdrs ,
stat )
end
end
The request_url in RequestFromEbeco is wrong, it should be "https://ebecoconnect.com/api/services/app/Devices/GetUserDevices" (without any additional parameters).
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
(08.08.2022, 06:04) admin Wrote: Use this:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
function GetToken ()
local response_body = {}
local request_body =
json.encode ({
userNameOrEmailAddress =
userNameOrEmailAddress ,
password =
password ,
})
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
'https://ebecoconnect.com/api/TokenAuth/Authenticate' ,
method =
'POST' ,
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Content-Length' ] = #
request_body ,
[
'Abp.TenantId' ] =
1 ,
},
source =
ltn12.source.string (
request_body ),
sink =
ltn12.sink.table (
response_body ),
}
if code ==
200 then
ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
log (
ret )
return ret.access_token
else
log (
'request failed' ,
body ,
code ,
hdrs ,
stat )
end
end
The request_url in RequestFromEbeco is wrong, it should be "https://ebecoconnect.com/api/services/app/Devices/GetUserDevices" (without any additional parameters).
Thanks, but did´nt get that to work either. But change my script line from having ". . ." to '. . .'
Then I put in log('request failed') and got this in response:
Ebeco REST API copy 08.08.2022 08:48:58
* arg: 1
* string: request failed
* arg: 2
* number: 1
* arg: 3
* number: 415
* arg: 4
* table:
["server"]
* string: Microsoft-IIS/10.0
["connection"]
* string: close
["content-length"]
* string: 0
["x-rate-limit-limit"]
* string: 60s
["x-rate-limit-remaining"]
* string: 29
["request-context"]
* string: appId=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
["x-frame-options"]
* string: SAMEORIGIN
["x-rate-limit-reset"]
* string: 2022-08-08T06:49:58.5482160Z
["date"]
* string: Mon, 08 Aug 2022 06:48:57 GMT
["x-xss-protection"]
* string: 1; mode=block
["set-cookie"]
* string: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxPath=/;HttpOnly;SameSite=None;Secure;Domain=ebecoconnect.com
["x-content-type-options"]
* string: nosniff
* arg: 5
* string: HTTP/1.1 415 Unsupported Media Type
I added the X:es if it might have been sensitive stuff
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
470
Try adding
Accept: application/json or
Accept: */* to headers in
GetToken function:
Code:
1 2 3 4 5 6
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Content-Length' ] = #
request_body ,
[
'Abp.TenantId' ] =
1 ,
[
'Accept' ] =
'application/json' ,
},
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
(08.08.2022, 07:06) admin Wrote: Try adding Accept: application/json or Accept: */* to headers in GetToken function:
Code:
1 2 3 4 5 6
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Content-Length' ] = #
request_body ,
[
'Abp.TenantId' ] =
1 ,
[
'Accept' ] =
'application/json' ,
},
Now intsted of "HTTP/1.1 415 Unsupported Media Type"
I get "HTTP/1.1 400 Bad Request"
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
470
Have you tried */* instead of application/json?
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
08.08.2022, 07:29
(This post was last modified: 08.08.2022, 07:31 by victor.back .)
(08.08.2022, 07:24) admin Wrote: Have you tried */* instead of application/json?
Yes it´s the same response as well "HTTP/1.1 400 Bad Request"
The response look like this:
* arg: 1
* string: request failed
* arg: 2
* number: 1
* arg: 3
* number: 400
* arg: 4
* table:
["server"]
* string: Microsoft-IIS/10.0
["content-type"]
* string: application/json; charset=utf-8
["connection"]
* string: close
["content-length"]
* string: 412
["x-rate-limit-limit"]
* string: 60s
["x-rate-limit-remaining"]
* string: 29
["request-context"]
* string: appId=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
["x-frame-options"]
* string: SAMEORIGIN
["x-rate-limit-reset"]
* string: 2022-08-08T07:31:10.2468154Z
["date"]
* string: Mon, 08 Aug 2022 07:30:10 GMT
["x-xss-protection"]
* string: 1; mode=block
["set-cookie"]
* string: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxDomain=ebecoconnect.com
["x-content-type-options"]
* string: nosniff
* arg: 5
* string: HTTP/1.1 400 Bad Request
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
470
Can you send credentials to us via e-mail so we can check locally?
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
(08.08.2022, 08:01) admin Wrote: Can you send credentials to us via e-mail so we can check locally?
sure, wich email?
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
470
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
470
This works for me using your credentials:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
require (
'json' )
require (
'ssl.https' )
require (
'ltn12' )
userNameOrEmailAddress =
'...'
password =
'...'
function GetToken ()
local response_body = {}
local request_body =
json.encode ({
userNameOrEmailAddress =
userNameOrEmailAddress ,
password =
password ,
})
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
'https://ebecoconnect.com/api/TokenAuth/Authenticate' ,
method =
'POST' ,
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Content-Length' ] = #
request_body ,
[
'Abp.TenantId' ] =
1 ,
},
source =
ltn12.source.string (
request_body ),
sink =
ltn12.sink.table (
response_body ),
}
if code ==
200 then
local ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
if type (
ret ) ==
'table' and type (
ret.result ) ==
'table' then
return ret.result.accessToken
end
else
log (
'request failed' ,
body ,
code ,
hdrs ,
stat )
end
end
API_Token =
GetToken ()
function RequestFromEbeco (
request ,
params )
local url =
'https://ebecoconnect.com/api/services/app/Devices/' ..
request
local response_body = {}
local request_body =
''
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
url ,
method =
'GET' ,
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Authorization' ] =
'Bearer ' ..
API_Token ,
},
source =
ltn12.source.string (
request_body ),
sink =
ltn12.sink.table (
response_body ),
}
if code ==
200 then
local ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
return ret
else
log (
'request failed' ,
body ,
code ,
hdrs ,
stat )
end
end
if API_Token then
devices =
RequestFromEbeco (
'GetUserDevices' )
log (
devices )
end
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
(08.08.2022, 12:07) admin Wrote: This works for me using your credentials:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
require (
'json' )
require (
'ssl.https' )
require (
'ltn12' )
userNameOrEmailAddress =
'...'
password =
'...'
function GetToken ()
local response_body = {}
local request_body =
json.encode ({
userNameOrEmailAddress =
userNameOrEmailAddress ,
password =
password ,
})
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
'https://ebecoconnect.com/api/TokenAuth/Authenticate' ,
method =
'POST' ,
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Content-Length' ] = #
request_body ,
[
'Abp.TenantId' ] =
1 ,
},
source =
ltn12.source.string (
request_body ),
sink =
ltn12.sink.table (
response_body ),
}
if code ==
200 then
local ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
if type (
ret ) ==
'table' and type (
ret.result ) ==
'table' then
return ret.result.accessToken
end
else
log (
'request failed' ,
body ,
code ,
hdrs ,
stat )
end
end
API_Token =
GetToken ()
function RequestFromEbeco (
request ,
params )
local url =
'https://ebecoconnect.com/api/services/app/Devices/' ..
request
local response_body = {}
local request_body =
''
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
url ,
method =
'GET' ,
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Authorization' ] =
'Bearer ' ..
API_Token ,
},
source =
ltn12.source.string (
request_body ),
sink =
ltn12.sink.table (
response_body ),
}
if code ==
200 then
local ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
return ret
else
log (
'request failed' ,
body ,
code ,
hdrs ,
stat )
end
end
if API_Token then
devices =
RequestFromEbeco (
'GetUserDevices' )
log (
devices )
end Now works fine for me too, thanks!
Looks like the problem was that I had used "..." insted of '...'
for some lines, including username
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
(08.08.2022, 12:07) admin Wrote: This works for me using your credentials:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
require (
'json' )
require (
'ssl.https' )
require (
'ltn12' )
userNameOrEmailAddress =
'...'
password =
'...'
function GetToken ()
local response_body = {}
local request_body =
json.encode ({
userNameOrEmailAddress =
userNameOrEmailAddress ,
password =
password ,
})
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
'https://ebecoconnect.com/api/TokenAuth/Authenticate' ,
method =
'POST' ,
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Content-Length' ] = #
request_body ,
[
'Abp.TenantId' ] =
1 ,
},
source =
ltn12.source.string (
request_body ),
sink =
ltn12.sink.table (
response_body ),
}
if code ==
200 then
local ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
if type (
ret ) ==
'table' and type (
ret.result ) ==
'table' then
return ret.result.accessToken
end
else
log (
'request failed' ,
body ,
code ,
hdrs ,
stat )
end
end
API_Token =
GetToken ()
function RequestFromEbeco (
request ,
params )
local url =
'https://ebecoconnect.com/api/services/app/Devices/' ..
request
local response_body = {}
local request_body =
''
local body ,
code ,
hdrs ,
stat =
ssl.https.request {
url =
url ,
method =
'GET' ,
headers = {
[
'Content-Type' ] =
'application/json' ,
[
'Authorization' ] =
'Bearer ' ..
API_Token ,
},
source =
ltn12.source.string (
request_body ),
sink =
ltn12.sink.table (
response_body ),
}
if code ==
200 then
local ret =
table.concat (
response_body )
ret =
json.pdecode (
ret )
return ret
else
log (
'request failed' ,
body ,
code ,
hdrs ,
stat )
end
end
if API_Token then
devices =
RequestFromEbeco (
'GetUserDevices' )
log (
devices )
end
Hi.
I´ve used this script for one device, but how do I get the data from data table 2-5?
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
if API_Token then
devices =
RequestFromEbeco (
'GetUserDevices' )
end
if devices and devices.result then
for _ ,
device in ipairs (
devices.result )
do
grp.checkwrite (
'32/2/1' ,
device [
"id" ])
grp.checkwrite (
'32/2/2' ,
device [
"relayOn" ])
grp.checkwrite (
'32/2/3' ,
device [
"minutesToTarget" ])
grp.checkwrite (
'32/2/4' ,
device [
"temperatureRoom" ])
grp.checkwrite (
'32/2/5' ,
device [
"temperatureRoomDecimals" ])
grp.checkwrite (
'32/2/6' ,
device [
"temperatureFloorDecimals" ])
grp.checkwrite (
'32/2/7' ,
device [
"remoteInput" ])
grp.checkwrite (
'32/2/8' ,
device [
"displayName" ])
grp.checkwrite (
'32/2/9' ,
device [
"temperatureSet" ])
grp.checkwrite (
'32/2/10' ,
device [
"building" ][
"name" ])
grp.checkwrite (
'32/2/11' ,
device [
"building" ][
"id" ])
grp.checkwrite (
'32/2/12' ,
device [
"programState" ])
grp.checkwrite (
'32/2/13' ,
device [
"temperatureFloor" ])
grp.checkwrite (
'32/2/14' ,
device [
"hasError" ])
grp.checkwrite (
'32/2/15' ,
device [
"installedEffect" ])
grp.checkwrite (
'32/2/16' ,
device [
"powerOn" ])
grp.checkwrite (
'32/2/17' ,
device [
"todaysOnMinutes" ])
grp.checkwrite (
'32/2/18' ,
device [
"selectedProgram" ])
grp.checkwrite (
'32/2/19' ,
device2 [
"id" ])
grp.checkwrite (
'32/2/20' ,
device2 [
"relayOn" ]
and 1 or 0 )
grp.checkwrite (
'32/2/21' ,
device2 [
"minutesToTarget" ])
grp.checkwrite (
'32/2/22' ,
device2 [
"temperatureRoom" ])
grp.checkwrite (
'32/2/23' ,
device2 [
"temperatureRoomDecimals" ])
grp.checkwrite (
'32/2/24' ,
device2 [
"temperatureFloorDecimals" ])
grp.checkwrite (
'32/2/25' ,
device2 [
"remoteInput" ]
and 1 or 0 )
grp.checkwrite (
'32/2/26' ,
device2 [
"displayName" ])
grp.checkwrite (
'32/2/27' ,
device2 [
"temperatureSet" ])
grp.checkwrite (
'32/2/28' ,
device2 [
"building" ][
"name" ])
grp.checkwrite (
'32/2/29' ,
device2 [
"building" ][
"id" ])
grp.checkwrite (
'32/2/30' ,
device2 [
"programState" ])
grp.checkwrite (
'32/2/31' ,
device2 [
"temperatureFloor" ])
grp.checkwrite (
'32/2/32' ,
device2 [
"hasError" ]
and 1 or 0 )
grp.checkwrite (
'32/2/33' ,
device2 [
"installedEffect" ])
grp.checkwrite (
'32/2/34' ,
device2 [
"powerOn" ]
and 1 or 0 )
grp.checkwrite (
'32/2/35' ,
device2 [
"todaysOnMinutes" ])
grp.checkwrite (
'32/2/36' ,
device2 [
"selectedProgram" ])
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
470
Remove the for loop and try this:
Code:
1 2 3 4 5 6 7
if devices and devices.result then
device =
devices.result [
1 ]
device2 =
devices.result [
2 ]
device3 =
devices.result [
3 ]
...
end
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
(31.10.2023, 07:57) admin Wrote: Remove the for loop and try this:
Code:
1 2 3 4 5 6 7
if devices and devices.result then
device =
devices.result [
1 ]
device2 =
devices.result [
2 ]
device3 =
devices.result [
3 ]
...
end
Thanks
It seems to work without the loop.