Page 1 of 1

Kodi: Automatic display of IP cam after doorbell event

Posted: Thursday 15 August 2019 16:47
by philchillbill
I've written a script in node.js that can be triggered on a doorbell event to automatically interrupt Kodi and show a live stream from e.g. your driveway IP cam for several seconds, before automatically reverting back to what was playing before the doorbell rang. No Kodi plugin is needed for this - it's all done with JSON RPC calls.

Kodi can play video playlist files which have a .strm file extension, so you can create a one-liner .strm file somewhere in your video library and add the rtsp url/path info for the camera you want to show briefly. For Hikvision, for example, the file can contain:

Code: Select all

rtsp://username:[email protected]:554/Streaming/Channels/101
where the IP address, username, password and port apply to the IP camera in question (port is usually 554 for RTSP protocol). You can in fact just browse to this .strm file any time you like from the regular Kodi UI to 'play' the camera stream - the script here just automates that process.

I have Kodi installed on a dedicated machine (running LibreELEC) which the script quickly pings to decide whether the doorbell-interruption makes sense or not. If you don't want that then strip the pinging code from the script below. If you do want to ping so as to exit if the machine is down, then you will need to install a required npm package via

Code: Select all

npm install ping --save
in order to to use it. If your Kodi machine is always up then the ping will succeed anyway and things will still work as designed.

Here's the script:

Code: Select all

/* eslint-disable  func-names */
/* eslint-disable  no-console */

// (c) philchillbill, 2019. No rights reserved

// Change the following SEVEN parameters to match your setup

const kodiIP = '192.168.1.5'; // IP address of kodi server on LAN
const kodiPort = '8080'; // port for HTTP control of Kodi
const authneeded = false; // set to true if your Kodi instance has password protection for HTTP access
const username = "kodiusername"; // only if the above is true
const password = "kodipassword"; // only if the above is true
const IPcamStreamFile = "smb://192.168.1.3//video/IPcams/driveway.strm"; // path to .strm file, here on different server
const showfor = 8; // number of seconds to show camera before reverting

//--------------------------------------------------------------------------------------------
// no more changes needed hereafter

const client = require('http');
const ping = require('ping');

if (authneeded) {
    global.auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64');
    global.reqheaders = { 'Authorization': auth, "Content-Type": "application/json" }
} else {
    global.reqheaders = { "Content-Type": "application/json" }
}

const cfg = {
    timeout: 1
};
ping.sys.probe(kodiIP, function(isAlive) {
    if (!isAlive) {
        console.log('Player ping failed, exiting');
        process.exit()
    }
}, cfg);


const apiKODI = function(query) {

    return new Promise((resolve, reject) => {
        var jbody = query
        console.log('\n' + query)
        var auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64');
        const options = {
            host: kodiIP,
            port: kodiPort,
            method: 'POST',
            json: true,
            path: '/jsonrpc?request=',
            headers: reqheaders,
            body: jbody
        }
        var req = client.request(options, (res) => {
            var rbody = []
            var response
            res.on('data', (chunk) => {
                rbody += chunk
            });
            res.on('end', () => {
                try {
                    var result = JSON.parse(rbody).result;
                    response = result
                    global.responsive = true
                } catch (e) {
                    console.log('apiKODI response body: ', rbody)
                    console.log('apiKODI error message: ', e)
                    response = {}
                    global.responsive = false
                }
                resolve(response)
            })
        });
        req.on('error', (e) => {
            console.error(e);
            resolve(false) // e.message
        });
        req.write(jbody);
        req.end()

    })
};


const showcamera = async() => {

    response = await apiKODI('{"jsonrpc":"2.0","method":"Player.GetProperties","params":{"playerid":1,"properties":["percentage"]},"id":"1"}')
    global.percentage = response.percentage
    if (responsive) { console.log(response) }

    response = await apiKODI(`{"jsonrpc":"2.0","id":"1","method":"Playlist.Add","params":{"playlistid":1, "item":{"file":${IPcamStreamFile}}}}`)
    if (responsive) { console.log(response) }

    response = await apiKODI(`{"jsonrpc":"2.0","method":"Player.GoTo","params":{"playerid":1,"to": "next"},"id":1}`)
    if (responsive) { console.log(response) }

    response = await apiKODI(`{"jsonrpc": "2.0", "method": "Playlist.GetItems", "params": { "playlistid": 1}, "id": 1}`)
    if (responsive) { console.log(response) }
    global.tempitem = response.items.length - 1

}


const resume = async() => {

    response = await apiKODI(`{"jsonrpc":"2.0","method":"Player.GoTo","params":{"playerid":1,"to": "previous"},"id":1}`)
    if (responsive) { console.log(response) }

    response = await apiKODI(`{"jsonrpc":"2.0","id":1, "method":"Playlist.Remove","params":{"playlistid":1,"position": ${tempitem}}}`)
    if (responsive) { console.log(response) }

    response = await apiKODI(`{"jsonrpc": "2.0", "method": "Playlist.GetItems", "params": { "playlistid": 1}, "id": 1}`)
    if (responsive) { console.log(response) }

    return setTimeout(goto, 2000);

}


const goto = async() => {

    response = await apiKODI(`{"jsonrpc":"2.0","id": 4,"method":"Player.Seek","params":{"playerid":1 ,"value":{"percentage": ${percentage}} } }`)
    if (responsive) { console.log(response) }

}

showcamera()
setTimeout(resume, Number(showfor * 1000));
If you use HTTPS instead of HTTP for Kodi access then change the require to HTTPS (no npm install needed). Note that the 2 second delay before the goto function gets called is needed as Kodi will not respond to Player.Seek immediately after starting a new playlist item. To debug your setup, verify that the .strm file plays normally from the Kodi UI first - if it does not work there then the script can't succeed either. In the example path to the stream file

Code: Select all

IPcamStreamFile = "smb://192.168.1.3//video/IPcams/driveway.strm"
you will need to use a path similar to the path to your normal video files as accessed by Kodi (in my example, using SMB protocol and on a remote Synology server at 192.168.1.3). Look at your library path in Kodi to see how to build this IPcamStreamFile path.

To trigger this script when the Domoticz-aware doorbell is pressed, add a script:// to the on-action for the switch in question.

Enjoy!

Re: Kodi: Automatic display of IP cam after doorbell event

Posted: Thursday 07 October 2021 21:30
by mojso
the script works great, but can it switch from Pvr to camera and back to Pvr. Pvr stalker channel does not appear in the playlist

Re: Kodi: Automatic display of IP cam after doorbell event

Posted: Saturday 13 August 2022 16:34
by lastofthejediknights
Hi,
Dumb question.
Where does the script go? on the domoticz installation device?

regards

Re: Kodi: Automatic display of IP cam after doorbell event

Posted: Sunday 14 August 2022 21:43
by mojso
/home/pi/domoticz/scripts
lastofthejediknights wrote: Saturday 13 August 2022 16:34 Hi,
Dumb question.
Where does the script go? on the domoticz installation device?

regards