<commit_before>"""For HA camera components."""
import logging
import queue
import re
from time import time

from .core import HAFFmpegWorker, HAFFMPEG_QUEUE_END, FFMPEG_STDOUT

_LOGGER = logging.getLogger(__name__)


class SensorNoise(HAFFmpegWorker):
    """Implement a noise detection on a autio stream."""

    STATE_NONE = 0
    STATE_NOISE = 1
    STATE_END = 2
    STATE_DETECT = 3

    def __init__(self, ffmpeg_bin, callback):
        """Init noise sensor."""
        super().__init__(ffmpeg_bin)

        self._callback = callback
        self._peak = -30
        self._time_duration = 1
        self._time_reset = 2

    def set_options(self, time_duration=1, time_reset=2, peak=-30):
        """Set option parameter for noise sensor."""
        self._time_duration = time_duration
        self._time_reset = time_reset
        self._peak = peak

    def open_sensor(self, input_source, output_dest=None, extra_cmd=None):
        """Open FFmpeg process for read autio stream."""
        command = [
            "-i",
            input_source,
            "-vn",
            "-filter:a",
            "silencedetect=n={}dB:d=1".format(self._peak)
        ]

        # run ffmpeg, read output
        self.start_worker(cmd=command, output=output_dest, extra_cmd=extra_cmd,
                          pattern="silence")

    def _worker_process(self):
        """This function run in thread for process que data."""
        state = self.STATE_DETECT
        timeout = self._time_duration

        re_start = re.compile("silence_start")
        re_end = re.compile("silence_end")

        # process queue data
        while True:
            try:
                _LOGGER.debug("Reading State: %d, timeout: %s", state, timeout)
                data = self._que.get(block=True, timeout=timeout)
                timeout = None
                if data == HAFFMPEG_QUEUE_END:
                    return
            except queue.Empty:
                _LOGGER.debug("Blocking timeout")
                # noise
                if state == self.STATE_DETECT:
                    # noise detected
                    self._callback(True)
                    state = self.STATE_NOISE

                elif state == self.STATE_END:
                    # no noise
                    self._callback(False)
                    state = self.STATE_NONE

                timeout = None
                continue

            if re_start.search(data):
                if state == self.STATE_NOISE:
                    # stop noise detection
                    state = self.STATE_END
                    timeout = self._time_reset
                elif state == self.STATE_DETECT:
                    # reset if only a peak
                    state = self.STATE_NONE
                continue

            if re_end.search(data):
                if state == self.STATE_NONE:
                    # detect noise begin
                    state = self.STATE_DETECT
                    timeout = self._time_duration
                elif state == self.STATE_END:
                    # back to noise status
                    state = self.STATE_NOISE
                continue

            _LOGGER.warning("Unknown data from queue!")


class SensorMotion(HAFFmpegWorker):
    """Implement motion detection with ffmpeg scene detection."""

    STATE_NONE = 0
    STATE_REPEAT = 1
    STATE_MOTION = 2

    MATCH = "\d,.*(\d),.*\d,.*\d,.*\d,.*\w"

    def __init__(self, ffmpeg_bin, callback):
        """Init motion sensor."""
        super().__init__(ffmpeg_bin)

        self._callback = callback
        self._changes = 10
        self._time_duration = 60
        self._time_repeat = 0
        self._repeat = 0

    def set_options(self, time_reset=60, time_repeat=0, repeat=0,
                    changes=10):
        """Set option parameter for noise sensor."""
        self._time_reset = time_reset
        self._time_repeat = time_repeat
        self._repeat = repeat
        self._changes = changes

    def open_sensor(self, input_source, extra_cmd=None):
        """Open FFmpeg process a video stream for motion detection."""
        command = [
            "-i",
            input_source,
            "-an",
            "-filter:v",
            "select=gt(scene\,{0})".format(self._changes / 100),
            "-hash",
            "md5",
            "-f",
            "framehash",
        ]

        # run ffmpeg, read output
        self.start_worker(cmd=command, output="-", extra_cmd=extra_cmd,
                          pattern=self.MATCH, reading=FFMPEG_STDOUT)

    def _worker_process(self):
        """This function run in thread for process que data."""
        state = self.STATE_NONE
        timeout = None

        # for repeat feature
        re_frame = 0
        re_time = 0

        re_data = re.compile(self.MATCH)

        # process queue data
        while True:
            try:
                _LOGGER.debug("Reading State: %d, timeout: %s", state, timeout)
                data = self._que.get(block=True, timeout=timeout)
                if data == HAFFMPEG_QUEUE_END:
                    return
            except queue.Empty:
                _LOGGER.debug("Blocking timeout")
                # reset motion detection
                if state == self.STATE_MOTION:
                    state = self.STATE_NONE
                    self._callback(False)
                    timeout = None
                # reset repeate state
                if state == self.STATE_REPEAT:
                    state = self.STATE_NONE
                    timeout = None
                continue

            frames = re_data.search(data)
            if frames:
                # repeat not used
                if self._repeat == 0 and state == self.STATE_NONE:
                    state = self.STATE_MOTION
                    self._callback(True)
                    timeout = self._time_reset

                # repeat feature is on / first motion
                if state == self.STATE_NONE:
                    state = self.STATE_REPEAT
                    re_frame = int(frames.group(1))
                    re_time = time()

                elif state == self.STATE_REPEAT:
                    # other repeat frame
                    tmp_frame = int(frames.group(1))

                    # REPEAT ready?
                    if tmp_frame - re_frame >= self._repeat:
                        state = self.STATE_MOTION
                        self._callback(True)
                        timeout = self._time_reset
                    else:
                        past = time() - re_time
                        timeout -= past

                    # REPEAT time down
                    if timeout <= 0:
                        _LOGGER.debug("Reset repeat to none")
                        state = self.STATE_NONE
                        timeout = None


                continue

            _LOGGER.warning("Unknown data from queue!")
<commit_msg>fix regex<commit_after>"""For HA camera components."""
import logging
import queue
import re
from time import time

from .core import HAFFmpegWorker, HAFFMPEG_QUEUE_END, FFMPEG_STDOUT

_LOGGER = logging.getLogger(__name__)


class SensorNoise(HAFFmpegWorker):
    """Implement a noise detection on a autio stream."""

    STATE_NONE = 0
    STATE_NOISE = 1
    STATE_END = 2
    STATE_DETECT = 3

    def __init__(self, ffmpeg_bin, callback):
        """Init noise sensor."""
        super().__init__(ffmpeg_bin)

        self._callback = callback
        self._peak = -30
        self._time_duration = 1
        self._time_reset = 2

    def set_options(self, time_duration=1, time_reset=2, peak=-30):
        """Set option parameter for noise sensor."""
        self._time_duration = time_duration
        self._time_reset = time_reset
        self._peak = peak

    def open_sensor(self, input_source, output_dest=None, extra_cmd=None):
        """Open FFmpeg process for read autio stream."""
        command = [
            "-i",
            input_source,
            "-vn",
            "-filter:a",
            "silencedetect=n={}dB:d=1".format(self._peak)
        ]

        # run ffmpeg, read output
        self.start_worker(cmd=command, output=output_dest, extra_cmd=extra_cmd,
                          pattern="silence")

    def _worker_process(self):
        """This function run in thread for process que data."""
        state = self.STATE_DETECT
        timeout = self._time_duration

        re_start = re.compile("silence_start")
        re_end = re.compile("silence_end")

        # process queue data
        while True:
            try:
                _LOGGER.debug("Reading State: %d, timeout: %s", state, timeout)
                data = self._que.get(block=True, timeout=timeout)
                timeout = None
                if data == HAFFMPEG_QUEUE_END:
                    return
            except queue.Empty:
                _LOGGER.debug("Blocking timeout")
                # noise
                if state == self.STATE_DETECT:
                    # noise detected
                    self._callback(True)
                    state = self.STATE_NOISE

                elif state == self.STATE_END:
                    # no noise
                    self._callback(False)
                    state = self.STATE_NONE

                timeout = None
                continue

            if re_start.search(data):
                if state == self.STATE_NOISE:
                    # stop noise detection
                    state = self.STATE_END
                    timeout = self._time_reset
                elif state == self.STATE_DETECT:
                    # reset if only a peak
                    state = self.STATE_NONE
                continue

            if re_end.search(data):
                if state == self.STATE_NONE:
                    # detect noise begin
                    state = self.STATE_DETECT
                    timeout = self._time_duration
                elif state == self.STATE_END:
                    # back to noise status
                    state = self.STATE_NOISE
                continue

            _LOGGER.warning("Unknown data from queue!")


class SensorMotion(HAFFmpegWorker):
    """Implement motion detection with ffmpeg scene detection."""

    STATE_NONE = 0
    STATE_REPEAT = 1
    STATE_MOTION = 2

    MATCH = r"\d,.*(\d),.*\d,.*\d,.*\d,.*\w"

    def __init__(self, ffmpeg_bin, callback):
        """Init motion sensor."""
        super().__init__(ffmpeg_bin)

        self._callback = callback
        self._changes = 10
        self._time_duration = 60
        self._time_repeat = 0
        self._repeat = 0

    def set_options(self, time_reset=60, time_repeat=0, repeat=0,
                    changes=10):
        """Set option parameter for noise sensor."""
        self._time_reset = time_reset
        self._time_repeat = time_repeat
        self._repeat = repeat
        self._changes = changes

    def open_sensor(self, input_source, extra_cmd=None):
        """Open FFmpeg process a video stream for motion detection."""
        command = [
            "-i",
            input_source,
            "-an",
            "-filter:v",
            "select=gt(scene\,{0})".format(self._changes / 100),
            "-hash",
            "md5",
            "-f",
            "framehash",
        ]

        # run ffmpeg, read output
        self.start_worker(cmd=command, output="-", extra_cmd=extra_cmd,
                          pattern=self.MATCH, reading=FFMPEG_STDOUT)

    def _worker_process(self):
        """This function run in thread for process que data."""
        state = self.STATE_NONE
        timeout = None

        # for repeat feature
        re_frame = 0
        re_time = 0

        re_data = re.compile(self.MATCH)

        # process queue data
        while True:
            try:
                _LOGGER.debug("Reading State: %d, timeout: %s", state, timeout)
                data = self._que.get(block=True, timeout=timeout)
                if data == HAFFMPEG_QUEUE_END:
                    return
            except queue.Empty:
                _LOGGER.debug("Blocking timeout")
                # reset motion detection
                if state == self.STATE_MOTION:
                    state = self.STATE_NONE
                    self._callback(False)
                    timeout = None
                # reset repeate state
                if state == self.STATE_REPEAT:
                    state = self.STATE_NONE
                    timeout = None
                continue

            frames = re_data.search(data)
            if frames:
                # repeat not used
                if self._repeat == 0 and state == self.STATE_NONE:
                    state = self.STATE_MOTION
                    self._callback(True)
                    timeout = self._time_reset

                # repeat feature is on / first motion
                if state == self.STATE_NONE:
                    state = self.STATE_REPEAT
                    re_frame = int(frames.group(1))
                    re_time = time()

                elif state == self.STATE_REPEAT:
                    # other repeat frame
                    tmp_frame = int(frames.group(1))

                    # REPEAT ready?
                    if tmp_frame - re_frame >= self._repeat:
                        state = self.STATE_MOTION
                        self._callback(True)
                        timeout = self._time_reset
                    else:
                        past = time() - re_time
                        timeout -= past

                    # REPEAT time down
                    if timeout <= 0:
                        _LOGGER.debug("Reset repeat to none")
                        state = self.STATE_NONE
                        timeout = None


                continue

            _LOGGER.warning("Unknown data from queue!")

{'fraction_non_alphanumeric': 0.08566697861924988, 'fraction_numerical': 0.005615146497732345, 'mean_word_length': 1.3585738539898133, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3903440', 'n_tokens_mistral': 3805, 'n_tokens_neox': 3486, 'n_words': 897}