Exemple #1
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'))
Exemple #2
0
    def get(self):
        # additional config
        main_sections = config.get_additional_structure(camera=False,
                                                        separators=True)[0]
        camera_sections = config.get_additional_structure(camera=True,
                                                          separators=True)[0]

        motion_info = motionctl.find_motion()
        os_version = update.get_os_version()

        self.render(
            'main.html',
            frame=False,
            motion_version=motion_info[1] if motion_info else '(none)',
            os_version=' '.join(os_version),
            enable_update=settings.ENABLE_UPDATE,
            enable_reboot=settings.ENABLE_REBOOT,
            add_remove_cameras=settings.ADD_REMOVE_CAMERAS,
            main_sections=main_sections,
            camera_sections=camera_sections,
            hostname=settings.SERVER_NAME,
            title=self.get_argument('title', None),
            admin_username=config.get_main().get('@admin_username'),
            has_h264_omx_support=motionctl.has_h264_omx_support(),
            has_h264_v4l2m2m_support=motionctl.has_h264_v4l2m2m_support(),
            has_h264_nvenc_support=motionctl.has_h264_nvenc_support(),
            has_h264_nvmpi_support=motionctl.has_h264_nvmpi_support(),
            has_hevc_nvenc_support=motionctl.has_hevc_nvenc_support(),
            has_hevc_nvmpi_support=motionctl.has_hevc_nvmpi_support(),
            has_h264_qsv_support=motionctl.has_h264_qsv_support(),
            has_hevc_qsv_support=motionctl.has_hevc_qsv_support(),
            has_motion=bool(motionctl.find_motion()[0]),
            mask_width=utils.MASK_WIDTH)
Exemple #3
0
def make_media_folders():
    from motioneye import config

    config.get_main()  # just to have main config already loaded

    camera_ids = config.get_camera_ids()
    for camera_id in camera_ids:
        camera_config = config.get_camera(camera_id)
        if 'target_dir' in camera_config:
            if not os.path.exists(camera_config['target_dir']):
                try:
                    os.makedirs(camera_config['target_dir'])

                except Exception as e:
                    logging.error(
                        'failed to create root media folder "%s" for camera with id %s: %s'
                        % (camera_config['target_dir'], camera_id, e))
Exemple #4
0
    def get_current_user(self):
        main_config = config.get_main()

        username = self.get_argument('_username', None)
        signature = self.get_argument('_signature', None)
        login = self.get_argument('_login', None) == 'true'

        admin_username = main_config.get('@admin_username')
        normal_username = main_config.get('@normal_username')

        admin_password = main_config.get('@admin_password')
        normal_password = main_config.get('@normal_password')

        admin_hash = hashlib.sha1(
            main_config['@admin_password'].encode('utf-8')).hexdigest()
        normal_hash = hashlib.sha1(
            main_config['@normal_password'].encode('utf-8')).hexdigest()

        if settings.HTTP_BASIC_AUTH and 'Authorization' in self.request.headers:
            up = utils.parse_basic_header(
                self.request.headers['Authorization'])
            if up:
                if (up['username'] == admin_username and admin_password
                        in (up['password'],
                            hashlib.sha1(
                                up['password'].encode('utf-8')).hexdigest())):
                    return 'admin'

                if (up['username'] == normal_username and normal_password
                        in (up['password'],
                            hashlib.sha1(
                                up['password'].encode('utf-8')).hexdigest())):
                    return 'normal'

        if (username == admin_username
                and (signature == utils.compute_signature(
                    self.request.method, self.request.uri, self.request.body,
                    admin_password) or signature == utils.compute_signature(
                        self.request.method, self.request.uri,
                        self.request.body, admin_hash))):
            return 'admin'

        if not username and not normal_password:  # no authentication required for normal user
            return 'normal'

        if (username == normal_username
                and (signature == utils.compute_signature(
                    self.request.method, self.request.uri, self.request.body,
                    normal_password) or signature == utils.compute_signature(
                        self.request.method, self.request.uri,
                        self.request.body, normal_hash))):
            return 'normal'

        if username and username != '_' and login:
            logging.error('authentication failed for user %(user)s' %
                          {'user': username})

        return None
Exemple #5
0
def motion_camera_id_to_camera_id(motion_camera_id):
    from motioneye import config

    main_config = config.get_main()
    cameras = main_config.get('camera', [])

    try:
        return int(
            re.search(r'camera-(\d+).conf',
                      cameras[int(motion_camera_id) - 1]).group(1))

    except IndexError:
        return None
Exemple #6
0
def camera_id_to_motion_camera_id(camera_id):
    from motioneye import config

    # find the corresponding motion camera_id
    # (which can be different from camera_id)

    main_config = config.get_main()
    cameras = main_config.get('camera', [])

    camera_filename = 'camera-%d.conf' % camera_id
    for i, camera in enumerate(cameras):
        if camera != camera_filename:
            continue

        return i + 1

    return None
Exemple #7
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)
Exemple #8
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': []})
Exemple #9
0
        def set_main_config(ui_config):
            logging.debug('setting main config...')

            old_main_config = config.get_main()
            old_admin_username = old_main_config.get('@admin_username')
            old_normal_username = old_main_config.get('@normal_username')

            main_config = config.main_ui_to_dict(ui_config)
            main_config.setdefault('camera', old_main_config.get('camera', []))

            admin_username = main_config.get('@admin_username')
            admin_password = main_config.get('@admin_password')

            normal_username = main_config.get('@normal_username')
            normal_password = main_config.get('@normal_password')

            additional_configs = config.get_additional_structure(
                camera=False)[1]
            reboot_config_names = [('@_' + c['name'])
                                   for c in list(additional_configs.values())
                                   if c.get('reboot')]
            reboot = bool([
                k for k in reboot_config_names
                if old_main_config.get(k) != main_config.get(k)
            ])

            config.set_main(main_config)

            reload = False
            restart = False

            if admin_username != old_admin_username or admin_password is not None:
                logging.debug('admin credentials changed, reload needed')

                reload = True

            if normal_username != old_normal_username or normal_password is not None:
                logging.debug(
                    'surveillance credentials changed, all camera configs must be updated'
                )

                # reconfigure all local cameras to update the stream authentication options
                for camera_id in config.get_camera_ids():
                    local_config = config.get_camera(camera_id)
                    if not utils.is_local_motion_camera(local_config):
                        continue

                    ui_config = config.motion_camera_dict_to_ui(local_config)
                    local_config = config.motion_camera_ui_to_dict(
                        ui_config, local_config)

                    config.set_camera(camera_id, local_config)

                    restart = True

            if reboot and settings.ENABLE_REBOOT:
                logging.debug('system settings changed, reboot needed')

            else:
                reboot = False

            return {'reload': reload, 'reboot': reboot, 'restart': restart}