'snapshot_filename': '',
'@preserve_pictures': int(ui['preserve_pictures']),
- # movies
- 'ffmpeg_output_movies': ui['motion_movies'],
- 'movie_filename': ui['movie_file_name'],
- 'ffmpeg_bps': 400000,
- '@preserve_movies': int(ui['preserve_movies']),
-
# motion detection
+ '@motion_detection': ui['motion_detection'],
'text_changes': ui['show_frame_changes'],
'locate_motion_mode': ui['show_frame_changes'],
'noise_tune': ui['auto_noise_detect'],
'pre_capture': int(ui['pre_capture']),
'post_capture': int(ui['post_capture']),
+ # movies
+ 'ffmpeg_output_movies': ui['motion_movies'],
+ 'movie_filename': ui['movie_file_name'],
+ 'ffmpeg_bps': 400000,
+ '@preserve_movies': int(ui['preserve_movies']),
+
# working schedule
'@working_schedule': '',
'snapshot_interval': 0,
'preserve_pictures': data['@preserve_pictures'],
- # motion movies
- 'motion_movies': data['ffmpeg_output_movies'],
- 'movie_file_name': data['movie_filename'],
- 'preserve_movies': data['@preserve_movies'],
-
# motion detection
+ 'motion_detection': data['@motion_detection'],
'show_frame_changes': data['text_changes'] or data['locate_motion_mode'],
'auto_noise_detect': data['noise_tune'],
'noise_level': int(int(data['noise_level']) / 2.55),
'pre_capture': int(data['pre_capture']),
'post_capture': int(data['post_capture']),
+ # motion movies
+ 'motion_movies': data['ffmpeg_output_movies'],
+ 'movie_file_name': data['movie_filename'],
+ 'preserve_movies': data['@preserve_movies'],
+
# motion notifications
'email_notifications_enabled': False,
'web_hook_notifications_enabled': False,
data.setdefault('text_right', '%Y-%m-%d\\n%T')
data.setdefault('text_double', False)
+ data.setdefault('@motion_detection', True)
data.setdefault('text_changes', False)
if old_motion:
data.setdefault('locate', False)
def on_response(remote_ui_config=None, error=None):
if error:
return self.finish_json({'error': 'Failed to get remote camera configuration for %(url)s: %(msg)s.' % {
- 'url': remote.make_camera_url(local_config)}, 'msg': error})
+ 'url': remote.make_camera_url(local_config), 'msg': error}})
for key, value in local_config.items():
remote_ui_config[key.replace('@', '')] = value
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import datetime
import errno
import logging
import os.path
import time
from tornado.httpclient import HTTPClient, AsyncHTTPClient, HTTPRequest
+from tornado.ioloop import IOLoop
import config
import settings
return _motion_binary_cache
+def _disable_motion_detection():
+ for camera_id in config.get_camera_ids():
+ camera_config = config.get_camera(camera_id)
+ if not camera_config['@motion_detection']:
+ logging.debug('motion detection disabled by config for camera with id %s' % camera_id)
+ set_motion_detection(camera_id, False)
+
+
def start():
global _started
# write the pid to file
with open(motion_pid_path, 'w') as f:
f.write(str(pid) + '\n')
+
+ IOLoop.instance().add_timeout(datetime.timedelta(seconds=5), _disable_motion_detection)
def stop():
continue
working_schedule = camera_config.get('@working_schedule')
+ motion_detection = camera_config.get('@motion_detection')
working_schedule_type = camera_config.get('@working_schedule_type') or 'outside'
- must_be_enabled = False
if not working_schedule: # working schedule disabled, motion detection left untouched
continue
- else:
- now_during = _during_working_schedule(now, working_schedule)
- must_be_enabled = (now_during and working_schedule_type == 'during') or (not now_during and working_schedule_type == 'outside')
+ if not motion_detection: # motion detection explicitly disabled
+ continue
+
+ now_during = _during_working_schedule(now, working_schedule)
+ must_be_enabled = (now_during and working_schedule_type == 'during') or (not now_during and working_schedule_type == 'outside')
currently_enabled = motionctl.get_motion_detection(camera_id)
if currently_enabled and not must_be_enabled:
$('#streamingServerResizeSwitch').change(updateConfigUi);
$('#stillImagesSwitch').change(updateConfigUi);
$('#preservePicturesSelect').change(updateConfigUi);
+ $('#motionDetectionSwitch').change(updateConfigUi);
$('#motionMoviesSwitch').change(updateConfigUi);
$('#preserveMoviesSelect').change(updateConfigUi);
$('#emailNotificationsSwitch').change(updateConfigUi);
'input.text-overlay, select.text-overlay, ' +
'input.streaming, select.streaming, ' +
'input.still-images, select.still-images, ' +
- 'input.motion-movies, select.motion-movies, ' +
'input.motion-detection, select.motion-detection, ' +
+ 'input.motion-movies, select.motion-movies, ' +
'input.notifications, select.notifications, ' +
'input.working-schedule, select.working-schedule').change(pushCameraConfig);
$('#picturesLifetime').parents('tr:eq(0)').each(markHide);
}
+ /* motion detection switch */
+ if (!$('#motionDetectionSwitch').get(0).checked) {
+ $('#motionDetectionSwitch').parent().next('table.settings').find('tr.settings-item').each(markHide);
+ $('#motionMoviesSwitch').parent().each(markHide);
+ $('#motionMoviesSwitch').parent().next('table.settings').each(markHide);
+ $('#emailNotificationsSwitch').parents('table.settings:eq(0)').each(markHide);
+ $('#emailNotificationsSwitch').parents('table.settings:eq(0)').prev().each(markHide);
+ $('#workingScheduleSwitch').parent().each(markHide);
+ $('#workingScheduleSwitch').parent().next('table.settings').each(markHide);
+ }
+
/* motion movies switch */
if (!$('#motionMoviesSwitch').get(0).checked) {
$('#motionMoviesSwitch').parent().next('table.settings').find('tr.settings-item').each(markHide);
'snapshot_interval': $('#snapshotIntervalEntry').val(),
'preserve_pictures': $('#preservePicturesSelect').val() >= 0 ? $('#preservePicturesSelect').val() : $('#picturesLifetime').val(),
- /* motion movies */
- 'motion_movies': $('#motionMoviesSwitch')[0].checked,
- 'movie_file_name': $('#movieFileNameEntry').val(),
- 'movie_quality': $('#movieQualitySlider').val(),
- 'preserve_movies': $('#preserveMoviesSelect').val() >= 0 ? $('#preserveMoviesSelect').val() : $('#moviesLifetime').val(),
-
/* motion detection */
+ 'motion_detection': $('#motionDetectionSwitch')[0].checked,
'show_frame_changes': $('#showFrameChangesSwitch')[0].checked,
'frame_change_threshold': $('#frameChangeThresholdSlider').val(),
'auto_noise_detect': $('#autoNoiseDetectSwitch')[0].checked,
'pre_capture': $('#preCaptureEntry').val(),
'post_capture': $('#postCaptureEntry').val(),
+ /* motion movies */
+ 'motion_movies': $('#motionMoviesSwitch')[0].checked,
+ 'movie_file_name': $('#movieFileNameEntry').val(),
+ 'movie_quality': $('#movieQualitySlider').val(),
+ 'preserve_movies': $('#preserveMoviesSelect').val() >= 0 ? $('#preserveMoviesSelect').val() : $('#moviesLifetime').val(),
+
/* motion notifications */
'email_notifications_enabled': $('#emailNotificationsSwitch')[0].checked,
'email_notifications_addresses': $('#emailAddressesEntry').val(),
}
$('#picturesLifetime').val(dict['preserve_pictures']);
+ /* motion detection */
+ $('#motionDetectionSwitch')[0].checked = dict['motion_detection'];
+ $('#showFrameChangesSwitch')[0].checked = dict['show_frame_changes'];
+ $('#frameChangeThresholdSlider').val(dict['frame_change_threshold']);
+ $('#autoNoiseDetectSwitch')[0].checked = dict['auto_noise_detect'];
+ $('#noiseLevelSlider').val(dict['noise_level']);
+ $('#eventGapEntry').val(dict['event_gap']);
+ $('#preCaptureEntry').val(dict['pre_capture']);
+ $('#postCaptureEntry').val(dict['post_capture']);
+
/* motion movies */
$('#motionMoviesSwitch')[0].checked = dict['motion_movies'];
$('#movieFileNameEntry').val(dict['movie_file_name']);
}
$('#moviesLifetime').val(dict['preserve_movies']);
- /* motion detection */
- $('#showFrameChangesSwitch')[0].checked = dict['show_frame_changes'];
- $('#frameChangeThresholdSlider').val(dict['frame_change_threshold']);
- $('#autoNoiseDetectSwitch')[0].checked = dict['auto_noise_detect'];
- $('#noiseLevelSlider').val(dict['noise_level']);
- $('#eventGapEntry').val(dict['event_gap']);
- $('#preCaptureEntry').val(dict['pre_capture']);
- $('#postCaptureEntry').val(dict['post_capture']);
-
/* motion notifications */
$('#emailNotificationsSwitch')[0].checked = dict['email_notifications_enabled'];
$('#emailAddressesEntry').val(dict['email_notifications_addresses']);
</tr>
</table>
- <div class="settings-section-title"><input type="checkbox" class="styled section motion-movies" id="motionMoviesSwitch">Motion Movies</div>
- <table class="settings">
- <tr class="settings-item advanced-setting">
- <td class="settings-item-label"><span class="settings-item-label">Movie File Name</span></td>
- <td class="settings-item-value"><input type="text" class="styled motion-movies" id="movieFileNameEntry" placeholder="file name pattern..."></td>
- <td><span class="help-mark" title="sets the name pattern for the movie (MPEG) files; the following special tokens are accepted: %Y = year, %m = month, %d = date, %H = hour, %M = minute, %S = second, %q = frame number, / = subfolder">?</span></td>
- </tr>
- <tr class="settings-item advanced-setting">
- <td class="settings-item-label"><span class="settings-item-label">Movie Quality</span></td>
- <td class="settings-item-value"><input type="text" class="range styled motion-movies" id="movieQualitySlider"></td>
- <td><span class="help-mark" title="sets the MPEG video quality (higher values produce a better video quality but require more storage space)">?</span></td>
- </tr>
- <tr class="settings-item">
- <td class="settings-item-label"><span class="settings-item-label">Preserve Movies</span></td>
- <td class="settings-item-value">
- <select class="styled motion-movies" id="preserveMoviesSelect">
- <option value="1">For One Day</option>
- <option value="7">For One Week</option>
- <option value="30">For One Month</option>
- <option value="365">For One Year</option>
- <option value="0">Forever</option>
- <option value="-1">Custom</option>
- </select>
- </td>
- <td><span class="help-mark" title="movies older than the specified duration are automatically deleted to free storage space">?</span></td>
- </tr>
- <tr class="settings-item">
- <td class="settings-item-label"><span class="settings-item-label">Movies Lifetime</span></td>
- <td class="settings-item-value"><input type="text" class="styled number still-images" id="moviesLifetime"><span class="settings-item-unit">days</span></td>
- <td><span class="help-mark" title="sets the number of days after which the movies will be deleted automatically">?</span></td>
- </tr>
- </table>
-
- <div class="settings-section-title advanced-setting">Motion Detection</div>
+ <div class="settings-section-title advanced-setting"><input type="checkbox" class="styled section motion-detection" id="motionDetectionSwitch">Motion Detection</div>
<table class="settings advanced-setting">
<tr class="settings-item advanced-setting">
<td class="settings-item-label"><span class="settings-item-label">Show Frame Changes</span></td>
</tr>
</table>
+ <div class="settings-section-title"><input type="checkbox" class="styled section motion-movies" id="motionMoviesSwitch">Motion Movies</div>
+ <table class="settings">
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Movie File Name</span></td>
+ <td class="settings-item-value"><input type="text" class="styled motion-movies" id="movieFileNameEntry" placeholder="file name pattern..."></td>
+ <td><span class="help-mark" title="sets the name pattern for the movie (MPEG) files; the following special tokens are accepted: %Y = year, %m = month, %d = date, %H = hour, %M = minute, %S = second, %q = frame number, / = subfolder">?</span></td>
+ </tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Movie Quality</span></td>
+ <td class="settings-item-value"><input type="text" class="range styled motion-movies" id="movieQualitySlider"></td>
+ <td><span class="help-mark" title="sets the MPEG video quality (higher values produce a better video quality but require more storage space)">?</span></td>
+ </tr>
+ <tr class="settings-item">
+ <td class="settings-item-label"><span class="settings-item-label">Preserve Movies</span></td>
+ <td class="settings-item-value">
+ <select class="styled motion-movies" id="preserveMoviesSelect">
+ <option value="1">For One Day</option>
+ <option value="7">For One Week</option>
+ <option value="30">For One Month</option>
+ <option value="365">For One Year</option>
+ <option value="0">Forever</option>
+ <option value="-1">Custom</option>
+ </select>
+ </td>
+ <td><span class="help-mark" title="movies older than the specified duration are automatically deleted to free storage space">?</span></td>
+ </tr>
+ <tr class="settings-item">
+ <td class="settings-item-label"><span class="settings-item-label">Movies Lifetime</span></td>
+ <td class="settings-item-value"><input type="text" class="styled number still-images" id="moviesLifetime"><span class="settings-item-unit">days</span></td>
+ <td><span class="help-mark" title="sets the number of days after which the movies will be deleted automatically">?</span></td>
+ </tr>
+ </table>
+
<div class="settings-section-title advanced-setting">Motion Notifications</div>
<table class="settings">
<tr class="settings-item advanced-setting">