_CAMERA_CONFIG_FILE_NAME = 'thread-%(id)s.conf'
_MAIN_CONFIG_FILE_NAME = 'motion.conf'
-_ACTIONS = ['lock', 'unlock', 'light_on', 'light_off', 'alarm_on', 'alarm_off', 'up',
- 'right', 'down', 'left', 'zoom_in', 'zoom_out',
+_ACTIONS = ['lock', 'unlock', 'light_on', 'light_off', 'alarm_on', 'alarm_off',
+ 'up', 'right', 'down', 'left', 'zoom_in', 'zoom_out',
'preset1', 'preset2', 'preset3', 'preset4', 'preset5', 'preset6', 'preset7', 'preset8', 'preset9']
_main_config_cache = None
'snapshot_filename': ui['image_file_name'],
'quality': max(1, int(ui['image_quality'])),
'@preserve_pictures': int(ui['preserve_pictures']),
+ '@manual_snapshots': ui['manual_snapshots'],
# movies
'ffmpeg_output_movies': False,
'image_quality': data['quality'],
'snapshot_interval': 0,
'preserve_pictures': data['@preserve_pictures'],
+ 'manual_snapshots': data['@manual_snapshots'],
# movies
'movies': False,
ui['extra_options'] = extra_options
# action commands
- action_commands = get_action_commands(data['@id'])
+ action_commands = get_action_commands(data)
ui['actions'] = action_commands.keys()
return ui
ui[name[1:]] = value
# action commands
- action_commands = get_action_commands(data['@id'])
+ action_commands = get_action_commands(data)
ui['actions'] = action_commands.keys()
return ui
-def get_action_commands(camera_id):
+def get_action_commands(camera_config):
+ camera_id = camera_config['@id']
+
action_commands = {}
for action in _ACTIONS:
path = os.path.join(settings.CONF_PATH, '%s_%s' % (action, camera_id))
if os.access(path, os.X_OK):
action_commands[action] = path
+ if camera_config.get('@manual_snapshots'):
+ action_commands['snapshot'] = True
+
+ if camera_config.get('@manual_record'):
+ action_commands['record'] = True
+
return action_commands
data.setdefault('snapshot_filename', '')
data.setdefault('quality', 85)
data.setdefault('@preserve_pictures', 0)
+ data.setdefault('@manual_snapshots', True)
data.setdefault('movie_filename', '%Y-%m-%d/%H-%M-%S')
data.setdefault('max_movie_time', 0)
data.setdefault('ffmpeg_variable_bitrate', _EXPONENTIAL_DEF_QUALITY)
data.setdefault('@preserve_movies', 0)
+ data.setdefault('@manual_record', False)
data.setdefault('@working_schedule', '')
data.setdefault('@working_schedule_type', 'outside')
if action == 'snapshot':
logging.debug('executing snapshot action for camera with id %s' % camera_id)
- return self.snapshot()
+ return self.snapshot(camera_id)
elif action == 'record_start':
logging.debug('executing record_start action for camera with id %s' % camera_id)
- return self.record_start()
+ return self.record_start(camera_id)
elif action == 'record_stop':
logging.debug('executing record_stop action for camera with id %s' % camera_id)
- return self.record_stop()
+ return self.record_stop(camera_id)
- action_commands = config.get_action_commands(camera_id)
+ action_commands = config.get_action_commands(local_config)
command = action_commands.get(action)
if not command:
raise HTTPError(400, 'unknown action')
else:
self.io_loop.add_timeout(datetime.timedelta(milliseconds=100), self.check_command)
- def snapshot(self):
+ def snapshot(self, camera_id):
+ motionctl.take_snapshot(camera_id)
self.finish_json({})
- def record_start(self):
+ def record_start(self, camera_id):
self.finish_json({})
- def record_stop(self):
+ def record_stop(self, camera_id):
self.finish_json({})
logging.error(error)
return callback(error=error)
- url = 'http://127.0.0.1:7999/%(id)s/detection/status' % {'id': thread_id}
+ url = 'http://127.0.0.1:%(port)s/%(id)s/detection/status' % {
+ 'port': settings.MOTION_CONTROL_PORT, 'id': thread_id}
def on_response(response):
if response.error:
'what': ['disabling', 'enabling'][enabled],
'id': camera_id})
- url = 'http://127.0.0.1:7999/%(id)s/detection/%(enabled)s' % {
+ url = 'http://127.0.0.1:%(port)s/%(id)s/detection/%(enabled)s' % {
+ 'port': settings.MOTION_CONTROL_PORT,
'id': thread_id,
'enabled': ['pause', 'start'][enabled]}
http_client.fetch(request, on_response)
+def take_snapshot(camera_id):
+ from tornado.httpclient import HTTPRequest, AsyncHTTPClient
+
+ thread_id = camera_id_to_thread_id(camera_id)
+ if thread_id is None:
+ return logging.error('could not find thread id for camera with id %s' % camera_id)
+
+ logging.debug('taking snapshot for camera with id %(id)s' % {'id': camera_id})
+
+ url = 'http://127.0.0.1:%(port)s/%(id)s/action/snapshot' % {
+ 'port': settings.MOTION_CONTROL_PORT,
+ 'id': thread_id}
+
+ def on_response(response):
+ if response.error:
+ logging.error('failed to take snapshot for camera with id %(id)s: %(msg)s' % {
+ 'id': camera_id,
+ 'msg': utils.pretty_http_error(response)})
+
+ else:
+ logging.debug('successfully took snapshot for camera with id %(id)s' % {'id': camera_id})
+
+ request = HTTPRequest(url, connect_timeout=_MOTION_CONTROL_TIMEOUT, request_timeout=_MOTION_CONTROL_TIMEOUT)
+ http_client = AsyncHTTPClient()
+ http_client.fetch(request, on_response)
+
+
def is_motion_detected(camera_id):
return _motion_detected.get(camera_id, False)
'capture_mode': $('#captureModeSelect').val(),
'snapshot_interval': $('#snapshotIntervalEntry').val(),
'preserve_pictures': $('#preservePicturesSelect').val() >= 0 ? $('#preservePicturesSelect').val() : $('#picturesLifetimeEntry').val(),
+ 'manual_snapshots': $('#manualSnapshotsSwitch')[0].checked,
/* movies */
'movies': $('#moviesEnabledSwitch')[0].checked,
}
markHideIfNull('preserve_pictures', 'preservePicturesSelect');
$('#picturesLifetimeEntry').val(dict['preserve_pictures']); markHideIfNull('preserve_pictures', 'picturesLifetimeEntry');
+ $('#manualSnapshotsSwitch')[0].checked = dict['manual_snapshots']; markHideIfNull('manual_snapshots', 'manualSnapshotsSwitch');
/* movies */
$('#moviesEnabledSwitch')[0].checked = dict['movies']; markHideIfNull('movies', 'moviesEnabledSwitch');
<td class="settings-item-value"><input type="text" class="styled number still-images camera-config" id="picturesLifetimeEntry"><span class="settings-item-unit">days</span></td>
<td><span class="help-mark" title="sets the number of days after which the pictures will be deleted automatically">?</span></td>
</tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Manual Snapshots</span></td>
+ <td class="settings-item-value"><input type="checkbox" class="styled still-images camera-config" id="manualSnapshotsSwitch"></td>
+ <td><span class="help-mark" title="when this is enabled, a button on the camera frame will allow you to manually take snapshots">?</span></td>
+ </tr>
{% for config in camera_sections.get('still-images', {}).get('configs', []) %}
{{config_item(config)}}
{% endfor %}