Skip to content
This repository has been archived by the owner on Mar 8, 2022. It is now read-only.

Commit

Permalink
Merge pull request #27 from Brahmah/master
Browse files Browse the repository at this point in the history
Support Choosing Camera
  • Loading branch information
jeroenterheerdt authored Nov 15, 2020
2 parents 4395308 + 8f8811a commit 7b0433b
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 68 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ This add-on wraps around [Dgreif's excellent work](https://github.com/dgreif/rin
2. Configure your Ring Refresh Token and port (see configuration below).
3. Start the "Ring Livestream" add-on. Check for errors in the logs.
4. For remote access, open up the port in your router.
5. Open the stream at http://hassio.local:port/public/stream.m3u8 to make sure it works before going any further. We recommend using VLC or equivalent.
5. Open the stream at http://homeassistant.local:port/public/stream.m3u8 to make sure it works before going any further. We recommend using VLC or equivalent.
6. Add a camera to Home Assistant, such as:
```yaml
camera:
- platform: generic
name: Ring Livestream
stream_source: http://hassio.local:port/public/stream.m3u8
still_image_url: http://hassio.local:port/public/stream.m3u8
stream_source: http://homeassistant.local:port/public/stream.m3u8
still_image_url: http://homeassistant.local:port/public/stream.m3u8
```
(Don't worry about the `still_image_url` not pointing to an actual image, we are not going to use it, but it is required.)
7. Add a card `Picture Glance` card to your UI, set the 'Camera Entity` to the camera you have just created.
8. Done! Enjoy your shiny new livestream!

## Configuration
Example configuration:
```json
{
"ring_refresh_token": your_refresh_token
}
```yaml
ring_refresh_token: your_refresh_token
camera_name: Front Door
```
You need to create a refresh token - see https://github.com/dgreif/ring/wiki/Refresh-Tokens on how to do that. Note that you will have to have node and npm installed on your machine.
* You need to create a refresh token - see https://github.com/dgreif/ring/wiki/Refresh-Tokens on how to do that. Note that you will have to have node and npm installed on your machine.
* The camera name is the name entred when setting up the camera in the Ring app.

## Taking a snapshot
Currently the addon does not support taking snapshots, but when it does this is the configuration you will need:
Expand Down
4 changes: 3 additions & 1 deletion ring_hassio/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Ring Livestream",
"version": "1.3",
"version": "1.35",
"slug": "ringlivestream",
"description": "A Home Assistant add-on to enable live streams of Ring Cameras.",
"url": "https://github.com/jeroenterheerdt/ring-hassio",
Expand All @@ -22,10 +22,12 @@
"webui": "http://[HOST]:[PORT:3000]/index.html",
"options": {
"ring_refresh_token": "refresh_token",
"camera_name": "Front Door",
"port": 3000
},
"schema": {
"ring_refresh_token":"str",
"camera_name": "str",
"port":"port"
},
"map": [
Expand Down
72 changes: 48 additions & 24 deletions ring_hassio/livestream.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,50 @@ require("dotenv/config");
var ring_client_api_1 = require("ring-client-api");
var util_1 = require("util");
var fs = require('fs'), path = require('path'), http = require('http'), url = require('url'), zlib = require('zlib');
//const PORT = 3000;
var PORT = process.env.RING_PORT;
//
var CAMERA_NAME = process.env.CAMERA_NAME;
var chosenCamera = CAMERA_NAME;
/**
* This example creates an hls stream which is viewable in a browser
* It also starts web app to view the stream at http://localhost:PORT
**/
function startStream() {
return __awaiter(this, void 0, void 0, function () {
///////////////
function getCamera() {
return __awaiter(this, void 0, void 0, function () {
var cameras, camera, i, cameraName;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, ringApi.getCameras()];
case 1:
cameras = _a.sent();
//
if (!chosenCamera) {
for (i = 0; i < cameras.length; i++) {
cameraName = cameras[i].initialData.description;
console.log("Checking If " + cameraName + " Is the same as the camera we are looking for (" + chosenCamera + ")");
if (chosenCamera == cameraName) {
camera = cameras[i];
console.log("Matched " + cameraName);
}
}
}
else {
camera = cameras[0];
}
//
if (!cameras) {
console.log('No cameras found');
return [2 /*return*/];
}
//
return [2 /*return*/, camera];
}
});
});
}
var ringApi, camera, publicOutputDirectory, server, sockets, nextSocketId, sipSession;
return __generator(this, function (_a) {
switch (_a.label) {
Expand All @@ -58,36 +94,24 @@ function startStream() {
refreshToken: process.env.RING_REFRESH_TOKEN,
debug: true
});
return [4 /*yield*/, ringApi.getCameras()];
return [4 /*yield*/, getCamera()
///////////////
];
case 1:
camera = (_a.sent())[0];
if (!camera) {
console.log('No cameras found');
return [2 /*return*/];
}
camera = _a.sent();
publicOutputDirectory = path.join('public/');
/*fs.readdir(publicOutputDirectory, (err, files) => {
if (err) throw err;
for (const file of files) {
var filepath = path.join(publicOutputDirectory,file);
if (path.extname(file) == ".ts") {
fs.unlink(filepath,err => {
if (err) throw err;
});
}
}
});*/
console.log('output directory: ' + publicOutputDirectory);
server = http.createServer(function (req, res) {
// Get URL
var uri = url.parse(req.url).pathname;
console.log('requested uri: ' + uri);
// If Accessing The Main Page
if (uri == '/index.html' || uri == '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('<html><head><title>Ring Livestream' +
'</title></head><body>');
res.write('<html><head><title>Ring Livestream</title></head><body>');
res.write('<h1>Welcome to your Ring Livestream!</h1>');
res.write('<video width="352" height="198" controls autoplay src="public/stream.m3u8"></video>');
res.write('<br/>If you cannot see the video above open <a href="public/stream.m3u8">the stream</a> in a player such as VLC.');
res.write("<video width=\"352\" height=\"198\" controls autoplay src=\"public/stream.m3u8\"></video>");
res.write("<br/>If you cannot see the video above open <a href=\"public/stream.m3u8\">the stream</a> in a player such as VLC.");
res.end();
return;
}
Expand Down Expand Up @@ -209,8 +233,8 @@ function startStream() {
});
});
}
if (!('RING_REFRESH_TOKEN' in process.env) || !('RING_PORT' in process.env)) {
console.log('Missing environment variables. Check RING_REFRESH_TOKEN and RING_PORT are set.');
if (!('RING_REFRESH_TOKEN' in process.env) || !('RING_PORT' in process.env) || !('CAMERA_NAME' in process.env)) {
console.log('Missing environment variables. Check RING_REFRESH_TOKEN, RING_PORT and CAMERA_NAME are set.');
process.exit();
}
else {
Expand Down
74 changes: 41 additions & 33 deletions ring_hassio/livestream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,64 @@ const fs = require('fs'),
url = require('url'),
zlib = require('zlib')

//const PORT = 3000;
const PORT = process.env.RING_PORT;
//
const CAMERA_NAME = process.env.CAMERA_NAME;
var chosenCamera = CAMERA_NAME;
/**
* This example creates an hls stream which is viewable in a browser
* It also starts web app to view the stream at http://localhost:PORT
**/

async function startStream() {
const ringApi = new RingApi({
//
const ringApi = new RingApi({
// Refresh token is used when 2fa is on
refreshToken: process.env.RING_REFRESH_TOKEN!,
debug: true
}),
[camera] = await ringApi.getCameras()

if (!camera) {
console.log('No cameras found')
return
})
///////////////
async function getCamera() {
var cameras = await ringApi.getCameras();
var camera;
//
if (!chosenCamera) {
for (var i=0; i < cameras.length; i++) {
var cameraName = cameras[i].initialData.description;
console.log(`Checking If ${cameraName} Is the same as the camera we are looking for (${chosenCamera})`);
if (chosenCamera == cameraName) {
camera = cameras[i];
console.log(`Matched ${cameraName}`);
}
}
} else {
camera = cameras[0]
}
//
if (!cameras) {
console.log('No cameras found')
return
}
//
return camera
}

//const publicOutputDirectory = path.join('public','output')
///////////////
var camera = await getCamera()
///////////////
const publicOutputDirectory = path.join('public/')
/*fs.readdir(publicOutputDirectory, (err, files) => {
if (err) throw err;
for (const file of files) {
var filepath = path.join(publicOutputDirectory,file);
if (path.extname(file) == ".ts") {
fs.unlink(filepath,err => {
if (err) throw err;
});
}
}
});*/
console.log('output directory: '+publicOutputDirectory)

var server = http.createServer(function (req, res) {
// Get URL
var uri = url.parse(req.url).pathname;
console.log('requested uri: '+uri)
// If Accessing The Main Page
if (uri == '/index.html' || uri == '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('<html><head><title>Ring Livestream' +
'</title></head><body>');
res.write('<html><head><title>Ring Livestream</title></head><body>');
res.write('<h1>Welcome to your Ring Livestream!</h1>');
res.write('<video width="352" height="198" controls autoplay src="public/stream.m3u8"></video>');
res.write('<br/>If you cannot see the video above open <a href="public/stream.m3u8">the stream</a> in a player such as VLC.');
res.write(`<video width="352" height="198" controls autoplay src="public/stream.m3u8"></video>`);
res.write(`<br/>If you cannot see the video above open <a href="public/stream.m3u8">the stream</a> in a player such as VLC.`);
res.end();
return;
}
Expand Down Expand Up @@ -135,7 +148,7 @@ const PORT = process.env.RING_PORT;
if (!(await promisify(fs.exists)(publicOutputDirectory))) {
await promisify(fs.mkdir)(publicOutputDirectory)
}

//
const sipSession = await camera.streamVideo({
output: [
'-preset',
Expand Down Expand Up @@ -176,15 +189,10 @@ const PORT = process.env.RING_PORT;
}, 10* 60 * 1000) // 10*60*1000 Stop after 10 minutes.
}

if(!('RING_REFRESH_TOKEN' in process.env) || !('RING_PORT' in process.env)) {
console.log('Missing environment variables. Check RING_REFRESH_TOKEN and RING_PORT are set.')
if(!('RING_REFRESH_TOKEN' in process.env) || !('RING_PORT' in process.env) || !('CAMERA_NAME' in process.env)) {
console.log('Missing environment variables. Check RING_REFRESH_TOKEN, RING_PORT and CAMERA_NAME are set.')
process.exit()
}
else {
startStream()
}





4 changes: 2 additions & 2 deletions ring_hassio/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ring_livestream",
"version": "1.3.0",
"version": "1.3.1",
"description": "Ring Livestream addon",
"author": "Jeroen ter Heerdt",
"main": "livestream.js",
Expand All @@ -9,7 +9,7 @@
},
"dependencies": {
"dotenv-extended": "^2.8.0",
"ring-client-api": "9.6.0",
"ring-client-api": "9.12.4",
"http": "^0.0.0",
"zlib": "^1.0.5",
"url": "^0.11.0"
Expand Down
1 change: 1 addition & 0 deletions ring_hassio/run.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/bash
CONFIG_PATH=/data/options.json
export RING_REFRESH_TOKEN="$(jq --raw-output '.ring_refresh_token' $CONFIG_PATH)"
export CAMERA_NAME="$(jq --raw-output '.camera_name' $CONFIG_PATH)"
export RING_PORT="$(jq --raw-output '.port' $CONFIG_PATH)"

cd /ring-hassio/ring_hassio
Expand Down

0 comments on commit 7b0433b

Please sign in to comment.