<commit_before>"""
homeassistant.components.device_tracker.owntracks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OwnTracks platform for the device tracker.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.owntracks/
"""
import json
import logging
import threading
from collections import defaultdict

import homeassistant.components.mqtt as mqtt
from homeassistant.const import STATE_HOME

DEPENDENCIES = ['mqtt']

REGIONS_ENTERED = defaultdict(list)
MOBILE_BEACONS_ACTIVE = defaultdict(list)

BEACON_DEV_ID = 'beacon'

LOCATION_TOPIC = 'owntracks/+/+'
EVENT_TOPIC = 'owntracks/+/+/event'

_LOGGER = logging.getLogger(__name__)

LOCK = threading.Lock()


def setup_scanner(hass, config, see):
    """ Set up an OwnTracks tracker. """

    def owntracks_location_update(topic, payload, qos):
        """ MQTT message received. """

        # Docs on available data:
        # http://owntracks.org/booklet/tech/json/#_typelocation
        try:
            data = json.loads(payload)
        except ValueError:
            # If invalid JSON
            _LOGGER.error(
                'Unable to parse payload as JSON: %s', payload)
            return

        if not isinstance(data, dict) or data.get('_type') != 'location':
            return

        dev_id, kwargs = _parse_see_args(topic, data)

        # Block updates if we're in a region
        with LOCK:
            if REGIONS_ENTERED[dev_id]:
                _LOGGER.debug(
                    "location update ignored - inside region %s",
                    REGIONS_ENTERED[-1])
                return

            see(**kwargs)
            see_beacons(dev_id, kwargs)

    def owntracks_event_update(topic, payload, qos):
        # pylint: disable=too-many-branches
        """ MQTT event (geofences) received. """

        # Docs on available data:
        # http://owntracks.org/booklet/tech/json/#_typetransition
        try:
            data = json.loads(payload)
        except ValueError:
            # If invalid JSON
            _LOGGER.error(
                'Unable to parse payload as JSON: %s', payload)
            return

        if not isinstance(data, dict) or data.get('_type') != 'transition':
            return

        # OwnTracks uses - at the start of a beacon zone
        # to switch on 'hold mode' - ignore this
        location = data['desc'].lstrip("-")
        if location.lower() == 'home':
            location = STATE_HOME

        dev_id, kwargs = _parse_see_args(topic, data)

        if data['event'] == 'enter':
            zone = hass.states.get("zone.{}".format(location))
            with LOCK:
                if zone is None:
                    if data['t'] == 'b':
                        # Not a HA zone, and a beacon so assume mobile
                        MOBILE_BEACONS_ACTIVE[dev_id].append(location)

                else:
                    # Normal region
                    kwargs['location_name'] = location

                    regions = REGIONS_ENTERED[dev_id]
                    if location not in regions:
                        regions.append(location)
                    _LOGGER.info("Enter region %s", location)
                    _set_gps_from_zone(kwargs, zone)

                see(**kwargs)
                see_beacons(dev_id, kwargs)

        elif data['event'] == 'leave':
            regions = REGIONS_ENTERED[dev_id]
            if location in regions:
                regions.remove(location)
            new_region = regions[-1] if regions else None

            if new_region:
                # Exit to previous region
                zone = hass.states.get("zone.{}".format(new_region))
                kwargs['location_name'] = new_region
                _set_gps_from_zone(kwargs, zone)
                _LOGGER.info("Exit from %s to %s", location, new_region)

            else:
                _LOGGER.info("Exit from %s to GPS", location)

            see(**kwargs)
            see_beacons(dev_id, kwargs)

            beacons = MOBILE_BEACONS_ACTIVE[dev_id]
            if location in beacons:
                beacons.remove(location)

        else:
            _LOGGER.error(
                'Misformatted mqtt msgs, _type=transition, event=%s',
                data['event'])
            return

    def see_beacons(dev_id, kwargs):
        """ Set active beacons to the current location """

        for beacon in MOBILE_BEACONS_ACTIVE[dev_id]:
            kwargs['dev_id'] = beacon
            kwargs['host_name'] = BEACON_DEV_ID
            see(**kwargs)

    mqtt.subscribe(hass, LOCATION_TOPIC, owntracks_location_update, 1)
<commit_msg>Revise beacon name. Add debug.<commit_after>"""
homeassistant.components.device_tracker.owntracks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OwnTracks platform for the device tracker.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.owntracks/
"""
import json
import logging
import threading
from collections import defaultdict

import homeassistant.components.mqtt as mqtt
from homeassistant.const import STATE_HOME

DEPENDENCIES = ['mqtt']

REGIONS_ENTERED = defaultdict(list)
MOBILE_BEACONS_ACTIVE = defaultdict(list)

BEACON_DEV_ID = 'beacon'

LOCATION_TOPIC = 'owntracks/+/+'
EVENT_TOPIC = 'owntracks/+/+/event'

_LOGGER = logging.getLogger(__name__)

LOCK = threading.Lock()


def setup_scanner(hass, config, see):
    """ Set up an OwnTracks tracker. """

    def owntracks_location_update(topic, payload, qos):
        """ MQTT message received. """

        # Docs on available data:
        # http://owntracks.org/booklet/tech/json/#_typelocation
        try:
            data = json.loads(payload)
        except ValueError:
            # If invalid JSON
            _LOGGER.error(
                'Unable to parse payload as JSON: %s', payload)
            return

        if not isinstance(data, dict) or data.get('_type') != 'location':
            return

        dev_id, kwargs = _parse_see_args(topic, data)

        # Block updates if we're in a region
        with LOCK:
            _LOGGER.error("REGIONS_ENTERED %s",REGIONS_ENTERED)
            _LOGGER.error("MOBILE_BEACONS_ACTIVE %s",MOBILE_BEACONS_ACTIVE)
            if REGIONS_ENTERED[dev_id]:
                _LOGGER.debug(
                    "location update ignored - inside region %s",
                    REGIONS_ENTERED[-1])
                return

            see(**kwargs)
            see_beacons(dev_id, kwargs)

    def owntracks_event_update(topic, payload, qos):
        # pylint: disable=too-many-branches
        """ MQTT event (geofences) received. """

        # Docs on available data:
        # http://owntracks.org/booklet/tech/json/#_typetransition
        try:
            data = json.loads(payload)
        except ValueError:
            # If invalid JSON
            _LOGGER.error(
                'Unable to parse payload as JSON: %s', payload)
            return

        _LOGGER.error("REGIONS_ENTERED %s",REGIONS_ENTERED)
        _LOGGER.error("MOBILE_BEACONS_ACTIVE %s",MOBILE_BEACONS_ACTIVE)


        if not isinstance(data, dict) or data.get('_type') != 'transition':
            return

        # OwnTracks uses - at the start of a beacon zone
        # to switch on 'hold mode' - ignore this
        location = data['desc'].lstrip("-")
        if location.lower() == 'home':
            location = STATE_HOME

        dev_id, kwargs = _parse_see_args(topic, data)

        if data['event'] == 'enter':
            zone = hass.states.get("zone.{}".format(location))
            with LOCK:
                if zone is None:
                    if data['t'] == 'b':
                        # Not a HA zone, and a beacon so assume mobile
                        MOBILE_BEACONS_ACTIVE[dev_id].append(location)
                else:
                    # Normal region
                    kwargs['location_name'] = location

                    regions = REGIONS_ENTERED[dev_id]
                    if location not in regions:
                        regions.append(location)
                    _LOGGER.info("Enter region %s", location)
                    _set_gps_from_zone(kwargs, zone)

                see(**kwargs)
                see_beacons(dev_id, kwargs)

        elif data['event'] == 'leave':
            regions = REGIONS_ENTERED[dev_id]
            if location in regions:
                regions.remove(location)
            new_region = regions[-1] if regions else None

            if new_region:
                # Exit to previous region
                zone = hass.states.get("zone.{}".format(new_region))
                kwargs['location_name'] = new_region
                _set_gps_from_zone(kwargs, zone)
                _LOGGER.info("Exit from to %s", new_region)

            else:
                _LOGGER.info("Exit from to GPS")

            see(**kwargs)
            see_beacons(dev_id, kwargs)

            beacons = MOBILE_BEACONS_ACTIVE[dev_id]
            if location in beacons:
                beacons.remove(location)

        else:
            _LOGGER.error(
                'Misformatted mqtt msgs, _type=transition, event=%s',
                data['event'])
            return

    def see_beacons(dev_id, kwargs):
        """ Set active beacons to the current location """

        for beacon in MOBILE_BEACONS_ACTIVE[dev_id]:
            kwargs['dev_id'] = "{}_{}".format(BEACON_DEV_ID, beacon)
            kwargs['host_name'] = beacon
            see(**kwargs)

    mqtt.subscribe(hass, LOCATION_TOPIC, owntracks_location_update, 1)

{'fraction_non_alphanumeric': 0.10520854949159576, 'fraction_numerical': 0.0006225357958082589, 'mean_word_length': 1.9244538834951457, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, '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': '3013604', 'n_tokens_mistral': 2847, 'n_tokens_neox': 2703, 'n_words': 665}