Merge branch 'storageareas' of github.com:ZoneMinder/ZoneMinder into storageareas

This commit is contained in:
Isaac Connor 2016-03-30 10:56:53 -04:00
commit e9c65785e8
16 changed files with 202 additions and 116 deletions

View File

@ -1,3 +1,27 @@
zoneminder (1.30.2-trusty-2016030702) trusty; urgency=medium
*
-- Isaac Connor <iconnor@connortechnology.com> Mon, 07 Mar 2016 22:14:03 -0500
zoneminder (1.30.2-trusty-2016030701) trusty; urgency=medium
* merge master. with telemetry
-- Isaac Connor <iconnor@connortechnology.com> Mon, 07 Mar 2016 21:47:53 -0500
zoneminder (1.30.2-trusty-2016022101) trusty; urgency=medium
* merge zmtrigger fix
-- Isaac Connor <iconnor@testing.internal.point-one.com> Mon, 22 Feb 2016 09:15:53 -0500
zoneminder (1.30.2-trusty-2016021901) trusty; urgency=medium
* zmtrigger improvements
-- Isaac Connor <iconnor@testing.internal.point-one.com> Fri, 19 Feb 2016 11:09:57 -0500
zoneminder (1.30.2-trusty-2016021701) trusty; urgency=medium
* printout id, and ip address when failing to connect

View File

@ -53,7 +53,7 @@ override_dh_auto_configure:
--with-mariadb=/usr --with-webdir=/usr/share/zoneminder \
--with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin \
--with-webuser=www-data --with-webgroup=www-data \
--enable-crashtrace=no --enable-mmap=yes $(DEBOPT)
--enable-mmap=yes $(DEBOPT)
override_dh_clean:
# Add here commands to clean up after the build process.

View File

@ -10,7 +10,6 @@ bin_SCRIPTS = \
zmdc.pl \
zmaudit.pl \
zmfilter.pl \
zmtelemetry.pl \
zmtrigger.pl \
zmx10.pl \
zmwatch.pl \
@ -20,7 +19,8 @@ bin_SCRIPTS = \
zmcontrol.pl \
zmtrack.pl \
zmcamtool.pl \
zmsystemctl.pl
zmsystemctl.pl \
zmtelemetry.pl
SUBDIRS = \
. \
@ -30,7 +30,6 @@ EXTRA_DIST = \
zmdc.pl.in \
zmaudit.pl.in \
zmfilter.pl.in \
zmtelemetry.pl.in \
zmtrigger.pl.in \
zmx10.pl.in \
zmwatch.pl.in \
@ -41,6 +40,7 @@ EXTRA_DIST = \
zmtrack.pl.in \
zmcamtool.pl.in \
zmsystemctl.pl.in \
zmtelemtry.pl.in \
ZoneMinder/Makefile.PL \
ZoneMinder/README \
ZoneMinder/Changes \

View File

@ -198,6 +198,7 @@ my %spawned_connections;
my %monitors;
my $monitor_reload_time = 0;
my $needsReload = 0;
$! = undef;
my $rin = '';
@ -218,8 +219,8 @@ while( 1 )
if ( $nfound > 0 )
{
Debug( "Got input from $nfound connections\n" );
foreach my $connection ( @in_select_connections )
{
foreach my $connection ( @in_select_connections ) {
if ( vec( $rout, $connection->fileno(), 1 ) )
{
Debug( "Got input from connection "
@ -311,8 +312,15 @@ while( 1 )
# Check for alarms that might have happened
my @out_messages;
foreach my $monitor ( values(%monitors) )
{
foreach my $monitor ( values(%monitors) ) {
my $memVerified = 1;
if ( !zmMemRead($monitor, "shared_data:valid") ) {
zmMemInvalidate($monitor);
$memVerified = zmMemVerify($monitor);
}
if ($memVerified) {
my ( $state, $last_event )
= zmMemRead( $monitor,
[ "shared_data:state",
@ -324,39 +332,36 @@ while( 1 )
#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" );
if ( $state == STATE_ALARM
|| $state == STATE_ALERT
) # In alarm state
{
) { # In alarm state
if ( !defined($monitor->{LastEvent})
|| ($last_event != $monitor->{LastEvent})
) # A new event
{
) { # A new event
push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event );
}
else # The same one as last time, so ignore it
{
} else { # The same one as last time, so ignore it
# Do nothing
}
}
elsif ( ($state == STATE_IDLE
} elsif ( ($state == STATE_IDLE
&& $monitor->{LastState} != STATE_IDLE
)
|| ($state == STATE_TAPE
&& $monitor->{LastState} != STATE_TAPE
)
) # Out of alarm state
{
) { # Out of alarm state
push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event );
}
elsif ( defined($monitor->{LastEvent})
&& ($last_event != $monitor->{LastEvent})
) # We've missed a whole event
{
) { # We've missed a whole event
push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event );
push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event );
}
$monitor->{LastState} = $state;
$monitor->{LastEvent} = $last_event;
} else { # Our attempt to verify the memory handle failed. We should reload the monitors.
$needsReload = 1;
}
}
foreach my $connection ( @out_connections )
{
if ( $connection->canWrite() )
@ -413,7 +418,7 @@ while( 1 )
}
# If necessary reload monitors
if ( (time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL )
if ( $needsReload || ((time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL ))
{
foreach my $monitor ( values(%monitors) )
{
@ -421,6 +426,7 @@ while( 1 )
zmMemInvalidate( $monitor );
}
loadMonitors();
$needsReload = 0;
}
}
Info( "Trigger daemon exiting\n" );

View File

@ -1221,6 +1221,17 @@ void EventStream::checkEventLoaded()
}
}
Image * EventStream::getImage( ) {
Event::Initialise();
static char filepath[PATH_MAX];
Debug( 2, "EventStream::getImage path(%s) frame(%d)", event_data->path, curr_frame_id );
snprintf( filepath, sizeof(filepath), Event::capture_file_format, event_data->path, curr_frame_id );
Debug( 2, "EventStream::getImage path(%s) ", filepath, curr_frame_id );
Image *image = new Image( filepath );
return image;
}
bool EventStream::sendFrame( int delta_us )
{
Debug( 2, "Sending frame %d", curr_frame_id );

View File

@ -265,6 +265,7 @@ public:
mode = p_mode;
}
void runStream();
Image *getImage();
};
#endif // ZM_EVENT_H

View File

@ -1131,13 +1131,32 @@ void Monitor::DumpZoneImage( const char *zone_string )
}
}
Image *zone_image = NULL;
if ( ( (!staticConfig.SERVER_ID) || ( staticConfig.SERVER_ID == server_id ) ) && mem_ptr ) {
Debug(3, "Trying to load from local zmc");
int index = shared_data->last_write_index;
Snapshot *snap = &image_buffer[index];
Image *snap_image = snap->image;
zone_image = new Image( *snap->image );
} else {
Debug(3, "Trying to load from event");
// Grab the most revent event image
std::string sql = stringtf( "SELECT MAX(Id) FROM Events WHERE MonitorId=%d AND Frames > 0", id );
MYSQL_ROW eventid_row = zmDbFetchOne(sql.c_str() );
if ( eventid_row ) {
int event_id = atoi( eventid_row[0] );
Image zone_image( *snap_image );
if(zone_image.Colours() == ZM_COLOUR_GRAY8) {
zone_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB );
Debug( 3, "Got event %d", event_id );
EventStream *stream = new EventStream();
stream->setStreamStart( event_id, 1 );
zone_image = stream->getImage();
} else {
Error("Unable to load an event for monitor %d", id );
return;
}
}
if(zone_image->Colours() == ZM_COLOUR_GRAY8) {
zone_image->Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB );
}
for( int i = 0; i < n_zones; i++ )
@ -1173,19 +1192,20 @@ void Monitor::DumpZoneImage( const char *zone_string )
colour = RGB_WHITE;
}
}
zone_image.Fill( colour, 2, zones[i]->GetPolygon() );
zone_image.Outline( colour, zones[i]->GetPolygon() );
zone_image->Fill( colour, 2, zones[i]->GetPolygon() );
zone_image->Outline( colour, zones[i]->GetPolygon() );
}
if ( extra_zone.getNumCoords() )
{
zone_image.Fill( extra_colour, 2, extra_zone );
zone_image.Outline( extra_colour, extra_zone );
zone_image->Fill( extra_colour, 2, extra_zone );
zone_image->Outline( extra_colour, extra_zone );
}
static char filename[PATH_MAX];
snprintf( filename, sizeof(filename), "Zones%d.jpg", id );
zone_image.WriteJpeg( filename );
zone_image->WriteJpeg( filename );
delete zone_image;
}
void Monitor::DumpImage( Image *dump_image ) const

View File

@ -27,6 +27,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
//
// Class representing 'remote' cameras, i.e. those which are

View File

@ -108,7 +108,12 @@ int RemoteCameraHttp::Connect()
{
close(sd);
sd = -1;
Warning("Can't connect to remote camera: %s", strerror(errno) );
char buf[sizeof(struct in6_addr)];
struct sockaddr_in *addr;
addr = (struct sockaddr_in *)p->ai_addr;
inet_ntop( AF_INET, &(addr->sin_addr), buf, INET6_ADDRSTRLEN );
Warning("Can't connect to remote camera mid: %d at %s: %s", id, buf, strerror(errno) );
continue;
}

View File

@ -493,7 +493,6 @@ int main( int argc, char *argv[] )
}
if ( ! monitor->connect() ) {
Error( "Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name() );
exit( -1 );
}
char separator = ' ';

View File

@ -66,7 +66,49 @@ class Event {
}
public function LinkPath() {
if ( ZM_USE_DEEP_STORAGE ) {
return $this->{'MonitorId'} .'/'.strftime( "%y/%m/%d/.", $this->{'Time'}).$this->{'Id'};
}
Error("Calling Link_Path when not using deep storage");
return '';
}
public function delete() {
dbQuery( 'DELETE FROM Events WHERE Id = ?', array($this->{'Id'}) );
if ( !ZM_OPT_FAST_DELETE ) {
dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}) );
dbQuery( 'DELETE FROM Frames WHERE EventId = ?', array($this->{'Id'}) );
if ( ZM_USE_DEEP_STORAGE ) {
# Assumption: All events haev a start time
$start_date = date_parse( $this->{'StartTime'} );
$start_date['year'] = $start_date['year'] % 100;
$Storage = $this->Storage();
# So this is because ZM creates a link under teh day pointing to the time that the event happened.
$eventlink_path = $Storage->Path().'/'.$this->Link_Path();
if ( $id_files = glob( $eventlink_path ) ) {
# I know we are using arrays here, but really there can only ever be 1 in the array
$eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] );
deletePath( $eventPath );
deletePath( $id_files[0] );
$pathParts = explode( '/', $eventPath );
for ( $i = count($pathParts)-1; $i >= 2; $i-- ) {
$deletePath = join( '/', array_slice( $pathParts, 0, $i ) );
if ( !glob( $deletePath."/*" ) ) {
deletePath( $deletePath );
}
}
} else {
Warning( "Found no event files under $eventlink_path" );
} # end if found files
} else {
$eventPath = $this->Path();
deletePath( $eventPath );
} # USE_DEEP_STORAGE OR NOT
} # ! ZM_OPT_FAST_DELETE
} # end Event->delete
} # end class
?>

View File

@ -26,6 +26,8 @@ class Storage {
public function Path() {
if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) {
return $this->{'Path'};
} else if ( ! $this->{'Id'} ) {
return ZM_DIR_EVENTS;
}
return $this->{'Name'};
}

View File

@ -537,7 +537,7 @@ function deletePath( $path )
}
}
function deleteEvent( $event, $mid=false ) {
function deleteEvent( $event ) {
if ( empty($event) ) {
Error( "Empty event passed to deleteEvent.");
@ -546,49 +546,13 @@ function deleteEvent( $event, $mid=false ) {
if ( gettype($event) != 'array' ) {
# $event could be an eid, so turn it into an event hash
$event = dbFetchOne( 'SELECT Id, MonitorId, StartTime FROM Events WHERE Id=?', NULL, array( $event ) );
$event = new Event( $event );
}
global $user;
if ( !$mid )
$mid = $event['MonitorId'];
if ( $user['Events'] == 'Edit' ) {
dbQuery( 'DELETE FROM Events WHERE Id = ?', array($event['Id']) );
if ( !ZM_OPT_FAST_DELETE ) {
dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($event['Id']) );
dbQuery( 'DELETE FROM Frames WHERE EventId = ?', array($event['Id']) );
if ( ZM_USE_DEEP_STORAGE ) {
# Assumption: All events haev a start time
$start_date = date_parse( $event['StartTime'] );
$start_date['year'] = $start_date['year'] % 100;
# So this is because ZM creates a link under teh day pointing to the time that the event happened.
$eventlink_path = sprintf('%s/%d/%02d/%02d/%02d/.%d', ZM_DIR_EVENTS, $mid, $start_date['year'], $start_date['month'], $start_date['day'], $event['Id'] );
if ( $id_files = glob( $eventlink_path ) ) {
# I know we are using arrays here, but really there can only ever be 1 in the array
$eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] );
deletePath( $eventPath );
deletePath( $id_files[0] );
$pathParts = explode( '/', $eventPath );
for ( $i = count($pathParts)-1; $i >= 2; $i-- ) {
$deletePath = join( '/', array_slice( $pathParts, 0, $i ) );
if ( !glob( $deletePath."/*" ) ) {
deletePath( $deletePath );
}
}
} else {
Warning( "Found no event files under $eventlink_path" );
} # end if found files
} else {
$eventPath = implode( '/', array( ZM_DIR_EVENTS, $mid, $event['Id'] ) );
deletePath( $eventPath );
} # USE_DEEP_STORAGE OR NOT
} # ! ZM_OPT_FAST_DELETE
$event->delete();
} # CAN EDIT
}
@ -1433,6 +1397,9 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' )
case 'MonitorName':
$filter['sql'] .= 'M.'.preg_replace( '/^Monitor/', '', $filter['terms'][$i]['attr'] );
break;
case 'ServerId':
$filter['sql'] .= 'M.ServerId';
break;
case 'DateTime':
$filter['sql'] .= "E.StartTime";
break;
@ -1448,6 +1415,7 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' )
case 'Id':
case 'Name':
case 'MonitorId':
case 'StorageId':
case 'Length':
case 'Frames':
case 'AlarmFrames':
@ -1480,6 +1448,12 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' )
case 'Notes':
$value = dbEscape($value);
break;
case 'ServerId':
if ( $value == 'ZM_SERVER_ID' ) {
$value = ZM_SERVER_ID;
} else {
$value = dbEscape($value);
}
case 'DateTime':
$value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'";
break;

View File

@ -49,6 +49,8 @@ if ( false )
require_once( 'includes/config.php' );
require_once( 'includes/logger.php' );
require_once( 'includes/Server.php' );
require_once( 'includes/Event.php' );
require_once( 'includes/Monitor.php' );
if ( isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' )
{

View File

@ -100,6 +100,8 @@ if ( !canView( 'Events' ) )
return;
}
require_once( 'includes/Monitor.php' );
if ( !empty($_REQUEST['group']) )
{
$group = $_REQUEST['group'];
@ -117,7 +119,7 @@ else
// Note we round up just a bit on the end time as otherwise you get gaps, like 59.78 to 00 in the next second, which can give blank frames when moved through slowly.
$eventsSql = "
select E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) as StartTimeSecs,
select E.Id,E.Name,E.StorageId,UNIX_TIMESTAMP(E.StartTime) as StartTimeSecs,
case when E.EndTime is null then (Select UNIX_TIMESTAMP(DATE_ADD(E.StartTime, Interval max(Delta)+0.5 Second)) from Frames F where F.EventId=E.Id)
else UNIX_TIMESTAMP(E.EndTime)
end as CalcEndTimeSecs, E.Length,
@ -553,13 +555,12 @@ function SetImageSource(monId,val)
else
{
var zeropad = <?php echo sprintf("\"%0" . ZM_EVENT_IMAGE_DIGITS . "d\"",0); ?>;
for(var i=0; i<ePath.length; i++) // Search for a match
for(var i=0, var eIdlength = eId.length; i<eIdlength; i++) // Search for a match
{
if(eMonId[i]==monId && val >= eStartSecs[i] && val <= eEndSecs[i])
{
var frame=parseInt((val - eStartSecs[i])/(eEndSecs[i]-eStartSecs[i])*eventFrames[i])+1;
// img = ePath[i] + zeropad.substr(frame.toString().length) + frame.toString() + "-capture.jpg";
img = "index.php?view=image&path=" + ePath[i].substring(6) + zeropad.substr(frame.toString().length) + frame.toString() + "-capture.jpg" + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height;
img = "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height;
return img;
}
}

View File

@ -25,13 +25,12 @@ if ( !canView( 'Monitors' ) )
}
$mid = validInt($_REQUEST['mid']);
$Monitor = new Monitor( $mid );
$wd = getcwd();
chdir( ZM_DIR_IMAGES );
$status = exec( escapeshellcmd( getZmuCommand( " -m ".$mid." -z" ) ) );
chdir( $wd );
$monitor = dbFetchMonitor( $mid );
$image = ZM_DIR_IMAGES.'/'.'Zones'.$Monitor->Id().'.jpg';
$zones = array();
foreach( dbFetchAll( 'select * from Zones where MonitorId = ? order by Area desc', NULL, array($mid) ) as $row )
{
@ -42,7 +41,6 @@ foreach( dbFetchAll( 'select * from Zones where MonitorId = ? order by Area desc
}
}
$image = 'Zones'.$monitor['Id'].'.jpg';
xhtmlHeaders(__FILE__, translate('Zones') );
?>
@ -58,13 +56,13 @@ xhtmlHeaders(__FILE__, translate('Zones') );
foreach( array_reverse($zones) as $zone )
{
?>
<area shape="poly" alt="<?php echo htmlspecialchars($zone['Name']) ?>" coords="<?php echo $zone['AreaCoords'] ?>" href="#" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor['Width'] ?>, <?php echo $monitor['Height'] ?> ); return( false );"/>
<area shape="poly" alt="<?php echo htmlspecialchars($zone['Name']) ?>" coords="<?php echo $zone['AreaCoords'] ?>" href="#" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $Monitor->Width ?>, <?php echo $Monitor->Height ?> ); return( false );"/>
<?php
}
?>
<!--<area shape="default" nohref>-->
</map>
<img src="<?php echo ZM_DIR_IMAGES.'/'.$image ?>" alt="zones" usemap="#zoneMap" width="<?php echo $monitor['Width'] ?>" height="<?php echo $monitor['Height'] ?>" border="0"/>
<img src="<?php echo $image ?>" alt="zones" usemap="#zoneMap" width="<?php echo $Monitor->Width ?>" height="<?php echo $Monitor->Height ?>" border="0"/>
<form name="contentForm" id="contentForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>">
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value="delete"/>
@ -84,9 +82,9 @@ foreach( $zones as $zone )
{
?>
<tr>
<td class="colName"><a href="#" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor['Width'] ?>, <?php echo $monitor['Height'] ?> ); return( false );"><?php echo $zone['Name'] ?></a></td>
<td class="colName"><a href="#" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $Monitor->Width ?>, <?php echo $Monitor->Height ?> ); return( false );"><?php echo $zone['Name'] ?></a></td>
<td class="colType"><?php echo $zone['Type'] ?></td>
<td class="colUnits"><?php echo $zone['Area'] ?>&nbsp;/&nbsp;<?php echo sprintf( "%.2f", ($zone['Area']*100)/($monitor['Width']*$monitor['Height']) ) ?></td>
<td class="colUnits"><?php echo $zone['Area'] ?>&nbsp;/&nbsp;<?php echo sprintf( "%.2f", ($zone['Area']*100)/($Monitor->Width*$Monitor->Height) ) ?></td>
<td class="colMark"><input type="checkbox" name="markZids[]" value="<?php echo $zone['Id'] ?>" onclick="configureDeleteButton( this );"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/></td>
</tr>
<?php
@ -95,7 +93,7 @@ foreach( $zones as $zone )
</tbody>
</table>
<div id="contentButtons">
<input type="button" value="<?php echo translate('AddNewZone') ?>" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=0', 'zmZone', 'zone', <?php echo $monitor['Width'] ?>, <?php echo $monitor['Height'] ?> );"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/>
<input type="button" value="<?php echo translate('AddNewZone') ?>" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=0', 'zmZone', 'zone', <?php echo $Monitor->Width ?>, <?php echo $Monitor->Height ?> );"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/>
<input type="submit" name="deleteBtn" value="<?php echo translate('Delete') ?>" disabled="disabled"/>
</div>
</form>