Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
I have an IP camera working and I can view it trough my logic machine.
The next step I like to reach is to send the snapshot to my telegram.
I have already configured my telegram, I can send messages. But it's impossible to send a snapshot.
I have a DAHUA camera, and the url to view the snapshot is this:
Http: // user: password@cameraip/cgi-bin/snapshot.cgi
I can view it in chrome without problems.
I try to send it with "sendphoto" command and with the example from here, in this case send through email.
https://forum.logicmachine.net/showthread.php?tid=1061
I do not know what else to do. Can someone help me?
Thanks.
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
First you need to retrieve the image using http request.
Then you can send the image using this example. filedata variable must contain image data as a string, change PUT_CHAT_ID_HERE and PUT_BOT_TOKEN_HERE placeholders
Code: require('ssl.https')
boundary = os.date('%d%m%Y%H%M%S')
filedata = '...' -- snapshot image data as a string
params = {
{
name = 'chat_id',
value = 'PUT_CHAT_ID_HERE',
},
{
name = 'photo',
filename = 'snapshot.jpg',
ctype = 'image/jpeg',
value = filedata,
}
}
body = { '--' .. boundary }
for _, param in ipairs(params) do
line = string.format('Content-Disposition: form-data; name=%q', param.name)
if param.filename then
line = string.format('%s; filename=%q', line, param.filename)
end
body[ #body + 1 ] = line
if param.ctype then
body[ #body + 1 ] = string.format('Content-Type: %s', param.ctype)
end
body[ #body + 1 ] = ''
body[ #body + 1 ] = param.value
body[ #body + 1 ] = '--' .. boundary
end
-- last boundary
body[ #body ] = body[ #body ] .. '--'
-- empty line at the end
body[ #body + 1 ] = ''
bodydata = table.concat(body, '\r\n')
resp = {}
log(
ssl.https.request({
url = 'https://api.telegram.org/PUT_BOT_TOKEN_HERE/sendPhoto',
sink = ltn12.sink.table(resp),
method = 'POST',
source = ltn12.source.string(bodydata),
headers = {
['content-length'] = #bodydata,
['content-type'] = 'multipart/form-data; boundary=' .. boundary
}
})
)
log(table.concat(resp))
Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
13.08.2020, 15:23
(This post was last modified: 13.08.2020, 15:23 by peyoe.)
Thanks for the answer.
I put my url snapshot on "filedata" and my CHATID and BOT_TOKEN, but it doesn't work.
The log says:
* arg: 1
* number: 1
* arg: 2
* number: 400
* arg: 3
* table:
["server"]
* string: nginx/1.16.1
["access-control-expose-headers"]
* string: Content-Length,Content-Type,Date,Server,Connection
["content-type"]
* string: application/json
["connection"]
* string: close
["content-length"]
* string: 79
["date"]
* string: Thu, 13 Aug 2020 15:18:09 GMT
["strict-transport-security"]
* string: max-age=31536000; includeSubDomains; preload
["access-control-allow-origin"]
* string: *
* arg: 4
* string: HTTP/1.1 400 Bad Request
* string: {"ok":false,"error_code":400,"description":"Bad Request: IMAGE_PROCESS_FAILED"}
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
As mentioned before first you need to retrieve the image from your camera via http request. You cannot pass a url to the snapshot here because telegram server cannot access your camera.
Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
Ok.
As you can see I'm a completely noob with LUA.
I will search info about that.
Thanks again.
Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
Hello.
I have tried to retrieve the image with no results.
I have used these examples:
https://forum.logicmachine.net/showthrea...tp+request
https://forum.logicmachine.net/showthrea...64#pid9364
Can you explain me how I need to do this?
Thanks in advance.
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
Log what you get when sending a request to the camera. Make sure that the URL is correct and it actually returns an image not a HTML page containing the image.
Code: require('socket.http')
log(socket.http.request('http://user:password@cameraip/cgi-bin/snapshot.cgi'))
Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
(14.08.2020, 08:08)admin Wrote: Log what you get when sending a request to the camera. Make sure that the URL is correct and it actually returns an image not a HTML page containing the image.
Code: require('socket.http')
log(socket.http.request('http://user:password@cameraip/cgi-bin/snapshot.cgi'))
Sure:
* arg: 1
* string:
* arg: 2
* number: 401
* arg: 3
* table:
["content-length"]
* string: 0
["www-authenticate"]
* string: Digest realm="Login to 5L02EC8PAGC1BC0", qop="auth", nonce="762101674", opaque="e65481894c6ae41a2f1296db7e53d66882f66471"
["connection"]
* string: close
* arg: 4
* string: HTTP/1.1 401 Unauthorized
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
This means that you need to use digest code example from here: https://forum.logicmachine.net/showthrea...64#pid9364
log what you get from the request:
Code: url = 'http://user:password@cameraip/cgi-bin/snapshot.cgi'
image, err, hdrs = request(url)
log(image, err, hdrs)
Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
(14.08.2020, 08:47)admin Wrote: This means that you need to use digest code example from here: https://forum.logicmachine.net/showthrea...64#pid9364
log what you get from the request:
Code: url = 'http://user:password@cameraip/cgi-bin/snapshot.cgi'
image, err, hdrs = request(url)
log(image, err, hdrs)
With the last code I have not had any records, instead that I had an error:
User script:21: attempt to call global 'request' (a nil value)
stack traceback:
User script:21: in main chunk
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
You need to copy the whole code from here: https://forum.logicmachine.net/showthrea...64#pid9364
And change the last lines as in my previous post.
Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
14.08.2020, 08:56
(This post was last modified: 14.08.2020, 10:56 by peyoe.)
(14.08.2020, 08:53)admin Wrote: You need to copy the whole code from here: https://forum.logicmachine.net/showthrea...64#pid9364
And change the last lines as in my previous post.
Ok, sorry. This is the log:
Code: * arg: 1
* string: ����
Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
14.08.2020, 11:01
(This post was last modified: 14.08.2020, 11:09 by peyoe.)
EDIT
It's working, I have to put on filedata, the name without ' '.
Thanks admin.
This is my whole code:
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
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
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
if ht.qop ~= 'auth' then
return nil, 'unsupported qop ' .. tostring(ht.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
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://USER:PASS@CAM IP/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg'
image, err, hdrs = request(url)
log(image, err, hdrs)
require('ssl.https')
boundary = os.date('%d%m%Y%H%M%S')
filedata = image -- snapshot image data as a string
params = {
{
name = 'chat_id',
value = 'MY CHAT ID',
},
{
name = 'photo',
filename = 'snapshot.jpg',
ctype = 'image/jpeg',
value = filedata,
}
}
body = { '--' .. boundary }
for _, param in ipairs(params) do
line = string.format('Content-Disposition: form-data; name=%q', param.name)
if param.filename then
line = string.format('%s; filename=%q', line, param.filename)
end
body[ #body + 1 ] = line
if param.ctype then
body[ #body + 1 ] = string.format('Content-Type: %s', param.ctype)
end
body[ #body + 1 ] = ''
body[ #body + 1 ] = param.value
body[ #body + 1 ] = '--' .. boundary
end
-- last boundary
body[ #body ] = body[ #body ] .. '--'
-- empty line at the end
body[ #body + 1 ] = ''
bodydata = table.concat(body, '\r\n')
resp = {}
log(
ssl.https.request({
url = 'https://api.telegram.org/MY BOT/sendPhoto',
sink = ltn12.sink.table(resp),
method = 'POST',
source = ltn12.source.string(bodydata),
headers = {
['content-length'] = #bodydata,
['content-type'] = 'multipart/form-data; boundary=' .. boundary
}
})
)
log(table.concat(resp))
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
This line is incorrect:
It should be
Posts: 22
Threads: 4
Joined: Nov 2019
Reputation:
0
(14.08.2020, 11:08)admin Wrote: This line is incorrect:
It should be
Yes, I just put it in my previous post. Thank you very much again.
|