This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

curl to LUA
#1
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:
1
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.
Reply
#2
See this example: https://forum.logicmachine.net/showthrea...64#pid9364
Reply
#3
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 ;-)
Reply
#4
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:
1234
url = 'http://admin:123456789@192.168.1.1/ISAPI/VideoIntercom/callStatus?format=json' res, err, hdrs = request(url) log(res, err, hdrs)
Reply
#5
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:
12345
{     "CallStatus":    {         "status":    "idle"     } }

But with the following script i get no value from the doorbell:

Code:
1234567891011121314
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)
Reply
#6
Try this:
Code:
123456
if type(data) == 'table' then   status = data.CallStatus.status   grp.checkwrite('32/5/1', status) else   alert('request failed') end
Reply
#7
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.
Reply
#8
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
Reply
#9
(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:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
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
Reply
#10
Line 136 should be:
data, err, hdrs = request(url)

Otherwise result is assigned to the image variable not data
Reply
#11
Angel Hoe could I be that stupid… tnx it works!
Reply
#12
I am sorry to hijack the thread, but how would implement the following in the script example that is provided by Admin?

Code:
123456
curl --location --request PUT 'https://exampleadr.com/pms_api/:subscription_id/:account_id/rooms/:room_id' \ --data-raw '{     "room": {         "housekeeping_status": "inspect"     } }'
Reply
#13
Use this, adjust URL (including id parameters) as needed:
Code:
123456789101112131415161718
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)
Reply
#14
(03.03.2022, 08:33)admin Wrote: Use this, adjust URL (including id parameters) as needed:
Code:
123456789101112131415161718
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?
Reply
#15
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:
123456789101112131415161718192021222324
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)
Reply
#16
(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:
123456789101112131415161718192021222324
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!
Reply
#17
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
Reply
#18
You need to use digest auth request function from this example: https://forum.logicmachine.net/showthrea...64#pid9364
Code:
12345678910
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)
Reply


Forum Jump: