So I have been thinking of having a snapshot from an IP camera connected to my Dahua NVR sent when a certain motion detector senses motion. I think this is possible with Reactor but I am not too sure how to go about this. The link to get the snapshot is http://xxxx:firstname.lastname@example.org/cgi-bin/snapshot.cgi?1 and works fine in my browser. I set up an action to have a HTTP GET command and send that output to an expression, but the expression is showing “Error 401”. I am assuming I am doing that part wrong, any suggestions would be nice!
Unfortunately, the LuaSocket HTTP library supports “Basic” authentication only. That 401 response is an authorization failure, and assuming you’ve provided the correct username and password, the remote end is asking for Digest authentication, and the Lua library can’t do it.
Edit: you should find a message in the LuaUPnP log confirming this. Search for “request action” in the log. There should be a yellow warning message nearby saying “WWW-Authenticate: Digest realm=…”
This is a job for
curl. If you are doing this in Reactor, you can set
urn:toggledbits-com:serviceId:ReactorSensor) to 1 to make the RS use curl for the request.
But then you have the issue of the response… Reactor can’t collect and store an image response.
So, I think you are on to writing Lua to call
os.execute() to run
curl to capture the image to a file, and then figure out how to build a MIME attachment and email it (assuming that’s what you want to do with the captured image). Probably doable, but outside scope for here.
Ah, this seems like it would be more complicated than anticipated. Thanks for the info though, maybe I can instead send a command to the NVR and have it email out a screenshot itself. Would have to see if thats even doable in the first place!
I haven’t had cause to do it (I use BlueIris and it can send email), but here’s a link to a Lua script that seems like it would (almost) work: https://gist.github.com/Danukeru/c6700d04237503424b878bbc315fb594
So the idea would be, use
os.execute() to run
curl to get the image to a fixed file (
/tmp/camerasnap.jpg or something), then modify the script to collect that file (replace their name/path with yours). I think the
content-type header in the script is wrong, it should contain the MIME type of the file (
image/jpeg or similar). The
server key (with mail server hostname or IP) needs to added to the call as well (before
source= for example).
That script should run fine in scene Lua or a Run Lua action in a ReactorSensor.
Dunno if this helps, but my favorite IP camera indeed can email a snapshot (or video clip) in response to its internal motion trigger. So I send those attachments to myself with a subject line that includes a certain hashtag.
Gmail then filters those incoming messages and places them in a specified folder for me.
Then I have a Google Apps Script routine run hourly which deletes the oldest of those messages so I only keep about the 70 most recent ones in Google Drive. Complicated, but effective.
In brief, keep Vera and Reactor out of the loop if you can.
That is one way to go about it, I just need snapshots thought when a certain motion sensor is tripped during a certain time. Hence why I need to add Vera into the equation. Have not found a HTTP command though that takes a snapshot and emails it unfortunately though.
I’m using Telegram. I built an external application to send video as gifs of the previous 10 seconds, by continually streaming and capturing the frames inside my app.
The principle is similar and if you need just a still image (and you know how to get it from your camera) it’ll work. I’ll post the code when back home.
Does Telegram require an extra PC or PI running?
No, just a bot i believe.
nope. as @ElCid said, just a bot.
Look at part 3.
When the bot is ready, just call this in LUA:
function sendCameraSnapshot(url, chatid, name, description) snapFile = "/tmp/camsnapshot" .. name ..".jpg" snapFile = snapFile:gsub("%s+", "") -- replace for a safe name luup.log('[sendCameraSnapshot] ' .. name .. snapFile); -- remove Image os.execute('/bin/rm ' .. snapFile) -- save locally local cmd = 'curl -H "Accept-Charset: utf-8" -H "Content-Type: application/x-www-form-urlencoded" -o ' .. snapFile .. ' "' .. url .. '"' os.execute(cmd) -- send via telegram local telegramUrl = "https://api.telegram.org/bot**yourBotID**:**yourBotKey**/sendPhoto" cmd = 'curl "' .. telegramUrl .. '" -F caption="Screenshot from ' .. name .. description ..'" -F chat_id=' .. chatid ..' -F photo=@' .. snapFile os.execute(cmd) end
Code should be straighforward.
Edit: unless is not
- url: your photo url. local or remote, everything works
- chatid: your chat id. I have a group with me and my wife, groups work too
- name: your sensor name, usually
- description: I’m using it to add more text (ie: door is open, door is still open after 45 minutes, etc).
I’m working on creating a plug-in very soon.
Awesome! Will give this a try this weekend, will the plugin have similar but more straightforward functionality?
Yep. Just a safer way to call it (via Reactor, or scene, or whatever you want, code-less). Both images and text-only will be supported.
BotId and key can be saved in the device itself, so it’s easier; very similar to my VeraAlexa plug-in. I’m busy with work+life, but I think I’ll work on this on sunday morning.
Is that getting the camera snapshot file off the Vera itself?
I just setup Telegram last week myself for text notications and some TTS calls for urgent announcements.
Working well so far.
Yeaup looks like the file is stored in the temp folder then deleted
Yes, the image is stored locally because curl needs it in order to send the binary to telegram.
I have not used this in the last 2 years, moving to a more complex setup I already described, but it worked fine for me. I used to get the image from the cam (Foscam) directly, but it will work with anything you want, even public webcams or dynamic image (think about weather maps or similar). It’s pretty cool and I think it was never documented here.
seems like with the bot the possibilities are endless