mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Add zodiac integration (#38935)
* add zodiac sign integration * add tests & refacto * Apply suggestions from code review Co-authored-by: Chris Talkington <chris@talkingtontech.com> * fix indentation from suggested correction, fix quality scale and remove useless functions * fix code formatting * Create const.py * Update sensor.py * Update const.py * Update test_sensor.py * Update test_sensor.py * Update test_sensor.py * Update test_sensor.py * Update test_sensor.py * Update sensor.py * Update test_sensor.py * Update __init__.py * Update sensor.py * Update test_sensor.py * Update sensor.py * Update __init__.py * Update test_sensor.py * Update __init__.py * Fix zodiac time patch * Delete sensor.fr.json * Update sensor.py * Delete sensor.en.json * Update test_sensor.py * Apply suggestions from code review Co-authored-by: Chris Talkington <chris@talkingtontech.com> Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
2ef3dfb673
commit
8b9c757fdc
@ -505,6 +505,7 @@ homeassistant/components/yi/* @bachya
|
||||
homeassistant/components/zeroconf/* @Kane610
|
||||
homeassistant/components/zerproc/* @emlove
|
||||
homeassistant/components/zha/* @dmulcahey @adminiuga
|
||||
homeassistant/components/zodiac/* @JulienTant
|
||||
homeassistant/components/zone/* @home-assistant/core
|
||||
homeassistant/components/zoneminder/* @rohankapoorcom @vangorra
|
||||
homeassistant/components/zwave/* @home-assistant/z-wave
|
||||
|
19
homeassistant/components/zodiac/__init__.py
Normal file
19
homeassistant/components/zodiac/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
"""The zodiac component."""
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.discovery import async_load_platform
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{vol.Optional(DOMAIN): {}},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict):
|
||||
"""Set up the zodiac component."""
|
||||
hass.async_create_task(async_load_platform(hass, "sensor", DOMAIN, {}, config))
|
||||
|
||||
return True
|
31
homeassistant/components/zodiac/const.py
Normal file
31
homeassistant/components/zodiac/const.py
Normal file
@ -0,0 +1,31 @@
|
||||
"""Constants for Zodiac."""
|
||||
DOMAIN = "zodiac"
|
||||
|
||||
# Signs
|
||||
SIGN_ARIES = "aries"
|
||||
SIGN_TAURUS = "taurus"
|
||||
SIGN_GEMINI = "gemini"
|
||||
SIGN_CANCER = "cancer"
|
||||
SIGN_LEO = "leo"
|
||||
SIGN_VIRGO = "virgo"
|
||||
SIGN_LIBRA = "libra"
|
||||
SIGN_SCORPIO = "scorpio"
|
||||
SIGN_SAGITTARIUS = "sagittarius"
|
||||
SIGN_CAPRICORN = "capricorn"
|
||||
SIGN_AQUARIUS = "aquarius"
|
||||
SIGN_PISCES = "pisces"
|
||||
|
||||
# Elements
|
||||
ELEMENT_FIRE = "fire"
|
||||
ELEMENT_AIR = "air"
|
||||
ELEMENT_EARTH = "earth"
|
||||
ELEMENT_WATER = "water"
|
||||
|
||||
# Modality
|
||||
MODALITY_CARDINAL = "cardinal"
|
||||
MODALITY_FIXED = "fixed"
|
||||
MODALITY_MUTABLE = "mutable"
|
||||
|
||||
# Attributes
|
||||
ATTR_ELEMENT = "element"
|
||||
ATTR_MODALITY = "modality"
|
7
homeassistant/components/zodiac/manifest.json
Normal file
7
homeassistant/components/zodiac/manifest.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"domain": "zodiac",
|
||||
"name": "Zodiac",
|
||||
"documentation": "https://www.home-assistant.io/integrations/zodiac",
|
||||
"codeowners": ["@JulienTant"],
|
||||
"quality_scale": "silver"
|
||||
}
|
220
homeassistant/components/zodiac/sensor.py
Normal file
220
homeassistant/components/zodiac/sensor.py
Normal file
@ -0,0 +1,220 @@
|
||||
"""Support for tracking the zodiac sign."""
|
||||
import logging
|
||||
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util.dt import as_local, utcnow
|
||||
|
||||
from .const import (
|
||||
ATTR_ELEMENT,
|
||||
ATTR_MODALITY,
|
||||
DOMAIN,
|
||||
ELEMENT_AIR,
|
||||
ELEMENT_EARTH,
|
||||
ELEMENT_FIRE,
|
||||
ELEMENT_WATER,
|
||||
MODALITY_CARDINAL,
|
||||
MODALITY_FIXED,
|
||||
MODALITY_MUTABLE,
|
||||
SIGN_AQUARIUS,
|
||||
SIGN_ARIES,
|
||||
SIGN_CANCER,
|
||||
SIGN_CAPRICORN,
|
||||
SIGN_GEMINI,
|
||||
SIGN_LEO,
|
||||
SIGN_LIBRA,
|
||||
SIGN_PISCES,
|
||||
SIGN_SAGITTARIUS,
|
||||
SIGN_SCORPIO,
|
||||
SIGN_TAURUS,
|
||||
SIGN_VIRGO,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ZODIAC_BY_DATE = (
|
||||
(
|
||||
(21, 3),
|
||||
(20, 4),
|
||||
SIGN_ARIES,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_FIRE,
|
||||
ATTR_MODALITY: MODALITY_CARDINAL,
|
||||
},
|
||||
),
|
||||
(
|
||||
(21, 4),
|
||||
(20, 5),
|
||||
SIGN_TAURUS,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_EARTH,
|
||||
ATTR_MODALITY: MODALITY_FIXED,
|
||||
},
|
||||
),
|
||||
(
|
||||
(21, 5),
|
||||
(21, 6),
|
||||
SIGN_GEMINI,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_AIR,
|
||||
ATTR_MODALITY: MODALITY_MUTABLE,
|
||||
},
|
||||
),
|
||||
(
|
||||
(22, 6),
|
||||
(22, 7),
|
||||
SIGN_CANCER,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_WATER,
|
||||
ATTR_MODALITY: MODALITY_CARDINAL,
|
||||
},
|
||||
),
|
||||
(
|
||||
(23, 7),
|
||||
(22, 8),
|
||||
SIGN_LEO,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_FIRE,
|
||||
ATTR_MODALITY: MODALITY_FIXED,
|
||||
},
|
||||
),
|
||||
(
|
||||
(23, 8),
|
||||
(21, 9),
|
||||
SIGN_VIRGO,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_EARTH,
|
||||
ATTR_MODALITY: MODALITY_MUTABLE,
|
||||
},
|
||||
),
|
||||
(
|
||||
(22, 9),
|
||||
(22, 10),
|
||||
SIGN_LIBRA,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_AIR,
|
||||
ATTR_MODALITY: MODALITY_CARDINAL,
|
||||
},
|
||||
),
|
||||
(
|
||||
(23, 10),
|
||||
(22, 11),
|
||||
SIGN_SCORPIO,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_WATER,
|
||||
ATTR_MODALITY: MODALITY_FIXED,
|
||||
},
|
||||
),
|
||||
(
|
||||
(23, 11),
|
||||
(21, 12),
|
||||
SIGN_SAGITTARIUS,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_FIRE,
|
||||
ATTR_MODALITY: MODALITY_MUTABLE,
|
||||
},
|
||||
),
|
||||
(
|
||||
(22, 12),
|
||||
(20, 1),
|
||||
SIGN_CAPRICORN,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_EARTH,
|
||||
ATTR_MODALITY: MODALITY_CARDINAL,
|
||||
},
|
||||
),
|
||||
(
|
||||
(21, 1),
|
||||
(19, 2),
|
||||
SIGN_AQUARIUS,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_AIR,
|
||||
ATTR_MODALITY: MODALITY_FIXED,
|
||||
},
|
||||
),
|
||||
(
|
||||
(20, 2),
|
||||
(20, 3),
|
||||
SIGN_PISCES,
|
||||
{
|
||||
ATTR_ELEMENT: ELEMENT_WATER,
|
||||
ATTR_MODALITY: MODALITY_MUTABLE,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
ZODIAC_ICONS = {
|
||||
SIGN_ARIES: "mdi:zodiac-aries",
|
||||
SIGN_TAURUS: "mdi:zodiac-taurus",
|
||||
SIGN_GEMINI: "mdi:zodiac-gemini",
|
||||
SIGN_CANCER: "mdi:zodiac-cancer",
|
||||
SIGN_LEO: "mdi:zodiac-leo",
|
||||
SIGN_VIRGO: "mdi:zodiac-virgo",
|
||||
SIGN_LIBRA: "mdi:zodiac-libra",
|
||||
SIGN_SCORPIO: "mdi:zodiac-scorpio",
|
||||
SIGN_SAGITTARIUS: "mdi:zodiac-sagittarius",
|
||||
SIGN_CAPRICORN: "mdi:zodiac-capricorn",
|
||||
SIGN_AQUARIUS: "mdi:zodiac-aquarius",
|
||||
SIGN_PISCES: "mdi:zodiac-pisces",
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||
"""Set up the Zodiac sensor platform."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
async_add_entities([ZodiacSensor()], True)
|
||||
|
||||
|
||||
class ZodiacSensor(Entity):
|
||||
"""Representation of a Zodiac sensor."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the zodiac sensor."""
|
||||
self._attrs = None
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return a unique ID."""
|
||||
return DOMAIN
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the entity."""
|
||||
return "Zodiac"
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the device class of the entity."""
|
||||
return "zodiac__sign"
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the device."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend, if any."""
|
||||
return ZODIAC_ICONS.get(self._state)
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
return self._attrs
|
||||
|
||||
async def async_update(self):
|
||||
"""Get the time and updates the state."""
|
||||
today = as_local(utcnow()).date()
|
||||
|
||||
month = int(today.month)
|
||||
day = int(today.day)
|
||||
|
||||
for sign in ZODIAC_BY_DATE:
|
||||
if (month == sign[0][1] and day >= sign[0][0]) or (
|
||||
month == sign[1][1] and day <= sign[1][0]
|
||||
):
|
||||
self._state = sign[2]
|
||||
self._attrs = sign[3]
|
||||
break
|
18
homeassistant/components/zodiac/strings.sensor.json
Normal file
18
homeassistant/components/zodiac/strings.sensor.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"state": {
|
||||
"zodiac__sign": {
|
||||
"aries": "Aries",
|
||||
"taurus": "Taurus",
|
||||
"gemini": "Gemini",
|
||||
"cancer": "Cancer",
|
||||
"leo": "Leo",
|
||||
"virgo": "Virgo",
|
||||
"libra": "Libra",
|
||||
"scorpio": "Scorpio",
|
||||
"sagittarius": "Sagittarius",
|
||||
"capricorn": "Capricorn",
|
||||
"aquarius": "Aquarius",
|
||||
"pisces": "Pisces"
|
||||
}
|
||||
}
|
||||
}
|
1
tests/components/zodiac/__init__.py
Normal file
1
tests/components/zodiac/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Tests for the zodiac component."""
|
50
tests/components/zodiac/test_sensor.py
Normal file
50
tests/components/zodiac/test_sensor.py
Normal file
@ -0,0 +1,50 @@
|
||||
"""The test for the zodiac sensor platform."""
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.zodiac.const import (
|
||||
ATTR_ELEMENT,
|
||||
ATTR_MODALITY,
|
||||
DOMAIN,
|
||||
ELEMENT_EARTH,
|
||||
ELEMENT_FIRE,
|
||||
ELEMENT_WATER,
|
||||
MODALITY_CARDINAL,
|
||||
MODALITY_FIXED,
|
||||
SIGN_ARIES,
|
||||
SIGN_SCORPIO,
|
||||
SIGN_TAURUS,
|
||||
)
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.async_mock import patch
|
||||
|
||||
DAY1 = datetime(2020, 11, 15, tzinfo=dt_util.UTC)
|
||||
DAY2 = datetime(2020, 4, 20, tzinfo=dt_util.UTC)
|
||||
DAY3 = datetime(2020, 4, 21, tzinfo=dt_util.UTC)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"now,sign,element,modality",
|
||||
[
|
||||
(DAY1, SIGN_SCORPIO, ELEMENT_WATER, MODALITY_FIXED),
|
||||
(DAY2, SIGN_ARIES, ELEMENT_FIRE, MODALITY_CARDINAL),
|
||||
(DAY3, SIGN_TAURUS, ELEMENT_EARTH, MODALITY_FIXED),
|
||||
],
|
||||
)
|
||||
async def test_zodiac_day(hass, now, sign, element, modality):
|
||||
"""Test the zodiac sensor."""
|
||||
config = {DOMAIN: {}}
|
||||
|
||||
with patch("homeassistant.components.zodiac.sensor.utcnow", return_value=now):
|
||||
assert await async_setup_component(hass, DOMAIN, config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.zodiac")
|
||||
assert state
|
||||
assert state.state == sign
|
||||
assert state.attributes
|
||||
assert state.attributes[ATTR_ELEMENT] == element
|
||||
assert state.attributes[ATTR_MODALITY] == modality
|
Loading…
x
Reference in New Issue
Block a user