Skip to content

Extend SunMoonData and improve sun.sun fallback for solar phase calculation #99

Description

@ElectroAttacks

The current solar phase logic in src/utils.ts only works with sunrise and sunset, and getTimeOfDayWithSunData() derives sunrise / day / sunset / night from fixed windows around those values.

This has two problems:

  1. it throws away richer solar event data available from sun.sun
  2. it can incorrectly switch to night because of the current > 12h adjustment heuristic when the next sunrise is tomorrow but less than 12 hours away

Current behavior

The current source priority should stay as-is:

  1. configured sunrise/sunset override entities
  2. weather entity attributes
  3. sun.sun
  4. static fallback

The problem is that the data model only preserves sunrise and sunset, so even if sun.sun provides richer fields like:

  • next_dawn
  • next_noon
  • next_dusk
  • elevation
  • azimuth

that information is lost before phase calculation.

Proposed change

Extend SunMoonData

Add support for richer solar fields, for example:

  • dawn?: Date | null
  • noon?: Date | null
  • dusk?: Date | null
  • elevation?: number | null
  • azimuth?: number | null

while keeping:

  • sunrise: Date | null
  • sunset: Date | null

Keep current fallback order

Do not change the existing retrieval precedence. Only improve what happens once sun.sun is used as fallback.

Use richer sun.sun data when available

If sun.sun provides enough data, derive phases from a linear solar timeline instead of hardcoded sunrise ± 1h / sunset ± 1h windows.

Suggested mapping:

  • sunrise: dawn -> sunrise
  • day: sunrise -> sunset
  • sunset: sunset -> dusk
  • night: otherwise

If only partial data exists, fall back gracefully to sunrise/sunset logic, and finally to the static fallback.

Why

This would:

  • preserve existing compatibility
  • improve the sun.sun fallback path
  • avoid the current incorrect night classification caused by the 12-hour heuristic
  • make the phase calculation better match Home Assistant’s available solar state without requiring complex calculations

Relevant code

The current heuristic is here:

export function getTimeOfDayWithSunData(sunData: SunMoonData & { hasSunData: boolean }): TimeOfDay {
  const now = new Date();

  // If we have real sun data, use it
  if (sunData.hasSunData && sunData.sunrise && sunData.sunset) {
    const currentTime = now.getTime();
    let sunriseTime = sunData.sunrise.getTime();
    let sunsetTime = sunData.sunset.getTime();

    // Check if sunrise/sunset are for tomorrow (common with Yandex Weather and similar integrations)
    // If sunrise is more than 12 hours in the future, subtract 24 hours to get today's time
    if (sunriseTime - currentTime > 12 * 60 * 60 * 1000) {
      sunriseTime -= 24 * 60 * 60 * 1000;
    }
    if (sunsetTime - currentTime > 12 * 60 * 60 * 1000) {
      sunsetTime -= 24 * 60 * 60 * 1000;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions