Hey guys, I interfaced this with ZoneMinder and decided to add a way to see motion from multiple cameras, as well as display them on all XBMC installations simultaneously. Here are my changes/scripts:
(The changes here are at the beginning as well as down further, the xoptions definition)
doorbell.py_________________________________________
Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui, time, urllib, xbmcvfs, xbmcaddon, os, sys
__addon__ = xbmcaddon.Addon()
__addonid__ = __addon__.getAddonInfo('id')
args = ['CamID','CamName']
dbvar = {'CamID': 1,
'CamName': 'Default Camera'}
for item in sys.argv:
arg = item.split('=')
i = arg[0]
if arg[0] in args:
j = arg[1]
dbvar.update({arg[0]:arg[1]})
url='http://zoneminderipaddr/cgi-bin/nph-zms?mode=single&monitor='+str(dbvar['CamID'])+'&scale=100&user=myZMuser&pass=myZMpass'
path = xbmc.translatePath('special://profile/addon_data/%s' % __addonid__)
if not xbmcvfs.exists(path):
xbmcvfs.mkdir(path)
imagefile = os.path.join(path, 'bell.jpg')
class CamView(xbmcgui.WindowDialog):
def __init__(self):
#set the initial image before the window is shown
urllib.urlretrieve(url, imagefile)
self.image = xbmcgui.ControlImage(635, 160, 640, 480, "")
self.addControl(self.image)
viewer = CamView()
viewer.show()
start_time = time.time()
firstimage = True
while(time.time() - start_time <= 14):
urllib.urlretrieve(url, imagefile)
viewer.image.setImage("")
viewer.image.setImage(imagefile)
curr_time = round(time.time() - start_time, 0)
if firstimage:
nowtime=time.strftime("%I:%M %p")
xoptions="Notification(\"Motion on "+str(dbvar['CamName'])+" camera detected\",%s, 13800, special://masterprofile/media/bell1.png)" % (nowtime)
xbmc.executebuiltin(xoptions)
viewer.image.setAnimations([('conditional', 'effect=fade start=0 end=90 time=250 delay=125 condition=true',), ('conditional', 'effect=slide start=0,400 end=0,0 time=250 condition=true',)])
firstimage = False
elif curr_time == 14:
viewer.image.setAnimations([('conditional', 'effect=fade start=90 end=90 time=0 condition=true',), ('conditional', 'effect=slide start=0,0 end=0,400 time=250 condition=true',)])
print "catch"
else:
viewer.image.setAnimations([('conditional', 'effect=fade start=90 end=90 time=0 condition=true',)])
print curr_time
xbmc.sleep(500)
viewer.close()
del viewer
For anyone else attempting to do this, I used the trigger script found in the ZM wiki:
http://www.zoneminder.com/wiki/index.php...n_alarm.3F
Code:
#!/usr/bin/perl -w
use strict;
use ZoneMinder;
$| = 1;
zmDbgInit( "myscript", level=>0, to_log=>0, to_syslog=>0, to_term=>1 );
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS );
my $sql = "select M.*, max(E.Id) as LastEventId from Monitors as M left join Events as E on M.Id = E.MonitorId where M.Function != 'None' group by (M.Id)";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
my @monitors;
while ( my $monitor = $sth->fetchrow_hashref() )
{
push( @monitors, $monitor );
}
while( 1 )
{
foreach my $monitor ( @monitors )
{
next if ( !zmMemVerify( $monitor ) );
if ( my $last_event_id = zmHasAlarmed( $monitor, $monitor->{LastEventId} ) )
{
$monitor->{LastEventId} = $last_event_id;
print( "Monitor ".$monitor->{Name}." has alarmed\n" );
#
# Do your stuff here
system(“/sbin/ZoneMinderTrigger CamID=”.$monitor->{Id}.” CamName=”.$monitor->{Name});
sleep(12)
#
}
}
sleep( 1 );
}
I have this as an upstart job on my Ubuntu server named ZoneMinderAlarm. In the “Do Your Stuff Here” section, I had it call a python script with the specific camera ID and Name, then pause for a bit instead of continually retriggering during the event
I’m more familiar with Python, so that’s why it’s not all confined in the ZM perl script
ZoneMinderTrigger_________________________________________
Code:
#!/usr/bin/python
# This script is called by the ZoneMinderAlarm daemon/script and notifies
# all XBMC installations to overlay pictures on the screen
# It requires the doorbell xbmc plugin
# http://homeawesomation.wordpress.com/2013/02/18/doorbell-ipcam-xbmc-update/
# Credit for send_json_command to u/sffjunkie
# http://forum.xbmc.org/showthread.php?tid=92196
import json, httplib, base64, sys
xbmc_host=['myxbmcmachine','192.168.1.1','etcetcetc'] #List of XBMC HTPCs to send notification to
xbmc_port='8080'
username='myxbmcuser'
password='myxbmcpass'
args = ['CamID','CamName']
dbvar = {'CamID': 1,
'CamName': 'Default'}
for item in sys.argv:
arg = item.split('=')
i = arg[0]
if arg[0] in args:
j = arg[1]
dbvar.update({arg[0]:arg[1]})
def send_json_command(xbmc_host, xbmc_port, method, params=None, id=1, username=username, password=password):
command = {'jsonrpc': '2.0', 'id': id, 'method': method}
if params is not None: command['params'] = params
payload = json.dumps(command, ensure_ascii=False, sort_keys=True)
payload.encode('utf-8')
headers = {'Content-Type': 'application/json'}
if password != '':
userpass = base64.encodestring('%s:%s' % (username, password))[:-1]
headers['Authorization'] = 'Basic %s' % userpass
conn = httplib.HTTPConnection(xbmc_host, xbmc_port)
data = None
try:
conn.request('POST', '/jsonrpc', payload, headers)
response = conn.getresponse()
if response.status == 200: data = json.loads(response.read())['result']
else: data = 'Response Error'
except:
data = 'Connection Error'
conn.close()
return data
def xbmc_doorbell(xbmc_host, xbmc_port=xbmc_port):
for x in range(0, len(xbmc_host)):
result = send_json_command(xbmc_host[x], xbmc_port, 'Addons.ExecuteAddon',{'addonid':'script.doorbell','params':{'CamID':str(dbvar['CamID']),'CamName':str(dbvar['CamName'])}})
print xbmc_host[x]+": "+result
xbmc_doorbell(xbmc_host)
_________________________________________
There’s probably better ways to do this (I’m a shadetree programmer), but it seems to work well for me.