mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
SolarPotential carries panel dims + per-segment centre/area 🟩
Enrich each SolarRoofSegment from roofSegmentStats (centre + areaMeters2, keyed by segmentIndex) and read panelHeightMeters/panelWidthMeters onto SolarPotential — the geometry the Dwelling-Roof Cap (ADR-0038) needs. All Optional; existing projection + config-selection tests stay green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cf2780ed77
commit
d6a59be950
1 changed files with 58 additions and 7 deletions
|
|
@ -62,6 +62,14 @@ class SolarRoofSegment:
|
|||
azimuth_degrees: float
|
||||
pitch_degrees: float
|
||||
yearly_energy_dc_kwh: float
|
||||
# Per-segment centre + roof-plane area, enriched from the top-level
|
||||
# `roofSegmentStats` (keyed by `segmentIndex`) — the per-config
|
||||
# `roofSegmentSummaries` omit them. Used by the Dwelling-Roof Cap
|
||||
# (ADR-0038) to rank segments by distance from the dwelling and bound the
|
||||
# array by usable roof area. None when the stats block lacks the segment.
|
||||
center_latitude: Optional[float] = None
|
||||
center_longitude: Optional[float] = None
|
||||
area_m2: Optional[float] = None
|
||||
|
||||
@property
|
||||
def sap_orientation(self) -> int:
|
||||
|
|
@ -94,6 +102,11 @@ class SolarPotential:
|
|||
panel_capacity_watts: float
|
||||
max_array_panels_count: int
|
||||
configurations: tuple[SolarPanelConfiguration, ...]
|
||||
# Physical panel footprint (Google `panelHeightMeters` / `panelWidthMeters`)
|
||||
# — the Dwelling-Roof Cap (ADR-0038) converts a usable roof-area budget into
|
||||
# a panel count via this. None for partial blocks lacking the fields.
|
||||
panel_height_m: Optional[float] = None
|
||||
panel_width_m: Optional[float] = None
|
||||
|
||||
@classmethod
|
||||
def from_building_insights(
|
||||
|
|
@ -111,18 +124,46 @@ class SolarPotential:
|
|||
or "panelCapacityWatts" not in solar_potential
|
||||
):
|
||||
return None
|
||||
# Per-segment centre + area live on the top-level `roofSegmentStats`,
|
||||
# keyed by `segmentIndex`; the per-config `roofSegmentSummaries` carry
|
||||
# only the panel/orientation fields. Build the lookup once.
|
||||
stats_by_index: dict[int, Mapping[str, Any]] = {
|
||||
int(stats["segmentIndex"]): stats
|
||||
for stats in solar_potential.get("roofSegmentStats", [])
|
||||
}
|
||||
|
||||
def _segment(summary: Mapping[str, Any]) -> SolarRoofSegment:
|
||||
index: int = int(summary["segmentIndex"])
|
||||
stats: Optional[Mapping[str, Any]] = stats_by_index.get(index)
|
||||
center: Mapping[str, Any] = (
|
||||
stats.get("center", {}) if stats is not None else {}
|
||||
)
|
||||
area: Optional[float] = (
|
||||
float(stats["stats"]["areaMeters2"])
|
||||
if stats is not None and "stats" in stats
|
||||
else None
|
||||
)
|
||||
return SolarRoofSegment(
|
||||
segment_index=index,
|
||||
panels_count=int(summary["panelsCount"]),
|
||||
azimuth_degrees=float(summary["azimuthDegrees"]),
|
||||
pitch_degrees=float(summary["pitchDegrees"]),
|
||||
yearly_energy_dc_kwh=float(summary["yearlyEnergyDcKwh"]),
|
||||
center_latitude=(
|
||||
float(center["latitude"]) if "latitude" in center else None
|
||||
),
|
||||
center_longitude=(
|
||||
float(center["longitude"]) if "longitude" in center else None
|
||||
),
|
||||
area_m2=area,
|
||||
)
|
||||
|
||||
configurations: tuple[SolarPanelConfiguration, ...] = tuple(
|
||||
SolarPanelConfiguration(
|
||||
panels_count=int(config["panelsCount"]),
|
||||
yearly_energy_dc_kwh=float(config["yearlyEnergyDcKwh"]),
|
||||
segments=tuple(
|
||||
SolarRoofSegment(
|
||||
segment_index=int(summary["segmentIndex"]),
|
||||
panels_count=int(summary["panelsCount"]),
|
||||
azimuth_degrees=float(summary["azimuthDegrees"]),
|
||||
pitch_degrees=float(summary["pitchDegrees"]),
|
||||
yearly_energy_dc_kwh=float(summary["yearlyEnergyDcKwh"]),
|
||||
)
|
||||
_segment(summary)
|
||||
for summary in config.get("roofSegmentSummaries", [])
|
||||
),
|
||||
)
|
||||
|
|
@ -132,4 +173,14 @@ class SolarPotential:
|
|||
panel_capacity_watts=float(solar_potential["panelCapacityWatts"]),
|
||||
max_array_panels_count=int(solar_potential["maxArrayPanelsCount"]),
|
||||
configurations=configurations,
|
||||
panel_height_m=(
|
||||
float(solar_potential["panelHeightMeters"])
|
||||
if "panelHeightMeters" in solar_potential
|
||||
else None
|
||||
),
|
||||
panel_width_m=(
|
||||
float(solar_potential["panelWidthMeters"])
|
||||
if "panelWidthMeters" in solar_potential
|
||||
else None
|
||||
),
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue