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: 8075
Threads: 43
Joined: Jun 2015
Reputation:
471
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
require (
'ssl.https' )
boundary =
os.date (
'%d%m%Y%H%M%S' )
filedata =
'...'
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
body [ #
body ] =
body [ #
body ] ..
'--'
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: 8075
Threads: 43
Joined: Jun 2015
Reputation:
471
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: 8075
Threads: 43
Joined: Jun 2015
Reputation:
471
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:
1 2
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:
1 2
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: 8075
Threads: 43
Joined: Jun 2015
Reputation:
471
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:
1 2 3
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:
1 2 3
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: 8075
Threads: 43
Joined: Jun 2015
Reputation:
471
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:
1 2
*
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
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
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
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
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
body [ #
body ] =
body [ #
body ] ..
'--'
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: 8075
Threads: 43
Joined: Jun 2015
Reputation:
471
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.