Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions homeassistant/components/microsoft_face.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
DOMAIN = 'microsoft_face'
DEPENDENCIES = ['camera']

FACE_API_URL = "https://westus.api.cognitive.microsoft.com/face/v1.0/{0}"
FACE_API_URL = "api.cognitive.microsoft.com/face/v1.0/{0}"

DATA_MICROSOFT_FACE = 'microsoft_face'

CONF_AZURE_REGION = 'azure_region'

SERVICE_CREATE_GROUP = 'create_group'
SERVICE_DELETE_GROUP = 'delete_group'
SERVICE_TRAIN_GROUP = 'train_group'
Expand All @@ -49,6 +51,7 @@
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_API_KEY): cv.string,
vol.Optional(CONF_AZURE_REGION, default="westus"): cv.string,
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
}),
}, extra=vol.ALLOW_EXTRA)
Expand Down Expand Up @@ -115,6 +118,7 @@ def async_setup(hass, config):
entities = {}
face = MicrosoftFace(
hass,
config[DOMAIN].get(CONF_AZURE_REGION),
config[DOMAIN].get(CONF_API_KEY),
config[DOMAIN].get(CONF_TIMEOUT),
entities
Expand Down Expand Up @@ -304,12 +308,13 @@ def device_state_attributes(self):
class MicrosoftFace(object):
"""Microsoft Face api for HomeAssistant."""

def __init__(self, hass, api_key, timeout, entities):
def __init__(self, hass, server_loc, api_key, timeout, entities):
"""Initialize Microsoft Face api."""
self.hass = hass
self.websession = async_get_clientsession(hass)
self.timeout = timeout
self._api_key = api_key
self._server_url = "https://{0}.{1}".format(server_loc, FACE_API_URL)
self._store = {}
self._entities = entities

Expand Down Expand Up @@ -346,7 +351,7 @@ def call_api(self, method, function, data=None, binary=False,
params=None):
"""Make a api call."""
headers = {"Ocp-Apim-Subscription-Key": self._api_key}
url = FACE_API_URL.format(function)
url = self._server_url.format(function)

payload = None
if binary:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ def setup_method(self):
}
}

self.endpoint_url = "https://westus.{0}".format(mf.FACE_API_URL)

def teardown_method(self):
"""Stop everything that was started."""
self.hass.stop()
Expand All @@ -108,15 +110,15 @@ def teardown_method(self):
def test_ms_detect_process_image(self, poll_mock, aioclient_mock):
"""Setup and scan a picture and test plates from event."""
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups"),
self.endpoint_url.format("persongroups"),
text=load_fixture('microsoft_face_persongroups.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group1/persons"),
self.endpoint_url.format("persongroups/test_group1/persons"),
text=load_fixture('microsoft_face_persons.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group2/persons"),
self.endpoint_url.format("persongroups/test_group2/persons"),
text=load_fixture('microsoft_face_persons.json')
)

Expand All @@ -139,7 +141,7 @@ def mock_face_event(event):
aioclient_mock.get(url, content=b'image')

aioclient_mock.post(
mf.FACE_API_URL.format("detect"),
self.endpoint_url.format("detect"),
text=load_fixture('microsoft_face_detect.json'),
params={'returnFaceAttributes': "age,gender"}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ def setup_method(self):
}
}

self.endpoint_url = "https://westus.{0}".format(mf.FACE_API_URL)

def teardown_method(self):
"""Stop everything that was started."""
self.hass.stop()
Expand All @@ -109,15 +111,15 @@ def teardown_method(self):
def test_ms_identify_process_image(self, poll_mock, aioclient_mock):
"""Setup and scan a picture and test plates from event."""
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups"),
self.endpoint_url.format("persongroups"),
text=load_fixture('microsoft_face_persongroups.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group1/persons"),
self.endpoint_url.format("persongroups/test_group1/persons"),
text=load_fixture('microsoft_face_persons.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group2/persons"),
self.endpoint_url.format("persongroups/test_group2/persons"),
text=load_fixture('microsoft_face_persons.json')
)

Expand All @@ -140,11 +142,11 @@ def mock_face_event(event):
aioclient_mock.get(url, content=b'image')

aioclient_mock.post(
mf.FACE_API_URL.format("detect"),
self.endpoint_url.format("detect"),
text=load_fixture('microsoft_face_detect.json')
)
aioclient_mock.post(
mf.FACE_API_URL.format("identify"),
self.endpoint_url.format("identify"),
text=load_fixture('microsoft_face_identify.json')
)

Expand Down
54 changes: 28 additions & 26 deletions tests/components/test_microsoft_face.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ def setup_method(self):
}
}

self.endpoint_url = "https://westus.{0}".format(mf.FACE_API_URL)

def teardown_method(self):
"""Stop everything that was started."""
self.hass.stop()
Expand All @@ -30,7 +32,7 @@ def teardown_method(self):
'MicrosoftFace.update_store', return_value=mock_coro())
def test_setup_component(self, mock_update):
"""Setup component."""
with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

@patch('homeassistant.components.microsoft_face.'
Expand All @@ -44,7 +46,7 @@ def test_setup_component_wrong_api_key(self, mock_update):
'MicrosoftFace.update_store', return_value=mock_coro())
def test_setup_component_test_service(self, mock_update):
"""Setup component."""
with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

assert self.hass.services.has_service(mf.DOMAIN, 'create_group')
Expand All @@ -57,19 +59,19 @@ def test_setup_component_test_service(self, mock_update):
def test_setup_component_test_entities(self, aioclient_mock):
"""Setup component."""
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups"),
self.endpoint_url.format("persongroups"),
text=load_fixture('microsoft_face_persongroups.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group1/persons"),
self.endpoint_url.format("persongroups/test_group1/persons"),
text=load_fixture('microsoft_face_persons.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group2/persons"),
self.endpoint_url.format("persongroups/test_group2/persons"),
text=load_fixture('microsoft_face_persons.json')
)

with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

assert len(aioclient_mock.mock_calls) == 3
Expand All @@ -95,15 +97,15 @@ def test_setup_component_test_entities(self, aioclient_mock):
def test_service_groups(self, mock_update, aioclient_mock):
"""Setup component, test groups services."""
aioclient_mock.put(
mf.FACE_API_URL.format("persongroups/service_group"),
self.endpoint_url.format("persongroups/service_group"),
status=200, text="{}"
)
aioclient_mock.delete(
mf.FACE_API_URL.format("persongroups/service_group"),
self.endpoint_url.format("persongroups/service_group"),
status=200, text="{}"
)

with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

mf.create_group(self.hass, 'Service Group')
Expand All @@ -123,29 +125,29 @@ def test_service_groups(self, mock_update, aioclient_mock):
def test_service_person(self, aioclient_mock):
"""Setup component, test person services."""
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups"),
self.endpoint_url.format("persongroups"),
text=load_fixture('microsoft_face_persongroups.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group1/persons"),
self.endpoint_url.format("persongroups/test_group1/persons"),
text=load_fixture('microsoft_face_persons.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group2/persons"),
self.endpoint_url.format("persongroups/test_group2/persons"),
text=load_fixture('microsoft_face_persons.json')
)

with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

assert len(aioclient_mock.mock_calls) == 3

aioclient_mock.post(
mf.FACE_API_URL.format("persongroups/test_group1/persons"),
self.endpoint_url.format("persongroups/test_group1/persons"),
text=load_fixture('microsoft_face_create_person.json')
)
aioclient_mock.delete(
mf.FACE_API_URL.format(
self.endpoint_url.format(
"persongroups/test_group1/persons/"
"25985303-c537-4467-b41d-bdb45cd95ca1"),
status=200, text="{}"
Expand Down Expand Up @@ -174,11 +176,11 @@ def test_service_person(self, aioclient_mock):
'MicrosoftFace.update_store', return_value=mock_coro())
def test_service_train(self, mock_update, aioclient_mock):
"""Setup component, test train groups services."""
with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

aioclient_mock.post(
mf.FACE_API_URL.format("persongroups/service_group/train"),
self.endpoint_url.format("persongroups/service_group/train"),
status=200, text="{}"
)

Expand All @@ -192,26 +194,26 @@ def test_service_train(self, mock_update, aioclient_mock):
def test_service_face(self, camera_mock, aioclient_mock):
"""Setup component, test person face services."""
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups"),
self.endpoint_url.format("persongroups"),
text=load_fixture('microsoft_face_persongroups.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group1/persons"),
self.endpoint_url.format("persongroups/test_group1/persons"),
text=load_fixture('microsoft_face_persons.json')
)
aioclient_mock.get(
mf.FACE_API_URL.format("persongroups/test_group2/persons"),
self.endpoint_url.format("persongroups/test_group2/persons"),
text=load_fixture('microsoft_face_persons.json')
)

self.config['camera'] = {'platform': 'demo'}
with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

assert len(aioclient_mock.mock_calls) == 3

aioclient_mock.post(
mf.FACE_API_URL.format(
self.endpoint_url.format(
"persongroups/test_group2/persons/"
"2ae4935b-9659-44c3-977f-61fac20d0538/persistedFaces"),
status=200, text="{}"
Expand All @@ -229,11 +231,11 @@ def test_service_face(self, camera_mock, aioclient_mock):
def test_service_status_400(self, mock_update, aioclient_mock):
"""Setup component, test groups services with error."""
aioclient_mock.put(
mf.FACE_API_URL.format("persongroups/service_group"),
self.endpoint_url.format("persongroups/service_group"),
status=400, text="{'error': {'message': 'Error'}}"
)

with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

mf.create_group(self.hass, 'Service Group')
Expand All @@ -248,11 +250,11 @@ def test_service_status_400(self, mock_update, aioclient_mock):
def test_service_status_timeout(self, mock_update, aioclient_mock):
"""Setup component, test groups services with timeout."""
aioclient_mock.put(
mf.FACE_API_URL.format("persongroups/service_group"),
self.endpoint_url.format("persongroups/service_group"),
status=400, exc=asyncio.TimeoutError()
)

with assert_setup_component(2, mf.DOMAIN):
with assert_setup_component(3, mf.DOMAIN):
setup_component(self.hass, mf.DOMAIN, self.config)

mf.create_group(self.hass, 'Service Group')
Expand Down