Posts: 117
Threads: 21
Joined: Apr 2018
Reputation:
2
Dear, as I am a novice in scripting. Anyone that can help me in reading out doorbell status to link to object in KNX?
Hik doorbell KV6113-WPE1 uses a curl command:
Code: curl -i --digest -u admin:xxx http://192.168.x.x/ISAPI/VideoIntercom/callStatus?format=json
Should give as output : “idle” , “ring” , “onCall”
during "ring" it must set a boolean to 1 All others 0.
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Posts: 117
Threads: 21
Joined: Apr 2018
Reputation:
2
I found that one using the search function but this is about getting a snapshot not a datapoint. So i don't understand the link. Sorry i am really novice in scripting ;-)
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Copy the script for the example and change two last lines and log the result. Change 123456789 to your device password and change the IP address as needed.
Code: url = 'http://admin:123456789@192.168.1.1/ISAPI/VideoIntercom/callStatus?format=json'
res, err, hdrs = request(url)
log(res, err, hdrs)
Posts: 117
Threads: 21
Joined: Apr 2018
Reputation:
2
01.01.2022, 20:30
(This post was last modified: 01.01.2022, 20:31 by KoBra.)
Thx for the help.
I made a script from some copy pasting of other scripts i have running. But i don't get the different value.
The reply from the bell in the JSON is the following:
Code: {
"CallStatus": {
"status": "idle"
}
}
But with the following script i get no value from the doorbell:
Code: require('json')
require('socket.http')
data = socket.http.request('http://admin:xxxx@192.168.0.0/ISAPI/VideoIntercom/callStatus?format=json')
data = json.pdecode(data)
if type(data) == 'table' then
data = data['CallStatus'][ 1 ]
log(data)
-- Status
grp.checkwrite('32/5/1', data.status)
else
alert('request failed')
end
Sorry i am just not good at scripting (yet)
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Try this:
Code: if type(data) == 'table' then
status = data.CallStatus.status
grp.checkwrite('32/5/1', status)
else
alert('request failed')
end
Posts: 117
Threads: 21
Joined: Apr 2018
Reputation:
2
02.01.2022, 14:05
(This post was last modified: 02.01.2022, 14:34 by KoBra.)
Tried it both as Resident or as Event based script but both don't write a value at the 32/5/1 address... "Request Failed". No idea where it goes wrong.
I tested the login with credential in Chrome on a incognito window. There it accepts the HTTP including the login credentials.
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
It does not work because the standard HTTP library does not support digest authentication scheme. You need to use code from this example instead: https://forum.logicmachine.net/showthrea...64#pid9364
Posts: 117
Threads: 21
Joined: Apr 2018
Reputation:
2
(03.01.2022, 06:27)admin Wrote: It does not work because the standard HTTP library does not support digest authentication scheme. You need to use code from this example instead: https://forum.logicmachine.net/showthrea...64#pid9364
If i test with script below i get the same error...
Code: local skthttp = require('socket.http')
local skturl = require('socket.url')
local ltn12 = require('ltn12')
local md5sum = require('encdec').md5
local hash = function(...)
return md5sum(table.concat({...}, ':'))
end
local parse_header = function(header)
local result = {}
for key, value in (header .. ','):gmatch('(%w+)=(.-),') do
if value:sub(1, 1) == '"' then -- strip quotes
result[ key:lower() ] = value:sub(2, -2)
else
result[ key:lower() ] = value
end
end
return result
end
local make_digest_header = function(headers)
local digest = {}
for _, header in ipairs(headers) do
if not header.unquote then
header[ 2 ] = '"' .. header[ 2 ] .. '"'
end
digest[ #digest + 1 ] = header[ 1 ] .. '=' .. header[ 2 ]
end
return 'Digest ' .. table.concat(digest, ', ')
end
local _request = function(req)
if not req.url then
return nil, 'missing url'
end
local url = skturl.parse(req.url)
local user, password = url.user, url.password
local sink = req.sink
if not user or not password then
return nil, 'missing credentials in url'
end
url.user, url.password, url.authority, url.userinfo = nil, nil, nil, nil
req.url = skturl.build(url)
local source
if req.source then
local chunks = {}
local capture = function(chunk)
if chunk then
chunks[ #chunks + 1 ] = chunk
end
return chunk
end
local chunk_id = 0
source = function()
chunk_id = chunk_id + 1
return chunks[ chunk_id ]
end
req.source = ltn12.source.chain(req.source, capture)
end
req.sink = nil
local body, code, hdrs = skthttp.request(req)
if code == 401 and hdrs['www-authenticate'] then
local ht = parse_header(hdrs['www-authenticate'])
if not ht.realm or not ht.nonce then
return nil, 'missing realm/nonce from response'
end
local qop = ht.qop
if qop and qop ~= 'auth' then
return nil, 'unsupported qop ' .. tostring(qop)
end
if ht.algorithm and ht.algorithm:lower() ~= 'md5' then
return nil, 'unsupported algo ' .. tostring(ht.algorithm)
end
local nc = '00000001'
local cnonce = string.format('%08x', os.time())
local uri = skturl.build({ path = url.path, query = url.query })
local method = req.method or 'GET'
local response = hash(
hash(user, ht.realm, password),
ht.nonce,
nc,
cnonce,
'auth',
hash(method, uri)
)
req.headers = req.headers or {}
local auth = {
{ 'username', user },
{ 'realm', ht.realm },
{ 'nonce', ht.nonce },
{ 'uri', uri },
{ 'cnonce', cnonce },
{ 'nc', nc, unquote = true },
{ 'qop', 'auth' },
{ 'algorithm', 'MD5' },
{ 'response', response },
}
if ht.opaque then
table.insert(auth, { 'opaque', ht.opaque })
end
req.headers.authorization = make_digest_header(auth)
if not req.headers.cookie and hdrs['set-cookie'] then
-- not really correct but enough for httpbin
local cookie = (hdrs['set-cookie'] .. ';'):match('(.-=.-)[;,]')
if cookie then
req.headers.cookie = '$Version: 0; ' .. cookie .. ';'
end
end
if req.source then
req.source = source
end
req.sink = sink
body, code, hdrs = skthttp.request(req)
end
return body, code, hdrs
end
local request = function(url)
local t = type(url)
if t == 'table' then
return _request(table.clone(url))
elseif t == 'string' then
local req = {}
local _, code, headers = _request({ url = url, sink = ltn12.sink.table(req) })
return table.concat(req), code, headers
end
end
url = 'http://admin:XXXX@192.168.0.1/ISAPI/VideoIntercom/callStatus?format=json'
image, err, hdrs = request(url)
require('json')
data = json.pdecode(data)
if type(data) == 'table' then
status = data.CallStatus.status
grp.checkwrite('32/5/1', data.CallStatus.status)
else
alert('request failed doorbell')
end
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Line 136 should be:
data, err, hdrs = request(url)
Otherwise result is assigned to the image variable not data
Posts: 117
Threads: 21
Joined: Apr 2018
Reputation:
2
Hoe could I be that stupid… tnx it works!
Posts: 60
Threads: 22
Joined: Jul 2017
Reputation:
0
03.03.2022, 07:08
(This post was last modified: 03.03.2022, 07:09 by Krstfr2k.)
I am sorry to hijack the thread, but how would implement the following in the script example that is provided by Admin?
Code: curl --location --request PUT 'https://exampleadr.com/pms_api/:subscription_id/:account_id/rooms/:room_id' \
--data-raw '{
"room": {
"housekeeping_status": "inspect"
}
}'
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Use this, adjust URL (including id parameters) as needed:
Code: http = require('socket.http')
json = require('json')
url = 'https://exampleadr.com/pms_api/:subscription_id/:account_id/rooms/:room_id'
body = json.encode({
room = {
housekeeping_status = 'inspect'
}
})
res, code = http.request({
url = url,
method = 'PUT',
body = body
})
log(res, code)
Posts: 60
Threads: 22
Joined: Jul 2017
Reputation:
0
(03.03.2022, 08:33)admin Wrote: Use this, adjust URL (including id parameters) as needed:
Code: http = require('socket.http')
json = require('json')
url = 'https://exampleadr.com/pms_api/:subscription_id/:account_id/rooms/:room_id'
body = json.encode({
room = {
housekeeping_status = 'inspect'
}
})
res, code = http.request({
url = url,
method = 'PUT',
body = body
})
log(res, code)
The API uses Digest Auth, would the example above work in that case or would the earlier example in this thread need to be adjusted?
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
In this case you need to pass request source differently and also put username and password into the URL. Also don't forget to include digest library code before this.
Code: json = require('json')
url = 'https://username:password@exampleadr.com/pms_api/:subscription_id/:account_id/rooms/:room_id'
body = json.encode({
room = {
housekeeping_status = 'inspect'
}
})
resp = {}
res, code = request({
url = url,
method = 'PUT',
headers = {
['Content-Type'] = 'application/json',
['Content-Length'] = #body,
},
source = ltn12.source.string(body),
sink = ltn12.sink.table(resp),
})
print(res, code, resp)
Posts: 60
Threads: 22
Joined: Jul 2017
Reputation:
0
(03.03.2022, 09:04)admin Wrote: In this case you need to pass request source differently and also put username and password into the URL. Also don't forget to include digest library code before this.
Code: json = require('json')
url = 'https://username:password@exampleadr.com/pms_api/:subscription_id/:account_id/rooms/:room_id'
body = json.encode({
room = {
housekeeping_status = 'inspect'
}
})
resp = {}
res, code = request({
url = url,
method = 'PUT',
headers = {
['Content-Type'] = 'application/json',
['Content-Length'] = #body,
},
source = ltn12.source.string(body),
sink = ltn12.sink.table(resp),
})
print(res, code, resp)
Thank you so much for the help, worked perfectly!
Posts: 49
Threads: 8
Joined: Jul 2015
Reputation:
0
How i can send a command for open a door / Relay:
curl -i --digest -u admin:xxx -X PUT -d '<RemoteControlDoor><cmd>open</cmd></RemoteControlDoor>' http://192.168.0.xx/ISAPI/AccessControl/...rol/door/1
thank you
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
You need to use digest auth request function from this example: https://forum.logicmachine.net/showthrea...64#pid9364
Code: body = '<RemoteControlDoor><cmd>open</cmd></RemoteControlDoor>'
res, code = request({
url = 'http://admin:123@IP/...',
method = 'PUT',
headers = {
['Content-Length'] = #body,
},
source = ltn12.source.string(body),
})
log(res, code)
|