"""Public schemas for protocol-agnostic meter sources and bindings.""" from __future__ import annotations from datetime import datetime from decimal import Decimal from typing import Any from pydantic import BaseModel, Field class SourceConfigFieldResponse(BaseModel): name: str value_type: str default: Any = None required: bool secret: bool class SourceProfileResponse(BaseModel): kind: str fields: list[SourceConfigFieldResponse] defaults: dict[str, Any] capabilities: list[str] allowed_units: list[str] class SourceProfilesResponse(BaseModel): items: list[SourceProfileResponse] class MeterSourceCreate(BaseModel): name: str = Field(..., min_length=1, max_length=255) kind: str = Field(..., min_length=1, max_length=64) config: dict[str, Any] = Field(default_factory=dict) enabled: bool = True class MeterSourcePatch(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=255) config: dict[str, Any] | None = None enabled: bool | None = None class MeterSourceResponse(BaseModel): uuid: str name: str kind: str enabled: bool config: dict[str, Any] status: str last_seen_at: datetime | None last_error: str | None created_at: datetime updated_at: datetime class MeterSourceListResponse(BaseModel): items: list[MeterSourceResponse] total: int class DiscoverResponse(BaseModel): requested: bool supported: bool status: str request_id: int | None = None detail: str | None = None channels: list["DiscoverChannelResponse"] = Field(default_factory=list) class DiscoverChannelResponse(BaseModel): uuid: str label: str unit: str latest_value: Decimal | None latest_at: datetime | None latest_quality: str | None class ChannelBindingSummaryResponse(BaseModel): count: int meter_ids: list[int] class CommodityResponse(BaseModel): key: str unit: str capabilities: list[str] class CommoditiesResponse(BaseModel): items: list[CommodityResponse] class MeterSourceChannelResponse(BaseModel): uuid: str label: str suggested_commodity: str | None unit: str device_type: str | None latest_value: Decimal | None latest_at: datetime | None latest_quality: str | None binding_count: int bound_meter_ids: list[int] binding_summary: ChannelBindingSummaryResponse class MeterSourceChannelListResponse(BaseModel): items: list[MeterSourceChannelResponse] total: int source_status: str class ChannelReadingResponse(BaseModel): recorded_at: datetime value: Decimal | None = None quality: str | None = None class ChannelReadingsResponse(BaseModel): items: list[ChannelReadingResponse] total: int class BindingCreate(BaseModel): source_channel_uuid: str = Field(..., min_length=1, max_length=36) started_at: datetime ended_at: datetime | None = None class BindingPatch(BaseModel): started_at: datetime | None = None ended_at: datetime | None = None class BindingResponse(BaseModel): uuid: str meter_id: int source_channel_uuid: str source_uuid: str started_at: datetime ended_at: datetime | None created_at: datetime updated_at: datetime class BindingListResponse(BaseModel): items: list[BindingResponse] total: int