示例#1
0
    async def start_auto_capturing(self, queue: asyncio.Queue, mode: str):
        """
        Run the auto mode 

        @todo: move to auto service
        """
        settings = await self.setting_service.get()

        # Start capturing particle
        await self.initiate_capturing(settings)

        # Submit the task, this doesn't block
        tid = await self.initiate_capturing_script("startautoflow", f"{mode} {settings}",
                                                   queue)
        detector_service_connected = self.detector_service.connected()
        classify_task = None

        try:
            if detector_service_connected:
                logger.info("detector is connected, try classifying images")
                # Detector is working, wait for the path to return
                # and start detecting
                sub = await self.hub.subscribe("results_path")
                monitor_mode = True
                try:
                    # Get the first result path
                    logger.info(f'waiting for the result path')
                    path = await asyncio.wait_for(sub.__anext__(), timeout=3)
                    logger.info(
                        f"get results_path {path}, starting classifier")
                    # Start detector
                    classify_coro = self.detector_service.start(
                        path, monitor_mode)
                    classify_task = asyncio.create_task(classify_coro)
                except asyncio.TimeoutError:
                    logger.error('get results_path timeout(3s)')
                    detector_service_connected = False

            # clean up
            # wait for the tasks to be done
            script_result = await self.task_service.running_tasks[tid]
            logger.info(f"completed script: {script_result=}")
            await asyncio.sleep(5)
        except Exception as e:
            logger.exception(f"failed to clean up auto mode: {e}")
        finally:
            # shutdown camera
            await self.stop_capturing("stopautoflow")

            # shutdown detector
            if detector_service_connected and classify_task is not None:
                await asyncio.sleep(3)
                classify_task.cancel()
                try:
                    await classify_task
                except asyncio.CancelledError:
                    logger.info('Classification task is cancelled')

            logger.info('completed start autoflow task')
示例#2
0
 def connected(self):
     try:
         self.conn.ping()
         return True
     except Exception:
         host, port = self.config.get('HOST'), self.config.getint('PORT')
         logger.error(f'Detector RPC is down! ({host}:{port})')
         return False
示例#3
0
文件: task.py 项目: yuanfeiz/wotapi
class TaskService:
    def __init__(self, root_path: Path):
        self.root_path = root_path
        self.running_tasks: MutableMapping[str, asyncio.Task] = {}

    async def _run_script(self,
                          filename: str,
                          queue: asyncio.Queue = None,
                          /,
                          **kwargs):
        script_path = f"{self.root_path}/{filename}"

        # process script arguments
        args = ""
        if "_" in kwargs:
            vs = kwargs.pop("_")
            args += " ".join([str(v) for v in vs])

        args += " ".join([f"--{k}={v}" for k, v in kwargs.items()])

        cmd = f"python -u {script_path} {args}"

        proc = await asyncio.create_subprocess_shell(
            cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE)
        logger.info(f"Executing --- ({proc.pid}) `$ {cmd}`")

        try:
            while not proc.stdout.at_eof():
                data = await proc.stdout.readline()
                line = data.decode("utf8").strip()

                if len(line) == 0:
                    continue

                logger.info(f"({filename}) >>> {line}")

                if queue:
                    await queue.put(line)
            exit_code = await proc.wait()
            logger.info(f'Finished ---- ({proc.pid}) `$ {cmd}` {exit_code=}')

            # raise exception if exit_code is not 0
            if exit_code != 0:
                msg = 'Execution abort! Reason: '

                # all stderr msg is buffered
                while not proc.stderr.at_eof():
                    data = await proc.stderr.readline()
                    line = data.decode("utf8").strip()
                    logger.error(f"({filename}) >>> {line}")
                    msg += line
                raise Exception(msg)

            return exit_code
        except asyncio.CancelledError as e:
            logger.warning(f"Cancel process {cmd}({proc.pid})")
            proc.terminate()
            raise e
示例#4
0
    def connected(self) -> bool:
        # Check RPC status
        try:
            self.rpc_conn.ping()
        except Exception as e:
            logger.error(f'Camera RPC is down! {e}')
            return False

        # Check queue status
        try:
            self.queue_mgr.connect()
        except Exception as e:
            logger.error(f'Camera QUEUE is down! ({e})')
            return False

        return True
示例#5
0
    async def start_manual_capturing(self) -> str:
        try:
            settings = await self.setting_service.get()

            # Step 1: send item to cqueue requesting start capturing
            await self.initiate_capturing(settings)
            tid = await self.initiate_capturing_script("mfs_pd", settings)
            return await self.task_service.get(tid)
        except CancelledError as e:
            logger.warning('cancelling manual capturing')
            raise e
        except Exception as e:
            logger.error(f'failed to run manual capturing: {e}')
            raise e
        finally:
            await self.stop_capturing('mfs_stop')
示例#6
0
    async def start(self, path, monitor_mode):
        """
        Start classifier. If monitor_mode is True, this function never ends and 
        progress bar will stick to 49%

        It will emit event logs via centralized hub, event types are Progress and State.

        It will raise Exception if there is an issue while running, after State chagned to TaskState.Failed

        @TODO: add tests
        """
        logger.info(f"start CG detection: {path=} {monitor_mode=}")
        p = Path(path)

        # path must be a directory
        if not p.exists():
            raise Exception(f'Path not exists: {p}')
        if not p.is_dir():
            raise Exception(f'Path is not directory: {p}')

        try:
            await self.hub.publish(EventTopics.State,
                                   self._event(TaskState.Ongoing))

            # these calls can be blocking, consider run_in_executor
            self.rpc.stopDetector()
            self.rpc.startDetector(path, monitor_mode)

            for i in range(1, 5):
                child_dir = p / str(i)
                child_dir.mkdir(exist_ok=True)
                logger.info(f"created result directory: {child_dir}")

            counter = Counter()
            progress_value = 0

            results = []
            while progress_value < 100:
                idx, total_count = self.rpc.getPos()

                # handle empty or error cases
                if total_count == -1:
                    logger.info('waiting for gathering samples')
                    continue
                elif total_count == 0:
                    logger.error(f"sample directory is empty: {p.resolve()}")
                    break

                logger.debug(f'getting detection results')
                result = copy.deepcopy(self.rpc.getResults())
                
                processed_count = len(result)
                
                logger.info(f"total processed counts: {processed_count}")

                progress_value = (idx + 1) / total_count * 100.0
                results = results + result
                logger.info(
                    f"detection progress: {progress_value}% ({idx}/{total_count})"
                )

                await self.hub.publish(
                    EventTopics.Logs,
                    self._event(
                        EventLogType.Progress, {
                            'progress': progress_value,
                            'processed': processed_count,
                            'total': total_count
                        }))

                # wait for another round
                await asyncio.sleep(0.5)

            # 4 kinds of label
            triggered_samples = {k: [] for k in self.label_txt_mappings}
            #print(triggered_samples)
            for item in results:
                filename, label, confidence_level = item
                logger.info(
                    f"{filename} : {label} {confidence_level}")
                label = int(label)
                label_txt = None
                try:
                    label_txt = self.label_txt_mappings[label]
                except IndexError:
                    raise IndexError(
                        f'{label=} is invalid. Max label index is {len(self.label_txt_mappings)}'
                    )

                if label == 0:
                    # skip item with label = 0
                    continue

                logger.info(
                    f"found result: {filename=} {label=} {confidence_level=}")

                bname = Path(filename).stem


                if confidence_level >= self.thresholds[label]:


                    counter[f'{label}|{label_txt}'] += 1
                    triggered_samples[label_txt].append({
                        'idx': int(bname),
                        'confidence': confidence_level,
                        'label': label_txt
                    })
                    logger.info(
                        f"{counter=}, details={triggered_samples}"
                            )

                pathd = (p / str(label) / f"{ confidence_level }_{bname}.png")
                paths = p / filename
                shutil.copyfile(paths, pathd)
                logger.debug(f"copy {paths=} to {pathd=}")

            logger.info(
                f"completed CG detection: {counter=}, details={triggered_samples}"
            )

            await self.hub.publish(
                EventTopics.Logs,
                self._event(
                    EventLogType.Results, {
                        'results': triggered_samples,
                        'labelMapping': self.label_txt_mappings
                    }))

        except Exception as e:
            logger.error(f"failed to run detector: {e}")
            await self.hub.publish(EventTopics.State,
                                   self._event(TaskState.Failed))
            # propogate error to caller
            raise e
        finally:
            logger.debug(f'wait 2s before stopping detector')
            await asyncio.sleep(2)
            await self.stop()
            await self.hub.publish(EventTopics.State,
                                   self._event(TaskState.Completed))