Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions homeassistant/components/emulated_hue/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .hue_api import (
HueAllGroupsStateView,
HueAllLightsStateView,
HueConfigView,
HueFullStateView,
HueGroupView,
HueOneLightChangeView,
Expand Down Expand Up @@ -119,6 +120,7 @@ async def async_setup(hass, yaml_config):
HueAllGroupsStateView(config).register(app, app.router)
HueGroupView(config).register(app, app.router)
HueFullStateView(config).register(app, app.router)
HueConfigView(config).register(app, app.router)

upnp_listener = UPNPResponderThread(
config.host_ip_addr,
Expand Down
33 changes: 33 additions & 0 deletions homeassistant/components/emulated_hue/hue_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,47 @@ def get(self, request, username):
"config": {
"mac": "00:00:00:00:00:00",
"swversion": "01003542",
"apiversion": "1.17.0",
"whitelist": {HUE_API_USERNAME: {"name": "HASS BRIDGE"}},
"ipaddress": f"{self.config.advertise_ip}:{self.config.advertise_port}",
"linkbutton": True,
},
}

return self.json(json_response)


class HueConfigView(HomeAssistantView):
"""Return config view of emulated hue."""

url = "/api/{username}/config"
name = "emulated_hue:username:config"
requires_auth = False

def __init__(self, config):
"""Initialize the instance of the view."""
self.config = config

@core.callback
def get(self, request, username):
"""Process a request to get the configuration."""
if not is_local(request[KEY_REAL_IP]):
return self.json_message("only local IPs allowed", HTTP_UNAUTHORIZED)
if username != HUE_API_USERNAME:
return self.json(UNAUTHORIZED_USER)

json_response = {
"mac": "00:00:00:00:00:00",
"swversion": "01003542",
"apiversion": "1.17.0",
"whitelist": {HUE_API_USERNAME: {"name": "HASS BRIDGE"}},
"ipaddress": f"{self.config.advertise_ip}:{self.config.advertise_port}",
Comment thread
bdraco marked this conversation as resolved.
"linkbutton": True,
}

return self.json(json_response)


class HueOneLightStateView(HomeAssistantView):
"""Handle requests for getting info about a single entity."""

Expand Down
13 changes: 7 additions & 6 deletions homeassistant/components/emulated_hue/upnp.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def get(self, request):
<modelName>Philips hue bridge 2015</modelName>
<modelNumber>BSB002</modelNumber>
<modelURL>http://www.meethue.com</modelURL>
<serialNumber>1234</serialNumber>
<serialNumber>001788FFFE23BFC2</serialNumber>
<UDN>uuid:2f402f80-da50-11e1-9b23-001788255acc</UDN>
</device>
</root>
Expand Down Expand Up @@ -74,13 +74,14 @@ def __init__(
# Note that the double newline at the end of
# this string is required per the SSDP spec
resp_template = f"""HTTP/1.1 200 OK
CACHE-CONTROL: max-age=60
HOST: 239.255.255.250:1900
Comment thread
bdraco marked this conversation as resolved.
Outdated
EXT:
CACHE-CONTROL: max-age=60
LOCATION: http://{advertise_ip}:{advertise_port}/description.xml
SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/0.1
hue-bridgeid: 1234
ST: urn:schemas-upnp-org:device:basic:1
USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1
SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.16.0
hue-bridgeid: 001788FFFE23BFC2
ST: upnp:rootdevice
USN: uuid:2f402f80-da50-11e1-9b23-00178829d301::upnp:rootdevice

"""

Expand Down
51 changes: 50 additions & 1 deletion tests/components/emulated_hue/test_hue_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
HUE_API_USERNAME,
HueAllGroupsStateView,
HueAllLightsStateView,
HueConfigView,
HueFullStateView,
HueOneLightChangeView,
HueOneLightStateView,
Expand Down Expand Up @@ -169,6 +170,7 @@ def hue_client(loop, hass_hue, aiohttp_client):
HueOneLightChangeView(config).register(web_app, web_app.router)
HueAllGroupsStateView(config).register(web_app, web_app.router)
HueFullStateView(config).register(web_app, web_app.router)
HueConfigView(config).register(web_app, web_app.router)

return loop.run_until_complete(aiohttp_client(web_app))

Expand Down Expand Up @@ -308,7 +310,7 @@ async def test_discover_full_state(hue_client):

# Make sure array is correct size
assert len(result_json) == 2
assert len(config_json) == 4
assert len(config_json) == 6
assert len(lights_json) >= 1

# Make sure the config wrapper added to the config is there
Expand All @@ -319,6 +321,49 @@ async def test_discover_full_state(hue_client):
assert "swversion" in config_json
assert "01003542" in config_json["swversion"]

# Make sure the api version is correct
assert "apiversion" in config_json
assert "1.17.0" in config_json["apiversion"]

# Make sure the correct username in config
assert "whitelist" in config_json
assert HUE_API_USERNAME in config_json["whitelist"]
assert "name" in config_json["whitelist"][HUE_API_USERNAME]
assert "HASS BRIDGE" in config_json["whitelist"][HUE_API_USERNAME]["name"]

# Make sure the correct ip in config
assert "ipaddress" in config_json
assert "127.0.0.1:8300" in config_json["ipaddress"]

# Make sure the device announces a link button
assert "linkbutton" in config_json
assert config_json["linkbutton"] is True


async def test_discover_config(hue_client):
"""Test the discovery of configuration."""
result = await hue_client.get(f"/api/{HUE_API_USERNAME}/config")

assert result.status == 200
assert "application/json" in result.headers["content-type"]

config_json = await result.json()

# Make sure array is correct size
assert len(config_json) == 6

# Make sure the config wrapper added to the config is there
assert "mac" in config_json
assert "00:00:00:00:00:00" in config_json["mac"]

# Make sure the correct version in config
assert "swversion" in config_json
assert "01003542" in config_json["swversion"]

# Make sure the api version is correct
assert "apiversion" in config_json
assert "1.17.0" in config_json["apiversion"]

# Make sure the correct username in config
assert "whitelist" in config_json
assert HUE_API_USERNAME in config_json["whitelist"]
Expand All @@ -329,6 +374,10 @@ async def test_discover_full_state(hue_client):
assert "ipaddress" in config_json
assert "127.0.0.1:8300" in config_json["ipaddress"]

# Make sure the device announces a link button
assert "linkbutton" in config_json
assert config_json["linkbutton"] is True


async def test_get_light_state(hass_hue, hue_client):
"""Test the getting of light state."""
Expand Down
4 changes: 3 additions & 1 deletion tests/components/emulated_hue/test_upnp.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ def test_description_xml(self):

# Make sure the XML is parsable
try:
ET.fromstring(result.text)
root = ET.fromstring(result.text)
ns = {"s": "urn:schemas-upnp-org:device-1-0"}
assert root.find("./s:device/s:serialNumber", ns).text == "001788FFFE23BFC2"
except: # noqa: E722 pylint: disable=bare-except
self.fail("description.xml is not valid XML!")

Expand Down