Fix spaceapi (#26453)
* fixed latitude/longitude keys to be conform with spaceapi specification * version is now a string as required by the spaceapi specification * add spacefed * fixed lat/lon in spaceapi tests * extended tests * add feeds * extended tests * add cache * add more tests * add projects * more tests * add radio_show * more tests * add additional contact attributes * corrected valid issue_repoer_channel options * validate min length of contact/keymasters * fixed location as address is not required by spec * Update homeassistant/components/spaceapi/__init__.py Co-Authored-By: Fabian Affolter <mail@fabian-affolter.ch> * Update homeassistant/components/spaceapi/__init__.py Co-Authored-By: Fabian Affolter <mail@fabian-affolter.ch> * fixed issue with name change for longitude/latitude
This commit is contained in:
parent
88dcecab39
commit
dc52b858a4
2 changed files with 229 additions and 16 deletions
|
@ -7,9 +7,7 @@ from homeassistant.components.http import HomeAssistantView
|
|||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_ICON,
|
||||
ATTR_LATITUDE,
|
||||
ATTR_LOCATION,
|
||||
ATTR_LONGITUDE,
|
||||
ATTR_STATE,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_ADDRESS,
|
||||
|
@ -26,6 +24,15 @@ import homeassistant.util.dt as dt_util
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_ADDRESS = "address"
|
||||
ATTR_SPACEFED = "spacefed"
|
||||
ATTR_CAM = "cam"
|
||||
ATTR_STREAM = "stream"
|
||||
ATTR_FEEDS = "feeds"
|
||||
ATTR_CACHE = "cache"
|
||||
ATTR_PROJECTS = "projects"
|
||||
ATTR_RADIO_SHOW = "radio_show"
|
||||
ATTR_LAT = "lat"
|
||||
ATTR_LON = "lon"
|
||||
ATTR_API = "api"
|
||||
ATTR_CLOSE = "close"
|
||||
ATTR_CONTACT = "contact"
|
||||
|
@ -49,32 +56,135 @@ CONF_ICONS = "icons"
|
|||
CONF_IRC = "irc"
|
||||
CONF_ISSUE_REPORT_CHANNELS = "issue_report_channels"
|
||||
CONF_LOCATION = "location"
|
||||
CONF_SPACEFED = "spacefed"
|
||||
CONF_SPACENET = "spacenet"
|
||||
CONF_SPACESAML = "spacesaml"
|
||||
CONF_SPACEPHONE = "spacephone"
|
||||
CONF_CAM = "cam"
|
||||
CONF_STREAM = "stream"
|
||||
CONF_M4 = "m4"
|
||||
CONF_MJPEG = "mjpeg"
|
||||
CONF_USTREAM = "ustream"
|
||||
CONF_FEEDS = "feeds"
|
||||
CONF_FEED_BLOG = "blog"
|
||||
CONF_FEED_WIKI = "wiki"
|
||||
CONF_FEED_CALENDAR = "calendar"
|
||||
CONF_FEED_FLICKER = "flicker"
|
||||
CONF_FEED_TYPE = "type"
|
||||
CONF_FEED_URL = "url"
|
||||
CONF_CACHE = "cache"
|
||||
CONF_CACHE_SCHEDULE = "schedule"
|
||||
CONF_PROJECTS = "projects"
|
||||
CONF_RADIO_SHOW = "radio_show"
|
||||
CONF_RADIO_SHOW_NAME = "name"
|
||||
CONF_RADIO_SHOW_URL = "url"
|
||||
CONF_RADIO_SHOW_TYPE = "type"
|
||||
CONF_RADIO_SHOW_START = "start"
|
||||
CONF_RADIO_SHOW_END = "end"
|
||||
CONF_LOGO = "logo"
|
||||
CONF_MAILING_LIST = "mailing_list"
|
||||
CONF_PHONE = "phone"
|
||||
CONF_SIP = "sip"
|
||||
CONF_KEYMASTERS = "keymasters"
|
||||
CONF_KEYMASTER_NAME = "name"
|
||||
CONF_KEYMASTER_IRC_NICK = "irc_nick"
|
||||
CONF_KEYMASTER_PHONE = "phone"
|
||||
CONF_KEYMASTER_EMAIL = "email"
|
||||
CONF_KEYMASTER_TWITTER = "twitter"
|
||||
CONF_TWITTER = "twitter"
|
||||
CONF_FACEBOOK = "facebook"
|
||||
CONF_IDENTICA = "identica"
|
||||
CONF_FOURSQUARE = "foursquare"
|
||||
CONF_ML = "ml"
|
||||
CONF_JABBER = "jabber"
|
||||
CONF_ISSUE_MAIL = "issue_mail"
|
||||
CONF_SPACE = "space"
|
||||
CONF_TEMPERATURE = "temperature"
|
||||
CONF_TWITTER = "twitter"
|
||||
|
||||
DATA_SPACEAPI = "data_spaceapi"
|
||||
DOMAIN = "spaceapi"
|
||||
|
||||
ISSUE_REPORT_CHANNELS = [CONF_EMAIL, CONF_IRC, CONF_MAILING_LIST, CONF_TWITTER]
|
||||
ISSUE_REPORT_CHANNELS = [CONF_EMAIL, CONF_ISSUE_MAIL, CONF_ML, CONF_TWITTER]
|
||||
|
||||
SENSOR_TYPES = [CONF_HUMIDITY, CONF_TEMPERATURE]
|
||||
SPACEAPI_VERSION = 0.13
|
||||
SPACEAPI_VERSION = "0.13"
|
||||
|
||||
URL_API_SPACEAPI = "/api/spaceapi"
|
||||
|
||||
LOCATION_SCHEMA = vol.Schema({vol.Optional(CONF_ADDRESS): cv.string}, required=True)
|
||||
LOCATION_SCHEMA = vol.Schema({vol.Optional(CONF_ADDRESS): cv.string})
|
||||
|
||||
SPACEFED_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_SPACENET): cv.boolean,
|
||||
vol.Optional(CONF_SPACESAML): cv.boolean,
|
||||
vol.Optional(CONF_SPACEPHONE): cv.boolean,
|
||||
}
|
||||
)
|
||||
|
||||
STREAM_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_M4): cv.url,
|
||||
vol.Optional(CONF_MJPEG): cv.url,
|
||||
vol.Optional(CONF_USTREAM): cv.url,
|
||||
}
|
||||
)
|
||||
|
||||
FEED_SCHEMA = vol.Schema(
|
||||
{vol.Optional(CONF_FEED_TYPE): cv.string, vol.Required(CONF_FEED_URL): cv.url}
|
||||
)
|
||||
|
||||
FEEDS_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_FEED_BLOG): FEED_SCHEMA,
|
||||
vol.Optional(CONF_FEED_WIKI): FEED_SCHEMA,
|
||||
vol.Optional(CONF_FEED_CALENDAR): FEED_SCHEMA,
|
||||
vol.Optional(CONF_FEED_FLICKER): FEED_SCHEMA,
|
||||
}
|
||||
)
|
||||
|
||||
CACHE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_CACHE_SCHEDULE): cv.matches_regex(
|
||||
r"(m.02|m.05|m.10|m.15|m.30|h.01|h.02|h.04|h.08|h.12|d.01)"
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
RADIO_SHOW_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_RADIO_SHOW_NAME): cv.string,
|
||||
vol.Required(CONF_RADIO_SHOW_URL): cv.url,
|
||||
vol.Required(CONF_RADIO_SHOW_TYPE): cv.matches_regex(r"(mp3|ogg)"),
|
||||
vol.Required(CONF_RADIO_SHOW_START): cv.string,
|
||||
vol.Required(CONF_RADIO_SHOW_END): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
KEYMASTER_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_KEYMASTER_NAME): cv.string,
|
||||
vol.Optional(CONF_KEYMASTER_IRC_NICK): cv.string,
|
||||
vol.Optional(CONF_KEYMASTER_PHONE): cv.string,
|
||||
vol.Optional(CONF_KEYMASTER_EMAIL): cv.string,
|
||||
vol.Optional(CONF_KEYMASTER_TWITTER): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
CONTACT_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_EMAIL): cv.string,
|
||||
vol.Optional(CONF_IRC): cv.string,
|
||||
vol.Optional(CONF_MAILING_LIST): cv.string,
|
||||
vol.Optional(CONF_ML): cv.string,
|
||||
vol.Optional(CONF_PHONE): cv.string,
|
||||
vol.Optional(CONF_TWITTER): cv.string,
|
||||
vol.Optional(CONF_SIP): cv.string,
|
||||
vol.Optional(CONF_FACEBOOK): cv.string,
|
||||
vol.Optional(CONF_IDENTICA): cv.string,
|
||||
vol.Optional(CONF_FOURSQUARE): cv.string,
|
||||
vol.Optional(CONF_JABBER): cv.string,
|
||||
vol.Optional(CONF_ISSUE_MAIL): cv.string,
|
||||
vol.Optional(CONF_KEYMASTERS): vol.All(
|
||||
cv.ensure_list, [KEYMASTER_SCHEMA], vol.Length(min=1)
|
||||
),
|
||||
},
|
||||
required=False,
|
||||
)
|
||||
|
@ -100,12 +210,23 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
vol.Required(CONF_ISSUE_REPORT_CHANNELS): vol.All(
|
||||
cv.ensure_list, [vol.In(ISSUE_REPORT_CHANNELS)]
|
||||
),
|
||||
vol.Required(CONF_LOCATION): LOCATION_SCHEMA,
|
||||
vol.Optional(CONF_LOCATION): LOCATION_SCHEMA,
|
||||
vol.Required(CONF_LOGO): cv.url,
|
||||
vol.Required(CONF_SPACE): cv.string,
|
||||
vol.Required(CONF_STATE): STATE_SCHEMA,
|
||||
vol.Required(CONF_URL): cv.string,
|
||||
vol.Optional(CONF_SENSORS): SENSOR_SCHEMA,
|
||||
vol.Optional(CONF_SPACEFED): SPACEFED_SCHEMA,
|
||||
vol.Optional(CONF_CAM): vol.All(
|
||||
cv.ensure_list, [cv.url], vol.Length(min=1)
|
||||
),
|
||||
vol.Optional(CONF_STREAM): STREAM_SCHEMA,
|
||||
vol.Optional(CONF_FEEDS): FEEDS_SCHEMA,
|
||||
vol.Optional(CONF_CACHE): CACHE_SCHEMA,
|
||||
vol.Optional(CONF_PROJECTS): vol.All(cv.ensure_list, [cv.url]),
|
||||
vol.Optional(CONF_RADIO_SHOW): vol.All(
|
||||
cv.ensure_list, [RADIO_SHOW_SCHEMA]
|
||||
),
|
||||
}
|
||||
)
|
||||
},
|
||||
|
@ -150,11 +271,14 @@ class APISpaceApiView(HomeAssistantView):
|
|||
spaceapi = dict(hass.data[DATA_SPACEAPI])
|
||||
is_sensors = spaceapi.get("sensors")
|
||||
|
||||
location = {
|
||||
ATTR_ADDRESS: spaceapi[ATTR_LOCATION][CONF_ADDRESS],
|
||||
ATTR_LATITUDE: hass.config.latitude,
|
||||
ATTR_LONGITUDE: hass.config.longitude,
|
||||
}
|
||||
location = {ATTR_LAT: hass.config.latitude, ATTR_LON: hass.config.longitude}
|
||||
|
||||
try:
|
||||
location[ATTR_ADDRESS] = spaceapi[ATTR_LOCATION][CONF_ADDRESS]
|
||||
except KeyError:
|
||||
pass
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
state_entity = spaceapi["state"][ATTR_ENTITY_ID]
|
||||
space_state = hass.states.get(state_entity)
|
||||
|
@ -186,6 +310,41 @@ class APISpaceApiView(HomeAssistantView):
|
|||
ATTR_URL: spaceapi[CONF_URL],
|
||||
}
|
||||
|
||||
try:
|
||||
data[ATTR_CAM] = spaceapi[CONF_CAM]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
data[ATTR_SPACEFED] = spaceapi[CONF_SPACEFED]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
data[ATTR_STREAM] = spaceapi[CONF_STREAM]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
data[ATTR_FEEDS] = spaceapi[CONF_FEEDS]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
data[ATTR_CACHE] = spaceapi[CONF_CACHE]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
data[ATTR_PROJECTS] = spaceapi[CONF_PROJECTS]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
data[ATTR_RADIO_SHOW] = spaceapi[CONF_RADIO_SHOW]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if is_sensors is not None:
|
||||
sensors = {}
|
||||
for sensor_type in is_sensors:
|
||||
|
|
|
@ -25,6 +25,34 @@ CONFIG = {
|
|||
"temperature": ["test.temp1", "test.temp2"],
|
||||
"humidity": ["test.hum1"],
|
||||
},
|
||||
"spacefed": {"spacenet": True, "spacesaml": False, "spacephone": True},
|
||||
"cam": ["https://home-assistant.io/cam1", "https://home-assistant.io/cam2"],
|
||||
"stream": {
|
||||
"m4": "https://home-assistant.io/m4",
|
||||
"mjpeg": "https://home-assistant.io/mjpeg",
|
||||
"ustream": "https://home-assistant.io/ustream",
|
||||
},
|
||||
"feeds": {
|
||||
"blog": {"url": "https://home-assistant.io/blog"},
|
||||
"wiki": {"type": "mediawiki", "url": "https://home-assistant.io/wiki"},
|
||||
"calendar": {"type": "ical", "url": "https://home-assistant.io/calendar"},
|
||||
"flicker": {"url": "https://www.flickr.com/photos/home-assistant"},
|
||||
},
|
||||
"cache": {"schedule": "m.02"},
|
||||
"projects": [
|
||||
"https://home-assistant.io/projects/1",
|
||||
"https://home-assistant.io/projects/2",
|
||||
"https://home-assistant.io/projects/3",
|
||||
],
|
||||
"radio_show": [
|
||||
{
|
||||
"name": "Radioshow",
|
||||
"url": "https://home-assistant.io/radio",
|
||||
"type": "ogg",
|
||||
"start": "2019-09-02T10:00Z",
|
||||
"end": "2019-09-02T12:00Z",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,11 +89,37 @@ async def test_spaceapi_get(hass, mock_client):
|
|||
assert data["space"] == "Home"
|
||||
assert data["contact"]["email"] == "hello@home-assistant.io"
|
||||
assert data["location"]["address"] == "In your Home"
|
||||
assert data["location"]["latitude"] == 32.87336
|
||||
assert data["location"]["longitude"] == -117.22743
|
||||
assert data["location"]["lat"] == 32.87336
|
||||
assert data["location"]["lon"] == -117.22743
|
||||
assert data["state"]["open"] == "null"
|
||||
assert data["state"]["icon"]["open"] == "https://home-assistant.io/open.png"
|
||||
assert data["state"]["icon"]["close"] == "https://home-assistant.io/close.png"
|
||||
assert data["spacefed"]["spacenet"] == bool(1)
|
||||
assert data["spacefed"]["spacesaml"] == bool(0)
|
||||
assert data["spacefed"]["spacephone"] == bool(1)
|
||||
assert data["cam"][0] == "https://home-assistant.io/cam1"
|
||||
assert data["cam"][1] == "https://home-assistant.io/cam2"
|
||||
assert data["stream"]["m4"] == "https://home-assistant.io/m4"
|
||||
assert data["stream"]["mjpeg"] == "https://home-assistant.io/mjpeg"
|
||||
assert data["stream"]["ustream"] == "https://home-assistant.io/ustream"
|
||||
assert data["feeds"]["blog"]["url"] == "https://home-assistant.io/blog"
|
||||
assert data["feeds"]["wiki"]["type"] == "mediawiki"
|
||||
assert data["feeds"]["wiki"]["url"] == "https://home-assistant.io/wiki"
|
||||
assert data["feeds"]["calendar"]["type"] == "ical"
|
||||
assert data["feeds"]["calendar"]["url"] == "https://home-assistant.io/calendar"
|
||||
assert (
|
||||
data["feeds"]["flicker"]["url"]
|
||||
== "https://www.flickr.com/photos/home-assistant"
|
||||
)
|
||||
assert data["cache"]["schedule"] == "m.02"
|
||||
assert data["projects"][0] == "https://home-assistant.io/projects/1"
|
||||
assert data["projects"][1] == "https://home-assistant.io/projects/2"
|
||||
assert data["projects"][2] == "https://home-assistant.io/projects/3"
|
||||
assert data["radio_show"][0]["name"] == "Radioshow"
|
||||
assert data["radio_show"][0]["url"] == "https://home-assistant.io/radio"
|
||||
assert data["radio_show"][0]["type"] == "ogg"
|
||||
assert data["radio_show"][0]["start"] == "2019-09-02T10:00Z"
|
||||
assert data["radio_show"][0]["end"] == "2019-09-02T12:00Z"
|
||||
|
||||
|
||||
async def test_spaceapi_state_get(hass, mock_client):
|
||||
|
|
Loading…
Add table
Reference in a new issue