{"action":"created","comment":{"url":"https://api.github.com/repos/home-assistant/home-assistant/pulls/comments/112496937","pull_request_review_id":33815007,"id":112496937,"diff_hunk":"@@ -0,0 +1,812 @@\n+\"\"\"\n+Bluesound.\n+\n+For more details about this platform, please refer to the documentation at\n+https://home-assistant.io/components/media_player.bluesound/\n+\"\"\"\n+import logging\n+from datetime import timedelta\n+from asyncio.futures import CancelledError\n+import asyncio\n+import voluptuous as vol\n+from aiohttp.client_exceptions import ClientError\n+import aiohttp\n+import async_timeout\n+from homeassistant.helpers.event import async_track_time_interval\n+from homeassistant.core import callback\n+from homeassistant.util import Throttle\n+from homeassistant.helpers.aiohttp_client import async_get_clientsession\n+import homeassistant.util.dt as dt_util\n+\n+from homeassistant.components.media_player import (\n+    SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, SUPPORT_SEEK,\n+    SUPPORT_PLAY_MEDIA, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_STOP,\n+    SUPPORT_PLAY, MediaPlayerDevice, PLATFORM_SCHEMA, MEDIA_TYPE_MUSIC,\n+    SUPPORT_CLEAR_PLAYLIST, SUPPORT_SELECT_SOURCE, SUPPORT_VOLUME_STEP)\n+from homeassistant.const import (\n+    EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,\n+    STATE_PLAYING, STATE_PAUSED, STATE_IDLE, CONF_HOSTS,\n+    CONF_HOST, CONF_PORT, CONF_NAME)\n+import homeassistant.helpers.config_validation as cv\n+\n+REQUIREMENTS = ['xmltodict==0.10.2']\n+\n+STATE_OFFLINE = 'offline'\n+ATTR_MODEL = 'model'\n+ATTR_MODEL_NAME = 'model_name'\n+ATTR_BRAND = 'brand'\n+\n+DATA_BLUESOUND = 'bluesound'\n+DEFAULT_PORT = 11000\n+\n+SYNC_STATUS_INTERVAL = timedelta(minutes=3)\n+UPDATE_CAPTURE_INTERVAL = timedelta(minutes=30)\n+UPDATE_SERVICES_INTERVAL = timedelta(minutes=30)\n+UPDATE_PRESETS_INTERVAL = timedelta(minutes=30)\n+NODE_OFFLINE_CHECK_TIMEOUT = 180\n+NODE_RETRY_INITIATION = timedelta(minutes=3)\n+\n+_LOGGER = logging.getLogger(__name__)\n+\n+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({\n+    vol.Optional(CONF_HOSTS): vol.All(cv.ensure_list, [{\n+        vol.Required(CONF_HOST): cv.string,\n+        vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,\n+        vol.Optional(CONF_NAME): cv.string,\n+    }])\n+})\n+\n+\n+def _add_player(hass, async_add_devices, host, port=None, name=None):\n+    if host in [x.host for x in hass.data[DATA_BLUESOUND]]:\n+        return\n+\n+    @callback\n+    def _start_polling(event=None):\n+        \"\"\"Start polling.\"\"\"\n+        player.start_polling()\n+\n+    @callback\n+    def _stop_polling():\n+        \"\"\"Stop polling.\"\"\"\n+        player.stop_polling()\n+\n+    @callback\n+    def _add_player_cb():\n+        \"\"\"Add player after first sync fetch.\"\"\"\n+        async_add_devices([player])\n+        _LOGGER.info('Added Bluesound device with name: %s', player.name)\n+\n+        if hass.is_running:\n+            _start_polling()\n+        else:\n+            hass.bus.async_listen_once(\n+                EVENT_HOMEASSISTANT_START,\n+                _start_polling\n+            )\n+\n+    hass.bus.async_listen_once(\n+        EVENT_HOMEASSISTANT_STOP,\n+        _stop_polling\n+    )\n+\n+    player = BluesoundPlayer(hass, host, port, name, _add_player_cb)\n+    hass.data[DATA_BLUESOUND].append(player)\n+    hass.async_run_job(player.async_init)\n+\n+\n+@asyncio.coroutine\n+def async_setup_platform(hass, config, async_add_devices, discovery_info=None):\n+    \"\"\"Set up the Bluesound platforms.\"\"\"\n+    if DATA_BLUESOUND not in hass.data:\n+        hass.data[DATA_BLUESOUND] = []\n+\n+    if discovery_info:\n+        _add_player(hass, async_add_devices, discovery_info.get('host'),\n+                    discovery_info.get('port', None))\n+        return\n+    else:\n+        hosts = config.get(CONF_HOSTS, None)\n+        if hosts:\n+            for host in hosts:\n+                _add_player(hass,\n+                            async_add_devices,\n+                            host.get(CONF_HOST),\n+                            host.get(CONF_PORT, None),\n+                            host.get(CONF_NAME, None))\n+\n+\n+class BluesoundPlayer(MediaPlayerDevice):\n+    \"\"\"Bluesound Player Object.\"\"\"\n+\n+    def __init__(self, hass, host, port=None, name=None, init_callback=None):\n+        \"\"\"Initialize the media player.\"\"\"\n+        self.host = host\n+        self._hass = hass\n+        self._port = port\n+        self._polling_session = async_get_clientsession(hass)\n+        self._polling_task = None  # The actuall polling task.\n+        self._name = name\n+        self._brand = None\n+        self._model = None\n+        self._model_name = None\n+        self._icon = None\n+        self._capture_items = []\n+        self._services_items = []\n+        self._preset_items = []\n+        self._sync_status = {}\n+        self._status = None\n+        self._last_status_update = None\n+        self._is_online = False\n+        self._retry_remove = None\n+        self._lastvol = None\n+        self._init_callback = init_callback\n+        if self._port is None:\n+            self._port = DEFAULT_PORT\n+\n+# Internal methods\n+    @staticmethod\n+    def _try_get_index(string, seach_string):\n+        try:\n+            return string.index(seach_string)\n+        except ValueError:\n+            return -1\n+\n+    @asyncio.coroutine\n+    def _internal_update_sync_status(self, on_updated_cb=None,\n+                                     raise_timeout=False):\n+        resp = None\n+        try:\n+            resp = yield from self.send_bluesound_command(\n+                'SyncStatus',\n+                raise_timeout, raise_timeout)\n+        except:\n+            raise\n+\n+        if not resp:\n+            return None\n+        self._sync_status = resp['SyncStatus'].copy()\n+\n+        if not self._name:\n+            self._name = self._sync_status.get('@name', self.host)\n+        if not self._brand:\n+            self._brand = self._sync_status.get('@brand', self.host)\n+        if not self._model:\n+            self._model = self._sync_status.get('@model', self.host)\n+        if not self._icon:\n+            self._icon = self._sync_status.get('@icon', self.host)\n+        if not self._model_name:\n+            self._model_name = self._sync_status.get('@modelName', self.host)\n+\n+        if on_updated_cb:\n+            on_updated_cb()\n+        return True\n+# END Internal methods\n+\n+# Poll functionality\n+    @asyncio.coroutine\n+    def _start_poll_command(self):\n+        \"\"\"\"Loop which polls the status of the player.\"\"\"\n+        try:\n+            while True:\n+                yield from self.async_update_status()\n+\n+        except (asyncio.TimeoutError, ClientError):\n+            _LOGGER.info(\"Bluesound node %s is offline, retrying later\",\n+                         self._name)\n+            yield from asyncio.sleep(NODE_OFFLINE_CHECK_TIMEOUT,\n+                                     loop=self._hass.loop)\n+            self.start_polling()\n+\n+        except CancelledError:\n+            _LOGGER.debug(\"Stopping bluesound polling of node %s\", self._name)\n+        except:\n+            _LOGGER.exception(\"Unexpected error in %s\", self._name)\n+            raise\n+\n+    def start_polling(self):\n+        \"\"\"Start the polling task.\"\"\"\n+        self._polling_task = self._hass.async_add_job(\n+            self._start_poll_command())\n+\n+    def stop_polling(self):\n+        \"\"\"Stop the polling task.\"\"\"\n+        self._polling_task.cancel()\n+# END Poll functionality\n+\n+# Initiator\n+    @asyncio.coroutine\n+    def async_init(self, what=None):\n+        \"\"\"Initiate the player async.\"\"\"\n+        if what is None:\n+            # if it's the first request.\n+            # let's make the request in a new thread\n+            self._retry_remove = async_track_time_interval(\n+                self._hass,\n+                self.async_init,\n+                timedelta(seconds=1))\n+            return\n+\n+        try:\n+            if self._retry_remove is not None:\n+                self._retry_remove()\n+                self._retry_remove = None\n+\n+            yield from self._internal_update_sync_status(self._init_callback,\n+                                                         True)\n+        except (asyncio.TimeoutError, ClientError):\n+            _LOGGER.info(\"Bluesound node %s is offline, retrying later\",\n+                         self.host)\n+            self._retry_remove = async_track_time_interval(\n+                self._hass,\n+                self.async_init,\n+                NODE_RETRY_INITIATION)\n+        except:\n+            _LOGGER.exception(\"Unexpected when initiating error in %s\",\n+                              self.host)\n+            raise\n+# END Initiator\n+\n+# Status updates fetchers\n+    @asyncio.coroutine\n+    def async_update(self):\n+        \"\"\"Update internal status of the entity.\"\"\"\n+        _LOGGER.info('vhecking')\n+        if not self._is_online:\n+            return\n+\n+        yield from self.async_update_sync_status()\n+        yield from self.async_update_presets()\n+        yield from self.async_update_captures()\n+        yield from self.async_update_services()\n+\n+    @asyncio.coroutine\n+    def send_bluesound_command(self, method, raise_timeout=False,\n+                               allow_offline=False):\n+        \"\"\"Send command to the player.\"\"\"\n+        import xmltodict\n+\n+        if not self._is_online and not allow_offline:\n+            return\n+\n+        if method[0] == '/':\n+            method = method[1:]\n+        url = \"http://{}:{}/{}\".format(self.host, self._port, method)\n+\n+        _LOGGER.info(\"calling URL: %s\", url)\n+        response = None\n+        try:\n+            websession = async_get_clientsession(self._hass)\n+            with async_timeout.timeout(10, loop=self._hass.loop):\n+                response = yield from websession.get(url)\n+\n+            if response.status == 200:\n+                result = yield from response.text()\n+                if len(result) < 1:\n+                    data = None\n+                else:\n+                    data = xmltodict.parse(result)\n+            else:\n+                _LOGGER.error(\"Error %s on %s\", response.status, url)\n+                return None\n+\n+        except (asyncio.TimeoutError, aiohttp.ClientError):\n+            if raise_timeout:\n+                _LOGGER.info(\"Timeout with Bluesound: %s\", self.host)\n+                raise\n+            else:\n+                _LOGGER.debug(\"Failed communicating with Bluesound: %s\",\n+                              self.host)\n+                return None\n+        finally:\n+            if response is not None:\n+                yield from response.release()\n+\n+        return data\n+\n+    @asyncio.coroutine\n+    def async_update_status(self):\n+        \"\"\"Using the poll session to always get the status of the player.\"\"\"\n+        import xmltodict\n+        response = None\n+\n+        url = 'Status'\n+        etag = ''\n+        if self._status is not None:\n+            etag = self._status.get('@etag', '')\n+\n+        if etag != '':\n+            url = 'Status?etag='+etag+'&timeout=60.0'\n+        url = \"http://{}:{}/{}\".format(self.host, self._port, url)\n+\n+        _LOGGER.debug(\"calling URL: %s\", url)\n+\n+        try:\n+\n+            with async_timeout.timeout(65, loop=self._hass.loop):\n+                response = yield from self._polling_session.get(\n+                    url,\n+                    headers={'connection': 'keep-alive'})\n+\n+            if response.status != 200:\n+                _LOGGER.error(\"Error %s on %s\", response.status, url)\n+\n+            result = yield from response.text()\n+            self._is_online = True\n+            self._last_status_update = dt_util.utcnow()\n+            self._status = xmltodict.parse(result)['status'].copy()\n+            self.schedule_update_ha_state()\n+\n+        except (asyncio.TimeoutError, ClientError):\n+            self._is_online = False\n+            self._last_status_update = None\n+            self._status = None\n+            self.schedule_update_ha_state()\n+            _LOGGER.info(\"Client connection error, marking %s as offline\",\n+                         self._name)\n+            raise\n+        finally:\n+            if response is not None:","path":"homeassistant/components/media_player/bluesound.py","position":349,"original_position":349,"commit_id":"c7a95bbb0318993d298a7b73e8d68088d8a451ef","original_commit_id":"c7a95bbb0318993d298a7b73e8d68088d8a451ef","user":{"login":"balloob","id":1444314,"avatar_url":"https://avatars0.githubusercontent.com/u/1444314?v=3","gravatar_id":"","url":"https://api.github.com/users/balloob","html_url":"https://github.com/balloob","followers_url":"https://api.github.com/users/balloob/followers","following_url":"https://api.github.com/users/balloob/following{/other_user}","gists_url":"https://api.github.com/users/balloob/gists{/gist_id}","starred_url":"https://api.github.com/users/balloob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/balloob/subscriptions","organizations_url":"https://api.github.com/users/balloob/orgs","repos_url":"https://api.github.com/users/balloob/repos","events_url":"https://api.github.com/users/balloob/events{/privacy}","received_events_url":"https://api.github.com/users/balloob/received_events","type":"User","site_admin":false},"body":"Can remove this.","created_at":"2017-04-20T16:18:55Z","updated_at":"2017-04-20T16:22:11Z","html_url":"https://github.com/home-assistant/home-assistant/pull/7192#discussion_r112496937","pull_request_url":"https://api.github.com/repos/home-assistant/home-assistant/pulls/7192","_links":{"self":{"href":"https://api.github.com/repos/home-assistant/home-assistant/pulls/comments/112496937"},"html":{"href":"https://github.com/home-assistant/home-assistant/pull/7192#discussion_r112496937"},"pull_request":{"href":"https://api.github.com/repos/home-assistant/home-assistant/pulls/7192"}}},"pull_request":{"url":"https://api.github.com/repos/home-assistant/home-assistant/pulls/7192","id":116747804,"html_url":"https://github.com/home-assistant/home-assistant/pull/7192","diff_url":"https://github.com/home-assistant/home-assistant/pull/7192.diff","patch_url":"https://github.com/home-assistant/home-assistant/pull/7192.patch","issue_url":"https://api.github.com/repos/home-assistant/home-assistant/issues/7192","number":7192,"state":"open","locked":false,"title":"New component: bluesound","user":{"login":"thrawnarn","id":5276026,"avatar_url":"https://avatars2.githubusercontent.com/u/5276026?v=3","gravatar_id":"","url":"https://api.github.com/users/thrawnarn","html_url":"https://github.com/thrawnarn","followers_url":"https://api.github.com/users/thrawnarn/followers","following_url":"https://api.github.com/users/thrawnarn/following{/other_user}","gists_url":"https://api.github.com/users/thrawnarn/gists{/gist_id}","starred_url":"https://api.github.com/users/thrawnarn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thrawnarn/subscriptions","organizations_url":"https://api.github.com/users/thrawnarn/orgs","repos_url":"https://api.github.com/users/thrawnarn/repos","events_url":"https://api.github.com/users/thrawnarn/events{/privacy}","received_events_url":"https://api.github.com/users/thrawnarn/received_events","type":"User","site_admin":false},"body":"## Description:\r\nNew platform for bluesound devices (hifi speakers and streamers)\r\n\r\n**Pull request in [home-assistant.github.io](https://github.com/home-assistant/home-assistant.github.io) with documentation (if applicable):** home-assistant/home-assistant.github.io#2460\r\n\r\n## Example entry for `configuration.yaml` (if applicable):\r\n```yaml\r\nmedia_player:\r\n  - platform: bluesound\r\n    hosts:\r\n      - host: 192.168.1.132\r\n```\r\n\r\n## Checklist:\r\n\r\nIf user exposed functionality or configuration variables are added/changed:\r\n  - [x] Documentation added/updated in [home-assistant.github.io](https://github.com/home-assistant/home-assistant.github.io)\r\n\r\nIf the code communicates with devices, web services, or third-party tools:\r\n  - [x] Local tests with `tox` run successfully. **Your PR cannot be merged unless tests pass**\r\n  - [x] New dependencies have been added to the `REQUIREMENTS` variable ([example][ex-requir]).\r\n  - [x] New dependencies are only imported inside functions that use them ([example][ex-import]).\r\n  - [x] New dependencies have been added to `requirements_all.txt` by running `script/gen_requirements_all.py`.\r\n  - [x] New files were added to `.coveragerc`.\r\n\r\n\r\n[ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L14\r\n[ex-import]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard.py#L54\r\n","created_at":"2017-04-20T11:20:03Z","updated_at":"2017-04-20T16:22:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"16928ff3f2baedd42b882f7f77cc8f413a5e9723","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/home-assistant/home-assistant/pulls/7192/commits","review_comments_url":"https://api.github.com/repos/home-assistant/home-assistant/pulls/7192/comments","review_comment_url":"https://api.github.com/repos/home-assistant/home-assistant/pulls/comments{/number}","comments_url":"https://api.github.com/repos/home-assistant/home-assistant/issues/7192/comments","statuses_url":"https://api.github.com/repos/home-assistant/home-assistant/statuses/c7a95bbb0318993d298a7b73e8d68088d8a451ef","head":{"label":"thrawnarn:bluesound","ref":"bluesound","sha":"c7a95bbb0318993d298a7b73e8d68088d8a451ef","user":{"login":"thrawnarn","id":5276026,"avatar_url":"https://avatars2.githubusercontent.com/u/5276026?v=3","gravatar_id":"","url":"https://api.github.com/users/thrawnarn","html_url":"https://github.com/thrawnarn","followers_url":"https://api.github.com/users/thrawnarn/followers","following_url":"https://api.github.com/users/thrawnarn/following{/other_user}","gists_url":"https://api.github.com/users/thrawnarn/gists{/gist_id}","starred_url":"https://api.github.com/users/thrawnarn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thrawnarn/subscriptions","organizations_url":"https://api.github.com/users/thrawnarn/orgs","repos_url":"https://api.github.com/users/thrawnarn/repos","events_url":"https://api.github.com/users/thrawnarn/events{/privacy}","received_events_url":"https://api.github.com/users/thrawnarn/received_events","type":"User","site_admin":false},"repo":{"id":87628764,"name":"home-assistant","full_name":"thrawnarn/home-assistant","owner":{"login":"thrawnarn","id":5276026,"avatar_url":"https://avatars2.githubusercontent.com/u/5276026?v=3","gravatar_id":"","url":"https://api.github.com/users/thrawnarn","html_url":"https://github.com/thrawnarn","followers_url":"https://api.github.com/users/thrawnarn/followers","following_url":"https://api.github.com/users/thrawnarn/following{/other_user}","gists_url":"https://api.github.com/users/thrawnarn/gists{/gist_id}","starred_url":"https://api.github.com/users/thrawnarn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thrawnarn/subscriptions","organizations_url":"https://api.github.com/users/thrawnarn/orgs","repos_url":"https://api.github.com/users/thrawnarn/repos","events_url":"https://api.github.com/users/thrawnarn/events{/privacy}","received_events_url":"https://api.github.com/users/thrawnarn/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/thrawnarn/home-assistant","description":":house_with_garden: Open-source home automation platform running on Python 3","fork":true,"url":"https://api.github.com/repos/thrawnarn/home-assistant","forks_url":"https://api.github.com/repos/thrawnarn/home-assistant/forks","keys_url":"https://api.github.com/repos/thrawnarn/home-assistant/keys{/key_id}","collaborators_url":"https://api.github.com/repos/thrawnarn/home-assistant/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/thrawnarn/home-assistant/teams","hooks_url":"https://api.github.com/repos/thrawnarn/home-assistant/hooks","issue_events_url":"https://api.github.com/repos/thrawnarn/home-assistant/issues/events{/number}","events_url":"https://api.github.com/repos/thrawnarn/home-assistant/events","assignees_url":"https://api.github.com/repos/thrawnarn/home-assistant/assignees{/user}","branches_url":"https://api.github.com/repos/thrawnarn/home-assistant/branches{/branch}","tags_url":"https://api.github.com/repos/thrawnarn/home-assistant/tags","blobs_url":"https://api.github.com/repos/thrawnarn/home-assistant/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/thrawnarn/home-assistant/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/thrawnarn/home-assistant/git/refs{/sha}","trees_url":"https://api.github.com/repos/thrawnarn/home-assistant/git/trees{/sha}","statuses_url":"https://api.github.com/repos/thrawnarn/home-assistant/statuses/{sha}","languages_url":"https://api.github.com/repos/thrawnarn/home-assistant/languages","stargazers_url":"https://api.github.com/repos/thrawnarn/home-assistant/stargazers","contributors_url":"https://api.github.com/repos/thrawnarn/home-assistant/contributors","subscribers_url":"https://api.github.com/repos/thrawnarn/home-assistant/subscribers","subscription_url":"https://api.github.com/repos/thrawnarn/home-assistant/subscription","commits_url":"https://api.github.com/repos/thrawnarn/home-assistant/commits{/sha}","git_commits_url":"https://api.github.com/repos/thrawnarn/home-assistant/git/commits{/sha}","comments_url":"https://api.github.com/repos/thrawnarn/home-assistant/comments{/number}","issue_comment_url":"https://api.github.com/repos/thrawnarn/home-assistant/issues/comments{/number}","contents_url":"https://api.github.com/repos/thrawnarn/home-assistant/contents/{+path}","compare_url":"https://api.github.com/repos/thrawnarn/home-assistant/compare/{base}...{head}","merges_url":"https://api.github.com/repos/thrawnarn/home-assistant/merges","archive_url":"https://api.github.com/repos/thrawnarn/home-assistant/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/thrawnarn/home-assistant/downloads","issues_url":"https://api.github.com/repos/thrawnarn/home-assistant/issues{/number}","pulls_url":"https://api.github.com/repos/thrawnarn/home-assistant/pulls{/number}","milestones_url":"https://api.github.com/repos/thrawnarn/home-assistant/milestones{/number}","notifications_url":"https://api.github.com/repos/thrawnarn/home-assistant/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/thrawnarn/home-assistant/labels{/name}","releases_url":"https://api.github.com/repos/thrawnarn/home-assistant/releases{/id}","deployments_url":"https://api.github.com/repos/thrawnarn/home-assistant/deployments","created_at":"2017-04-08T11:22:21Z","updated_at":"2017-04-08T11:22:27Z","pushed_at":"2017-04-20T12:51:41Z","git_url":"git://github.com/thrawnarn/home-assistant.git","ssh_url":"git@github.com:thrawnarn/home-assistant.git","clone_url":"https://github.com/thrawnarn/home-assistant.git","svn_url":"https://github.com/thrawnarn/home-assistant","homepage":"https://home-assistant.io","size":58304,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"dev"}},"base":{"label":"home-assistant:dev","ref":"dev","sha":"eb2e5e5b9da3129e97ab80868b0fb91bbd365982","user":{"login":"home-assistant","id":13844975,"avatar_url":"https://avatars0.githubusercontent.com/u/13844975?v=3","gravatar_id":"","url":"https://api.github.com/users/home-assistant","html_url":"https://github.com/home-assistant","followers_url":"https://api.github.com/users/home-assistant/followers","following_url":"https://api.github.com/users/home-assistant/following{/other_user}","gists_url":"https://api.github.com/users/home-assistant/gists{/gist_id}","starred_url":"https://api.github.com/users/home-assistant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/home-assistant/subscriptions","organizations_url":"https://api.github.com/users/home-assistant/orgs","repos_url":"https://api.github.com/users/home-assistant/repos","events_url":"https://api.github.com/users/home-assistant/events{/privacy}","received_events_url":"https://api.github.com/users/home-assistant/received_events","type":"Organization","site_admin":false},"repo":{"id":12888993,"name":"home-assistant","full_name":"home-assistant/home-assistant","owner":{"login":"home-assistant","id":13844975,"avatar_url":"https://avatars0.githubusercontent.com/u/13844975?v=3","gravatar_id":"","url":"https://api.github.com/users/home-assistant","html_url":"https://github.com/home-assistant","followers_url":"https://api.github.com/users/home-assistant/followers","following_url":"https://api.github.com/users/home-assistant/following{/other_user}","gists_url":"https://api.github.com/users/home-assistant/gists{/gist_id}","starred_url":"https://api.github.com/users/home-assistant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/home-assistant/subscriptions","organizations_url":"https://api.github.com/users/home-assistant/orgs","repos_url":"https://api.github.com/users/home-assistant/repos","events_url":"https://api.github.com/users/home-assistant/events{/privacy}","received_events_url":"https://api.github.com/users/home-assistant/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/home-assistant/home-assistant","description":":house_with_garden: Open-source home automation platform running on Python 3","fork":false,"url":"https://api.github.com/repos/home-assistant/home-assistant","forks_url":"https://api.github.com/repos/home-assistant/home-assistant/forks","keys_url":"https://api.github.com/repos/home-assistant/home-assistant/keys{/key_id}","collaborators_url":"https://api.github.com/repos/home-assistant/home-assistant/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/home-assistant/home-assistant/teams","hooks_url":"https://api.github.com/repos/home-assistant/home-assistant/hooks","issue_events_url":"https://api.github.com/repos/home-assistant/home-assistant/issues/events{/number}","events_url":"https://api.github.com/repos/home-assistant/home-assistant/events","assignees_url":"https://api.github.com/repos/home-assistant/home-assistant/assignees{/user}","branches_url":"https://api.github.com/repos/home-assistant/home-assistant/branches{/branch}","tags_url":"https://api.github.com/repos/home-assistant/home-assistant/tags","blobs_url":"https://api.github.com/repos/home-assistant/home-assistant/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/home-assistant/home-assistant/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/home-assistant/home-assistant/git/refs{/sha}","trees_url":"https://api.github.com/repos/home-assistant/home-assistant/git/trees{/sha}","statuses_url":"https://api.github.com/repos/home-assistant/home-assistant/statuses/{sha}","languages_url":"https://api.github.com/repos/home-assistant/home-assistant/languages","stargazers_url":"https://api.github.com/repos/home-assistant/home-assistant/stargazers","contributors_url":"https://api.github.com/repos/home-assistant/home-assistant/contributors","subscribers_url":"https://api.github.com/repos/home-assistant/home-assistant/subscribers","subscription_url":"https://api.github.com/repos/home-assistant/home-assistant/subscription","commits_url":"https://api.github.com/repos/home-assistant/home-assistant/commits{/sha}","git_commits_url":"https://api.github.com/repos/home-assistant/home-assistant/git/commits{/sha}","comments_url":"https://api.github.com/repos/home-assistant/home-assistant/comments{/number}","issue_comment_url":"https://api.github.com/repos/home-assistant/home-assistant/issues/comments{/number}","contents_url":"https://api.github.com/repos/home-assistant/home-assistant/contents/{+path}","compare_url":"https://api.github.com/repos/home-assistant/home-assistant/compare/{base}...{head}","merges_url":"https://api.github.com/repos/home-assistant/home-assistant/merges","archive_url":"https://api.github.com/repos/home-assistant/home-assistant/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/home-assistant/home-assistant/downloads","issues_url":"https://api.github.com/repos/home-assistant/home-assistant/issues{/number}","pulls_url":"https://api.github.com/repos/home-assistant/home-assistant/pulls{/number}","milestones_url":"https://api.github.com/repos/home-assistant/home-assistant/milestones{/number}","notifications_url":"https://api.github.com/repos/home-assistant/home-assistant/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/home-assistant/home-assistant/labels{/name}","releases_url":"https://api.github.com/repos/home-assistant/home-assistant/releases{/id}","deployments_url":"https://api.github.com/repos/home-assistant/home-assistant/deployments","created_at":"2013-09-17T07:29:48Z","updated_at":"2017-04-20T14:17:34Z","pushed_at":"2017-04-20T15:44:34Z","git_url":"git://github.com/home-assistant/home-assistant.git","ssh_url":"git@github.com:home-assistant/home-assistant.git","clone_url":"https://github.com/home-assistant/home-assistant.git","svn_url":"https://github.com/home-assistant/home-assistant","homepage":"https://home-assistant.io","size":58291,"stargazers_count":6565,"watchers_count":6565,"language":"Python","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1926,"mirror_url":null,"open_issues_count":429,"forks":1926,"open_issues":429,"watchers":6565,"default_branch":"dev"}},"_links":{"self":{"href":"https://api.github.com/repos/home-assistant/home-assistant/pulls/7192"},"html":{"href":"https://github.com/home-assistant/home-assistant/pull/7192"},"issue":{"href":"https://api.github.com/repos/home-assistant/home-assistant/issues/7192"},"comments":{"href":"https://api.github.com/repos/home-assistant/home-assistant/issues/7192/comments"},"review_comments":{"href":"https://api.github.com/repos/home-assistant/home-assistant/pulls/7192/comments"},"review_comment":{"href":"https://api.github.com/repos/home-assistant/home-assistant/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/home-assistant/home-assistant/pulls/7192/commits"},"statuses":{"href":"https://api.github.com/repos/home-assistant/home-assistant/statuses/c7a95bbb0318993d298a7b73e8d68088d8a451ef"}}}}
{"actor":{"display_login":"balloob"}}