mirror of
https://github.com/home-assistant/core.git
synced 2025-08-05 13:45:12 +02:00
refactor habitica sensors, add strings and icon translations
This commit is contained in:
@@ -550,8 +550,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/group/ @home-assistant/core
|
||||
/homeassistant/components/guardian/ @bachya
|
||||
/tests/components/guardian/ @bachya
|
||||
/homeassistant/components/habitica/ @ASMfreaK @leikoilja
|
||||
/tests/components/habitica/ @ASMfreaK @leikoilja
|
||||
/homeassistant/components/habitica/ @ASMfreaK @leikoilja @tr4nt0r
|
||||
/tests/components/habitica/ @ASMfreaK @leikoilja @tr4nt0r
|
||||
/homeassistant/components/hardkernel/ @home-assistant/core
|
||||
/tests/components/hardkernel/ @home-assistant/core
|
||||
/homeassistant/components/hardware/ @home-assistant/core
|
||||
|
@@ -15,3 +15,6 @@ ATTR_ARGS = "args"
|
||||
# event constants
|
||||
EVENT_API_CALL_SUCCESS = f"{DOMAIN}_{SERVICE_API_CALL}_success"
|
||||
ATTR_DATA = "data"
|
||||
|
||||
MANUFACTURER = "HabitRPG, Inc."
|
||||
NAME = "Habitica"
|
||||
|
@@ -1,5 +1,51 @@
|
||||
{
|
||||
"services": {
|
||||
"api_call": "mdi:console"
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"name": {
|
||||
"default": "mdi:account-circle"
|
||||
},
|
||||
"hp": {
|
||||
"default": "mdi:heart",
|
||||
"state": {
|
||||
"0": "mdi:skull-outline"
|
||||
}
|
||||
},
|
||||
"maxhealth": {
|
||||
"default": "mdi:heart"
|
||||
},
|
||||
"mp": {
|
||||
"default": "mdi:flask",
|
||||
"state": {
|
||||
"0": "mdi:flask-empty-outline"
|
||||
}
|
||||
},
|
||||
"maxmp": {
|
||||
"default": "mdi:flask"
|
||||
},
|
||||
"exp": {
|
||||
"default": "mdi:star-four-points"
|
||||
},
|
||||
"tonextlevel": {
|
||||
"default": "mdi:star-four-points"
|
||||
},
|
||||
"lvl": {
|
||||
"default": "mdi:crown-circle"
|
||||
},
|
||||
"gp": {
|
||||
"default": "mdi:sack"
|
||||
},
|
||||
"class": {
|
||||
"default": "mdi:sword",
|
||||
"state": {
|
||||
"warrior": "mdi:sword",
|
||||
"healer": "mdi:shield",
|
||||
"wizard": "mdi:wizard-hat",
|
||||
"rogue": "mdi:ninja"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"domain": "habitica",
|
||||
"name": "Habitica",
|
||||
"codeowners": ["@ASMfreaK", "@leikoilja"],
|
||||
"codeowners": ["@ASMfreaK", "@leikoilja", "@tr4nt0r"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/habitica",
|
||||
"iot_class": "cloud_polling",
|
||||
|
@@ -3,20 +3,22 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from http import HTTPStatus
|
||||
import logging
|
||||
|
||||
from aiohttp import ClientResponseError
|
||||
|
||||
from homeassistant.components.sensor import SensorEntity
|
||||
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.const import CONF_NAME, CONF_URL
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
from .const import DOMAIN
|
||||
from .const import DOMAIN, MANUFACTURER, NAME
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -39,6 +41,78 @@ SENSORS_TYPES = {
|
||||
"class": SensorType("Class", "mdi:sword", None, ["stats", "class"]),
|
||||
}
|
||||
|
||||
|
||||
@dataclass(kw_only=True, frozen=True)
|
||||
class HabitipySensorEntityDescription(SensorEntityDescription):
|
||||
"""Habitipy Sensor Description."""
|
||||
|
||||
value_path: list[str]
|
||||
|
||||
|
||||
SENSOR_DESCRIPTIONS: dict[str, HabitipySensorEntityDescription] = {
|
||||
"name": HabitipySensorEntityDescription(
|
||||
key="name",
|
||||
translation_key="name",
|
||||
value_path=["profile", "name"],
|
||||
),
|
||||
"hp": HabitipySensorEntityDescription(
|
||||
key="hp",
|
||||
translation_key="hp",
|
||||
native_unit_of_measurement="HP",
|
||||
suggested_display_precision=0,
|
||||
value_path=["stats", "hp"],
|
||||
),
|
||||
"maxHealth": HabitipySensorEntityDescription(
|
||||
key="maxHealth",
|
||||
translation_key="maxhealth",
|
||||
native_unit_of_measurement="HP",
|
||||
value_path=["stats", "maxHealth"],
|
||||
),
|
||||
"mp": HabitipySensorEntityDescription(
|
||||
key="mp",
|
||||
translation_key="mp",
|
||||
native_unit_of_measurement="MP",
|
||||
suggested_display_precision=0,
|
||||
value_path=["stats", "mp"],
|
||||
),
|
||||
"maxMP": HabitipySensorEntityDescription(
|
||||
key="maxMP",
|
||||
translation_key="maxmp",
|
||||
native_unit_of_measurement="MP",
|
||||
value_path=["stats", "maxMP"],
|
||||
),
|
||||
"exp": HabitipySensorEntityDescription(
|
||||
key="exp",
|
||||
translation_key="exp",
|
||||
native_unit_of_measurement="XP",
|
||||
value_path=["stats", "exp"],
|
||||
),
|
||||
"toNextLevel": HabitipySensorEntityDescription(
|
||||
key="toNextLevel",
|
||||
translation_key="tonextlevel",
|
||||
native_unit_of_measurement="XP",
|
||||
value_path=["stats", "toNextLevel"],
|
||||
),
|
||||
"lvl": HabitipySensorEntityDescription(
|
||||
key="lvl",
|
||||
translation_key="lvl",
|
||||
native_unit_of_measurement="Lvl",
|
||||
value_path=["stats", "lvl"],
|
||||
),
|
||||
"gp": HabitipySensorEntityDescription(
|
||||
key="gp",
|
||||
translation_key="gp",
|
||||
native_unit_of_measurement="🜚", # alchemy symbol for gold
|
||||
suggested_display_precision=2,
|
||||
value_path=["stats", "gp"],
|
||||
),
|
||||
"class": HabitipySensorEntityDescription(
|
||||
key="class",
|
||||
translation_key="class",
|
||||
value_path=["stats", "class"],
|
||||
),
|
||||
}
|
||||
|
||||
TASKS_TYPES = {
|
||||
"habits": SensorType(
|
||||
"Habits", "mdi:clipboard-list-outline", "n_of_tasks", ["habits"]
|
||||
@@ -92,7 +166,8 @@ async def async_setup_entry(
|
||||
await sensor_data.update()
|
||||
|
||||
entities: list[SensorEntity] = [
|
||||
HabitipySensor(name, sensor_type, sensor_data) for sensor_type in SENSORS_TYPES
|
||||
HabitipySensor(sensor_data, description, config_entry)
|
||||
for description in SENSOR_DESCRIPTIONS.values()
|
||||
]
|
||||
entities.extend(
|
||||
HabitipyTaskSensor(name, task_type, sensor_data) for task_type in TASKS_TYPES
|
||||
@@ -153,41 +228,37 @@ class HabitipyData:
|
||||
class HabitipySensor(SensorEntity):
|
||||
"""A generic Habitica sensor."""
|
||||
|
||||
def __init__(self, name, sensor_name, updater):
|
||||
_attr_has_entity_name = True
|
||||
entity_description: HabitipySensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
updater,
|
||||
entity_description: HabitipySensorEntityDescription,
|
||||
entry: ConfigEntry,
|
||||
) -> None:
|
||||
"""Initialize a generic Habitica sensor."""
|
||||
self._name = name
|
||||
self._sensor_name = sensor_name
|
||||
self._sensor_type = SENSORS_TYPES[sensor_name]
|
||||
self._state = None
|
||||
super().__init__()
|
||||
assert entry.unique_id
|
||||
self._updater = updater
|
||||
self.entity_description = entity_description
|
||||
self._attr_unique_id = f"{entry.unique_id}_{entity_description.key}"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
entry_type=DeviceEntryType.SERVICE,
|
||||
manufacturer=MANUFACTURER,
|
||||
model=NAME,
|
||||
name=entry.data[CONF_NAME],
|
||||
configuration_url=entry.data[CONF_URL],
|
||||
identifiers={(DOMAIN, entry.unique_id)},
|
||||
)
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Update Condition and Forecast."""
|
||||
await self._updater.update()
|
||||
data = self._updater.data
|
||||
for element in self._sensor_type.path:
|
||||
for element in self.entity_description.value_path:
|
||||
data = data[element]
|
||||
self._state = data
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon to use in the frontend, if any."""
|
||||
return self._sensor_type.icon
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return f"{DOMAIN}_{self._name}_{self._sensor_name}"
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the state of the device."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self):
|
||||
"""Return the unit the value is expressed in."""
|
||||
return self._sensor_type.unit
|
||||
self._attr_native_value = data
|
||||
|
||||
|
||||
class HabitipyTaskSensor(SensorEntity):
|
||||
|
@@ -38,5 +38,45 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"name": {
|
||||
"name": "Display name"
|
||||
},
|
||||
"hp": {
|
||||
"name": "Health"
|
||||
},
|
||||
"maxhealth": {
|
||||
"name": "Health max."
|
||||
},
|
||||
"mp": {
|
||||
"name": "Mana"
|
||||
},
|
||||
"maxmp": {
|
||||
"name": "Mana max."
|
||||
},
|
||||
"exp": {
|
||||
"name": "Experience"
|
||||
},
|
||||
"tonextlevel": {
|
||||
"name": "Next Level"
|
||||
},
|
||||
"lvl": {
|
||||
"name": "Level"
|
||||
},
|
||||
"gp": {
|
||||
"name": "Gold"
|
||||
},
|
||||
"class": {
|
||||
"name": "Class",
|
||||
"state": {
|
||||
"warrior": "Warrior",
|
||||
"healer": "Healer",
|
||||
"wizard": "Mage",
|
||||
"rogue": "Rogue"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user