Getting security cam picture to send over telegram

I have several Amcrest and Reolink security cameras, including Unifi G4 Pro doorbell. I don't want any of them to touch the internet because they are never going to be secure.

Since I have this diverse group of cams I wanted to get reliable notifications to my phone. I ended up using PIR motion sensors to notify me of movement around the house but had no way to connect the notifications, with an associated picture.

This script runs locally on my network (or remotely, whatever, you do you) so only the server hosting the file needs to touch the internet (not even hubitat).

After tons of searching and copy-pasting prototype endgeneering, I was able to get 2 workable solutions. One for reolink and probably other cams that use a URL variable for the password, and another similar solution for cameras that pass a digest password (user:password@ht tp://foo.com)

so here are the 2 PHP scripts. Paste one into a text doc named with ".php". Edit the lines needing your information, put it on a server hosting PHP (rpi or equivalent, or a nas will work for this) and then you can get this working for yourself.

In hubitat, just have the action be an HTTP get with this url. then when your camera url gives a picture, it will get uploaded to your telegram chat through your bot.

Here is the simpler one for cams that support u/p as get variables:

Example URL
ht tp://myLocalServer/thisfile.php?url=aHR0cDovL2NhbWVyYXVybGZvcnBpY3M=&caption=this_is_a_caption

<?php
/*
	This script sends a picture to telegram from a security cam url. 
	This won't work with some urls that prepend the address with user:password@http://...
	thisfile.php?url=<b64 encoded url>&caption=<plaintextcaption, nospaces>
	The caption replaces underscores with spaces, but if you wanted to have more freedom, 
	you could b64 it to send it through an html get like the same way as the url
	*/
	$chat_id 	= '<put your chatid here>';
    $bot_url    = "ht tps://api.telegram.org/bot<put your bot api here>/";
    $url        = $bot_url . "sendPhoto?chat_id=" . $chat_id ;
    $caption 	= str_replace("_", " ", $_GET['caption']);
    $img 		= '/tmp/foo.jpeg'; //local path where image should be saved

    /* Get the image from the URL and save to your own path. You need to add 
    allow_url_fopen=On to your php.ini file for the below code to work */

    file_put_contents($img, file_get_contents(base64_decode($_GET['url']))); 
    $post_fields = array('chat_id'   => $chat_id,
    'photo'     => new CURLFile(realpath($img)),
    'caption' => $caption
    );

    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type:multipart/form-data"));
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields); 
    $output = curl_exec($ch);
    curl_close($ch); //close curl


?>

Here is the other one for cameras that use user:pass@ht tp://foo.com

Example URL
ht tp://myLocalServer/thisfile.php?url=aHR0cDovL2NhbWVyYXVybGZvcnBpY3M=&caption=this_is_a_caption&username=mysecretuser&password=ILikePonys

<?php
	/*
	This script sends a picture to telegram from a security cam url (with any html password normally passed as user:pass)
	thisfile.php?url=<b64 encoded url>&usename=<plaintextuser>&password=<plaintextpass>&caption=<plaintextcaption, no spaces>
	The caption replaces underscores with spaces, but if you wanted to have more freedom, 
	you could b64 it to send it through an html get like the same way as the url
	*/
	$chat_id 	= '<your chatid here>';
	$bot_url    = "ht tps://api.telegram.org/bot<your bot api here>/";
    $url        = $bot_url . "sendPhoto?chat_id=" . $chat_id ;
    $caption 	= str_replace("_", " ", $_GET['caption']);
    $img 		= '/tmp/foo.jpeg'; //local path where image should be saved

	/* Put the picture in a stream variable*/
	$nurl = base64_decode($_GET['url']);
	$curl = curl_init();
	curl_setopt($curl, CURLOPT_URL, $nurl);
	curl_setopt($curl,  CURLOPT_HTTPAUTH, CURLAUTH_ANY);
	curl_setopt($curl, CURLOPT_USERPWD, $_GET['username'].":".$_GET['password']);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($curl, CURLOPT_HEADER, false);
	$picdata = curl_exec($curl);
	curl_close($curl);	

    /* Put the picturestream into a file and send it to telegram
	Get the image from the URL and save to your own path. You need to add 
    allow_url_fopen=On to your php.ini file for the below code to work */

    file_put_contents($img, $picdata); 
    $post_fields = array('chat_id'   => $chat_id,
    'photo'     => new CURLFile(realpath($img)),
    'caption' => $caption
    );

    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type:multipart/form-data"));
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields); 
    $output = curl_exec($ch);
    curl_close($ch); //close curl


?>

if you don't get notifications then turn on PHP errors in your php ini so that you can see what it's unhappy about. That's the only way sometimes....

I hope this can help some of you get over the hump on this.

Why am I doing this setup?

I run Graphene OS on my phone and notifications for some apps are non-existant without firebase. Unifi apps barely work and do not notify, even locally, also they can go to heck for not allowing protect to work over a vpn at all. They claim to be "secure on site" but for some insane reason require using their p2p "everything must be cloud based" service. I want less man in the middle risks in my life. Telemetry is bad enough.

2 Likes

I had to put spaces in the urls so watch out for that in the script where it says http also just in case someone doesn't know:

Paste this into powershell if you want to convert B64 offline. there are plenty of websites that wil convert a text string but you may not want to put your camera passwords online.

[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('http://cameraurlforpics'))