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.

HIKVision support
#1
My client has on his house HIKVision cameras and I am so impressed about its quality and also modern webserver and API. But it is fresh software so I must update my scripts to support such cameras. I found that I cannot download an image in same way as before in BCS cameras. I have right path:
http://username:password@ip_address:port/ISAPI/Streaming/channels/102/picture

and it's work perfectly on webbrowser but unfortunately not in script.

This is my script:

Code:
1234
require('socket.http') local image1 = socket.http.request('http://username:password@ip_address:port/ISAPI/Streaming/channels/102/picture') log(#image1)


And it logs that length of image1 is nil.


I've found this specification:
http://down.dipol.com.pl/Cctv/-Hikvision...ervice.pdf

I've had similar differences when I've tried get image from old BCS camera and new HIK by Postman app and I've figured out that on HIK cameras autentification must be set to Digest Auth. How can I do it in Lua?
Done is better than perfect
Reply
#2
Also I see that there is possibility to download uptodate list or have connection with camera and get notified when new event occured but it is not so easy to me. In node js all would be easy but how use this function in Lua?

http://www.ragingcomputer.com/2016/06/hi...ng-node-js

Perfect would if admin could give some short start guide how get the data(without parsing) like in nodejs:
https://github.com/ragingcomputer/node-h...kvision.js
Done is better than perfect
Reply
#3
Try code for digest auth in this post: https://forum.logicmachine.net/showthrea...64#pid9364
Reply
#4
(06.10.2018, 05:01)admin Wrote: Try code for digest auth in this post: https://forum.logicmachine.net/showthrea...64#pid9364

It works in local with http. I see that the library is not a 4 line codeWink ThanksWink And what do you think admin about this alertStream?

I think this could be a very good option to integrate e.g. linedetection or facedetection from so sharp camera.
Done is better than perfect
Reply
#5
Try this for alert stream:
Code:
12345678910111213141516171819202122232425
socket = require('socket') mime = require('mime') host = '192.168.1.2' port = 80 auth = 'user:password' init = 'GET /ISAPI/Event/notification/alertStream HTTP/1.1\r\n' .. 'Host: ' .. host .. ':' .. port .. '\r\n' .. 'Authorization: Basic ' .. mime.b64(auth) .. '\r\n' .. 'Accept: multipart/x-mixed-replace\r\n\r\n' sock = socket.tcp() sock:settimeout(60) res, err = sock:connect(host, port) if res then   alert('connection ok')      sock:send(init)   line, err = sock:receive('*l')   log(line, err) else   alert('connection failed: ' .. tostring(err)) end
Reply
#6
Today I will check for sure. Very thanks and this is really nice featureWink
Done is better than perfect
Reply
#7
I have the info that module socket.mime not found
Done is better than perfect
Reply
#8
Replace it with require('mime')
Reply
#9
This script should be in resident 0s? Now I have it in resident 10s and updated version returns in Alerts "connection failed: nil"
Done is better than perfect
Reply
#10
I've updated the script, try again. Use a resident script with sleep time more than zero for testing, otherwise you might get too many alerts/logs.
Reply
#11
Now is unauthorized message:

Code:
1234
* arg: 1  * string: HTTP/1.1 401 Unauthorized * arg: 2  * nil


I'm sure I have right credentialsWink
Done is better than perfect
Reply
#12
Replace *l with *a and post the whole output.
Reply
#13
Below whole result:

Code:
123456789101112131415161718
* arg: 1  * string: HTTP/1.1 401 Unauthorized Date: Tue, 09 Oct 2018 19:29:04 GMT Server: App-webs/ Content-Length: 178 Content-Type: text/html Connection: close WWW-Authenticate: Digest qop="auth", realm="IP Camera(13656)", nonce="4e3245794d444a684f6a56684e47526b5a575179", stale="FALSE" <!DOCTYPE html> <html><head><title>Document Error: Unauthorized</title></head> <body><h2>Access Error: 401 -- Unauthorized</h2> <p>Authentication Error</p> </body> </html> * arg: 2  * nil
Done is better than perfect
Reply
#14
This means that you need to use digest auth here as well. Considering the code complexity, writing any examples without access to the real device is like shooting in the dark, sorry.
Reply
#15
(10.10.2018, 10:22)admin Wrote: This means that you need to use digest auth here as well. Considering the code complexity, writing any examples without access to the real device is like shooting in the dark, sorry.

Thanks for your efforts. I can give you an access to the real device via private message.
Done is better than perfect
Reply
#16
Try this, change IP, port, user and pass as needed. If this works correctly, you should get xml payloads in Logs tab, otherwise errors will go to Alerts tab.

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
require('socket') md5sum = require('encdec').md5 host = '192.168.1.2' port = 80 user = 'username' pass = 'password' uri = '/ISAPI/Event/notification/alertStream' function getheader(resp, header)   local st, en   header = header .. '="'   st = resp:find(header)   if st then     en = resp:find('"', st + #header)     if en then       return resp:sub(st + #header, en - 1)     end   end end function makedigestheader(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 function hash(...)   return md5sum(table.concat({...}, ':')) end init = {   'GET ' .. uri .. ' HTTP/1.1',   'Host: ' .. host,   'Accept: multipart/x-mixed-replace', } sock = socket.tcp() sock:settimeout(60) res, err = sock:connect(host, port) if not res then   alert('init connection failed: ' .. tostring(err))   return end sock:send(table.concat(init, '\r\n') .. '\r\n\r\n') resp, err = sock:receive('*a') sock:close() if not resp then   alert('no response: ' .. tostring(err))   return end realm = getheader(resp, 'realm') nonce = getheader(resp, 'nonce') if not realm or not nonce then   alert('no realm/nonce')   return end nc = '00000001' cnonce = string.format('%08x', os.time()) method = 'GET' response = hash(   hash(user, realm, pass),   nonce,   nc,   cnonce,   'auth',   hash(method, uri) ) auth = {   { 'username', user },   { 'realm', realm },   { 'nonce', nonce },   { 'uri', uri },   { 'cnonce', cnonce },   { 'nc', nc, unquote = true },   { 'qop', 'auth' },   { 'algorithm', 'MD5' },   { 'response', response }, } table.insert(init, 2, 'Authorization: ' .. makedigestheader(auth)) sock = socket.tcp() sock:settimeout(60) res, err = sock:connect(host, port) if not res then   alert('data connection failed: ' .. tostring(err))   return end sock:send(table.concat(init, '\r\n') .. '\r\n\r\n') cl = 'Content-Length:' while true do   line, err = sock:receive('*l')   if line then     if line:find(cl, 1, true) then       len = tonumber(line:sub(#cl + 1))       if len then         sock:receive('*l') -- skip empty line         data, err = sock:receive(len)         if data then           log(data)         else           alert('data receive failed: ' .. tostring(err))         end       end     end   else     alert('line receive failed: ' .. tostring(err))     break   end end sock:close()
Reply
#17
It works I see such output:

Code:
12345678910111213
* string: <EventNotificationAlert version="2.0" xmlns="http://www.hikvision.com/ver20/XMLSchema"> <ipAddress>192.168.101.201</ipAddress> <portNo>80</portNo> <protocol>HTTP</protocol> <macAddress>aa:bb:cc:dd:ee:ff</macAddress> <channelID>1</channelID> <dateTime>2018-10-10T14:31:43+01:00</dateTime> <activePostCount>0</activePostCount> <eventType>videoloss</eventType> <eventState>inactive</eventState> <eventDescription>videoloss alarm</eventDescription> <channelName>K03 Podjazd</channelName> </EventNotificationAlert>


I will find how to parse it. Thank you very much, you are very wiseWink
Done is better than perfect
Reply
#18
Hello, 

I rescue this thread to see if anyone can help me,

How can I find the values in the XML data that the string returns? specifically what I need are the ones marked in yellow in the attached screenshot. These records are only sent if: <statisticalMethods> realTime </statisticalMethods>

Thank you very much in advance !!

Best regards

Attached Files Thumbnail(s)
   
Reply
#19
Hi,

You need to parse the XML data to get values from it, you can use the build in LuaExpat lib for that.

See this post for a sample how to use the lpx parser: https://forum.logicmachine.net/showthrea...2#pid11472

BR,

Erwin
Reply
#20
(28.05.2020, 21:16)Erwin van der Zwart Wrote: Hi,

You need to parse the XML data to get values from it, you can use the build in LuaExpat lib for that.

See this post for a sample how to use the lpx parser: https://forum.logicmachine.net/showthrea...2#pid11472

BR,

Erwin

Thank you very much Erwin, it's just what i needed.

BR, 

Alberto R.
Reply


Forum Jump: