if settings.THUMBNAILER_INTERVAL:
_start_thumbnailer()
-
+
_run_server()
ui['friday_from'] + '-' + ui['friday_to'] + '|' +
ui['saturday_from'] + '-' + ui['saturday_to'] + '|' +
ui['sunday_from'] + '-' + ui['sunday_to'])
+
+ data['@working_schedule_type'] = ui['working_schedule_type']
# event start notifications
on_event_start = []
working_schedule = data['@working_schedule']
if working_schedule:
days = working_schedule.split('|')
+ ui['working_schedule'] = True
ui['monday_from'], ui['monday_to'] = days[0].split('-')
ui['tuesday_from'], ui['tuesday_to'] = days[1].split('-')
ui['wednesday_from'], ui['wednesday_to'] = days[2].split('-')
ui['friday_from'], ui['friday_to'] = days[4].split('-')
ui['saturday_from'], ui['saturday_to'] = days[5].split('-')
ui['sunday_from'], ui['sunday_to'] = days[6].split('-')
- ui['working_schedule'] = True
+ ui['working_schedule_type'] = data['@working_schedule_type']
# event start notifications
on_event_start = data.get('on_event_start') or []
data.setdefault('@preserve_movies', 0)
data.setdefault('@working_schedule', '')
+ data.setdefault('@working_schedule_type', 'outside')
data.setdefault('on_event_start', '')
import subprocess
import time
+from tornado.httpclient import HTTPClient, AsyncHTTPClient, HTTPRequest
+
import config
import settings
+import utils
_started = False
return _started
+def get_motion_detection(camera_id):
+ thread_id = _get_thread_id(camera_id)
+ if thread_id is None:
+ return logging.error('could not find thread id for camera with id %s' % camera_id)
+
+ url = 'http://127.0.0.1:7999/%(id)s/detection/status' % {'id': thread_id}
+
+ request = HTTPRequest(url, connect_timeout=2, request_timeout=2)
+ http_client = HTTPClient()
+ response = http_client.fetch(request)
+
+ if response.error:
+ logging.error('failed to get motion detection status for camera with id %(id)s: %(msg)s' % {
+ 'id': camera_id,
+ 'msg': unicode(response.error)})
+
+ return None
+
+ enabled = bool(response.body.lower().count('active'))
+
+ logging.debug('motion detection is %(what)s for camera with id %(id)s' % {
+ 'what': ['disabled', 'enabled'][enabled],
+ 'id': camera_id})
+
+ return enabled
+
+
+def set_motion_detection(camera_id, enabled):
+ thread_id = _get_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('%(what)s motion detection for camera with id %(id)s' % {
+ 'what': ['disabling', 'enabling'][enabled],
+ 'id': camera_id})
+
+ url = 'http://127.0.0.1:7999/%(id)s/detection/%(enabled)s' % {
+ 'id': thread_id,
+ 'enabled': ['pause', 'start'][enabled]}
+
+ def on_response(response):
+ if response.error:
+ logging.error('failed to %(what)s motion detection for camera with id %(id)s: %(msg)s' % {
+ 'what': ['disable', 'enable'][enabled],
+ 'id': camera_id,
+ 'msg': unicode(response.error)})
+
+ else:
+ logging.debug('successfully %(what)s motion detection for camera with id %(id)s' % {
+ 'what': ['disabled', 'enabled'][enabled],
+ 'id': camera_id})
+
+ request = HTTPRequest(url, connect_timeout=4, request_timeout=4)
+ http_client = AsyncHTTPClient()
+ http_client.fetch(request, on_response)
+
+
+def _get_thread_id(camera_id):
+ # find the corresponding thread_id
+ # (which can be different from camera_id)
+ camera_ids = config.get_camera_ids()
+ thread_id = 0
+ for cid in camera_ids:
+ camera_config = config.get_camera(cid)
+ if utils.local_camera(camera_config):
+ thread_id += 1
+
+ if cid == camera_id:
+ break
+
+ else:
+ return None
+
+ if thread_id == 0:
+ return None
+
+ return thread_id
+
+
def _get_pid():
motion_pid_path = os.path.join(settings.RUN_PATH, 'motion.pid')
import config
import motionctl
+import utils
def start():
- pass
+ ioloop = tornado.ioloop.IOLoop.instance()
+ ioloop.add_timeout(datetime.timedelta(seconds=10), _check_ws)
+
+
+def _during_working_schedule(now, working_schedule):
+ parts = working_schedule.split('|')
+ if len(parts) < 7:
+ return False # invalid ws
+
+ ws_day = parts[now.weekday()]
+ parts = ws_day.split('-')
+ if len(parts) != 2:
+ return False # invalid ws
+
+ _from, to = parts
+ if not _from or not to:
+ return False # ws disabled for this day
+
+ _from = _from.split(':')
+ to = to.split(':')
+ if len(_from) != 2 or len(to) != 2:
+ return False # invalid ws
+
+ try:
+ from_h = int(_from[0])
+ from_m = int(_from[1])
+ to_h = int(to[0])
+ to_m = int(to[1])
+
+ except ValueError:
+ return False # invalid ws
+
+ if now.hour < from_h or now.hour > to_h:
+ return False
+
+ if now.hour == from_h and now.minute < from_m:
+ return False
+
+ if now.hour == to_h and now.minute > to_m:
+ return False
+
+ return True
def _check_ws():
if not motionctl.running():
return
+
+ now = datetime.datetime.now()
+ for camera_id in config.get_camera_ids():
+ camera_config = config.get_camera(camera_id)
+ if not utils.local_camera(camera_config):
+ continue
+
+ working_schedule = camera_config.get('@working_schedule')
+ working_schedule_type = camera_config.get('@working_schedule_type') or 'outside'
+
+ must_be_enabled = False
+ if not working_schedule: # working schedule disabled, motion detection always on
+ must_be_enabled = True
+
+ 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')
+
+ currently_enabled = motionctl.get_motion_detection(camera_id)
+ if currently_enabled and not must_be_enabled:
+ logging.debug('must disable motion detection for camera with id %(id)s (%(what)s working schedule)' % {
+ 'id': camera_id,
+ 'what': working_schedule_type})
+
+ motionctl.set_motion_detection(camera_id, False)
+
+ elif not currently_enabled and must_be_enabled:
+ logging.debug('must enable motion detection for camera with id %(id)s (%(what)s working schedule)' % {
+ 'id': camera_id,
+ 'what': working_schedule_type})
+
+ motionctl.set_motion_detection(camera_id, True)
if (!$('#webHookNotificationsSwitch').get(0).checked) {
$('#webHookUrlEntry').parents('tr:eq(0)').each(markHide);
- $('#webHookHttpMethod').parents('tr:eq(0)').each(markHide);
+ $('#webHookHttpMethodSelect').parents('tr:eq(0)').each(markHide);
}
if (!$('#commandNotificationsSwitch').get(0).checked) {
'email_notifications_smtp_tls': $('#smtpTlsSwitch')[0].checked,
'web_hook_notifications_enabled': $('#webHookNotificationsSwitch')[0].checked,
'web_hook_notifications_url': $('#webHookUrlEntry').val(),
- 'web_hook_notifications_http_method': $('#webHookHttpMethod').val(),
+ 'web_hook_notifications_http_method': $('#webHookHttpMethodSelect').val(),
'command_notifications_enabled': $('#commandNotificationsSwitch')[0].checked,
'command_notifications_exec': $('#commandNotificationsEntry').val(),
'saturday_to': $('#saturdayEnabledSwitch')[0].checked ? $('#saturdayToEntry').val() : '',
'sunday_from': $('#sundayEnabledSwitch')[0].checked ? $('#sundayFromEntry').val() : '',
'sunday_to': $('#sundayEnabledSwitch')[0].checked ? $('#sundayToEntry').val() : '',
+ 'working_schedule_type': $('#workingScheduleTypeSelect').val(),
};
if ($('#resolutionSelect')[0].selectedIndex != -1) {
$('#smtpTlsSwitch')[0].checked = dict['email_notifications_smtp_tls'];
$('#webHookNotificationsSwitch')[0].checked = dict['web_hook_notifications_enabled'];
$('#webHookUrlEntry').val(dict['web_hook_notifications_url']);
- $('#webHookHttpMethod').val(dict['web_hook_notifications_http_method']);
+ $('#webHookHttpMethodSelect').val(dict['web_hook_notifications_http_method']);
$('#commandNotificationsSwitch')[0].checked = dict['command_notifications_enabled'];
$('#commandNotificationsEntry').val(dict['command_notifications_exec']);
$('#sundayEnabledSwitch')[0].checked = Boolean(dict['sunday_from'] && dict['sunday_to']);
$('#sundayFromEntry').val(dict['sunday_from']);
$('#sundayToEntry').val(dict['sunday_to']);
+ $('#workingScheduleTypeSelect').val(dict['working_schedule_type']);
updateConfigUi();
}
<tr class="settings-item advanced-setting">
<td class="settings-item-label"><span class="settings-item-label">HTTP Method</span></td>
<td class="settings-item-value">
- <select class="styled notifications" id="webHookHttpMethod">
+ <select class="styled notifications" id="webHookHttpMethodSelect">
<option value="GET">GET</option>
<option value="POST">POST</option>
</select>
</td>
<td><span class="help-mark" title="sets the working schedule time interval for Sunday">?</span></td>
</tr>
+ <tr class="settings-item">
+ <td class="settings-item-label"><span class="settings-item-label">Detect Motion</span></td>
+ <td class="settings-item-value">
+ <select class="styled working-schedule" id="workingScheduleTypeSelect">
+ <option value="during">During Working Schedule</option>
+ <option value="outside">Outside Working Schedule</option>
+ </select>
+ </td>
+ <td><span class="help-mark" title="sets whether motion detection should be active during or outside the working schedule">?</span></td>
+ </tr>
</table>
<div class="settings-progress"></div>