Beispiel #1
0
    async def zipped(self, camera_id, group):
        key = self.get_argument('key', None)
        camera_config = config.get_camera(camera_id)

        if key:
            logging.debug('serving zip file for group "%(group)s" of camera %(id)s with key %(key)s' % {
                'group': group or 'ungrouped', 'id': camera_id, 'key': key})

            if utils.is_local_motion_camera(camera_config):
                data = mediafiles.get_prepared_cache(key)
                if not data:
                    logging.error('prepared cache data for key "%s" does not exist' % key)

                    raise HTTPError(404, 'no such key')

                pretty_filename = camera_config['camera_name'] + '_' + group
                pretty_filename = re.sub('[^a-zA-Z0-9]', '_', pretty_filename)

                self.set_header('Content-Type', 'application/zip')
                self.set_header('Content-Disposition', 'attachment; filename=' + pretty_filename + '.zip;')
                return self.finish(data)

            elif utils.is_remote_camera(camera_config):
                resp = await remote.get_zipped_content(camera_config, media_type='picture', key=key, group=group)
                if resp.error:
                    return self.finish_json({'error': 'Failed to download zip file from %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config), 'msg': resp.error}})

                self.set_header('Content-Type', resp.result['content_type'])
                self.set_header('Content-Disposition', resp.result['content_disposition'])
                return self.finish(resp.result['data'])

            else:  # assuming simple mjpeg camera
                raise HTTPError(400, 'unknown operation')

        else:  # prepare
            logging.debug('preparing zip file for group "%(group)s" of camera %(id)s' % {
                'group': group or 'ungrouped', 'id': camera_id})

            if utils.is_local_motion_camera(camera_config):
                data = await mediafiles.get_zipped_content(camera_config, media_type='picture', group=group)
                if data is None:
                    return self.finish_json({'error': 'Failed to create zip file.'})

                key = mediafiles.set_prepared_cache(data)
                logging.debug('prepared zip file for group "%(group)s" of camera %(id)s with key %(key)s' % {
                    'group': group or 'ungrouped', 'id': camera_id, 'key': key})
                self.finish_json({'key': key})

            elif utils.is_remote_camera(camera_config):
                resp = await remote.make_zipped_content(camera_config, media_type='picture', group=group)
                if resp.error:
                    return self.finish_json({'error': 'Failed to make zip file at %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config), 'msg': resp.error}})

                return self.finish_json({'key': resp.result['key']})

            else:  # assuming simple mjpeg camera
                raise HTTPError(400, 'unknown operation')
Beispiel #2
0
    async def list(self, camera_id):
        logging.debug('listing movies for camera %(id)s' % {'id': camera_id})

        camera_config = config.get_camera(camera_id)
        if utils.is_local_motion_camera(camera_config):
            media_list = await mediafiles.list_media(camera_config,
                                                     media_type='movie',
                                                     prefix=self.get_argument(
                                                         'prefix', None))
            if media_list is None:
                self.finish_json({'error': 'Failed to get movies list.'})

            return self.finish_json({
                'mediaList': media_list,
                'cameraName': camera_config['camera_name']
            })

        elif utils.is_remote_camera(camera_config):
            resp = await remote.list_media(camera_config,
                                           media_type='movie',
                                           prefix=self.get_argument(
                                               'prefix', None))
            if resp.error:
                return self.finish_json({
                    'error':
                    'Failed to get movie list for %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config),
                        'msg': resp.error
                    }
                })

            return self.finish_json(resp.media_list)

        else:  # assuming simple mjpeg camera
            raise HTTPError(400, 'unknown operation')
Beispiel #3
0
    async def delete_all(self, camera_id, group):
        logging.debug('deleting movie group "%(group)s" of camera %(id)s' % {
            'group': group or 'ungrouped',
            'id': camera_id
        })

        camera_config = config.get_camera(camera_id)
        if utils.is_local_motion_camera(camera_config):
            try:
                mediafiles.del_media_group(camera_config, group, 'movie')
                return self.finish_json()

            except Exception as e:
                return self.finish_json({'error': str(e)})

        elif utils.is_remote_camera(camera_config):
            resp = await remote.del_media_group(camera_config,
                                                group=group,
                                                media_type='movie')
            if resp.error:
                return self.finish_json({
                    'error':
                    'Failed to delete movie group at %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config),
                        'msg': resp.error
                    }
                })

            return self.finish_json()

        else:  # assuming simple mjpeg camera
            raise HTTPError(400, 'unknown operation')
Beispiel #4
0
    async def delete(self, camera_id, filename):
        logging.debug('deleting movie %(filename)s of camera %(id)s' % {
            'filename': filename,
            'id': camera_id
        })

        camera_config = config.get_camera(camera_id)
        if utils.is_local_motion_camera(camera_config):
            try:
                mediafiles.del_media_content(camera_config, filename, 'movie')
                return self.finish_json()

            except Exception as e:
                return self.finish_json({'error': str(e)})

        elif utils.is_remote_camera(camera_config):
            resp = await remote.del_media_content(camera_config,
                                                  filename=filename,
                                                  media_type='movie')
            if resp.error:
                return self.finish_json({
                    'error':
                    'Failed to delete movie from %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config),
                        'msg': resp.error
                    }
                })

            return self.finish_json()

        else:  # assuming simple mjpeg camera
            raise HTTPError(400, 'unknown operation')
Beispiel #5
0
    async def preview(self, camera_id, filename):
        logging.debug('previewing picture %(filename)s of camera %(id)s' % {
            'filename': filename, 'id': camera_id})

        camera_config = config.get_camera(camera_id)
        if utils.is_local_motion_camera(camera_config):
            content = mediafiles.get_media_preview(camera_config, filename, 'picture',
                                                   width=self.get_argument('width', None),
                                                   height=self.get_argument('height', None))

            if content:
                self.set_header('Content-Type', 'image/jpeg')

            else:
                self.set_header('Content-Type', 'image/svg+xml')
                content = open(os.path.join(settings.STATIC_PATH, 'img', 'no-preview.svg'), 'rb').read()

            return self.finish(content)

        elif utils.is_remote_camera(camera_config):
            resp = await remote.get_media_preview(camera_config, filename=filename, media_type='picture',
                                                  width=self.get_argument('width', None),
                                                  height=self.get_argument('height', None))
            content = resp.result
            if content:
                self.set_header('Content-Type', 'image/jpeg')

            else:
                self.set_header('Content-Type', 'image/svg+xml')
                content = open(os.path.join(settings.STATIC_PATH, 'img', 'no-preview.svg')).read()

            return self.finish(content)

        else:  # assuming simple mjpeg camera
            raise HTTPError(400, 'unknown operation')
Beispiel #6
0
    async def frame(self, camera_id):
        camera_config = config.get_camera(camera_id)

        if (utils.is_local_motion_camera(camera_config) or
                utils.is_simple_mjpeg_camera(camera_config) or
                self.get_argument('title', None) is not None):

            return self.render('main.html', frame=True, camera_id=camera_id, camera_config=camera_config,
                               title=self.get_argument('title', camera_config.get('camera_name', '')),
                               admin_username=config.get_main().get('@admin_username'),
                               static_path='../../../static/')

        elif utils.is_remote_camera(camera_config):
            resp = await remote.get_config(camera_config)
            if resp.error:
                return self.render('main.html',
                                   frame=True,
                                   camera_id=camera_id,
                                   camera_config=camera_config,
                                   title=self.get_argument('title', ''))

            # issue a fake motion_camera_ui_to_dict() call to transform
            # the remote UI values into motion config directives
            remote_config = config.motion_camera_ui_to_dict(resp.remote_ui_config)

            return self.render('main.html', frame=True, camera_id=camera_id, camera_config=remote_config,
                               title=self.get_argument('title', remote_config['camera_name']),
                               admin_username=config.get_main().get('@admin_username'))
Beispiel #7
0
    async def download(self, camera_id, filename):
        logging.debug('downloading picture %(filename)s of camera %(id)s' % {
            'filename': filename, 'id': camera_id})

        camera_config = config.get_camera(camera_id)
        if utils.is_local_motion_camera(camera_config):
            content = mediafiles.get_media_content(camera_config, filename, 'picture')

            pretty_filename = camera_config['camera_name'] + '_' + os.path.basename(filename)
            self.set_header('Content-Type', 'image/jpeg')
            self.set_header('Content-Disposition', 'attachment; filename=' + pretty_filename + ';')

            return self.finish(content)

        elif utils.is_remote_camera(camera_config):
            resp = await remote.get_media_content(camera_config, filename=filename, media_type='picture')
            if resp.error:
                return self.finish_json({'error': 'Failed to download picture from %(url)s: %(msg)s.' % {
                    'url': remote.pretty_camera_url(camera_config), 'msg': resp.error}})

            pretty_filename = os.path.basename(filename)  # no camera name available w/o additional request
            self.set_header('Content-Type', 'image/jpeg')
            self.set_header('Content-Disposition', 'attachment; filename=' + pretty_filename + ';')

            return self.finish(resp.result)

        else:  # assuming simple mjpeg camera
            raise HTTPError(400, 'unknown operation')
Beispiel #8
0
        async def set_camera_config(camera_id, ui_config, on_finish):
            logging.debug('setting config for camera %(id)s...' %
                          {'id': camera_id})

            if camera_id not in camera_ids:
                raise HTTPError(404, 'no such camera')

            local_config = config.get_camera(camera_id)
            if utils.is_local_motion_camera(local_config):
                local_config = config.motion_camera_ui_to_dict(
                    ui_config, local_config)

                config.set_camera(camera_id, local_config)

                on_finish(None, True)  # (no error, motion needs restart)

            elif utils.is_remote_camera(local_config):
                # update the camera locally
                local_config['@enabled'] = ui_config['enabled']
                config.set_camera(camera_id, local_config)

                if 'name' in ui_config:

                    def on_finish_wrapper(e=None):
                        return on_finish(e, False)

                    ui_config[
                        'enabled'] = True  # never disable the camera remotely
                    result = await remote.set_config(local_config, ui_config)
                    return on_finish(result, False)

                else:
                    # when the ui config supplied has only the enabled state
                    # and no useful fields (such as "name"),
                    # the camera was probably disabled due to errors
                    on_finish(None, False)

            else:  # assuming simple mjpeg camera
                local_config = config.simple_mjpeg_camera_ui_to_dict(
                    ui_config, local_config)

                config.set_camera(camera_id, local_config)

                on_finish(None,
                          False)  # (no error, motion doesn't need restart)
Beispiel #9
0
    async def post(self, camera_id, action):
        camera_id = int(camera_id)
        if camera_id not in config.get_camera_ids():
            raise HTTPError(404, 'no such camera')

        local_config = config.get_camera(camera_id)
        if utils.is_remote_camera(local_config):
            resp = await remote.exec_action(local_config, action)
            if resp.error:
                msg = 'Failed to execute action on remote camera at %(url)s: %(msg)s.' % {
                    'url': remote.pretty_camera_url(local_config),
                    'msg': resp.error
                }

                return self.finish_json({'error': msg})

            return self.finish_json()

        if action == 'snapshot':
            logging.debug('executing snapshot action for camera with id %s' %
                          camera_id)
            await self.snapshot(camera_id)
            return

        elif action == 'record_start':
            logging.debug(
                'executing record_start action for camera with id %s' %
                camera_id)
            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(camera_id)

        action_commands = config.get_action_commands(local_config)
        command = action_commands.get(action)
        if not command:
            raise HTTPError(400, 'unknown action')

        logging.debug('executing %s action for camera with id %s: "%s"' %
                      (action, camera_id, command))
        self.run_command_bg(command)
Beispiel #10
0
    async def current(self, camera_id, retry=0):
        self.set_header('Content-Type', 'image/jpeg')
        self.set_header('Cache-Control', 'no-store, must-revalidate')
        self.set_header('Pragma', 'no-cache')
        self.set_header('Expires', '0')

        width = self.get_argument('width', None)
        height = self.get_argument('height', None)

        width = width and float(width)
        height = height and float(height)

        camera_id_str = str(camera_id)

        camera_config = config.get_camera(camera_id)
        if utils.is_local_motion_camera(camera_config):
            picture = mediafiles.get_current_picture(camera_config, width=width, height=height)

            # picture is not available usually when the corresponding internal mjpeg client has been closed;
            # get_current_picture() will make sure to start a client, but a jpeg frame is not available right away;
            # wait at most 5 seconds and retry every 200 ms.
            if not picture and retry < 25:
                return IOLoop.instance().add_timeout(datetime.timedelta(seconds=0.2), self.current,
                                                     camera_id=camera_id, retry=retry + 1)

            self.set_cookie('motion_detected_' + camera_id_str, str(motionctl.is_motion_detected(camera_id)).lower())
            self.set_cookie('capture_fps_' + camera_id_str, '%.1f' % mjpgclient.get_fps(camera_id))
            self.set_cookie('monitor_info_' + camera_id_str, monitor.get_monitor_info(camera_id))

            return self.try_finish(picture)

        elif utils.is_remote_camera(camera_config):
            resp = await remote.get_current_picture(camera_config, width=width, height=height)
            if resp.error:
                return self.try_finish(None)

            self.set_cookie('motion_detected_' + camera_id_str, str(resp.motion_detected).lower())
            self.set_cookie('capture_fps_' + camera_id_str, '%.1f' % resp.capture_fps)
            self.set_cookie('monitor_info_' + camera_id_str, resp.monitor_info or '')

            return self.try_finish(resp.picture)

        else:  # assuming simple mjpeg camera
            raise HTTPError(400, 'unknown operation')
Beispiel #11
0
    async def add_camera(self):
        logging.debug('adding new camera')

        try:
            device_details = json.loads(self.request.body)

        except Exception as e:
            logging.error('could not decode json: %(msg)s' % {'msg': str(e)})

            raise

        camera_config = config.add_camera(device_details)

        if utils.is_local_motion_camera(camera_config):
            motionctl.stop()

            if settings.SMB_SHARES:
                stop, start = smbctl.update_mounts()  # @UnusedVariable

                if start:
                    motionctl.start()

            else:
                motionctl.start()

            ui_config = config.motion_camera_dict_to_ui(camera_config)

            return self.finish_json(ui_config)

        elif utils.is_remote_camera(camera_config):
            resp = await remote.get_config(camera_config)
            if resp.error:
                return self.finish_json_with_error(resp.error)

            for key, value in list(camera_config.items()):
                resp.remote_ui_config[key.replace('@', '')] = value

            return self.finish_json(resp.remote_ui_config)

        else:  # assuming simple mjpeg camera
            ui_config = config.simple_mjpeg_camera_dict_to_ui(camera_config)

            return self.finish_json(ui_config)
Beispiel #12
0
    async def get_config(self, camera_id):
        if camera_id:
            logging.debug('getting config for camera %(id)s' %
                          {'id': camera_id})

            if camera_id not in config.get_camera_ids():
                raise HTTPError(404, 'no such camera')

            local_config = config.get_camera(camera_id)
            if utils.is_local_motion_camera(local_config):
                ui_config = config.motion_camera_dict_to_ui(local_config)

                return self.finish_json(ui_config)

            elif utils.is_remote_camera(local_config):
                resp = await remote.get_config(local_config)
                if resp.error:
                    msg = 'Failed to get remote camera configuration for %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(local_config),
                        'msg': resp.error
                    }
                    return self.finish_json_with_error(msg)

                for key, value in list(local_config.items()):
                    resp.remote_ui_config[key.replace('@', '')] = value

                # replace the real device url with the remote camera path
                resp.remote_ui_config['device_url'] = remote.pretty_camera_url(
                    local_config)
                return self.finish_json(resp.remote_ui_config)

            else:  # assuming simple mjpeg camera
                ui_config = config.simple_mjpeg_camera_dict_to_ui(local_config)

                return self.finish_json(ui_config)

        else:
            logging.debug('getting main config')

            ui_config = config.main_dict_to_ui(config.get_main())
            return self.finish_json(ui_config)
    async def get(self, camera_id, filename=None, include_body=True):
        logging.debug('downloading movie %(filename)s of camera %(id)s' % {
            'filename': filename,
            'id': camera_id
        })

        self.pretty_filename = os.path.basename(filename)

        if camera_id is not None:
            camera_id = int(camera_id)
            if camera_id not in config.get_camera_ids():
                raise HTTPError(404, 'no such camera')

        camera_config = config.get_camera(camera_id)

        if utils.is_local_motion_camera(camera_config):
            filename = mediafiles.get_media_path(camera_config, filename,
                                                 'movie')
            self.pretty_filename = camera_config[
                'camera_name'] + '_' + self.pretty_filename
            await StaticFileHandler.get(self,
                                        filename,
                                        include_body=include_body)
            return

        elif utils.is_remote_camera(camera_config):
            # we will cache the movie since it takes a while to fetch from the remote camera
            # and we may be going to play it back in the browser, which will fetch the video in chunks
            tmpfile = self.tmpdir + '/' + self.pretty_filename
            if os.path.isfile(tmpfile):
                # have a cached copy, update the timestamp so it's not flushed
                import time
                mtime = os.stat(tmpfile).st_mtime
                os.utime(tmpfile, (time.time(), mtime))
                await StaticFileHandler.get(self,
                                            tmpfile,
                                            include_body=include_body)
                return

            resp = await remote.get_media_content(camera_config,
                                                  filename,
                                                  media_type='movie')
            if resp.error:
                return self.finish_json({
                    'error':
                    'Failed to download movie from %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config),
                        'msg': resp.error
                    }
                })

            # check if the file has been created by another request while we were fetching the movie
            if not os.path.isfile(tmpfile):
                tmp = open(tmpfile, 'wb')
                tmp.write(resp.result)
                tmp.close()

            await StaticFileHandler.get(self,
                                        tmpfile,
                                        include_body=include_body)
            return

        else:  # assuming simple mjpeg camera
            raise HTTPError(400, 'unknown operation')
Beispiel #14
0
    async def timelapse(self, camera_id, group):
        key = self.get_argument('key', None)
        check = self.get_argument('check', False)
        camera_config = config.get_camera(camera_id)

        if key:  # download
            logging.debug('serving timelapse movie for group "%(group)s" of camera %(id)s with key %(key)s' % {
                'group': group or 'ungrouped', 'id': camera_id, 'key': key})

            if utils.is_local_motion_camera(camera_config):
                data = mediafiles.get_prepared_cache(key)
                if data is None:
                    logging.error('prepared cache data for key "%s" does not exist' % key)

                    raise HTTPError(404, 'no such key')

                pretty_filename = camera_config['camera_name'] + '_' + group
                pretty_filename = re.sub('[^a-zA-Z0-9]', '_', pretty_filename)
                pretty_filename += '.' + mediafiles.FFMPEG_EXT_MAPPING.get(camera_config['movie_codec'], 'avi')

                self.set_header('Content-Type', 'video/x-msvideo')
                self.set_header('Content-Disposition', 'attachment; filename=' + pretty_filename + ';')
                return self.finish(data)

            elif utils.is_remote_camera(camera_config):
                resp = await remote.get_timelapse_movie(camera_config, key, group=group)
                if resp.error:
                    msg = 'Failed to download timelapse movie from %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config), 'msg': resp.error}

                    return self.finish_json({'error': msg})

                self.set_header('Content-Type', resp.result['content_type'])
                self.set_header('Content-Disposition', resp.result['content_disposition'])
                return self.finish(resp.result['data'])

            else:  # assuming simple mjpeg camera
                raise HTTPError(400, 'unknown operation')

        elif check:
            logging.debug('checking timelapse movie status for group "%(group)s" of camera %(id)s' % {
                'group': group or 'ungrouped', 'id': camera_id})

            if utils.is_local_motion_camera(camera_config):
                status = mediafiles.check_timelapse_movie()
                if status['progress'] == -1 and status['data']:
                    key = mediafiles.set_prepared_cache(status['data'])
                    logging.debug('prepared timelapse movie for group "%(group)s" of camera %(id)s with key %(key)s' % {
                        'group': group or 'ungrouped', 'id': camera_id, 'key': key})
                    return self.finish_json({'key': key, 'progress': -1})

                else:
                    return self.finish_json(status)

            elif utils.is_remote_camera(camera_config):
                resp = await remote.check_timelapse_movie(camera_config, group=group)
                if resp.error:
                    msg = 'Failed to check timelapse movie progress at %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config), 'msg': resp.error}

                    return self.finish_json({'error': msg})

                if resp.result['progress'] == -1 and resp.result.get('key'):
                    self.finish_json({'key': resp.result['key'], 'progress': -1})

                else:
                    self.finish_json(resp.result)

            else:  # assuming simple mjpeg camera
                raise HTTPError(400, 'unknown operation')

        else:  # start timelapse
            interval = int(self.get_argument('interval'))
            framerate = int(self.get_argument('framerate'))

            msg = 'preparing timelapse movie for group "%(group)s" of camera %(id)s with rate %(framerate)s/%(int)s' % {
                'group': group or 'ungrouped', 'id': camera_id, 'framerate': framerate, 'int': interval}
            logging.debug(msg)

            if utils.is_local_motion_camera(camera_config):
                status = mediafiles.check_timelapse_movie()
                if status['progress'] != -1:
                    return self.finish_json({'progress': status['progress']})  # timelapse already active

                else:
                    mediafiles.make_timelapse_movie(camera_config, framerate, interval, group=group)
                    return self.finish_json({'progress': -1})

            elif utils.is_remote_camera(camera_config):
                check_timelapse_resp = await remote.check_timelapse_movie(camera_config, group=group)
                if check_timelapse_resp.error:
                    return self.finish_json({'error': 'Failed to make timelapse movie at %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config), 'msg': check_timelapse_resp.error}})

                if check_timelapse_resp.result['progress'] != -1:
                    # timelapse already active
                    return self.finish_json({'progress': check_timelapse_resp.result['progress']})

                make_timelapse_resp = await remote.make_timelapse_movie(camera_config, framerate, interval, group=group)
                if make_timelapse_resp.error:
                    return self.finish_json({'error': 'Failed to make timelapse movie at %(url)s: %(msg)s.' % {
                        'url': remote.pretty_camera_url(camera_config), 'msg': make_timelapse_resp.error}})

                return self.finish_json({'progress': -1})

            else:  # assuming simple mjpeg camera
                raise HTTPError(400, 'unknown operation')
Beispiel #15
0
    async def test(self, camera_id):
        what = self.get_argument('what')
        data = self.get_all_arguments()
        camera_config = config.get_camera(camera_id)

        if utils.is_local_motion_camera(camera_config):
            if what == 'upload_service':
                service_name = data['service']
                ConfigHandler._upload_service_test_info = (self, service_name)

                result = uploadservices.test_access(camera_id=camera_id,
                                                    service_name=service_name,
                                                    data=data)
                logging.debug('test access %s result %s' %
                              (service_name, result))
                if result is True:
                    logging.info('accessing %s succeeded.result %s' %
                                 (service_name, result))
                    return self.finish_json()
                else:
                    logging.warning('accessing %s failed: %s' %
                                    (service_name, result))
                    return self.finish_json({'error': result})

            elif what == 'email':
                from motioneye import sendmail
                import smtplib

                logging.debug('testing notification email')

                try:
                    subject = sendmail.subjects['motion_start']
                    message = sendmail.messages['motion_start']
                    format_dict = {
                        'camera':
                        camera_config['camera_name'],
                        'hostname':
                        socket.gethostname(),
                        'moment':
                        datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    }
                    if settings.LOCAL_TIME_FILE:
                        format_dict['timezone'] = tzctl.get_time_zone()

                    else:
                        format_dict['timezone'] = 'local time'

                    message = message % format_dict
                    subject = subject % format_dict

                    old_timeout = settings.SMTP_TIMEOUT
                    settings.SMTP_TIMEOUT = 10
                    sendmail.send_mail(data['smtp_server'],
                                       int(data['smtp_port']),
                                       data['smtp_account'],
                                       data['smtp_password'],
                                       data['smtp_tls'],
                                       data['from'], [data['addresses']],
                                       subject=subject,
                                       message=message,
                                       files=[])

                    settings.SMTP_TIMEOUT = old_timeout
                    logging.debug('notification email test succeeded')
                    return self.finish_json()

                except Exception as e:
                    if isinstance(e, smtplib.SMTPResponseException):
                        msg = e.smtp_error

                    else:
                        msg = str(e)

                    msg_lower = msg.lower()
                    if msg_lower.count('tls'):
                        msg = 'TLS might be required'

                    elif msg_lower.count('authentication'):
                        msg = 'authentication error'

                    elif msg_lower.count('name or service not known'):
                        msg = 'check SMTP server name'

                    elif msg_lower.count('connection refused'):
                        msg = 'check SMTP port'

                    logging.error('notification email test failed: %s' % msg,
                                  exc_info=True)
                    return self.finish_json({'error': str(msg)})

            elif what == 'telegram':
                from motioneye import sendtelegram

                logging.debug('testing telegram notification')

                try:
                    message = 'This is a test of motionEye\'s telegram messaging'
                    sendtelegram.send_message(data['api'],
                                              int(data['chatid']),
                                              message=message,
                                              files=[])

                    self.finish_json()

                    logging.debug('telegram notification test succeeded')

                except Exception as e:
                    msg = str(e)

                    msg_lower = msg.lower()
                    logging.error('telegram notification test failed: %s' %
                                  msg,
                                  exc_info=True)
                    self.finish_json({'error': str(msg)})

            elif what == 'network_share':
                logging.debug('testing access to network share //%s/%s' %
                              (data['server'], data['share']))

                try:
                    smbctl.test_share(data['server'], data['share'],
                                      data['smb_ver'], data['username'],
                                      data['password'], data['root_directory'])

                    logging.debug('access to network share //%s/%s succeeded' %
                                  (data['server'], data['share']))
                    return self.finish_json()

                except Exception as e:
                    logging.error(
                        'access to network share //%s/%s failed: %s' %
                        (data['server'], data['share'], e))
                    return self.finish_json({'error': str(e)})

            else:
                raise HTTPError(400, 'unknown test %s' % what)

        elif utils.is_remote_camera(camera_config):
            resp = await remote.test(camera_config, data)
            if resp.result is True:
                return self.finish_json()
            else:
                result = resp.result or resp.error
                return self.finish_json_with_error(result)

        else:
            raise HTTPError(400, 'cannot test features on this type of camera')
Beispiel #16
0
    async def list(self):
        logging.debug('listing cameras')

        proto = self.get_argument('proto')
        if proto == 'motioneye':  # remote listing
            return self._handle_list_cameras_response(
                await remote.list_cameras(self.get_all_arguments()))

        elif proto == 'netcam':
            scheme = self.get_argument('scheme', 'http')

            if scheme in ['http', 'https', 'mjpeg']:
                resp = await test_mjpeg_url(self.get_all_arguments(),
                                            auth_modes=['basic'],
                                            allow_jpeg=True)
                return self._handle_list_cameras_response(resp)

            elif scheme == 'rtsp':
                resp = await test_rtsp_url(self.get_all_arguments())
                return self._handle_list_cameras_response(resp)

            elif scheme == 'rtmp':
                resp = test_rtmp_url(self.get_all_arguments())
                return self._handle_list_cameras_response(resp)

            else:
                return self.finish_json_with_error(
                    f'protocol {scheme} not supported')

        elif proto == 'mjpeg':
            resp = await test_mjpeg_url(self.get_all_arguments(),
                                        auth_modes=['basic', 'digest'],
                                        allow_jpeg=False)
            return self._handle_list_cameras_response(resp)

        elif proto == 'v4l2':
            configured_devices = set()
            for camera_id in config.get_camera_ids():
                data = config.get_camera(camera_id)
                if utils.is_v4l2_camera(data):
                    configured_devices.add(data['videodevice'])

            cameras = [{
                'id': d[1],
                'name': d[2]
            } for d in v4l2ctl.list_devices()
                       if (d[0] not in configured_devices) and (
                           d[1] not in configured_devices)]

            return self.finish_json({'cameras': cameras})

        elif proto == 'mmal':
            configured_devices = set()
            for camera_id in config.get_camera_ids():
                data = config.get_camera(camera_id)
                if utils.is_mmal_camera(data):
                    configured_devices.add(data['mmalcam_name'])

            cameras = [{
                'id': d[0],
                'name': d[1]
            } for d in mmalctl.list_devices()
                       if (d[0] not in configured_devices)]

            return self.finish_json({'cameras': cameras})

        else:  # assuming local motionEye camera listing
            cameras = []
            camera_ids = config.get_camera_ids()
            if not config.get_main().get('@enabled'):
                camera_ids = []

            length = [len(camera_ids)]

            for camera_id in camera_ids:
                local_config = config.get_camera(camera_id)
                if local_config is None:
                    continue

                if utils.is_local_motion_camera(local_config):
                    ui_config = config.motion_camera_dict_to_ui(local_config)
                    cameras.append(ui_config)
                    finished = self.check_finished(cameras, length)
                    if finished:
                        return

                elif utils.is_remote_camera(local_config):
                    if local_config.get('@enabled') or self.get_argument(
                            'force', None) == 'true':
                        resp = await remote.get_config(local_config)
                        return self._handle_get_config_response(
                            camera_id, local_config, resp, cameras, length)

                    else:  # don't try to reach the remote of the camera is disabled
                        return self._handle_get_config_response(
                            camera_id, local_config,
                            utils.GetConfigResponse(None, error=True), cameras,
                            length)

                else:  # assuming simple mjpeg camera
                    ui_config = config.simple_mjpeg_camera_dict_to_ui(
                        local_config)
                    cameras.append(ui_config)
                    return self.check_finished(cameras, length)

            if length[0] == 0:
                return self.finish_json({'cameras': []})