From 610b329682c81782e23e906f9f30c33ecfb15546 Mon Sep 17 00:00:00 2001 From: Mohamad Date: Sun, 8 Apr 2018 14:03:54 -0400 Subject: [PATCH 1/8] Adding USCIS component --- .coveragerc | 1 + homeassistant/components/sensor/uscis.py | 115 +++++++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 119 insertions(+) create mode 100644 homeassistant/components/sensor/uscis.py diff --git a/.coveragerc b/.coveragerc index e9c69d137e2a09..3d951e9e2549f8 100644 --- a/.coveragerc +++ b/.coveragerc @@ -669,6 +669,7 @@ omit = homeassistant/components/sensor/uber.py homeassistant/components/sensor/upnp.py homeassistant/components/sensor/ups.py + homeassistant/components/sensor/uscis.py homeassistant/components/sensor/vasttrafik.py homeassistant/components/sensor/viaggiatreno.py homeassistant/components/sensor/waqi.py diff --git a/homeassistant/components/sensor/uscis.py b/homeassistant/components/sensor/uscis.py new file mode 100644 index 00000000000000..ad7e82b0e62f97 --- /dev/null +++ b/homeassistant/components/sensor/uscis.py @@ -0,0 +1,115 @@ +""" +Support for USCIS Case Status. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.uscis/ +""" + +import logging +from datetime import timedelta +import voluptuous as vol + +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.helpers import config_validation as cv +from homeassistant.const import CONF_FRIENDLY_NAME + + +_LOGGER = logging.getLogger(__name__) + +REQUIREMENTS = ['lxml==3.5.0'] + +DEFAULT_NAME = "USCIS" + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_FRIENDLY_NAME, default=DEFAULT_NAME): cv.string, + vol.Required('case_id'): cv.string, +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setting the platform in HASS and Case Information.""" + uscis = UscisSensor(config['case_id'], config[CONF_FRIENDLY_NAME]) + uscis.update() + if uscis.valid_case_id: + add_devices([uscis]) + else: + _LOGGER.error("Setup USCIS Sensor Fail" + " check if your Case ID is Valid") + return + + +class UscisSensor(Entity): + """USCIS Sensor will check case status on daily basis.""" + HOURS_TO_UPDATE = timedelta(hours=24) + + CURRENT_STATUS = "current_status" + LAST_CASE_UPDATE = "last_update_date" + CASE_DATE_PATTERN = r"[(A-Za-z)]*\s[\d]*,\s[\d]*" + URL = "https://egov.uscis.gov/casestatus/mycasestatus.do" + APP_RECEIPT_NUM = "appReceiptNum" + INIT_CASE_SEARCH = "initCaseSearch" + CASE_STATUS = "CHECK STATUS" + UPDATE_TEXT_XPATH = "/html/body/div[2]/form/div/div[1]" \ + "/div/div/div[2]/div[3]/p/text()" + USCIS_WEBSITE = "http://egov.uscis.gov/" + MISSING_URL_PATTEN = "','|', '" + TEXT_FILTER_PATTERN = r"['\[\]]" + + def __init__(self, case, name): + """Initialize the sensor.""" + self._state = None + self._case_id = case + self._attributes = None + self.valid_case_id = None + self._name = name + + @property + def name(self): + """Return the name.""" + return self._name + + @property + def state(self): + """Return the state.""" + return self._state + + @property + def device_state_attributes(self): + """Return the state attributes.""" + return self._attributes + + @Throttle(HOURS_TO_UPDATE) + def update(self): + """Using Request to access USCIS website and fetch data.""" + import requests + import re + from datetime import datetime + from lxml import html + + data = {self.APP_RECEIPT_NUM: self._case_id, + self.INIT_CASE_SEARCH: self.CASE_STATUS} + request = requests.post(self.URL, data=data) + + content = html.fromstring(request.content) + text = str(content.xpath(self.UPDATE_TEXT_XPATH)) + if len(text) > 2: + text = str(re.sub("','|', '", 'USCIS website', text)) + status_message = re.sub(r"['\[\]]", ' ', text) + p_search = re.search(self.CASE_DATE_PATTERN, status_message) + match = p_search.group(0) + + last_update_date = datetime.strptime(str(match), "%B %d, %Y") + last_update_date = last_update_date.strftime('%m/%d/%Y') + + self._attributes = { + self.CURRENT_STATUS: status_message, + self.LAST_CASE_UPDATE: last_update_date + } + self._state = last_update_date + self.valid_case_id = True + + else: + self.valid_case_id = False + _LOGGER.error("Invalid Case Id for USCIS") diff --git a/requirements_all.txt b/requirements_all.txt index 532c723365b0f5..f927972a7ca7ad 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -495,6 +495,9 @@ locationsharinglib==0.4.0 # homeassistant.components.sensor.luftdaten luftdaten==0.1.3 +# homeassistant.components.sensor.uscis +lxml==3.5.0 + # homeassistant.components.sensor.lyft lyft_rides==0.2 From b4d376cf772f9a1da6745a3e4351d54f30f5916a Mon Sep 17 00:00:00 2001 From: Mohamad Date: Sun, 8 Apr 2018 14:26:51 -0400 Subject: [PATCH 2/8] Adding Line after the class DOC --- homeassistant/components/sensor/uscis.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/sensor/uscis.py b/homeassistant/components/sensor/uscis.py index ad7e82b0e62f97..5e275ea516fba7 100644 --- a/homeassistant/components/sensor/uscis.py +++ b/homeassistant/components/sensor/uscis.py @@ -42,6 +42,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class UscisSensor(Entity): """USCIS Sensor will check case status on daily basis.""" + HOURS_TO_UPDATE = timedelta(hours=24) CURRENT_STATUS = "current_status" From 1ef3fb25ac283a23699779c20bebb7b313b57e7a Mon Sep 17 00:00:00 2001 From: Mohamad Date: Mon, 9 Apr 2018 01:10:02 -0400 Subject: [PATCH 3/8] Update : Extract USCIS logic code to Component --- homeassistant/components/sensor/uscis.py | 56 +++++------------------- requirements_all.txt | 6 +-- 2 files changed, 15 insertions(+), 47 deletions(-) diff --git a/homeassistant/components/sensor/uscis.py b/homeassistant/components/sensor/uscis.py index 5e275ea516fba7..cf538a051fc5e5 100644 --- a/homeassistant/components/sensor/uscis.py +++ b/homeassistant/components/sensor/uscis.py @@ -18,7 +18,7 @@ _LOGGER = logging.getLogger(__name__) -REQUIREMENTS = ['lxml==3.5.0'] +REQUIREMENTS = ['uscisstatus==0.1'] DEFAULT_NAME = "USCIS" @@ -45,19 +45,6 @@ class UscisSensor(Entity): HOURS_TO_UPDATE = timedelta(hours=24) - CURRENT_STATUS = "current_status" - LAST_CASE_UPDATE = "last_update_date" - CASE_DATE_PATTERN = r"[(A-Za-z)]*\s[\d]*,\s[\d]*" - URL = "https://egov.uscis.gov/casestatus/mycasestatus.do" - APP_RECEIPT_NUM = "appReceiptNum" - INIT_CASE_SEARCH = "initCaseSearch" - CASE_STATUS = "CHECK STATUS" - UPDATE_TEXT_XPATH = "/html/body/div[2]/form/div/div[1]" \ - "/div/div/div[2]/div[3]/p/text()" - USCIS_WEBSITE = "http://egov.uscis.gov/" - MISSING_URL_PATTEN = "','|', '" - TEXT_FILTER_PATTERN = r"['\[\]]" - def __init__(self, case, name): """Initialize the sensor.""" self._state = None @@ -84,33 +71,14 @@ def device_state_attributes(self): @Throttle(HOURS_TO_UPDATE) def update(self): """Using Request to access USCIS website and fetch data.""" - import requests - import re - from datetime import datetime - from lxml import html - - data = {self.APP_RECEIPT_NUM: self._case_id, - self.INIT_CASE_SEARCH: self.CASE_STATUS} - request = requests.post(self.URL, data=data) - - content = html.fromstring(request.content) - text = str(content.xpath(self.UPDATE_TEXT_XPATH)) - if len(text) > 2: - text = str(re.sub("','|', '", 'USCIS website', text)) - status_message = re.sub(r"['\[\]]", ' ', text) - p_search = re.search(self.CASE_DATE_PATTERN, status_message) - match = p_search.group(0) - - last_update_date = datetime.strptime(str(match), "%B %d, %Y") - last_update_date = last_update_date.strftime('%m/%d/%Y') - - self._attributes = { - self.CURRENT_STATUS: status_message, - self.LAST_CASE_UPDATE: last_update_date - } - self._state = last_update_date - self.valid_case_id = True - - else: - self.valid_case_id = False - _LOGGER.error("Invalid Case Id for USCIS") + import uscisstatus + try: + status, date = uscisstatus.get_case_status(self._case_id) + except Exception: + _LOGGER("Please check you provide valid case id") + self._attributes = { + self.CURRENT_STATUS: status, + self.LAST_CASE_UPDATE: date + } + self._state = date + self.valid_case_id = True diff --git a/requirements_all.txt b/requirements_all.txt index f927972a7ca7ad..2a949e7a6c6109 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -495,9 +495,6 @@ locationsharinglib==0.4.0 # homeassistant.components.sensor.luftdaten luftdaten==0.1.3 -# homeassistant.components.sensor.uscis -lxml==3.5.0 - # homeassistant.components.sensor.lyft lyft_rides==0.2 @@ -1265,6 +1262,9 @@ upcloud-api==0.4.2 # homeassistant.components.sensor.ups upsmychoice==1.0.6 +# homeassistant.components.sensor.uscis +uscisstatus==0.1 + # homeassistant.components.camera.uvc uvcclient==0.10.1 From edf34b496a4a308b4bb4f8de96e662a70264bdb3 Mon Sep 17 00:00:00 2001 From: Mohamad Date: Mon, 9 Apr 2018 01:11:04 -0400 Subject: [PATCH 4/8] Update : Extract USCIS logic code to Component --- homeassistant/components/sensor/uscis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/uscis.py b/homeassistant/components/sensor/uscis.py index cf538a051fc5e5..32b35b9696305f 100644 --- a/homeassistant/components/sensor/uscis.py +++ b/homeassistant/components/sensor/uscis.py @@ -75,7 +75,7 @@ def update(self): try: status, date = uscisstatus.get_case_status(self._case_id) except Exception: - _LOGGER("Please check you provide valid case id") + _LOGGER("Please Check that you have valid USCIS case id") self._attributes = { self.CURRENT_STATUS: status, self.LAST_CASE_UPDATE: date From a01695e5f662cf922fddb26833b62b6f2b9fdc65 Mon Sep 17 00:00:00 2001 From: Mohamad Date: Mon, 9 Apr 2018 01:42:30 -0400 Subject: [PATCH 5/8] Adding CURRENT_STATUS --- homeassistant/components/sensor/uscis.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/sensor/uscis.py b/homeassistant/components/sensor/uscis.py index 32b35b9696305f..f9c5626f121f3b 100644 --- a/homeassistant/components/sensor/uscis.py +++ b/homeassistant/components/sensor/uscis.py @@ -45,6 +45,9 @@ class UscisSensor(Entity): HOURS_TO_UPDATE = timedelta(hours=24) + CURRENT_STATUS = "current_status" + LAST_CASE_UPDATE = "last_update_date" + def __init__(self, case, name): """Initialize the sensor.""" self._state = None @@ -74,11 +77,13 @@ def update(self): import uscisstatus try: status, date = uscisstatus.get_case_status(self._case_id) + self._attributes = { + self.CURRENT_STATUS: status, + self.LAST_CASE_UPDATE: date + } + self._state = date + self.valid_case_id = True + except Exception: _LOGGER("Please Check that you have valid USCIS case id") - self._attributes = { - self.CURRENT_STATUS: status, - self.LAST_CASE_UPDATE: date - } - self._state = date - self.valid_case_id = True + self.valid_case_id = False From 74d077e85015875ebfa2f38ae529393a60d02fe2 Mon Sep 17 00:00:00 2001 From: Mohamad Date: Mon, 9 Apr 2018 18:07:48 -0400 Subject: [PATCH 6/8] Change Error handling, remove date from attributes --- homeassistant/components/sensor/uscis.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/sensor/uscis.py b/homeassistant/components/sensor/uscis.py index f9c5626f121f3b..5fbc63c0da4784 100644 --- a/homeassistant/components/sensor/uscis.py +++ b/homeassistant/components/sensor/uscis.py @@ -37,7 +37,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): else: _LOGGER.error("Setup USCIS Sensor Fail" " check if your Case ID is Valid") - return class UscisSensor(Entity): @@ -76,14 +75,13 @@ def update(self): """Using Request to access USCIS website and fetch data.""" import uscisstatus try: - status, date = uscisstatus.get_case_status(self._case_id) + status = uscisstatus.get_case_status(self._case_id) self._attributes = { - self.CURRENT_STATUS: status, - self.LAST_CASE_UPDATE: date + self.CURRENT_STATUS: status['status'] } - self._state = date + self._state = status['date'] self.valid_case_id = True - except Exception: + except ValueError: _LOGGER("Please Check that you have valid USCIS case id") self.valid_case_id = False From 5199964833df8fbd8509f5e70c2e12ac0bd8363d Mon Sep 17 00:00:00 2001 From: Mohamad Date: Mon, 9 Apr 2018 18:33:38 -0400 Subject: [PATCH 7/8] Update the Version for USCIS --- homeassistant/components/sensor/uscis.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/uscis.py b/homeassistant/components/sensor/uscis.py index 5fbc63c0da4784..53dd90c6e2d5ca 100644 --- a/homeassistant/components/sensor/uscis.py +++ b/homeassistant/components/sensor/uscis.py @@ -18,7 +18,7 @@ _LOGGER = logging.getLogger(__name__) -REQUIREMENTS = ['uscisstatus==0.1'] +REQUIREMENTS = ['uscisstatus==0.1.1'] DEFAULT_NAME = "USCIS" diff --git a/requirements_all.txt b/requirements_all.txt index 2a949e7a6c6109..2e6354f9901f26 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1263,7 +1263,7 @@ upcloud-api==0.4.2 upsmychoice==1.0.6 # homeassistant.components.sensor.uscis -uscisstatus==0.1 +uscisstatus==0.1.1 # homeassistant.components.camera.uvc uvcclient==0.10.1 From ee480aae85d523e7ec67990017ca19181f239f27 Mon Sep 17 00:00:00 2001 From: Mohamad Tarbin Date: Tue, 10 Apr 2018 20:03:21 -0400 Subject: [PATCH 8/8] Update uscis.py --- homeassistant/components/sensor/uscis.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/uscis.py b/homeassistant/components/sensor/uscis.py index 53dd90c6e2d5ca..ed3c9ca8587557 100644 --- a/homeassistant/components/sensor/uscis.py +++ b/homeassistant/components/sensor/uscis.py @@ -42,7 +42,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class UscisSensor(Entity): """USCIS Sensor will check case status on daily basis.""" - HOURS_TO_UPDATE = timedelta(hours=24) + MIN_TIME_BETWEEN_UPDATES = timedelta(hours=24) CURRENT_STATUS = "current_status" LAST_CASE_UPDATE = "last_update_date" @@ -70,7 +70,7 @@ def device_state_attributes(self): """Return the state attributes.""" return self._attributes - @Throttle(HOURS_TO_UPDATE) + @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Using Request to access USCIS website and fetch data.""" import uscisstatus