From 71313a83c94eadcf9bc382ffd1ed17b90c2e5ac0 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sun, 24 Aug 2014 12:01:59 +0300 Subject: [PATCH] enabled working schedule UI --- motioneye.py | 11 ++++- src/cleanup.py | 14 +++--- src/config.py | 16 +++---- src/motionctl.py | 2 +- src/thumbnailer.py | 14 +++--- src/wsswitch.py | 36 ++++++++++++++ static/css/ui.css | 4 +- static/js/main.js | 114 +++++++++++++++++++++++++++----------------- static/js/ui.js | 66 +++++-------------------- templates/main.html | 41 +++++++++------- 10 files changed, 174 insertions(+), 144 deletions(-) create mode 100644 src/wsswitch.py diff --git a/motioneye.py b/motioneye.py index 4d93d6b..a44ea58 100755 --- a/motioneye.py +++ b/motioneye.py @@ -301,7 +301,7 @@ def _start_motion(): if ioloop._stopped: return - if not motionctl.running() and motionctl.started() and config.has_enabled_cameras(): + if not motionctl.running() and motionctl.started() and config.has_local_enabled_cameras(): try: logging.error('motion not running, starting it') motionctl.start() @@ -324,6 +324,13 @@ def _start_cleanup(): logging.info('cleanup started') +def _start_wsswitch(): + import wsswitch + + wsswitch.start() + logging.info('wsswitch started') + + def _start_thumbnailer(): import thumbnailer @@ -341,6 +348,7 @@ if __name__ == '__main__': _configure_signals() _configure_logging() + if settings.SMB_SHARES: stop, start = smbctl.update_mounts() if start: @@ -350,6 +358,7 @@ if __name__ == '__main__': _start_motion() _start_cleanup() + _start_wsswitch() if settings.THUMBNAILER_INTERVAL: _start_thumbnailer() diff --git a/src/cleanup.py b/src/cleanup.py index 6e3a882..847c7fa 100644 --- a/src/cleanup.py +++ b/src/cleanup.py @@ -30,9 +30,6 @@ _process = None def start(): - if running(): - raise Exception('cleanup is already running') - _run_process() @@ -40,7 +37,8 @@ def stop(): global _process if not running(): - raise Exception('cleanup is not running') + _process = None + return if _process.is_alive(): _process.join(timeout=10) @@ -59,16 +57,16 @@ def running(): def _run_process(): global _process + # schedule the next call + ioloop = tornado.ioloop.IOLoop.instance() + ioloop.add_timeout(datetime.timedelta(seconds=settings.CLEANUP_INTERVAL), _run_process) + if not _process or not _process.is_alive(): # check that the previous process has finished logging.debug('running cleanup process...') _process = multiprocessing.Process(target=_do_cleanup) _process.start() - # schedule the next call - ioloop = tornado.ioloop.IOLoop.instance() - ioloop.add_timeout(datetime.timedelta(seconds=settings.CLEANUP_INTERVAL), _run_process) - def _do_cleanup(): # this will be executed in a separate subprocess diff --git a/src/config.py b/src/config.py index aa39b16..1e4b106 100644 --- a/src/config.py +++ b/src/config.py @@ -187,7 +187,7 @@ def get_camera_ids(): return filtered_camera_ids -def has_enabled_cameras(): +def has_local_enabled_cameras(): if not get_main().get('@enabled'): return False @@ -810,13 +810,13 @@ def camera_dict_to_ui(data): # working schedule 'working_schedule': False, - 'monday_from': '09:00', 'monday_to': '17:00', - 'tuesday_from': '09:00', 'tuesday_to': '17:00', - 'wednesday_from': '09:00', 'wednesday_to': '17:00', - 'thursday_from': '09:00', 'thursday_to': '17:00', - 'friday_from': '09:00', 'friday_to': '17:00', - 'saturday_from': '09:00', 'saturday_to': '17:00', - 'sunday_from': '09:00', 'sunday_to': '17:00' + 'monday_from': '', 'monday_to': '', + 'tuesday_from': '', 'tuesday_to': '', + 'wednesday_from': '', 'wednesday_to': '', + 'thursday_from': '', 'thursday_to': '', + 'friday_from': '', 'friday_to': '', + 'saturday_from': '', 'saturday_to': '', + 'sunday_from': '', 'sunday_to': '' } if utils.net_camera(data): diff --git a/src/motionctl.py b/src/motionctl.py index e62aa5c..9d681bf 100644 --- a/src/motionctl.py +++ b/src/motionctl.py @@ -61,7 +61,7 @@ def start(): _started = True - if running() or not config.has_enabled_cameras(): + if running() or not config.has_local_enabled_cameras(): return logging.debug('starting motion') diff --git a/src/thumbnailer.py b/src/thumbnailer.py index 1c8fded..c3b4809 100644 --- a/src/thumbnailer.py +++ b/src/thumbnailer.py @@ -30,9 +30,6 @@ _process = None def start(): - if running(): - raise Exception('thumbnailer is already running') - _run_process() @@ -40,7 +37,8 @@ def stop(): global _process if not running(): - raise Exception('thumbnailer is not running') + _process = None + return if _process.is_alive(): _process.join(timeout=10) @@ -59,16 +57,16 @@ def running(): def _run_process(): global _process + # schedule the next call + ioloop = tornado.ioloop.IOLoop.instance() + ioloop.add_timeout(datetime.timedelta(seconds=settings.THUMBNAILER_INTERVAL), _run_process) + if not _process or not _process.is_alive(): # check that the previous process has finished logging.debug('running thumbnailer process...') _process = multiprocessing.Process(target=_do_next_movie_thumbail) _process.start() - # schedule the next call - ioloop = tornado.ioloop.IOLoop.instance() - ioloop.add_timeout(datetime.timedelta(seconds=settings.THUMBNAILER_INTERVAL), _run_process) - def _do_next_movie_thumbail(): # this will be executed in a separate subprocess diff --git a/src/wsswitch.py b/src/wsswitch.py new file mode 100644 index 0000000..9a63d55 --- /dev/null +++ b/src/wsswitch.py @@ -0,0 +1,36 @@ + +# Copyright (c) 2013 Calin Crisan +# This file is part of motionEye. +# +# motionEye is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import datetime +import logging +import tornado + +import config +import motionctl + + +def start(): + pass + + +def _check_ws(): + # schedule the next call + ioloop = tornado.ioloop.IOLoop.instance() + ioloop.add_timeout(datetime.timedelta(seconds=60), _check_ws) + + if not motionctl.running(): + return diff --git a/static/css/ui.css b/static/css/ui.css index b0b555f..da85d83 100644 --- a/static/css/ui.css +++ b/static/css/ui.css @@ -157,7 +157,7 @@ input[type=text].styled:FOCUS { } input[type=text].number { - width: 100px; + width: 5em; } input[type=text].error, @@ -168,7 +168,7 @@ input[type=password].error { } input[type=text].time { - width: 75px; + width: 3.5em; } diff --git a/static/js/main.js b/static/js/main.js index ab77d63..ae9542e 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -244,20 +244,20 @@ function initUI() { makeNumberValidator($('#smtpPortEntry'), 1, 65535, false, false, true); /* time validators */ - makeTimeValidator($('#mondayFrom')); - makeTimeValidator($('#mondayTo')); - makeTimeValidator($('#tuesdayFrom')); - makeTimeValidator($('#tuesdayTo')); - makeTimeValidator($('#wednesdayFrom')); - makeTimeValidator($('#wednesdayTo')); - makeTimeValidator($('#thursdayFrom')); - makeTimeValidator($('#thursdayTo')); - makeTimeValidator($('#fridayFrom')); - makeTimeValidator($('#fridayTo')); - makeTimeValidator($('#saturdayFrom')); - makeTimeValidator($('#saturdayTo')); - makeTimeValidator($('#sundayFrom')); - makeTimeValidator($('#sundayTo')); + makeTimeValidator($('#mondayFromEntry')); + makeTimeValidator($('#mondayToEntry')); + makeTimeValidator($('#tuesdayFromEntry')); + makeTimeValidator($('#tuesdayToEntry')); + makeTimeValidator($('#wednesdayFromEntry')); + makeTimeValidator($('#wednesdayToEntry')); + makeTimeValidator($('#thursdayFromEntry')); + makeTimeValidator($('#thursdayToEntry')); + makeTimeValidator($('#fridayFromEntry')); + makeTimeValidator($('#fridayToEntry')); + makeTimeValidator($('#saturdayFromEntry')); + makeTimeValidator($('#saturdayToEntry')); + makeTimeValidator($('#sundayFromEntry')); + makeTimeValidator($('#sundayToEntry')); /* ui elements that enable/disable other ui elements */ $('#motionEyeSwitch').change(updateConfigUi); @@ -282,6 +282,14 @@ function initUI() { $('#commandNotificationsSwitch').change(updateConfigUi); $('#workingScheduleSwitch').change(updateConfigUi); + $('#mondayEnabledSwitch').change(updateConfigUi); + $('#tuesdayEnabledSwitch').change(updateConfigUi); + $('#wednesdayEnabledSwitch').change(updateConfigUi); + $('#thursdayEnabledSwitch').change(updateConfigUi); + $('#fridayEnabledSwitch').change(updateConfigUi); + $('#saturdayEnabledSwitch').change(updateConfigUi); + $('#sundayEnabledSwitch').change(updateConfigUi); + $('#storageDeviceSelect').change(function () { $('#rootDirectoryEntry').val('/'); }); @@ -502,7 +510,7 @@ function updateConfigUi() { $('#moviesLifetime').parents('tr:eq(0)').each(markHide); } - /* email notifications switch */ + /* event notifications */ if (!$('#emailNotificationsSwitch').get(0).checked) { $('#emailAddressesEntry').parents('tr:eq(0)').each(markHide); $('#smtpServerEntry').parents('tr:eq(0)').each(markHide); @@ -521,11 +529,22 @@ function updateConfigUi() { $('#commandNotificationsEntry').parents('tr:eq(0)').each(markHide); } - /* working schedule switch */ + /* working schedule */ if (!$('#workingScheduleSwitch').get(0).checked) { $('#workingScheduleSwitch').parent().next('table.settings').find('tr.settings-item').each(markHide); } + var weekDays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']; + weekDays.forEach(function (weekDay) { + var check = $('#' + weekDay + 'EnabledSwitch'); + if (check.get(0).checked) { + check.parent().find('.time').show(); + } + else { + check.parent().find('.time').hide(); + } + }); + objs.each(function () { if (this._hide) { $(this).hide(200); @@ -688,20 +707,20 @@ function cameraUi2Dict() { /* working schedule */ 'working_schedule': $('#workingScheduleSwitch')[0].checked, - 'monday_from': $('#mondayFrom').val(), - 'monday_to':$('#mondayTo').val(), - 'tuesday_from': $('#tuesdayFrom').val(), - 'tuesday_to': $('#tuesdayTo').val(), - 'wednesday_from': $('#wednesdayFrom').val(), - 'wednesday_to': $('#wednesdayTo').val(), - 'thursday_from': $('#thursdayFrom').val(), - 'thursday_to': $('#thursdayTo').val(), - 'friday_from':$('#fridayFrom').val(), - 'friday_to': $('#fridayTo').val(), - 'saturday_from':$('#saturdayFrom').val(), - 'saturday_to': $('#saturdayTo').val(), - 'sunday_from': $('#sundayFrom').val(), - 'sunday_to': $('#sundayTo').val(), + 'monday_from': $('#mondayEnabledSwitch')[0].checked ? $('#mondayFromEntry').val() : '', + 'monday_to':$('#mondayEnabledSwitch')[0].checked ? $('#mondayToEntry').val() : '', + 'tuesday_from': $('#tuesdayEnabledSwitch')[0].checked ? $('#tuesdayFromEntry').val() : '', + 'tuesday_to': $('#tuesdayEnabledSwitch')[0].checked ? $('#tuesdayToEntry').val() : '', + 'wednesday_from': $('#wednesdayEnabledSwitch')[0].checked ? $('#wednesdayFromEntry').val() : '', + 'wednesday_to': $('#wednesdayEnabledSwitch')[0].checked ? $('#wednesdayToEntry').val() : '', + 'thursday_from': $('#thursdayEnabledSwitch')[0].checked ? $('#thursdayFromEntry').val() : '', + 'thursday_to': $('#thursdayEnabledSwitch')[0].checked ? $('#thursdayToEntry').val() : '', + 'friday_from': $('#fridayEnabledSwitch')[0].checked ? $('#fridayFromEntry').val() : '', + 'friday_to': $('#fridayEnabledSwitch')[0].checked ? $('#fridayToEntry').val() :'', + 'saturday_from': $('#saturdayEnabledSwitch')[0].checked ? $('#saturdayFromEntry').val() : '', + 'saturday_to': $('#saturdayEnabledSwitch')[0].checked ? $('#saturdayToEntry').val() : '', + 'sunday_from': $('#sundayEnabledSwitch')[0].checked ? $('#sundayFromEntry').val() : '', + 'sunday_to': $('#sundayEnabledSwitch')[0].checked ? $('#sundayToEntry').val() : '', }; if ($('#resolutionSelect')[0].selectedIndex != -1) { @@ -901,20 +920,27 @@ function dict2CameraUi(dict) { /* working schedule */ $('#workingScheduleSwitch')[0].checked = dict['working_schedule']; - $('#mondayFrom').val(dict['monday_from']); - $('#mondayTo').val(dict['monday_to']); - $('#tuesdayFrom').val(dict['tuesday_from']); - $('#tuesdayTo').val(dict['tuesday_to']); - $('#wednesdayFrom').val(dict['wednesday_from']); - $('#wednesdayTo').val(dict['wednesday_to']); - $('#thursdayFrom').val(dict['thursday_from']); - $('#thursdayTo').val(dict['thursday_to']); - $('#fridayFrom').val(dict['friday_from']); - $('#fridayTo').val(dict['friday_to']); - $('#saturdayFrom').val(dict['saturday_from']); - $('#saturdayTo').val(dict['saturday_to']); - $('#sundayFrom').val(dict['sunday_from']); - $('#sundayTo').val(dict['sunday_to']); + $('#mondayEnabledSwitch')[0].checked = Boolean(dict['monday_from'] && dict['monday_to']); + $('#mondayFromEntry').val(dict['monday_from']); + $('#mondayToEntry').val(dict['monday_to']); + $('#tuesdayEnabledSwitch')[0].checked = Boolean(dict['tuesday_from'] && dict['tuesday_to']); + $('#tuesdayFromEntry').val(dict['tuesday_from']); + $('#tuesdayToEntry').val(dict['tuesday_to']); + $('#wednesdayEnabledSwitch')[0].checked = Boolean(dict['wednesday_from'] && dict['wednesday_to']); + $('#wednesdayFromEntry').val(dict['wednesday_from']); + $('#wednesdayToEntry').val(dict['wednesday_to']); + $('#thursdayEnabledSwitch')[0].checked = Boolean(dict['thursday_from'] && dict['thursday_to']); + $('#thursdayFromEntry').val(dict['thursday_from']); + $('#thursdayToEntry').val(dict['thursday_to']); + $('#fridayEnabledSwitch')[0].checked = Boolean(dict['friday_from'] && dict['friday_to']); + $('#fridayFromEntry').val(dict['friday_from']); + $('#fridayToEntry').val(dict['friday_to']); + $('#saturdayEnabledSwitch')[0].checked = Boolean(dict['saturday_from'] && dict['saturday_to']); + $('#saturdayFromEntry').val(dict['saturday_from']); + $('#saturdayToEntry').val(dict['saturday_to']); + $('#sundayEnabledSwitch')[0].checked = Boolean(dict['sunday_from'] && dict['sunday_to']); + $('#sundayFromEntry').val(dict['sunday_from']); + $('#sundayToEntry').val(dict['sunday_to']); updateConfigUi(); } diff --git a/static/js/ui.js b/static/js/ui.js index 723697b..ede3317 100644 --- a/static/js/ui.js +++ b/static/js/ui.js @@ -306,7 +306,7 @@ function makeTextValidator($input, required) { } function isValid(strVal) { - if (!$input.parents('tr:eq(0)').is(':visible')) { + if (!$input.is(':visible')) { return true; /* an invisible element is considered always valid */ } @@ -350,7 +350,7 @@ function makeComboValidator($select, required) { } function isValid(strVal) { - if (!$select.parents('tr:eq(0)').is(':visible')) { + if (!$select.is(':visible')) { return true; /* an invisible element is considered always valid */ } @@ -406,7 +406,7 @@ function makeNumberValidator($input, minVal, maxVal, floating, sign, required) { } function isValid(strVal) { - if (!$input.parents('tr:eq(0)').is(':visible')) { + if (!$input.is(':visible')) { return true; /* an invisible element is considered always valid */ } @@ -484,16 +484,16 @@ function makeNumberValidator($input, minVal, maxVal, floating, sign, required) { function makeTimeValidator($input) { function isValid(strVal) { + if (!$input.is(':visible')) { + return true; /* an invisible element is considered always valid */ + } + return strVal.match(new RegExp('^[0-2][0-9]:[0-5][0-9]$')) != null; } var msg = 'enter a valid time in the following format: HH:MM'; function validate() { - if (!$input.parents('tr:eq(0)').is(':visible')) { - return true; /* an invisible element is considered always valid */ - } - var strVal = $input.val(); if (isValid(strVal)) { $input.attr('title', ''); @@ -525,58 +525,14 @@ function makeTimeValidator($input) { function makeUrlValidator($input) { function isValid(strVal) { - return strVal.match(new RegExp('^([a-zA-Z]+)://([\\w\-.]+)(:\\d+)?(/.*)?$')) != null; - } - - var msg = 'enter a valid URL (e.g. http://example.com:8080/cams/)'; - - function validate() { - if (!$input.parents('tr:eq(0)').is(':visible')) { + if (!$input.is(':visible')) { return true; /* an invisible element is considered always valid */ } - - var strVal = $input.val(); - if (isValid(strVal)) { - $input.attr('title', ''); - $input.removeClass('error'); - $input[0].invalid = false; - } - else { - $input.attr('title', msg); - $input.addClass('error'); - $input[0].invalid = true; - } - } - - $input.keyup(validate); - $input.blur(validate); - $input.change(validate).change(); - - $input.addClass('validator'); - $input.addClass('url-validator'); - $input.each(function () { - this.validate = validate; - }); -} -function makeRegexValidator($input, regex, required) { - if (required == null) { - required = true; - } - - function isValid(strVal) { - if (!$input.parents('tr:eq(0)').is(':visible')) { - return true; /* an invisible element is considered always valid */ - } - - if (strVal.length === 0 && !required) { - return true; - } - - return strVal.match(new RegExp(regex)) != null; + return strVal.match(new RegExp('^([a-zA-Z]+)://([\\w\-.]+)(:\\d+)?(/.*)?$')) != null; } - var msg = 'enter a valid value'; + var msg = 'enter a valid URL (e.g. http://example.com:8080/cams/)'; function validate() { var strVal = $input.val(); @@ -597,7 +553,7 @@ function makeRegexValidator($input, regex, required) { $input.change(validate).change(); $input.addClass('validator'); - $input.addClass('regex-validator'); + $input.addClass('url-validator'); $input.each(function () { this.validate = validate; }); diff --git a/templates/main.html b/templates/main.html index 8a0337a..c0a878f 100644 --- a/templates/main.html +++ b/templates/main.html @@ -386,7 +386,7 @@ ? - Automatic Noise Detection + Auto Noise Detection ? @@ -490,61 +490,68 @@ - - +
Working Schedule
+ -- 2.39.5
Monday - from - to + + from + to ?
Tuesday - from - to + + from + to ?
Wednesday - from - to + + from + to ?
Thursday - from - to + + from + to ?
Friday - from - to + + from + to ?
Saturday - from - to + + from + to ?
Sunday - from - to + + from + to ?