Add support for resource_template for rest sensor (#27869)

* add support for resource_template

* fix tests

* updated tests and xor(CONF_RESOURCE_TEMPLATE, CONF_RESOURCE)
This commit is contained in:
Fredrik Erlandsson 2019-10-23 07:43:28 +02:00 committed by Paulus Schoutsen
parent 4cb984842a
commit 09d8a4204a
3 changed files with 65 additions and 1 deletions

View file

@ -16,6 +16,7 @@ from homeassistant.const import (
CONF_PASSWORD,
CONF_PAYLOAD,
CONF_RESOURCE,
CONF_RESOURCE_TEMPLATE,
CONF_UNIT_OF_MEASUREMENT,
CONF_USERNAME,
CONF_TIMEOUT,
@ -42,7 +43,8 @@ METHODS = ["POST", "GET"]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_RESOURCE): cv.url,
vol.Exclusive(CONF_RESOURCE, CONF_RESOURCE): cv.url,
vol.Exclusive(CONF_RESOURCE_TEMPLATE, CONF_RESOURCE): cv.template,
vol.Optional(CONF_AUTHENTICATION): vol.In(
[HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION]
),
@ -62,11 +64,16 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
}
)
PLATFORM_SCHEMA = vol.All(
cv.has_at_least_one_key(CONF_RESOURCE, CONF_RESOURCE_TEMPLATE), PLATFORM_SCHEMA
)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the RESTful sensor."""
name = config.get(CONF_NAME)
resource = config.get(CONF_RESOURCE)
resource_template = config.get(CONF_RESOURCE_TEMPLATE)
method = config.get(CONF_METHOD)
payload = config.get(CONF_PAYLOAD)
verify_ssl = config.get(CONF_VERIFY_SSL)
@ -83,6 +90,10 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
if value_template is not None:
value_template.hass = hass
if resource_template is not None:
resource_template.hass = hass
resource = resource_template.render()
if username and password:
if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION:
auth = HTTPDigestAuth(username, password)
@ -108,6 +119,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
value_template,
json_attrs,
force_update,
resource_template,
)
],
True,
@ -127,6 +139,7 @@ class RestSensor(Entity):
value_template,
json_attrs,
force_update,
resource_template,
):
"""Initialize the REST sensor."""
self._hass = hass
@ -139,6 +152,7 @@ class RestSensor(Entity):
self._json_attrs = json_attrs
self._attributes = None
self._force_update = force_update
self._resource_template = resource_template
@property
def name(self):
@ -172,6 +186,9 @@ class RestSensor(Entity):
def update(self):
"""Get the latest data from REST API and update the state."""
if self._resource_template is not None:
self.rest.set_url(self._resource_template.render())
self.rest.update()
value = self.rest.data
@ -217,6 +234,10 @@ class RestData:
self._timeout = timeout
self.data = None
def set_url(self, url):
"""Set url."""
self._request.prepare_url(url, None)
def update(self):
"""Get the latest data from REST service with provided method."""
_LOGGER.debug("Updating from %s", self._request.url)

View file

@ -124,6 +124,7 @@ CONF_RECIPIENT = "recipient"
CONF_REGION = "region"
CONF_RESOURCE = "resource"
CONF_RESOURCES = "resources"
CONF_RESOURCE_TEMPLATE = "resource_template"
CONF_RGB = "rgb"
CONF_ROOM = "room"
CONF_SCAN_INTERVAL = "scan_interval"

View file

@ -76,6 +76,40 @@ class TestRestSensorSetup(unittest.TestCase):
)
assert 2 == mock_req.call_count
@requests_mock.Mocker()
def test_setup_minimum_resource_template(self, mock_req):
"""Test setup with minimum configuration (resource_template)."""
mock_req.get("http://localhost", status_code=200)
with assert_setup_component(1, "sensor"):
assert setup_component(
self.hass,
"sensor",
{
"sensor": {
"platform": "rest",
"resource_template": "http://localhost",
}
},
)
assert mock_req.call_count == 2
@requests_mock.Mocker()
def test_setup_duplicate_resource(self, mock_req):
"""Test setup with duplicate resources."""
mock_req.get("http://localhost", status_code=200)
with assert_setup_component(0, "sensor"):
assert setup_component(
self.hass,
"sensor",
{
"sensor": {
"platform": "rest",
"resource": "http://localhost",
"resource_template": "http://localhost",
}
},
)
@requests_mock.Mocker()
def test_setup_get(self, mock_req):
"""Test setup with valid configuration."""
@ -152,6 +186,7 @@ class TestRestSensor(unittest.TestCase):
self.value_template = template("{{ value_json.key }}")
self.value_template.hass = self.hass
self.force_update = False
self.resource_template = None
self.sensor = rest.RestSensor(
self.hass,
@ -162,6 +197,7 @@ class TestRestSensor(unittest.TestCase):
self.value_template,
[],
self.force_update,
self.resource_template,
)
def tearDown(self):
@ -222,6 +258,7 @@ class TestRestSensor(unittest.TestCase):
None,
[],
self.force_update,
self.resource_template,
)
self.sensor.update()
assert "plain_state" == self.sensor.state
@ -242,6 +279,7 @@ class TestRestSensor(unittest.TestCase):
None,
["key"],
self.force_update,
self.resource_template,
)
self.sensor.update()
assert "some_json_value" == self.sensor.device_state_attributes["key"]
@ -261,6 +299,7 @@ class TestRestSensor(unittest.TestCase):
None,
["key"],
self.force_update,
self.resource_template,
)
self.sensor.update()
assert {} == self.sensor.device_state_attributes
@ -282,6 +321,7 @@ class TestRestSensor(unittest.TestCase):
None,
["key"],
self.force_update,
self.resource_template,
)
self.sensor.update()
assert {} == self.sensor.device_state_attributes
@ -303,6 +343,7 @@ class TestRestSensor(unittest.TestCase):
None,
["key"],
self.force_update,
self.resource_template,
)
self.sensor.update()
assert {} == self.sensor.device_state_attributes
@ -326,6 +367,7 @@ class TestRestSensor(unittest.TestCase):
self.value_template,
["key"],
self.force_update,
self.resource_template,
)
self.sensor.update()