165 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
"""Support for Vulcan Calendar platform."""
 | 
						|
from __future__ import annotations
 | 
						|
 | 
						|
from datetime import date, datetime, timedelta
 | 
						|
import logging
 | 
						|
 | 
						|
from aiohttp import ClientConnectorError
 | 
						|
from vulcan import UnauthorizedCertificateException
 | 
						|
 | 
						|
from homeassistant.components.calendar import (
 | 
						|
    ENTITY_ID_FORMAT,
 | 
						|
    CalendarEntity,
 | 
						|
    CalendarEvent,
 | 
						|
)
 | 
						|
from homeassistant.config_entries import ConfigEntry
 | 
						|
from homeassistant.core import HomeAssistant
 | 
						|
from homeassistant.exceptions import ConfigEntryAuthFailed
 | 
						|
from homeassistant.helpers.device_registry import DeviceEntryType
 | 
						|
from homeassistant.helpers.entity import generate_entity_id
 | 
						|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
 | 
						|
 | 
						|
from . import DOMAIN
 | 
						|
from .fetch_data import get_lessons, get_student_info
 | 
						|
 | 
						|
_LOGGER = logging.getLogger(__name__)
 | 
						|
 | 
						|
 | 
						|
async def async_setup_entry(
 | 
						|
    hass: HomeAssistant,
 | 
						|
    config_entry: ConfigEntry,
 | 
						|
    async_add_entities: AddEntitiesCallback,
 | 
						|
) -> None:
 | 
						|
    """Set up the calendar platform for entity."""
 | 
						|
    client = hass.data[DOMAIN][config_entry.entry_id]
 | 
						|
    data = {
 | 
						|
        "student_info": await get_student_info(
 | 
						|
            client, config_entry.data.get("student_id")
 | 
						|
        ),
 | 
						|
    }
 | 
						|
    async_add_entities(
 | 
						|
        [
 | 
						|
            VulcanCalendarEntity(
 | 
						|
                client,
 | 
						|
                data,
 | 
						|
                generate_entity_id(
 | 
						|
                    ENTITY_ID_FORMAT,
 | 
						|
                    f"vulcan_calendar_{data['student_info']['full_name']}",
 | 
						|
                    hass=hass,
 | 
						|
                ),
 | 
						|
            )
 | 
						|
        ],
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
class VulcanCalendarEntity(CalendarEntity):
 | 
						|
    """A calendar entity."""
 | 
						|
 | 
						|
    def __init__(self, client, data, entity_id) -> None:
 | 
						|
        """Create the Calendar entity."""
 | 
						|
        self.student_info = data["student_info"]
 | 
						|
        self._event: CalendarEvent | None = None
 | 
						|
        self.client = client
 | 
						|
        self.entity_id = entity_id
 | 
						|
        self._unique_id = f"vulcan_calendar_{self.student_info['id']}"
 | 
						|
        self._attr_name = f"Vulcan calendar - {self.student_info['full_name']}"
 | 
						|
        self._attr_unique_id = f"vulcan_calendar_{self.student_info['id']}"
 | 
						|
        self._attr_device_info = {
 | 
						|
            "identifiers": {(DOMAIN, f"calendar_{self.student_info['id']}")},
 | 
						|
            "entry_type": DeviceEntryType.SERVICE,
 | 
						|
            "name": f"{self.student_info['full_name']}: Calendar",
 | 
						|
            "model": (
 | 
						|
                f"{self.student_info['full_name']} -"
 | 
						|
                f" {self.student_info['class']} {self.student_info['school']}"
 | 
						|
            ),
 | 
						|
            "manufacturer": "Uonet +",
 | 
						|
            "configuration_url": (
 | 
						|
                f"https://uonetplus.vulcan.net.pl/{self.student_info['symbol']}"
 | 
						|
            ),
 | 
						|
        }
 | 
						|
 | 
						|
    @property
 | 
						|
    def event(self) -> CalendarEvent | None:
 | 
						|
        """Return the next upcoming event."""
 | 
						|
        return self._event
 | 
						|
 | 
						|
    async def async_get_events(
 | 
						|
        self, hass: HomeAssistant, start_date: datetime, end_date: datetime
 | 
						|
    ) -> list[CalendarEvent]:
 | 
						|
        """Get all events in a specific time frame."""
 | 
						|
        try:
 | 
						|
            events = await get_lessons(
 | 
						|
                self.client,
 | 
						|
                date_from=start_date,
 | 
						|
                date_to=end_date,
 | 
						|
            )
 | 
						|
        except UnauthorizedCertificateException as err:
 | 
						|
            raise ConfigEntryAuthFailed(
 | 
						|
                "The certificate is not authorized, please authorize integration again"
 | 
						|
            ) from err
 | 
						|
        except ClientConnectorError as err:
 | 
						|
            if self.available:
 | 
						|
                _LOGGER.warning(
 | 
						|
                    "Connection error - please check your internet connection: %s", err
 | 
						|
                )
 | 
						|
            events = []
 | 
						|
 | 
						|
        event_list = []
 | 
						|
        for item in events:
 | 
						|
            event = CalendarEvent(
 | 
						|
                start=datetime.combine(item["date"], item["time"].from_),
 | 
						|
                end=datetime.combine(item["date"], item["time"].to),
 | 
						|
                summary=item["lesson"],
 | 
						|
                location=item["room"],
 | 
						|
                description=item["teacher"],
 | 
						|
            )
 | 
						|
 | 
						|
            event_list.append(event)
 | 
						|
 | 
						|
        return event_list
 | 
						|
 | 
						|
    async def async_update(self) -> None:
 | 
						|
        """Get the latest data."""
 | 
						|
 | 
						|
        try:
 | 
						|
            events = await get_lessons(self.client)
 | 
						|
 | 
						|
            if not self.available:
 | 
						|
                _LOGGER.info("Restored connection with API")
 | 
						|
                self._attr_available = True
 | 
						|
 | 
						|
            if events == []:
 | 
						|
                events = await get_lessons(
 | 
						|
                    self.client,
 | 
						|
                    date_to=date.today() + timedelta(days=7),
 | 
						|
                )
 | 
						|
                if events == []:
 | 
						|
                    self._event = None
 | 
						|
                    return
 | 
						|
        except UnauthorizedCertificateException as err:
 | 
						|
            raise ConfigEntryAuthFailed(
 | 
						|
                "The certificate is not authorized, please authorize integration again"
 | 
						|
            ) from err
 | 
						|
        except ClientConnectorError as err:
 | 
						|
            if self.available:
 | 
						|
                _LOGGER.warning(
 | 
						|
                    "Connection error - please check your internet connection: %s", err
 | 
						|
                )
 | 
						|
                self._attr_available = False
 | 
						|
            return
 | 
						|
 | 
						|
        new_event = min(
 | 
						|
            events,
 | 
						|
            key=lambda d: (
 | 
						|
                datetime.combine(d["date"], d["time"].to) < datetime.now(),
 | 
						|
                abs(datetime.combine(d["date"], d["time"].to) - datetime.now()),
 | 
						|
            ),
 | 
						|
        )
 | 
						|
        self._event = CalendarEvent(
 | 
						|
            start=datetime.combine(new_event["date"], new_event["time"].from_),
 | 
						|
            end=datetime.combine(new_event["date"], new_event["time"].to),
 | 
						|
            summary=new_event["lesson"],
 | 
						|
            location=new_event["room"],
 | 
						|
            description=new_event["teacher"],
 | 
						|
        )
 |