text: """Support for interface with a Gree climate systems."""
  from __future__ import annotations
  
  import logging
  
  from greeclimate.device import (
      TEMP_MAX,
      TEMP_MAX_F,
      TEMP_MIN,
      TEMP_MIN_F,
      FanSpeed,
      HorizontalSwing,
      Mode,
      TemperatureUnits,
      VerticalSwing,
  )
  
  from homeassistant.components.climate import ClimateEntity
  from homeassistant.components.climate.const import (
      FAN_AUTO,
      FAN_HIGH,
      FAN_LOW,
      FAN_MEDIUM,
      HVAC_MODE_AUTO,
      HVAC_MODE_COOL,
      HVAC_MODE_DRY,
      HVAC_MODE_FAN_ONLY,
      HVAC_MODE_HEAT,
      HVAC_MODE_OFF,
      PRESET_AWAY,
      PRESET_BOOST,
      PRESET_ECO,
      PRESET_NONE,
      PRESET_SLEEP,
      SUPPORT_FAN_MODE,
      SUPPORT_PRESET_MODE,
      SUPPORT_SWING_MODE,
      SUPPORT_TARGET_TEMPERATURE,
      SWING_BOTH,
      SWING_HORIZONTAL,
      SWING_OFF,
      SWING_VERTICAL,
  )
  from homeassistant.config_entries import ConfigEntry
  from homeassistant.const import (
      ATTR_TEMPERATURE,
      PRECISION_WHOLE,
      TEMP_CELSIUS,
      TEMP_FAHRENHEIT,
  )
  from homeassistant.core import HomeAssistant, callback
  from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
  from homeassistant.helpers.dispatcher import async_dispatcher_connect
  from homeassistant.helpers.entity import DeviceInfo
  from homeassistant.helpers.entity_platform import AddEntitiesCallback
  from homeassistant.helpers.update_coordinator import CoordinatorEntity
  
  from .const import (
      COORDINATORS,
      DISPATCH_DEVICE_DISCOVERED,
      DISPATCHERS,
      DOMAIN,
      FAN_MEDIUM_HIGH,
      FAN_MEDIUM_LOW,
      TARGET_TEMPERATURE_STEP,
  )
  
  _LOGGER = logging.getLogger(__name__)
  
  HVAC_MODES = {
      Mode.Auto: HVAC_MODE_AUTO,
      Mode.Cool: HVAC_MODE_COOL,
      Mode.Dry: HVAC_MODE_DRY,
      Mode.Fan: HVAC_MODE_FAN_ONLY,
      Mode.Heat: HVAC_MODE_HEAT,
  }
  HVAC_MODES_REVERSE = {v: k for k, v in HVAC_MODES.items()}
  
  PRESET_MODES = [
      PRESET_ECO,  # Power saving mode
      PRESET_AWAY,  # Steady heat, or 8C mode on gree units
      PRESET_BOOST,  # Turbo mode
      PRESET_NONE,  # Default operating mode
      PRESET_SLEEP,  # Sleep mode
  ]
  
  FAN_MODES = {
      FanSpeed.Auto: FAN_AUTO,
      FanSpeed.Low: FAN_LOW,
      FanSpeed.MediumLow: FAN_MEDIUM_LOW,
      FanSpeed.Medium: FAN_MEDIUM,
      FanSpeed.MediumHigh: FAN_MEDIUM_HIGH,
      FanSpeed.High: FAN_HIGH,
  }
  FAN_MODES_REVERSE = {v: k for k, v in FAN_MODES.items()}
  
  SWING_MODES = [SWING_OFF, SWING_VERTICAL, SWING_HORIZONTAL, SWING_BOTH]
  
  SUPPORTED_FEATURES = (
      SUPPORT_TARGET_TEMPERATURE
      | SUPPORT_FAN_MODE
      | SUPPORT_PRESET_MODE
      | SUPPORT_SWING_MODE
  )
  
  
  async def async_setup_entry(
      hass: HomeAssistant,
      config_entry: ConfigEntry,
      async_add_entities: AddEntitiesCallback,
  ) -> None:
      """Set up the Gree HVAC device from a config entry."""
  
      @callback
      def init_device(coordinator):
          """Register the device."""
          async_add_entities([GreeClimateEntity(coordinator)])
  
      for coordinator in hass.data[DOMAIN][COORDINATORS]:
          init_device(coordinator)
  
      hass.data[DOMAIN][DISPATCHERS].append(
          async_dispatcher_connect(hass, DISPATCH_DEVICE_DISCOVERED, init_device)
      )
  
  
  class GreeClimateEntity(CoordinatorEntity, ClimateEntity):
      """Representation of a Gree HVAC device."""
  
      def __init__(self, coordinator):
          """Initialize the Gree device."""
          super().__init__(coordinator)
          self._name = coordinator.device.device_info.name
          self._mac = coordinator.device.device_info.mac
  
      @property
      def name(self) -> str:
          """Return the name of the device."""
          return self._name
  
      @property
      def unique_id(self) -> str:
          """Return a unique id for the device."""
          return self._mac
  
      @property
      def device_info(self) -> DeviceInfo:
          """Return device specific attributes."""
          return DeviceInfo(
              connections={(CONNECTION_NETWORK_MAC, self._mac)},
              identifiers={(DOMAIN, self._mac)},
              manufacturer="Gree",
              name=self._name,
          )
  
      @property
      def temperature_unit(self) -> str:
          """Return the temperature units for the device."""
          units = self.coordinator.device.temperature_units
          return TEMP_CELSIUS if units == TemperatureUnits.C else TEMP_FAHRENHEIT
  
      @property
      def precision(self) -> float:
          """Return the precision of temperature for the device."""
          return PRECISION_WHOLE
  
      @property
      def current_temperature(self) -> float:
          """Return the reported current temperature for the device."""
          return self.coordinator.device.current_temperature
  
      @property
      def target_temperature(self) -> float:
          """Return the target temperature for the device."""
          return self.coordinator.device.target_temperature
  
      async def async_set_temperature(self, **kwargs):
          """Set new target temperature."""
          if ATTR_TEMPERATURE not in kwargs:
              raise ValueError(f"Missing parameter {ATTR_TEMPERATURE}")
  
          temperature = kwargs[ATTR_TEMPERATURE]
          _LOGGER.debug(
              "Setting temperature to %d for %s",
              temperature,
              self._name,
          )
  
          self.coordinator.device.target_temperature = round(temperature)
          await self.coordinator.push_state_update()
          self.async_write_ha_state()
  
      @property
      def min_temp(self) -> float:
          """Return the minimum temperature supported by the device."""
          return TEMP_MIN if self.temperature_unit == TEMP_CELSIUS else TEMP_MIN_F
  
      @property
      def max_temp(self) -> float:
          """Return the maximum temperature supported by the device."""
          return TEMP_MAX if self.temperature_unit == TEMP_CELSIUS else TEMP_MAX_F
  
      @property
      def target_temperature_step(self) -> float:
          """Return the target temperature step support by the device."""
          return TARGET_TEMPERATURE_STEP
  
      @property
      def hvac_mode(self) -> str:
          """Return the current HVAC mode for the device."""
          if not self.coordinator.device.power:
              return HVAC_MODE_OFF
  
          return HVAC_MODES.get(self.coordinator.device.mode)
  
      async def async_set_hvac_mode(self, hvac_mode) -> None:
          """Set new target hvac mode."""
          if hvac_mode not in self.hvac_modes:
              raise ValueError(f"Invalid hvac_mode: {hvac_mode}")
  
          _LOGGER.debug(
              "Setting HVAC mode to %s for device %s",
              hvac_mode,
              self._name,
          )
  
          if hvac_mode == HVAC_MODE_OFF:
              self.coordinator.device.power = False
              await self.coordinator.push_state_update()
              self.async_write_ha_state()
              return
  
          if not self.coordinator.device.power:
              self.coordinator.device.power = True
  
          self.coordinator.device.mode = HVAC_MODES_REVERSE.get(hvac_mode)
          await self.coordinator.push_state_update()
          self.async_write_ha_state()
  
      async def async_turn_on(self) -> None:
          """Turn on the device."""
          _LOGGER.debug("Turning on HVAC for device %s", self._name)
  
          self.coordinator.device.power = True
          await self.coordinator.push_state_update()
          self.async_write_ha_state()
  
      async def async_turn_off(self) -> None:
          """Turn off the device."""
          _LOGGER.debug("Turning off HVAC for device %s", self._name)
  
          self.coordinator.device.power = False
          await self.coordinator.push_state_update()
          self.async_write_ha_state()
  
      @property
      def hvac_modes(self) -> list[str]:
          """Return the HVAC modes support by the device."""
          modes = [*HVAC_MODES_REVERSE]
          modes.append(HVAC_MODE_OFF)
          return modes
  
      @property
      def preset_mode(self) -> str:
          """Return the current preset mode for the device."""
          if self.coordinator.device.steady_heat:
              return PRESET_AWAY
          if self.coordinator.device.power_save:
              return PRESET_ECO
          if self.coordinator.device.sleep:
              return PRESET_SLEEP
          if self.coordinator.device.turbo:
              return PRESET_BOOST
          return PRESET_NONE
  
      async def async_set_preset_mode(self, preset_mode):
          """Set new preset mode."""
          if preset_mode not in PRESET_MODES:
              raise ValueError(f"Invalid preset mode: {preset_mode}")
  
          _LOGGER.debug(
              "Setting preset mode to %s for device %s",
              preset_mode,
              self._name,
          )
  
          self.coordinator.device.steady_heat = False
          self.coordinator.device.power_save = False
          self.coordinator.device.turbo = False
          self.coordinator.device.sleep = False
  
          if preset_mode == PRESET_AWAY:
              self.coordinator.device.steady_heat = True
          elif preset_mode == PRESET_ECO:
              self.coordinator.device.power_save = True
          elif preset_mode == PRESET_BOOST:
              self.coordinator.device.turbo = True
          elif preset_mode == PRESET_SLEEP:
              self.coordinator.device.sleep = True
  
          await self.coordinator.push_state_update()
          self.async_write_ha_state()
  
      @property
      def preset_modes(self) -> list[str]:
          """Return the preset modes support by the device."""
          return PRESET_MODES
  
      @property
      def fan_mode(self) -> str:
          """Return the current fan mode for the device."""
          speed = self.coordinator.device.fan_speed
          return FAN_MODES.get(speed)
  
      async def async_set_fan_mode(self, fan_mode):
          """Set new target fan mode."""
          if fan_mode not in FAN_MODES_REVERSE:
              raise ValueError(f"Invalid fan mode: {fan_mode}")
  
          self.coordinator.device.fan_speed = FAN_MODES_REVERSE.get(fan_mode)
          await self.coordinator.push_state_update()
          self.async_write_ha_state()
  
      @property
      def fan_modes(self) -> list[str]:
          """Return the fan modes support by the device."""
          return [*FAN_MODES_REVERSE]
  
      @property
      def swing_mode(self) -> str:
          """Return the current swing mode for the device."""
          h_swing = self.coordinator.device.horizontal_swing == HorizontalSwing.FullSwing
          v_swing = self.coordinator.device.vertical_swing == VerticalSwing.FullSwing
  
          if h_swing and v_swing:
              return SWING_BOTH
          if h_swing:
              return SWING_HORIZONTAL
          if v_swing:
              return SWING_VERTICAL
          return SWING_OFF
  
      async def async_set_swing_mode(self, swing_mode):
          """Set new target swing operation."""
          if swing_mode not in SWING_MODES:
              raise ValueError(f"Invalid swing mode: {swing_mode}")
  
          _LOGGER.debug(
              "Setting swing mode to %s for device %s",
              swing_mode,
              self._name,
          )
  
          self.coordinator.device.horizontal_swing = HorizontalSwing.Center
          self.coordinator.device.vertical_swing = VerticalSwing.FixedMiddle
          if swing_mode in (SWING_BOTH, SWING_HORIZONTAL):
              self.coordinator.device.horizontal_swing = HorizontalSwing.FullSwing
          if swing_mode in (SWING_BOTH, SWING_VERTICAL):
              self.coordinator.device.vertical_swing = VerticalSwing.FullSwing
  
          await self.coordinator.push_state_update()
          self.async_write_ha_state()
  
      @property
      def swing_modes(self) -> list[str]:
          """Return the swing modes currently supported for this device."""
          return SWING_MODES
  
      @property
      def supported_features(self) -> int:
          """Return the supported features for this device integration."""
          return SUPPORTED_FEATURES
  