示例#1
0
class PostConfigFieldMixin:
    camera_config_service = obj_graph().provide(CameraConfigService)

    def post_config_field(self, camera_id: str, config_field: SingleConfigForm):
        form = config_field

        if len(form.visible_fields()) == 0 or form.field.disabled:
            return

        if not (form.is_valid() and form.has_changed()):
            return

        try:
            self.camera_config_service.set_config(
                camera_id=camera_id,
                config_name=form.name,
                config_value=form.cleaned_data.get(form.name))

            form.tried_to_change = True

            # Check if it actually changed
            field_config = self.camera_config_service.get_config(camera_id=camera_id, config_name=form.name)
            form.managed_to_change = (field_config.value == form.cleaned_data[form.name])

            # Set the current value if it didn't change
            if not form.managed_to_change:
                form.set_value(field_config.value)

        except CameraException as e:
            form.add_error(form.name, str(e))
示例#2
0
class CameraPreviewSource(View):
    camera_ctrl_service = obj_graph().provide(CameraCtrlService)

    def get(self, request, *args, **kwargs):
        camera_id = kwargs['camera_id']

        return StreamingHttpResponse(
            self._preview_generator(camera_id=camera_id),
            content_type="multipart/x-mixed-replace;boundary=frame")

    def _preview_generator(self, camera_id):
        try:
            while True:
                frame = self\
                    .camera_ctrl_service\
                    .camera_capture_preview(camera_id=camera_id)

                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + frame.tobytes() +
                       b'\r\n')

        except CameraNotFoundException:
            return CameraNotFoundApiException(camera_id=camera_id)

        except CameraException as e:
            return HttpResponseServerError(content=str(e))
class AllConfigs(TemplateView, PostConfigFieldMixin, ErrorUtilsMixin):
    template_name = 'camera_config/all_configs.html'
    camera_config_service = obj_graph().provide(CameraConfigService)

    def dispatch(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        camera_id = kwargs['camera_id']
        context['camera_id'] = camera_id

        try:
            configs_dto = self.camera_config_service.get_all_configs(
                camera_id=camera_id)

            config_form_manager = CameraConfigFormManager(request.POST or None)
            config_form_manager.load_from_configs_dto(configs=configs_dto)

            if request.method == 'POST':
                self.post(camera_id=camera_id,
                          config_form_manager=config_form_manager)

        except CameraException as e:
            return self.render_to_error(request=request, error=str(e))

        context['form'] = config_form_manager
        return self.render_to_response(context=context)

    def post(self, camera_id: str,
             config_form_manager: CameraConfigFormManager):
        for section in config_form_manager.sections:
            for field in section.form_fields:
                self.post_config_field(camera_id=camera_id, config_field=field)
class CronScheduleUpdate(UpdateView):
    model = CronSchedule
    template_name = 'scheduling/cron/cron_schedule_create.html'

    success_message = 'Schedule successfully updated'

    fields = [
        'name', 'start_date', 'end_date', 'year', 'month', 'day', 'week',
        'day_of_week', 'hour', 'minute', 'second'
    ]

    scheduler = obj_graph().provide(_DiScheduler).scheduler

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['updating'] = True
        return context

    def form_valid(self, form):
        response = super().form_valid(form)

        schedule = cron_schedule.CronSchedule(**vars(self.object))
        hard_map_objects(self.object, schedule)

        try:
            self.scheduler.modify(schedule)
        except Exception as e:
            form.add_error(None, str(e))
            return super().form_invalid(form)

        messages.success(self.request, self.success_message)
        return response
class FavFieldsListUpdate(TemplateView, ErrorUtilsMixin):
    template_name = 'app_settings/fav_fields_settings.html'
    favourite_configs_service: FavouriteConfigsService = obj_graph().provide(FavouriteConfigsService)

    def dispatch(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        fav_field_formset = list(self._create_formset(request=request))
        if request.method == 'POST':
            self.post(formset=fav_field_formset)

        context['formset'] = fav_field_formset
        return self.render_to_response(context=context)

    def post(self, formset: Iterable[FavouriteConfigForm]):
        for form in formset:
            if not (form.is_valid() and form.has_changed()):
                continue

            self.favourite_configs_service.update(pk=form.cleaned_data['pk'], config_name=form.cleaned_data['name'])

    def _create_formset(self, request):
        fav_fields = list(self.favourite_configs_service.get_all())

        for fav_field in fav_fields:
            initial = {'pk': fav_field.pk, 'name': fav_field.name}
            form = FavouriteConfigForm(request.POST or None, initial=initial, prefix='field_{}'.format(fav_field.pk))
            form.model_pk = fav_field.pk
            yield form
示例#6
0
class TimelapseCreate(CreateView):
    template_name = 'scheduling/timelapse/timelapse_create.html'

    model = Timelapse
    fields = ['name', 'storage_dir_format', 'filename_format', 'schedule']
    success_message = 'Successfully created timelapse'

    schedule_service = obj_graph().provide(ScheduleService)

    def form_valid(self, form):
        response = super().form_valid(form)
        assert isinstance(self.object, Timelapse)

        schedule = CronSchedule.objects.filter(pk=self.object.schedule_id)
        if len(schedule) != 0:
            schedule = schedule[0]

            try:
                self.do_the_schedule_thing(schedule)
            except Exception as e:
                form.add_error(None, str(e))
                return super().form_invalid(form)

        messages.success(request=self.request, message=self.success_message)
        return response

    def do_the_schedule_thing(self, schedule: CronSchedule):
        dto = cron_schedule.CronSchedule(**vars(schedule))
        dto.pk = schedule.pk

        job_id = self.schedule_service.run_timelapse(self.object.pk, dto)
        self.object.schedule_job_id = job_id
        self.object.save()
class SingleConfig(TemplateView, PostConfigFieldMixin, ErrorUtilsMixin):
    template_name = 'camera_config/single_config.html'
    camera_config_service = obj_graph().provide(CameraConfigService)

    def dispatch(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        camera_id = kwargs['camera_id']
        context['camera_id'] = camera_id

        config_name = kwargs['config_name']

        try:
            config = self.camera_config_service.get_config(
                camera_id=camera_id, config_name=config_name)
            form = SingleConfigForm.from_config_dto(config_dto=config,
                                                    post_data=request.POST
                                                    or None)
            context['form'] = form

            if request.method == 'POST':
                self.post_config_field(camera_id=camera_id, config_field=form)

        except CameraException as e:
            return self.render_to_error(request=request, error=str(e))

        return self.render_to_response(context=context)
class FavFieldAdd(View):
    default_dummy_value = 'shutterspeed'
    favourite_configs_service = obj_graph().provide(FavouriteConfigsService)

    def get(self, request, *args, **kwargs):
        self.favourite_configs_service.add(
            config_name=self.default_dummy_value)
        return HttpResponse(status=201)
class FavFieldRemove(DeleteView):
    favourite_configs_service = obj_graph().provide(FavouriteConfigsService)

    def delete(self, request, *args, **kwargs):
        fav_field_pk = kwargs['pk']

        self.favourite_configs_service.remove(pk=int(fav_field_pk))
        return HttpResponse(status=200)
class MultiPreview(TemplateView):
    template_name = 'camera_ctrl/multi_preview.html'

    camera_ctrl_service = obj_graph().provide(CameraCtrlService)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        cameras = self.camera_ctrl_service.cameras_get_all()
        context['cameras'] = list(map_cameras_to_view_models(cameras))
        return context
class CamerasAutodetect(View):
    camera_ctrl_service = obj_graph().provide(CameraCtrlService)

    def get(self, request):
        try:
            self.camera_ctrl_service.cameras_autodetect()
            return HttpResponse(status=200)

        except CameraException as e:
            return HttpResponseServerError(content=str(e))
示例#12
0
class CameraRemove(View):
    camera_ctrl_service = obj_graph().provide(CameraCtrlService)

    def get(self, request, *args, **kwargs):
        camera_id = kwargs['camera_id']

        try:
            self.camera_ctrl_service.camera_remove(camera_id=camera_id)
            return HttpResponse(status=204)

        except CameraNotFoundException:
            return CameraNotFoundApiException(camera_id=camera_id)
示例#13
0
class SinglePreview(TemplateView, FavConfigsMixin, ErrorUtilsMixin):
    template_name = 'camera_ctrl/single_preview.html'

    camera_ctrl_service = obj_graph().provide(CameraCtrlService)
    camera_config_service = obj_graph().provide(CameraConfigService)

    def dispatch(self, request, *args, **kwargs):
        context = super().get_context_data(**kwargs)
        camera_id = kwargs['camera_id']

        try:
            camera = self.camera_ctrl_service.camera_get(camera_id=camera_id)

            context['camera'] = map_camera_to_view_model(camera)
            context['form'] = self.fav_configs_dispatch(request=request,
                                                        camera_id=camera_id)

        except CameraException as e:
            return self.render_to_error(request=request, error=str(e))

        return self.render_to_response(context=context)
示例#14
0
class CamerasHardResetAll(View):
    camera_ctrl_service = obj_graph().provide(CameraCtrlService)

    def get(self, request):
        try:
            self.camera_ctrl_service.hard_reset_all_cameras()
            return HttpResponse(status=200)

        except CameraResetException as e:
            return HttpResponseServerError(content=str(e))

        except CameraException as e:
            return HttpResponseServerError(content=str(e))
class CronScheduleDelete(DeleteView):
    model = CronSchedule
    scheduler = obj_graph().provide(_DiScheduler).scheduler

    def get(self, request, *args, **kwargs):
        try:
            obj = self.get_object()
            self.scheduler.delete(obj.pk)
            obj.delete()

        except Exception as e:
            return HttpResponseServerError(content=str(e))

        return HttpResponse(status=200)
示例#16
0
class CameraReconnect(View):
    camera_ctrl_service = obj_graph().provide(CameraCtrlService)

    def get(self, request, *args, **kwargs):
        camera_id = kwargs['camera_id']

        try:
            self.camera_ctrl_service.camera_reconnect(camera_id=camera_id)
            return HttpResponse(status=200)

        except CameraNotFoundException:
            return CameraNotFoundApiException(camera_id=camera_id)

        except CameraException as e:
            return HttpResponseServerError(content=str(e))
class ScheduledConfigCreate(CreateView):
    model = ScheduledConfig
    fields = ['name', 'schedule']
    template_name = 'scheduling/scheduled_config/scheduled_config_create.html'
    schedule_service = obj_graph().provide(ScheduleService)

    def get_context_data(self, **kwargs):
        # we need to overwrite get_context_data
        # to make sure that our formset is rendered
        data = super().get_context_data(**kwargs)
        if self.request.POST:
            data['fields'] = ScheduledConfigFieldFormSet(self.request.POST)
        else:
            data['fields'] = ScheduledConfigFieldFormSet()
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        fields = context['fields']

        self.object = form.save()
        if fields.is_valid():
            fields.instance = self.object
            fields.save()
        else:
            return super().form_invalid(form)

        response = super().form_valid(form)
        schedules = CronSchedule.objects.filter(pk=self.object.schedule_id)
        if len(schedules) != 0:
            schedule = schedules[0]

            try:
                self.do_the_schedule_thing(schedule)
            except Exception as e:
                form.add_error(None, str(e))
                return super().form_invalid(form)

        return response

    def do_the_schedule_thing(self, schedule: CronSchedule):
        dto = cron_schedule.CronSchedule(**vars(schedule))
        dto.pk = schedule.pk

        job_id = self.schedule_service.run_scheduled_config(
            self.object.pk, dto)
        self.object.schedule_job_id = job_id
        self.object.save()
示例#18
0
class FavConfigsMixin(PostConfigFieldMixin):
    camera_config_service = obj_graph().provide(CameraConfigService)

    def fav_configs_dispatch(self, request, camera_id: str):
        fav_configs = self.camera_config_service.get_favourite_configs(camera_id=camera_id)
        fav_configs_section = ConfigFormSection(
            name='favourite',
            label='Favourite',
            post_data=request.POST or None)
        fav_configs_section.add_fields(fields=fav_configs)

        if request.method == 'POST':
            for field in fav_configs_section.form_fields:
                self.post_config_field(camera_id=camera_id, config_field=field)

        return fav_configs_section
示例#19
0
class TimelapseUpdate(UpdateView):
    template_name = 'scheduling/timelapse/timelapse_create.html'

    model = Timelapse
    fields = ['name', 'storage_dir_format', 'filename_format', 'schedule']

    success_message = 'Timelapse successfully updated'
    schedule_service = obj_graph().provide(ScheduleService)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['updating'] = True
        return context

    def form_valid(self, form):
        previous_job_id = self.object.schedule_job_id

        response = super().form_valid(form)
        assert isinstance(self.object, Timelapse)

        try:
            if previous_job_id:
                self.schedule_service.delete_job(job_id=previous_job_id)
                self.object.schedule_job_id = None
                self.object.save()

            self.set_new_schedule_job()

        except Exception as e:
            form.add_error(None, str(e))
            return super().form_invalid(form)

        messages.success(request=self.request, message=self.success_message)
        return response

    def set_new_schedule_job(self):
        schedule = CronSchedule.objects.filter(pk=self.object.schedule_id)
        if len(schedule) == 0:
            return

        schedule = schedule[0]
        dto = cron_schedule.CronSchedule(**vars(schedule))
        dto.pk = schedule.pk

        job_id = self.schedule_service.run_timelapse(self.object.pk, dto)
        self.object.schedule_job_id = job_id
        self.object.save()
示例#20
0
class ConfigList(TemplateView, ErrorUtilsMixin):
    template_name = 'camera_config/config_list.html'
    camera_config_service = obj_graph().provide(CameraConfigService)

    def dispatch(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        camera_id = kwargs['camera_id']
        context['camera_id'] = camera_id

        try:
            config_names = self.camera_config_service.get_all_config_names(
                camera_id=camera_id)
            context['config_names'] = list(config_names)

        except CameraException as e:
            return self.render_to_error(request=request, error=str(e))

        return self.render_to_response(context=context)
示例#21
0
class CameraCaptureImgAndDownload(View):
    camera_ctrl_service = obj_graph().provide(CameraCtrlService)

    def get(self, request, *args, **kwargs):
        camera_id = kwargs['camera_id']

        try:
            capture_dto = self\
                .camera_ctrl_service\
                .camera_capture_img_and_download(camera_id=camera_id)

            return FileResponse(
                open(capture_dto.real_file_path, 'rb'),
                as_attachment=True,
                filename=capture_dto.download_filename)

        except CameraNotFoundException:
            return CameraNotFoundApiException(camera_id=camera_id)

        except CameraException as e:
            return HttpResponseServerError(content=str(e))
示例#22
0
def startup_factory() -> WebStartup:
    return obj_graph().provide(WebStartup)
示例#23
0
class CameraConfigsView(APIView):
    camera_ctrl_service = obj_graph().provide(CameraCtrlService)
    camera_config_service = obj_graph().provide(CameraConfigService)

    def get(self, request, *args, **kwargs):
        camera_id = kwargs['camera_id']
        config_name = kwargs['config_name']

        try:
            if camera_id.lower() == 'first':
                camera = self.camera_ctrl_service.cameras_get_first()
                if camera is None:
                    raise CameraNotFoundException()
                camera_id = camera.id

            config = self.camera_config_service.get_config(
                camera_id=camera_id, config_name=config_name)
            return HttpResponse(content=config.value)

        except CameraNotFoundException:
            return CameraNotFoundApiException(camera_id=camera_id)

        except InvalidConfigException as e:
            return HttpResponseBadRequest(content=str(e))

        except CameraException as e:
            return HttpResponseServerError(content=str(e))

    def put(self, request, *args, **kwargs):
        camera_id = kwargs['camera_id']
        config_name = kwargs['config_name']
        config_value = request.GET.get('value')

        try:
            if camera_id.lower() == 'first':
                camera = self.camera_ctrl_service.cameras_get_first()
                if camera is None:
                    raise CameraNotFoundException()
                camera_id = camera.id

            self.camera_config_service.set_config(camera_id=camera_id,
                                                  config_name=config_name,
                                                  config_value=config_value)

            current_config = self.camera_config_service.get_config(
                camera_id=camera_id, config_name=config_name)

            managed_to_change = (str(current_config.value) == config_value)

            if not managed_to_change:
                error = f'Failed to change {config_name} to {config_value}'
                return HttpResponseBadRequest(content=error)

            return HttpResponse(
                content=f'Changed {config_name} to {config_value}')

        except CameraNotFoundException:
            return CameraNotFoundApiException(camera_id=camera_id)

        except InvalidConfigException as e:
            return HttpResponseBadRequest(content=str(e))

        except CameraException as e:
            return HttpResponseServerError(content=str(e))
class ScheduledConfigUpdate(UpdateView):
    model = ScheduledConfig
    schedule_service = obj_graph().provide(ScheduleService)
    success_message = 'Scheduled Config successfully updated'
    template_name = 'scheduling/scheduled_config/scheduled_config_create.html'

    fields = ['name', 'schedule']

    def get_context_data(self, **kwargs):
        scheduled_config = ScheduledConfig.objects.get(id=self.kwargs['pk'])
        context = super().get_context_data(**kwargs)
        context['updating'] = True

        if self.request.POST:
            context['fields'] = ScheduledConfigFieldFormSet(
                self.request.POST, instance=scheduled_config)
        else:
            context['fields'] = ScheduledConfigFieldFormSet(
                instance=scheduled_config)

        return context

    def form_valid(self, form):
        previous_job_id = self.object.schedule_job_id

        context = self.get_context_data()
        fields = context['fields']

        self.object = form.save()
        if fields.is_valid():
            fields.instance = self.object
            fields.save()
        else:
            return super().form_invalid(form)

        response = super().form_valid(form)

        try:
            if previous_job_id:
                self.schedule_service.delete_job(job_id=previous_job_id)
                self.object.schedule_job_id = None
                self.object.save()

            self._reschedule_job()

        except Exception as e:
            form.add_error(None, str(e))
            return super().form_invalid(form)

        messages.success(request=self.request, message=self.success_message)
        return response

    def _reschedule_job(self):
        schedule = CronSchedule.objects.filter(pk=self.object.schedule_id)
        if len(schedule) == 0:
            return

        schedule = schedule[0]
        dto = cron_schedule.CronSchedule(**vars(schedule))
        dto.pk = schedule.pk

        job_id = self.schedule_service.run_scheduled_config(
            self.object.pk, dto)
        self.object.schedule_job_id = job_id
        self.object.save()