diff --git a/.coveragerc b/.coveragerc index eb0fbdc1fcf..cbdcc60b421 100644 --- a/.coveragerc +++ b/.coveragerc @@ -372,6 +372,7 @@ omit = homeassistant/components/goalfeed/* homeassistant/components/goalzero/__init__.py homeassistant/components/goalzero/binary_sensor.py + homeassistant/components/goalzero/sensor.py homeassistant/components/goalzero/switch.py homeassistant/components/google/* homeassistant/components/google_cloud/tts.py diff --git a/homeassistant/components/goalzero/__init__.py b/homeassistant/components/goalzero/__init__.py index 8838d3f20fa..f3889d1d385 100644 --- a/homeassistant/components/goalzero/__init__.py +++ b/homeassistant/components/goalzero/__init__.py @@ -4,6 +4,7 @@ import logging from goalzero import Yeti, exceptions from homeassistant.components.binary_sensor import DOMAIN as DOMAIN_BINARY_SENSOR +from homeassistant.components.sensor import DOMAIN as DOMAIN_SENSOR from homeassistant.components.switch import DOMAIN as DOMAIN_SWITCH from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, CONF_NAME @@ -21,7 +22,7 @@ from .const import DATA_KEY_API, DATA_KEY_COORDINATOR, DOMAIN, MIN_TIME_BETWEEN_ _LOGGER = logging.getLogger(__name__) -PLATFORMS = [DOMAIN_BINARY_SENSOR, DOMAIN_SWITCH] +PLATFORMS = [DOMAIN_BINARY_SENSOR, DOMAIN_SENSOR, DOMAIN_SWITCH] async def async_setup_entry(hass, entry): @@ -42,7 +43,7 @@ async def async_setup_entry(hass, entry): try: await api.get_state() except exceptions.ConnectError as err: - raise UpdateFailed(f"Failed to communicating with device {err}") from err + raise UpdateFailed("Failed to communicate with device") from err coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/goalzero/binary_sensor.py b/homeassistant/components/goalzero/binary_sensor.py index 59a8a6b3443..aec9fdb0354 100644 --- a/homeassistant/components/goalzero/binary_sensor.py +++ b/homeassistant/components/goalzero/binary_sensor.py @@ -22,7 +22,7 @@ async def async_setup_entry(hass, entry, async_add_entities): ) for sensor_name in BINARY_SENSOR_DICT ] - async_add_entities(sensors, True) + async_add_entities(sensors) class YetiBinarySensor(YetiEntity, BinarySensorEntity): diff --git a/homeassistant/components/goalzero/config_flow.py b/homeassistant/components/goalzero/config_flow.py index cea47c967a8..50450f95a69 100644 --- a/homeassistant/components/goalzero/config_flow.py +++ b/homeassistant/components/goalzero/config_flow.py @@ -18,8 +18,6 @@ from .const import DEFAULT_NAME, DOMAIN _LOGGER = logging.getLogger(__name__) -DATA_SCHEMA = vol.Schema({vol.Required("host"): str, vol.Required("name"): str}) - class GoalZeroFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow for Goal Zero Yeti.""" diff --git a/homeassistant/components/goalzero/const.py b/homeassistant/components/goalzero/const.py index 826c2621e23..643c632a352 100644 --- a/homeassistant/components/goalzero/const.py +++ b/homeassistant/components/goalzero/const.py @@ -6,7 +6,37 @@ from homeassistant.components.binary_sensor import ( DEVICE_CLASS_CONNECTIVITY, DEVICE_CLASS_POWER, ) +from homeassistant.components.sensor import ( + ATTR_STATE_CLASS, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, +) +from homeassistant.const import ( + ATTR_DEVICE_CLASS, + ATTR_NAME, + ATTR_UNIT_OF_MEASUREMENT, + ELECTRICAL_CURRENT_AMPERE, + ENERGY_WATT_HOUR, + PERCENTAGE, + POWER_WATT, + SIGNAL_STRENGTH_DECIBELS, + TEMP_CELSIUS, + TIME_MINUTES, + TIME_SECONDS, + VOLT, +) +ATTR_DEFAULT_ENABLED = "default_enabled" + +CONF_IDENTIFIERS = "identifiers" +CONF_MANUFACTURER = "manufacturer" +CONF_MODEL = "model" +CONF_SW_VERSION = "sw_version" DATA_KEY_COORDINATOR = "coordinator" DOMAIN = "goalzero" DEFAULT_NAME = "Yeti" @@ -25,6 +55,86 @@ BINARY_SENSOR_DICT = { "inputDetected": ["Input Detected", DEVICE_CLASS_POWER, None], } +SENSOR_DICT = { + "wattsIn": { + ATTR_NAME: "Watts In", + ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER, + ATTR_UNIT_OF_MEASUREMENT: POWER_WATT, + ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, + ATTR_DEFAULT_ENABLED: True, + }, + "ampsIn": { + ATTR_NAME: "Amps In", + ATTR_DEVICE_CLASS: DEVICE_CLASS_CURRENT, + ATTR_UNIT_OF_MEASUREMENT: ELECTRICAL_CURRENT_AMPERE, + ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, + ATTR_DEFAULT_ENABLED: False, + }, + "wattsOut": { + ATTR_NAME: "Watts Out", + ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER, + ATTR_UNIT_OF_MEASUREMENT: POWER_WATT, + ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, + ATTR_DEFAULT_ENABLED: True, + }, + "ampsOut": { + ATTR_NAME: "Amps Out", + ATTR_DEVICE_CLASS: DEVICE_CLASS_CURRENT, + ATTR_UNIT_OF_MEASUREMENT: ELECTRICAL_CURRENT_AMPERE, + ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, + ATTR_DEFAULT_ENABLED: False, + }, + "whOut": { + ATTR_NAME: "WH Out", + ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY, + ATTR_UNIT_OF_MEASUREMENT: ENERGY_WATT_HOUR, + ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, + ATTR_DEFAULT_ENABLED: False, + }, + "whStored": { + ATTR_NAME: "WH Stored", + ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY, + ATTR_UNIT_OF_MEASUREMENT: ENERGY_WATT_HOUR, + ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, + ATTR_DEFAULT_ENABLED: True, + }, + "volts": { + ATTR_NAME: "Volts", + ATTR_DEVICE_CLASS: DEVICE_CLASS_VOLTAGE, + ATTR_UNIT_OF_MEASUREMENT: VOLT, + ATTR_DEFAULT_ENABLED: False, + }, + "socPercent": { + ATTR_NAME: "State of Charge Percent", + ATTR_DEVICE_CLASS: DEVICE_CLASS_BATTERY, + ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE, + ATTR_DEFAULT_ENABLED: True, + }, + "timeToEmptyFull": { + ATTR_NAME: "Time to Empty/Full", + ATTR_DEVICE_CLASS: TIME_MINUTES, + ATTR_UNIT_OF_MEASUREMENT: TIME_MINUTES, + ATTR_DEFAULT_ENABLED: True, + }, + "temperature": { + ATTR_NAME: "Temperature", + ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, + ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, + ATTR_DEFAULT_ENABLED: True, + }, + "wifiStrength": { + ATTR_NAME: "Wifi Strength", + ATTR_DEVICE_CLASS: DEVICE_CLASS_SIGNAL_STRENGTH, + ATTR_UNIT_OF_MEASUREMENT: SIGNAL_STRENGTH_DECIBELS, + ATTR_DEFAULT_ENABLED: True, + }, + "timestamp": { + ATTR_NAME: "Up Time", + ATTR_UNIT_OF_MEASUREMENT: TIME_SECONDS, + ATTR_DEFAULT_ENABLED: False, + }, +} + SWITCH_DICT = { "v12PortStatus": "12V Port Status", "usbPortStatus": "USB Port Status", diff --git a/homeassistant/components/goalzero/sensor.py b/homeassistant/components/goalzero/sensor.py new file mode 100644 index 00000000000..8464104a61f --- /dev/null +++ b/homeassistant/components/goalzero/sensor.py @@ -0,0 +1,59 @@ +"""Support for Goal Zero Yeti Sensors.""" +from homeassistant.components.sensor import ATTR_LAST_RESET, ATTR_STATE_CLASS +from homeassistant.const import ( + ATTR_DEVICE_CLASS, + ATTR_NAME, + ATTR_UNIT_OF_MEASUREMENT, + CONF_NAME, +) + +from . import YetiEntity +from .const import ( + ATTR_DEFAULT_ENABLED, + DATA_KEY_API, + DATA_KEY_COORDINATOR, + DOMAIN, + SENSOR_DICT, +) + + +async def async_setup_entry(hass, entry, async_add_entities): + """Set up the Goal Zero Yeti sensor.""" + name = entry.data[CONF_NAME] + goalzero_data = hass.data[DOMAIN][entry.entry_id] + sensors = [ + YetiSensor( + goalzero_data[DATA_KEY_API], + goalzero_data[DATA_KEY_COORDINATOR], + name, + sensor_name, + entry.entry_id, + ) + for sensor_name in SENSOR_DICT + ] + async_add_entities(sensors, True) + + +class YetiSensor(YetiEntity): + """Representation of a Goal Zero Yeti sensor.""" + + def __init__(self, api, coordinator, name, sensor_name, server_unique_id): + """Initialize a Goal Zero Yeti sensor.""" + super().__init__(api, coordinator, name, server_unique_id) + + self._condition = sensor_name + + sensor = SENSOR_DICT[sensor_name] + self._attr_name = f"{name} {sensor.get(ATTR_NAME)}" + self._attr_unique_id = f"{self._server_unique_id}/{sensor_name}" + self._attr_unit_of_measurement = sensor.get(ATTR_UNIT_OF_MEASUREMENT) + self._attr_entity_registry_enabled_default = sensor.get(ATTR_DEFAULT_ENABLED) + self._device_class = sensor.get(ATTR_DEVICE_CLASS) + self._attr_last_reset = sensor.get(ATTR_LAST_RESET) + self._attr_state_class = sensor.get(ATTR_STATE_CLASS) + + @property + def state(self): + """Return the state.""" + if self.api.data: + return self.api.data[self._condition]