# timeout in seconds to use when talking to the SMTP server
smtp_timeout 60
+# timeout in seconds to wait media files list
+list_media_timeout 120
+
# timeout in seconds to wait for zip file creation
zip_timeout 500
+# timeout in seconds to wait for timelapse creation
+timelapse_timeout 500
+
# enable adding and removing cameras from UI
add_remove_cameras true
import multiprocessing
import os
import signal
-import tornado
+
+from tornado.ioloop import IOLoop
import mediafiles
import settings
return
# schedule the first call a bit later to improve performance at startup
- ioloop = tornado.ioloop.IOLoop.instance()
- ioloop.add_timeout(datetime.timedelta(seconds=min(settings.CLEANUP_INTERVAL, 60)), _run_process)
+ io_loop = IOLoop.instance()
+ io_loop.add_timeout(datetime.timedelta(seconds=min(settings.CLEANUP_INTERVAL, 60)), _run_process)
def stop():
def _run_process():
global _process
- ioloop = tornado.ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
if thumbnailer.running():
# postpone if thumbnailer is currently running
- ioloop.add_timeout(datetime.timedelta(seconds=60), _run_process)
+ io_loop.add_timeout(datetime.timedelta(seconds=60), _run_process)
return
else:
# schedule the next call
- ioloop.add_timeout(datetime.timedelta(seconds=settings.CLEANUP_INTERVAL), _run_process)
+ io_loop.add_timeout(datetime.timedelta(seconds=settings.CLEANUP_INTERVAL), _run_process)
if not running(): # check that the previous process has finished
logging.debug('running cleanup process...')
import utils
import v4l2ctl
-from utils import OrderedDict
-
_CAMERA_CONFIG_FILE_NAME = 'thread-%(id)s.conf'
_MAIN_CONFIG_FILE_NAME = 'motion.conf'
def later():
powerctl.reboot()
- IOLoop.instance().add_timeout(datetime.timedelta(seconds=2), later)
+ io_loop = IOLoop.instance()
+ io_loop.add_timeout(datetime.timedelta(seconds=2), later)
else:
logging.info('invalidating config cache')
def _conf_to_dict(lines, list_names=[], no_convert=[]):
- data = OrderedDict()
+ data = utils.OrderedDict()
for line in lines:
line = line.strip()
def _dict_to_conf(lines, data, list_names=[]):
conf_lines = []
- remaining = OrderedDict(data)
+ remaining = utils.OrderedDict(data)
processed = set()
# parse existing lines and replace the values
'with' if separators else 'without'))
# gather sections
- sections = OrderedDict()
+ sections = utils.OrderedDict()
for func in _additional_section_funcs:
result = func()
if not result:
logging.debug('additional config section: %s' % result['name'])
- configs = OrderedDict()
+ configs = utils.OrderedDict()
for func in _additional_config_funcs:
result = func()
if not result:
import socket
import subprocess
-from tornado.web import RequestHandler, HTTPError, asynchronous
from tornado.ioloop import IOLoop
+from tornado.web import RequestHandler, HTTPError, asynchronous
import config
import mediafiles
def call_reboot():
powerctl.reboot()
- ioloop = IOLoop.instance()
- ioloop.add_timeout(datetime.timedelta(seconds=2), call_reboot)
+ io_loop = IOLoop.instance()
+ io_loop.add_timeout(datetime.timedelta(seconds=2), call_reboot)
return self.finish({'reload': False, 'reboot': True, 'error': None})
else:
self.reboot()
def shut_down(self):
- IOLoop.instance().add_timeout(datetime.timedelta(seconds=2), powerctl.shut_down)
+ io_loop = IOLoop.instance()
+ io_loop.add_timeout(datetime.timedelta(seconds=2), powerctl.shut_down)
def reboot(self):
- IOLoop.instance().add_timeout(datetime.timedelta(seconds=2), powerctl.reboot)
+ io_loop = IOLoop.instance()
+ io_loop.add_timeout(datetime.timedelta(seconds=2), powerctl.reboot)
class VersionHandler(BaseHandler):
import multiprocessing
import os.path
import re
+import signal
import stat
import StringIO
import subprocess
import time
-import tornado
import zipfile
from PIL import Image
-from tornado import ioloop
+from tornado.ioloop import IOLoop
import config
import settings
media_list.append(parent_pipe.recv())
def poll_process():
- ioloop = tornado.ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
if process.is_alive(): # not finished yet
now = datetime.datetime.now()
delta = now - started
- if delta.seconds < 120:
- ioloop.add_timeout(datetime.timedelta(seconds=0.5), poll_process)
+ if delta.seconds < settings.LIST_MEDIA_TIMEOUT:
+ io_loop.add_timeout(datetime.timedelta(seconds=0.5), poll_process)
read_media_list()
- else: # process did not finish within 2 minutes
+ else: # process did not finish in time
logging.error('timeout waiting for the media listing process to finish')
+ try:
+ os.kill(process.pid, signal.SIGTERM)
+ except:
+ pass # nevermind
+
callback(None)
else: # finished
started = datetime.datetime.now()
def poll_process():
- ioloop = tornado.ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
if working.value:
now = datetime.datetime.now()
delta = now - started
if delta.seconds < settings.ZIP_TIMEOUT:
- ioloop.add_timeout(datetime.timedelta(seconds=0.5), poll_process)
+ io_loop.add_timeout(datetime.timedelta(seconds=0.5), poll_process)
- else: # process did not finish within 2 minutes
+ else: # process did not finish in time
logging.error('timeout waiting for the zip process to finish')
+ try:
+ os.kill(process.pid, signal.SIGTERM)
+
+ except:
+ pass # nevermind
callback(None)
media_list.append(parent_pipe.recv())
def poll_media_list_process():
- ioloop = tornado.ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
if _timelapse_process.is_alive(): # not finished yet
now = datetime.datetime.now()
delta = now - started[0]
- if delta.seconds < 300: # the subprocess has 5 minutes to complete its job
- ioloop.add_timeout(datetime.timedelta(seconds=0.5), poll_media_list_process)
+ if delta.seconds < settings.TIMELAPSE_TIMEOUT: # the subprocess has limited time to complete its job
+ io_loop.add_timeout(datetime.timedelta(seconds=0.5), poll_media_list_process)
read_media_list()
- else: # process did not finish within 2 minutes
+ else: # process did not finish in time
logging.error('timeout waiting for the media listing process to finish')
+ try:
+ os.kill(_timelapse_process.pid, signal.SIGTERM)
+ except:
+ pass # nevermind
+
_timelapse_process.progress = -1
else: # finished
global _timelapse_process
global _timelapse_data
- ioloop = tornado.ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
if _timelapse_process.poll() is None: # not finished yet
- ioloop.add_timeout(datetime.timedelta(seconds=0.5), functools.partial(poll_movie_process, pictures))
+ io_loop.add_timeout(datetime.timedelta(seconds=0.5), functools.partial(poll_movie_process, pictures))
try:
output = _timelapse_process.stdout.read()
logging.warn('key "%s" was still present in the prepared cache, removed' % key)
timeout = 3600 # the user has 1 hour to download the file after creation
- ioloop.IOLoop.instance().add_timeout(datetime.timedelta(seconds=timeout), clear)
+
+ io_loop = IOLoop.instance()
+ io_loop.add_timeout(datetime.timedelta(seconds=timeout), clear)
return key
import pipes
import sys
-from tornado.httpclient import AsyncHTTPClient
-
# make sure motioneye is on python path
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
def configure_tornado():
+ from tornado.httpclient import AsyncHTTPClient
+
AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient', max_clients=16)
command = sys.argv[1]
arg_parser = make_arg_parser(command)
- import relayevent
- import sendmail
- import server
- import webhook
if command in ('startserver', 'stopserver'):
+ import server
server.main(arg_parser, sys.argv[2:], command[:-6])
elif command == 'sendmail':
+ import sendmail
sendmail.main(arg_parser, sys.argv[2:])
elif command == 'relayevent':
+ import relayevent
relayevent.main(arg_parser, sys.argv[2:])
elif command == 'webhook':
+ import webhook
webhook.main(arg_parser, sys.argv[2:])
else:
import socket
import time
-from tornado import iostream, ioloop
+from tornado.ioloop import IOLoop
+from tornado.iostream import IOStream
import config
import motionctl
import utils
-class MjpgClient(iostream.IOStream):
+class MjpgClient(IOStream):
clients = {} # dictionary of clients indexed by camera id
last_jpgs = {} # dictionary of jpg contents indexed by camera id
last_jpg_moment = {} # dictionary of moments of the last received jpeg indexed by camera id
self._auth_digest_state = {}
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
- iostream.IOStream.__init__(self, s)
+ IOStream.__init__(self, s)
self.set_close_callback(self.on_close)
def connect(self):
- iostream.IOStream.connect(self, ('localhost', self._port), self._on_connect)
+ IOStream.connect(self, ('localhost', self._port), self._on_connect)
MjpgClient.clients[self._camera_id] = self
logging.debug('mjpg client for camera %(camera_id)s connecting on port %(port)s...' % {
def start():
# schedule the garbage collector
- io_loop = ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
io_loop.add_timeout(datetime.timedelta(seconds=settings.MJPG_CLIENT_TIMEOUT), _garbage_collector)
def _garbage_collector():
logging.debug('running garbage collector for mjpg clients...')
- io_loop = ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
io_loop.add_timeout(datetime.timedelta(seconds=settings.MJPG_CLIENT_TIMEOUT), _garbage_collector)
now = datetime.datetime.utcnow()
import subprocess
import time
-from tornado import gen
-from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.ioloop import IOLoop
import config
-import mjpgclient
import powerctl
import settings
import utils
+_MOTION_CONTROL_TIMEOUT = 5
_started = False
_motion_binary_cache = None
def start(deferred=False):
+ import mjpgclient
+
if deferred:
- return IOLoop.instance().add_callback(start, deferred=False)
+ io_loop = IOLoop.instance()
+ io_loop.add_callback(start, deferred=False)
global _started
def stop(invalidate=False):
+ import mjpgclient
+
global _started
_started = False
return _started
-@gen.coroutine
-def get_motion_detection(camera_id):
+def get_motion_detection(camera_id, callback):
+ from tornado.httpclient import HTTPRequest, AsyncHTTPClient
+
thread_id = camera_id_to_thread_id(camera_id)
if thread_id is None:
- logging.error('could not find thread id for camera with id %s' % camera_id)
- return
+ error = 'could not find thread id for camera with id %s' % camera_id
+ logging.error(error)
+ return callback(error=error)
url = 'http://127.0.0.1:7999/%(id)s/detection/status' % {'id': thread_id}
- request = HTTPRequest(url, connect_timeout=5, request_timeout=5)
- http_client = AsyncHTTPClient()
- try:
- response = yield http_client.fetch(request)
+ def on_response(response):
if response.error:
- raise response.error
+ return callback(error=utils.pretty_http_error())
- except Exception as e:
- logging.error('failed to get motion detection status for camera with id %(id)s: %(msg)s' % {
- 'id': camera_id,
- 'msg': unicode(e)})
-
- return
+ 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})
- 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})
+ callback(enabled)
- raise gen.Return(enabled)
+ request = HTTPRequest(url, connect_timeout=_MOTION_CONTROL_TIMEOUT, request_timeout=_MOTION_CONTROL_TIMEOUT)
+ http_client = AsyncHTTPClient()
+ http_client.fetch(request, callback=on_response)
def set_motion_detection(camera_id, enabled):
+ 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)
'what': ['disabled', 'enabled'][enabled],
'id': camera_id})
- request = HTTPRequest(url, connect_timeout=4, request_timeout=4)
+ request = HTTPRequest(url, connect_timeout=_MOTION_CONTROL_TIMEOUT, request_timeout=_MOTION_CONTROL_TIMEOUT)
http_client = AsyncHTTPClient()
http_client.fetch(request, on_response)
import logging
import os
import re
+import signal
import smtplib
import socket
import time
from email.mime.text import MIMEText
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
+
from tornado.ioloop import IOLoop
import settings
def make_message(subject, message, camera_id, moment, timespan, callback):
camera_config = config.get_camera(camera_id)
+ # we must start the IO loop for the media list subprocess polling
+ io_loop = IOLoop.instance()
+
def on_media_files(media_files):
- logging.debug('got media files')
+ io_loop.stop()
timestamp = time.mktime(moment.timetuple())
- media_files = [m for m in media_files if abs(m['timestamp'] - timestamp) < timespan] # filter out non-recent media files
- media_files.sort(key=lambda m: m['timestamp'], reverse=True)
- media_files = [os.path.join(camera_config['target_dir'], re.sub('^/', '', m['path'])) for m in media_files]
+ if media_files:
+ logging.debug('got media files')
+ media_files = [m for m in media_files if abs(m['timestamp'] - timestamp) < timespan] # filter out non-recent media files
+ media_files.sort(key=lambda m: m['timestamp'], reverse=True)
+ media_files = [os.path.join(camera_config['target_dir'], re.sub('^/', '', m['path'])) for m in media_files]
- logging.debug('selected %d pictures' % len(media_files))
+ logging.debug('selected %d pictures' % len(media_files))
format_dict = {
'camera': camera_config['@name'],
}
if settings.LOCAL_TIME_FILE:
- format_dict['timezone'] = tzctl._get_time_zone()
-
+ format_dict['timezone'] = tzctl.get_time_zone()
+
else:
format_dict['timezone'] = 'local time'
if not timespan:
return on_media_files([])
-
- logging.debug('creating email message')
-
+
+ logging.debug('waiting for pictures to be taken')
time.sleep(timespan) # give motion some time to create motion pictures
+
+ logging.debug('creating email message')
mediafiles.list_media(camera_config, media_type='picture', callback=on_media_files)
+
+ io_loop.start()
def parse_options(parser, args):
def main(parser, args):
import meyectl
+ # the motion daemon overrides SIGCHLD,
+ # so we must restore it here,
+ # or otherwise media listing won't work
+ signal.signal(signal.SIGCHLD,signal.SIG_DFL)
+
options = parse_options(parser, args)
meyectl.configure_logging('sendmail', options.log_to_file)
- meyectl.configure_tornado()
logging.debug('hello!')
subject = subjects.get(options.msg_id)
options.moment = datetime.datetime.strptime(options.moment, '%Y-%m-%dT%H:%M:%S')
+ # do not wait too long for media list,
+ # email notifications are critical
+ settings.LIST_MEDIA_TIMEOUT = 10
+
logging.debug('server = %s' % options.server)
logging.debug('port = %s' % options.port)
logging.debug('account = %s' % options.account)
to = [t.strip() for t in re.split('[,;| ]', options.to)]
to = [t for t in to if t]
- io_loop = IOLoop.instance()
-
def on_message(subject, message, files):
try:
send_mail(options.server, options.port, options.account, options.password,
- options.tls, to, subject, message, files)
+ options.tls, to, subject, message, files or [])
logging.info('email sent')
except Exception as e:
logging.error('failed to send mail: %s' % e, exc_info=True)
- io_loop.stop()
-
- def ioloop_timeout():
- io_loop.stop()
+ logging.debug('bye!')
make_message(subject, message, options.camera_id, options.moment, options.timespan, on_message)
-
- io_loop.add_timeout(datetime.timedelta(seconds=settings.SMTP_TIMEOUT), ioloop_timeout)
- io_loop.start()
-
- logging.debug('bye!')
import sys
import time
-from tornado.web import Application
from tornado.ioloop import IOLoop
+from tornado.web import Application
import handlers
import settings
def start_motion():
- import tornado.ioloop
import config
import motionctl
- ioloop = tornado.ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
# add a motion running checker
def checker():
- if ioloop._stopped:
+ if io_loop._stopped:
return
if not motionctl.running() and motionctl.started() and config.get_enabled_local_motion_cameras():
logging.error('failed to start motion: %(msg)s' % {
'msg': unicode(e)}, exc_info=True)
- ioloop.add_timeout(datetime.timedelta(seconds=settings.MOTION_CHECK_INTERVAL), checker)
+ io_loop.add_timeout(datetime.timedelta(seconds=settings.MOTION_CHECK_INTERVAL), checker)
motionctl.start()
- ioloop.add_timeout(datetime.timedelta(seconds=settings.MOTION_CHECK_INTERVAL), checker)
+ io_loop.add_timeout(datetime.timedelta(seconds=settings.MOTION_CHECK_INTERVAL), checker)
def parse_options(parser, args):
application.listen(settings.PORT, settings.LISTEN)
logging.info('server started')
- IOLoop.instance().start()
+ io_loop = IOLoop.instance()
+ io_loop.start()
logging.info('server stopped')
# timeout in seconds to use when talking to the SMTP server
SMTP_TIMEOUT = 60
+# timeout in seconds to wait media files list
+LIST_MEDIA_TIMEOUT = 120
+
# timeout in seconds to wait for zip file creation
ZIP_TIMEOUT = 500
+# timeout in seconds to wait for timelapse creation
+TIMELAPSE_TIMEOUT = 500
+
# enable adding and removing cameras from UI
ADD_REMOVE_CAMERAS = True
import subprocess
import time
-from tornado import ioloop
+from tornado.ioloop import IOLoop
import config
import settings
def start():
- io_loop = ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
io_loop.add_timeout(datetime.timedelta(seconds=settings.MOUNT_CHECK_INTERVAL), _check_mounts)
if start:
motionctl.start()
- io_loop = ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
io_loop.add_timeout(datetime.timedelta(seconds=settings.MOUNT_CHECK_INTERVAL), _check_mounts)
import multiprocessing
import os
import signal
-import tornado
+
+from tornado.ioloop import IOLoop
import cleanup
import mediafiles
return
# schedule the first call a bit later to improve performance at startup
- ioloop = tornado.ioloop.IOLoop.instance()
- ioloop.add_timeout(datetime.timedelta(seconds=min(settings.THUMBNAILER_INTERVAL, 30)), _run_process)
+ io_loop = IOLoop.instance()
+ io_loop.add_timeout(datetime.timedelta(seconds=min(settings.THUMBNAILER_INTERVAL, 30)), _run_process)
def stop():
global _process
# schedule the next call
- ioloop = tornado.ioloop.IOLoop.instance()
- ioloop.add_timeout(datetime.timedelta(seconds=settings.THUMBNAILER_INTERVAL), _run_process)
+ io_loop = IOLoop.instance()
+ io_loop.add_timeout(datetime.timedelta(seconds=settings.THUMBNAILER_INTERVAL), _run_process)
if not running() and not cleanup.running(): # check that the previous process has finished and that cleanup is not running
logging.debug('running thumbnailer process...')
LOCAL_TIME_FILE = settings.LOCAL_TIME_FILE # @UndefinedVariable
+def get_time_zone():
+ return _get_time_zone_symlink() or _get_time_zone_md5() or 'UTC'
+
+
def _get_time_zone_symlink():
file = settings.LOCAL_TIME_FILE
if not file:
return time_zone
-def _get_time_zone():
- return _get_time_zone_symlink() or _get_time_zone_md5() or 'UTC'
-
-
def _set_time_zone(time_zone):
time_zone = time_zone or 'UTC'
'section': 'general',
'advanced': True,
'reboot': True,
- 'get': _get_time_zone,
+ 'get': get_time_zone,
'set': _set_time_zone
}
import settings
-
try:
from collections import OrderedDict # @UnusedImport
called = [False]
timeout = [None]
stream = None
+
+ io_loop = IOLoop.instance()
def connect():
logging.debug('testing rtsp netcam at %s' % url)
stream.set_close_callback(on_close)
stream.connect((data['host'], int(data['port'])), on_connect)
- timeout[0] = IOLoop.instance().add_timeout(datetime.timedelta(seconds=settings.MJPG_CLIENT_TIMEOUT),
+ timeout[0] = io_loop.add_timeout(datetime.timedelta(seconds=settings.MJPG_CLIENT_TIMEOUT),
functools.partial(on_connect, _timeout=True))
return stream
def on_connect(_timeout=False):
- IOLoop.instance().remove_timeout(timeout[0])
+ io_loop.remove_timeout(timeout[0])
if _timeout:
return handle_error('timeout connecting to rtsp netcam')
return
stream.read_until_regex('RTSP/1.0 \d+ ', on_rtsp)
- timeout[0] = IOLoop.instance().add_timeout(datetime.timedelta(seconds=settings.MJPG_CLIENT_TIMEOUT), on_rtsp)
+ timeout[0] = io_loop.add_timeout(datetime.timedelta(seconds=settings.MJPG_CLIENT_TIMEOUT), on_rtsp)
def on_rtsp(data):
- IOLoop.instance().remove_timeout(timeout[0])
+ io_loop.remove_timeout(timeout[0])
if data:
if data.endswith('200 '):
return
stream.read_until_regex('Server: .*', on_server)
- timeout[0] = IOLoop.instance().add_timeout(datetime.timedelta(seconds=1), on_server)
+ timeout[0] = io_loop.add_timeout(datetime.timedelta(seconds=1), on_server)
def on_server(data=None):
- IOLoop.instance().remove_timeout(timeout[0])
+ io_loop.remove_timeout(timeout[0])
if data:
identifier = re.findall('Server: (.*)', data)[0].strip()
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime
+import functools
import logging
-from tornado import ioloop, gen
+from tornado.ioloop import IOLoop
import config
import motionctl
def start():
- io_loop = ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
io_loop.add_timeout(datetime.timedelta(seconds=1), _check_ws)
return True
-@gen.coroutine
def _check_ws():
# schedule the next call
- io_loop = ioloop.IOLoop.instance()
+ io_loop = IOLoop.instance()
io_loop.add_timeout(datetime.timedelta(seconds=10), _check_ws)
if not motionctl.running():
return
+ def on_motion_detection_status(camera_id, must_be_enabled, working_schedule_type, enabled=None, error=None):
+ if error: # could not detect current status
+ return logging.warn('skipping motion detection status update for camera with id %(id)s' % {'id': camera_id})
+
+ if 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 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)
+
now = datetime.datetime.now()
for camera_id in config.get_camera_ids():
camera_config = config.get_camera(camera_id)
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 = yield motionctl.get_motion_detection(camera_id)
- if currently_enabled is None: # could not detect current status
- logging.warn('skipping motion detection status update for camera with id %(id)s' % {'id': camera_id})
- continue
-
- 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)
+ motionctl.get_motion_detection(camera_id, functools.partial(
+ on_motion_detection_status, camera_id, must_be_enabled, working_schedule_type))