Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed sensor issue with Google Wifi routers in bridge mode #8710

Merged
merged 2 commits into from Jul 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
85 changes: 48 additions & 37 deletions homeassistant/components/sensor/google_wifi.py
Expand Up @@ -37,32 +37,32 @@

MONITORED_CONDITIONS = {
ATTR_CURRENT_VERSION: [
'Current Version',
['software', 'softwareVersion'],
None,
'mdi:checkbox-marked-circle-outline'
],
ATTR_NEW_VERSION: [
'New Version',
['software', 'updateNewVersion'],
None,
'mdi:update'
],
ATTR_UPTIME: [
'Uptime',
['system', 'uptime'],
'days',
'mdi:timelapse'
],
ATTR_LAST_RESTART: [
'Last Network Restart',
['system', 'uptime'],
None,
'mdi:restart'
],
ATTR_LOCAL_IP: [
'Local IP Address',
['wan', 'localIpAddress'],
None,
'mdi:access-point-network'
],
ATTR_STATUS: [
'Status',
['wan', 'online'],
None,
'mdi:google'
]
Expand All @@ -80,13 +80,14 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Google Wifi sensor."""
name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
conditions = config.get(CONF_MONITORED_CONDITIONS)

api = GoogleWifiAPI(host)
api = GoogleWifiAPI(host, conditions)
dev = []
for condition in conditions:
dev.append(GoogleWifiSensor(hass, api, name, condition))

sensors = [GoogleWifiSensor(hass, api, name, condition)
for condition in config[CONF_MONITORED_CONDITIONS]]

add_devices(sensors, True)
add_devices(dev, True)


class GoogleWifiSensor(Entity):
Expand Down Expand Up @@ -141,13 +142,13 @@ def update(self):
class GoogleWifiAPI(object):
"""Get the latest data and update the states."""

def __init__(self, host):
def __init__(self, host, conditions):
"""Initialize the data object."""
uri = 'http://'
resource = "{}{}{}".format(uri, host, ENDPOINT)

self._request = requests.Request('GET', resource).prepare()
self.raw_data = None
self.conditions = conditions
self.data = {
ATTR_CURRENT_VERSION: STATE_UNKNOWN,
ATTR_NEW_VERSION: STATE_UNKNOWN,
Expand All @@ -163,39 +164,49 @@ def __init__(self, host):
def update(self):
"""Get the latest data from the router."""
try:
_LOGGER.error("Before request")
with requests.Session() as sess:
response = sess.send(
self._request, timeout=10)
self.raw_data = response.json()
_LOGGER.error(self.raw_data)
self.data_format()
self.availiable = True
except ValueError:
_LOGGER.error("Unable to fetch data from Google Wifi")
_LOGGER.error('Unable to fetch data from Google Wifi')
self.availiable = False
self.raw_data = None

def data_format(self):
"""Format raw data into easily accessible dict."""
for key, value in self.raw_data.items():
if key == 'software':
self.data[ATTR_CURRENT_VERSION] = value['softwareVersion']
if value['updateNewVersion'] == '0.0.0.0':
self.data[ATTR_NEW_VERSION] = 'Latest'
else:
self.data[ATTR_NEW_VERSION] = value['updateNewVersion']
elif key == 'system':
self.data[ATTR_UPTIME] = value['uptime'] / (3600 * 24)
last_restart = dt.now() - timedelta(seconds=value['uptime'])
self.data[ATTR_LAST_RESTART] = \
last_restart.strftime("%Y-%m-%d %H:%M:%S")
elif key == 'wan':
if value['online']:
self.data[ATTR_STATUS] = 'Online'
else:
self.data[ATTR_STATUS] = 'Offline'
if not value['ipAddress']:
self.data[ATTR_LOCAL_IP] = STATE_UNKNOWN
else:
self.data[ATTR_LOCAL_IP] = value['localIpAddress']
for attr_key in self.conditions:
value = MONITORED_CONDITIONS[attr_key]
try:
primary_key = value[0][0]
sensor_key = value[0][1]
if primary_key in self.raw_data:
sensor_value = self.raw_data[primary_key][sensor_key]
# Format sensor for better readability
if (attr_key == ATTR_NEW_VERSION and
sensor_value == '0.0.0.0'):
sensor_value = 'Latest'
elif attr_key == ATTR_UPTIME:
sensor_value /= 3600 * 24
elif attr_key == ATTR_LAST_RESTART:
last_restart = (dt.now() -
timedelta(seconds=sensor_value))
sensor_value = last_restart.strftime(('%Y-%m-%d '
'%H:%M:%S'))
elif attr_key == ATTR_STATUS:
if sensor_value:
sensor_value = 'Online'
else:
sensor_value = 'Offline'
elif attr_key == ATTR_LOCAL_IP:
if not self.raw_data['wan']['online']:
sensor_value = STATE_UNKNOWN

self.data[attr_key] = sensor_value
except KeyError:
_LOGGER.error('Router does not support %s field. '
'Please remove %s from monitored_conditions.',
sensor_key, attr_key)
self.data[attr_key] = STATE_UNKNOWN
24 changes: 22 additions & 2 deletions tests/components/sensor/test_google_wifi.py
Expand Up @@ -26,6 +26,10 @@
'"wan": {"localIpAddress":"next", "online":false,'
'"ipAddress":false}}')

MOCK_DATA_MISSING = ('{"software": {},'
'"system": {},'
'"wan": {}}')


class TestGoogleWifiSetup(unittest.TestCase):
"""Tests for setting up the Google Wifi switch platform."""
Expand All @@ -47,9 +51,11 @@ def test_setup_minimum(self, mock_req):
mock_req.get(resource, status_code=200)
self.assertTrue(setup_component(self.hass, 'sensor', {
'sensor': {
'platform': 'google_wifi'
'platform': 'google_wifi',
'monitored_conditions': ['uptime']
}
}))
assert_setup_component(1, 'sensor')

@requests_mock.Mocker()
def test_setup_get(self, mock_req):
Expand Down Expand Up @@ -95,7 +101,9 @@ def setup_api(self, data, mock_req):
now = datetime(1970, month=1, day=1)
with patch('homeassistant.util.dt.now', return_value=now):
mock_req.get(resource, text=data, status_code=200)
self.api = google_wifi.GoogleWifiAPI("localhost")
conditions = google_wifi.MONITORED_CONDITIONS.keys()
self.api = google_wifi.GoogleWifiAPI("localhost",
conditions)
self.name = NAME
self.sensor_dict = dict()
for condition, cond_list in google_wifi.MONITORED_CONDITIONS.items():
Expand Down Expand Up @@ -188,6 +196,18 @@ def test_update_when_value_changed(self, mock_req):
else:
self.assertEqual('next', sensor.state)

@requests_mock.Mocker()
def test_when_api_data_missing(self, mock_req):
"""Test state logs an error when data is missing."""
self.setup_api(MOCK_DATA_MISSING, mock_req)
now = datetime(1970, month=1, day=1)
with patch('homeassistant.util.dt.now', return_value=now):
for name in self.sensor_dict:
sensor = self.sensor_dict[name]['sensor']
self.fake_delay(2)
sensor.update()
self.assertEqual(STATE_UNKNOWN, sensor.state)

def test_update_when_unavailiable(self):
"""Test state updates when Google Wifi unavailiable."""
self.api.update = Mock('google_wifi.GoogleWifiAPI.update',
Expand Down