![]() |
|
Ebeco floorheat thermostat - Printable Version +- LogicMachine Forum (https://forum.logicmachine.net) +-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1) +--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8) +--- Thread: Ebeco floorheat thermostat (/showthread.php?tid=3756) |
Ebeco floorheat thermostat - victor.back - 17.12.2021 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 RE: Ebeco floorheat thermostat - admin - 17.12.2021 First you need to get the bearer token manually as described in the API link you've provided. Then you can use it to make requests as documented here: https://ebecoconnect.com/swagger/index.html Topics where you can find example code: https://forum.logicmachine.net/showthread.php?tid=2185 https://forum.logicmachine.net/showthread.php?tid=3308 https://forum.logicmachine.net/showthread.php?tid=3121 https://forum.logicmachine.net/showthread.php?tid=1786 RE: Ebeco floorheat thermostat - victor.back - 07.08.2022 Hi. I ran this in Postman where I got the accessToken with success. Code: curl --location --request POST 'https://ebecoconnect.com/api/TokenAuth/Authenticate' \
--header 'Content-Type: application/json' \
--header 'Abp.TenantId: 1' \
--data-raw ' {
"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: -- Load modules
require('json')
require('ssl.https')
require('ltn12')
-- Set credentials for Ebecoconnect API
userNameOrEmailAddress = "xxxxx@xxxxx.com" -- your email for Ebecoconnect account
password = "xxxxx" -- your password for Ebecoconnect account
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 -- could be some other field, try to log ret to be sure
end
end
-- Request token
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() -- request a new token
end
end
-- Get products
products = RequestFromEbeco('products')
log(products) -- Checks your Ebeco thermostatsEbecos API documentation here https://www.ebeco.se/radgivning/guider/ebeco-oppet-api RE: Ebeco floorheat thermostat - admin - 08.08.2022 Use this: Code: 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 -- could be some other field, try to log ret to be sure
else
log('request failed', body, code, hdrs, stat)
end
endThe request_url in RequestFromEbeco is wrong, it should be "https://ebecoconnect.com/api/services/app/Devices/GetUserDevices" (without any additional parameters). RE: Ebeco floorheat thermostat - victor.back - 08.08.2022 (08.08.2022, 06:04)admin Wrote: Use this: 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
RE: Ebeco floorheat thermostat - admin - 08.08.2022 Try adding Accept: application/json or Accept: */* to headers in GetToken function: Code: headers = {
['Content-Type'] = 'application/json',
['Content-Length'] = #request_body,
['Abp.TenantId'] = 1,
['Accept'] = 'application/json',
},RE: Ebeco floorheat thermostat - victor.back - 08.08.2022 (08.08.2022, 07:06)admin Wrote: Try adding Accept: application/json or Accept: */* to headers in GetToken function: Now intsted of "HTTP/1.1 415 Unsupported Media Type" I get "HTTP/1.1 400 Bad Request" RE: Ebeco floorheat thermostat - admin - 08.08.2022 Have you tried */* instead of application/json? RE: Ebeco floorheat thermostat - victor.back - 08.08.2022 (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 RE: Ebeco floorheat thermostat - admin - 08.08.2022 Can you send credentials to us via e-mail so we can check locally? RE: Ebeco floorheat thermostat - victor.back - 08.08.2022 (08.08.2022, 08:01)admin Wrote: Can you send credentials to us via e-mail so we can check locally? sure, wich email? RE: Ebeco floorheat thermostat - admin - 08.08.2022 Send to info@openrb.com RE: Ebeco floorheat thermostat - admin - 08.08.2022 This works for me using your credentials: Code: require('json')
require('ssl.https')
require('ltn12')
-- Set credentials for Ebecoconnect API
userNameOrEmailAddress = '...' -- your email for Ebecoconnect account
password = '...' -- your password for Ebecoconnect account
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)
endRE: Ebeco floorheat thermostat - victor.back - 08.08.2022 (08.08.2022, 12:07)admin Wrote: This works for me using your credentials:Now works fine for me too, thanks! Looks like the problem was that I had used "..." insted of '...' for some lines, including username RE: Ebeco floorheat thermostat - victor.back - 31.10.2023 (08.08.2022, 12:07)admin Wrote: This works for me using your credentials: Hi. I´ve used this script for one device, but how do I get the data from data table 2-5? Code: if API_Token then
devices = RequestFromEbeco('GetUserDevices')
--log(devices)
end
if devices and devices.result then
for _, device in ipairs(devices.result) do
-- Enhetsdata 1
grp.checkwrite('32/2/1', device["id"]) -- id (Number)
grp.checkwrite('32/2/2', device["relayOn"]) -- relayOn (Bool)
grp.checkwrite('32/2/3', device["minutesToTarget"]) -- minutesToTarget (Number)
grp.checkwrite('32/2/4', device["temperatureRoom"]) -- temperatureRoom (Number)
grp.checkwrite('32/2/5', device["temperatureRoomDecimals"]) -- temperatureRoomDecimals (Number)
grp.checkwrite('32/2/6', device["temperatureFloorDecimals"]) -- temperatureFloorDecimals (Number)
grp.checkwrite('32/2/7', device["remoteInput"]) -- remoteInput (Bool)
grp.checkwrite('32/2/8', device["displayName"]) -- displayName (String)
grp.checkwrite('32/2/9', device["temperatureSet"]) -- temperatureSet (Number)
-- "errorMessage" ignorerad (userdata: NULL)
grp.checkwrite('32/2/10', device["building"]["name"]) -- building name (String)
grp.checkwrite('32/2/11', device["building"]["id"]) -- building id (Number)
grp.checkwrite('32/2/12', device["programState"]) -- programState (String)
grp.checkwrite('32/2/13', device["temperatureFloor"]) -- temperatureFloor (Number)
grp.checkwrite('32/2/14', device["hasError"]) -- hasError (Bool)
grp.checkwrite('32/2/15', device["installedEffect"]) -- installedEffect (Number)
grp.checkwrite('32/2/16', device["powerOn"]) -- powerOn (Bool)
grp.checkwrite('32/2/17', device["todaysOnMinutes"]) -- todaysOnMinutes (Number)
grp.checkwrite('32/2/18', device["selectedProgram"]) -- selectedProgram (String)
-- Enhetsdata 2
grp.checkwrite('32/2/19', device2["id"]) -- id (Number)
grp.checkwrite('32/2/20', device2["relayOn"] and 1 or 0) -- relayOn (Bool)
grp.checkwrite('32/2/21', device2["minutesToTarget"]) -- minutesToTarget (Number)
grp.checkwrite('32/2/22', device2["temperatureRoom"]) -- temperatureRoom (Number)
grp.checkwrite('32/2/23', device2["temperatureRoomDecimals"]) -- temperatureRoomDecimals (Number)
grp.checkwrite('32/2/24', device2["temperatureFloorDecimals"]) -- temperatureFloorDecimals (Number)
grp.checkwrite('32/2/25', device2["remoteInput"] and 1 or 0) -- remoteInput (Bool)
grp.checkwrite('32/2/26', device2["displayName"]) -- displayName (String)
grp.checkwrite('32/2/27', device2["temperatureSet"]) -- temperatureSet (Number)
-- "errorMessage" ignorerad (userdata: NULL)
grp.checkwrite('32/2/28', device2["building"]["name"]) -- building name (String)
grp.checkwrite('32/2/29', device2["building"]["id"]) -- building id (Number)
grp.checkwrite('32/2/30', device2["programState"]) -- programState (String)
grp.checkwrite('32/2/31', device2["temperatureFloor"]) -- temperatureFloor (Number)
grp.checkwrite('32/2/32', device2["hasError"] and 1 or 0) -- hasError (Bool)
grp.checkwrite('32/2/33', device2["installedEffect"]) -- installedEffect (Number)
grp.checkwrite('32/2/34', device2["powerOn"] and 1 or 0) -- powerOn (Bool)
grp.checkwrite('32/2/35', device2["todaysOnMinutes"]) -- todaysOnMinutes (Number)
grp.checkwrite('32/2/36', device2["selectedProgram"]) -- selectedProgram (String)RE: Ebeco floorheat thermostat - admin - 31.10.2023 Remove the for loop and try this: Code: if devices and devices.result then
device = devices.result[1]
device2 = devices.result[2]
device3 = devices.result[3]
...
endRE: Ebeco floorheat thermostat - victor.back - 31.10.2023 (31.10.2023, 07:57)admin Wrote: Remove the for loop and try this: Thanks It seems to work without the loop. |