diff --git a/homeassistant/components/knx/__init__.py b/homeassistant/components/knx/__init__.py index cfa01d93d97..7e56d2a955a 100644 --- a/homeassistant/components/knx/__init__.py +++ b/homeassistant/components/knx/__init__.py @@ -37,6 +37,7 @@ from .schema import ( SceneSchema, SensorSchema, SwitchSchema, + WeatherSchema, ) _LOGGER = logging.getLogger(__name__) @@ -102,6 +103,9 @@ CONFIG_SCHEMA = vol.Schema( vol.Optional(SupportedPlatforms.scene.value): vol.All( cv.ensure_list, [SceneSchema.SCHEMA] ), + vol.Optional(SupportedPlatforms.weather.value): vol.All( + cv.ensure_list, [WeatherSchema.SCHEMA] + ), } ) }, diff --git a/homeassistant/components/knx/const.py b/homeassistant/components/knx/const.py index f259638457a..a81fc526415 100644 --- a/homeassistant/components/knx/const.py +++ b/homeassistant/components/knx/const.py @@ -39,6 +39,7 @@ class SupportedPlatforms(Enum): notify = "notify" scene = "scene" sensor = "sensor" + weather = "weather" # Map KNX operation modes to HA modes. This list might not be complete. diff --git a/homeassistant/components/knx/factory.py b/homeassistant/components/knx/factory.py index a596875c27b..42c4dd675f5 100644 --- a/homeassistant/components/knx/factory.py +++ b/homeassistant/components/knx/factory.py @@ -12,6 +12,7 @@ from xknx.devices import ( Scene as XknxScene, Sensor as XknxSensor, Switch as XknxSwitch, + Weather as XknxWeather, ) from homeassistant.const import CONF_ADDRESS, CONF_DEVICE_CLASS, CONF_NAME, CONF_TYPE @@ -28,6 +29,7 @@ from .schema import ( SceneSchema, SensorSchema, SwitchSchema, + WeatherSchema, ) @@ -62,6 +64,9 @@ def create_knx_device( if platform is SupportedPlatforms.binary_sensor: return _create_binary_sensor(hass, knx_module, config) + if platform is SupportedPlatforms.weather: + return _create_weather(knx_module, config) + def _create_cover(knx_module: XKNX, config: ConfigType) -> XknxCover: """Return a KNX Cover device to be used within XKNX.""" @@ -263,3 +268,34 @@ def _create_binary_sensor( reset_after=config.get(BinarySensorSchema.CONF_RESET_AFTER), actions=actions, ) + + +def _create_weather(knx_module: XKNX, config: ConfigType) -> XknxWeather: + """Return a KNX weather device to be used within XKNX.""" + return XknxWeather( + knx_module, + name=config[CONF_NAME], + sync_state=config[WeatherSchema.CONF_SYNC_STATE], + expose_sensors=config[WeatherSchema.CONF_KNX_EXPOSE_SENSORS], + group_address_temperature=config[WeatherSchema.CONF_KNX_TEMPERATURE_ADDRESS], + group_address_brightness_south=config.get( + WeatherSchema.CONF_KNX_BRIGHTNESS_SOUTH_ADDRESS + ), + group_address_brightness_east=config.get( + WeatherSchema.CONF_KNX_BRIGHTNESS_EAST_ADDRESS + ), + group_address_brightness_west=config.get( + WeatherSchema.CONF_KNX_BRIGHTNESS_WEST_ADDRESS + ), + group_address_wind_speed=config.get(WeatherSchema.CONF_KNX_WIND_SPEED_ADDRESS), + group_address_rain_alarm=config.get(WeatherSchema.CONF_KNX_RAIN_ALARM_ADDRESS), + group_address_frost_alarm=config.get( + WeatherSchema.CONF_KNX_FROST_ALARM_ADDRESS + ), + group_address_wind_alarm=config.get(WeatherSchema.CONF_KNX_WIND_ALARM_ADDRESS), + group_address_day_night=config.get(WeatherSchema.CONF_KNX_DAY_NIGHT_ADDRESS), + group_address_air_pressure=config.get( + WeatherSchema.CONF_KNX_AIR_PRESSURE_ADDRESS + ), + group_address_humidity=config.get(WeatherSchema.CONF_KNX_HUMIDITY_ADDRESS), + ) diff --git a/homeassistant/components/knx/schema.py b/homeassistant/components/knx/schema.py index 3b9436a4eee..a436f2dcdc8 100644 --- a/homeassistant/components/knx/schema.py +++ b/homeassistant/components/knx/schema.py @@ -340,3 +340,46 @@ class SceneSchema: vol.Required(CONF_SCENE_NUMBER): cv.positive_int, } ) + + +class WeatherSchema: + """Voluptuous schema for KNX weather station.""" + + CONF_SYNC_STATE = CONF_SYNC_STATE + CONF_KNX_TEMPERATURE_ADDRESS = "address_temperature" + CONF_KNX_BRIGHTNESS_SOUTH_ADDRESS = "address_brightness_south" + CONF_KNX_BRIGHTNESS_EAST_ADDRESS = "address_brightness_east" + CONF_KNX_BRIGHTNESS_WEST_ADDRESS = "address_brightness_west" + CONF_KNX_WIND_SPEED_ADDRESS = "address_wind_speed" + CONF_KNX_RAIN_ALARM_ADDRESS = "address_rain_alarm" + CONF_KNX_FROST_ALARM_ADDRESS = "address_frost_alarm" + CONF_KNX_WIND_ALARM_ADDRESS = "address_wind_alarm" + CONF_KNX_DAY_NIGHT_ADDRESS = "address_day_night" + CONF_KNX_AIR_PRESSURE_ADDRESS = "address_air_pressure" + CONF_KNX_HUMIDITY_ADDRESS = "address_humidity" + CONF_KNX_EXPOSE_SENSORS = "expose_sensors" + + DEFAULT_NAME = "KNX Weather Station" + + SCHEMA = vol.Schema( + { + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_SYNC_STATE, default=True): vol.Any( + vol.All(vol.Coerce(int), vol.Range(min=2, max=1440)), + cv.boolean, + cv.string, + ), + vol.Optional(CONF_KNX_EXPOSE_SENSORS, default=False): cv.boolean, + vol.Required(CONF_KNX_TEMPERATURE_ADDRESS): cv.string, + vol.Optional(CONF_KNX_BRIGHTNESS_SOUTH_ADDRESS): cv.string, + vol.Optional(CONF_KNX_BRIGHTNESS_EAST_ADDRESS): cv.string, + vol.Optional(CONF_KNX_BRIGHTNESS_WEST_ADDRESS): cv.string, + vol.Optional(CONF_KNX_WIND_SPEED_ADDRESS): cv.string, + vol.Optional(CONF_KNX_RAIN_ALARM_ADDRESS): cv.string, + vol.Optional(CONF_KNX_FROST_ALARM_ADDRESS): cv.string, + vol.Optional(CONF_KNX_WIND_ALARM_ADDRESS): cv.string, + vol.Optional(CONF_KNX_DAY_NIGHT_ADDRESS): cv.string, + vol.Optional(CONF_KNX_AIR_PRESSURE_ADDRESS): cv.string, + vol.Optional(CONF_KNX_HUMIDITY_ADDRESS): cv.string, + } + ) diff --git a/homeassistant/components/knx/weather.py b/homeassistant/components/knx/weather.py new file mode 100644 index 00000000000..aed376ec066 --- /dev/null +++ b/homeassistant/components/knx/weather.py @@ -0,0 +1,62 @@ +"""Support for KNX/IP weather station.""" +from xknx.devices import Weather as XknxWeather + +from homeassistant.components.weather import WeatherEntity +from homeassistant.const import TEMP_CELSIUS + +from .const import DATA_KNX + + +async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): + """Set up the scenes for KNX platform.""" + entities = [] + for device in hass.data[DATA_KNX].xknx.devices: + if isinstance(device, XknxWeather): + entities.append(KNXWeather(device)) + async_add_entities(entities) + + +class KNXWeather(WeatherEntity): + """Representation of a KNX weather device.""" + + def __init__(self, device: XknxWeather): + """Initialize of a KNX sensor.""" + self.device = device + + @property + def temperature(self): + """Return current temperature.""" + return self.device.temperature + + @property + def temperature_unit(self): + """Return temperature unit.""" + return TEMP_CELSIUS + + @property + def pressure(self): + """Return current air pressure.""" + # KNX returns pA - HA requires hPa + return ( + self.device.air_pressure / 100 + if self.device.air_pressure is not None + else None + ) + + @property + def condition(self): + """Return current weather condition.""" + return self.device.ha_current_state().value + + @property + def humidity(self): + """Return current humidity.""" + return self.device.humidity if self.device.humidity is not None else None + + @property + def wind_speed(self): + """Return current wind speed in km/h.""" + # KNX only supports wind speed in m/s + return ( + self.device.wind_speed * 3.6 if self.device.wind_speed is not None else None + )