o
    9i'                     @   sR  d Z ddlZddlZddlZddlZddlZddlmZmZmZm	Z	 dZ
dZdZdZdZd	Zd
Zi ddddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7Zd8d9 ZG d:d; d;ZdDd=d>Zed?kred@ e Ze Zee eejeddAdBddC  dS dS )Eu  
WashOS — Open-Meteo Wetter-Poller v1
========================================
Pollt Open-Meteo (kostenlos, kein API-Key) für Lüneburg.
Liefert historische Tageswerte (letzte 90 Tage) + 7-Tage-Forecast
für Korrelation mit Umsatzdaten.

Open-Meteo Endpunkte:
  - /v1/archive  : historisch bis 2 Tage vor heute
  - /v1/forecast : aktueller Tag + 7 Tage Vorhersage

Starten: Wird automatisch von washos-server.py gestartet.
    N)datetimetimezone	timedeltadategH}J@g $@u	   LüneburgzEurope/Berlin      i`T  )Klarsonne   )u   Überwiegend klarr	      )u   Teils bewölktwolken   )u   Bewölktr   -   )Nebelr   0   )	Reifnebelr   3   )zLeichter Nieselregenregen5   )Nieselregenr   7   )zStarker Nieselregenr   8   )zGefrierender Nieselregenr   9   )zStarker gefr. Nieselr   =   )zLeichter Regenr   ?   )Regenr   A   )zStarker Regenr   B   )zGefrierender Regenr   C   )zStarker gefr. Regenr   G   )zLeichter Schneefallschnee)
Schneefallr    )zStarker Schneefallr    )Schneegrieselr    )Regenschauerr   )zStarke Regenschauerr   )zHeftige Regenschauerr   )zLeichte Schneeschauerr    )zStarke Schneeschauerr    )Gewitterr   )zGewitter mit Hagelr   )zSchweres Gewitterr   )I   K   M   P   Q   R   U   V   _   `   c   c                 C   sT   | du rdS t t| d\}}|dkr|dur|dkrdS |dur(|dkr(dS |S )	u8   Kategorie ableiten (für Umsatz-Korrelation verwendbar).N	unbekannt?r0   r	      heiss   r   )WEATHER_CODESgetint)code	precip_mmtmax_clabelcat r>   /app/server/washos-weather.pyclassify_weather?   s   r@   c                   @   sT   e Zd ZdddZdd Zdd Zdd	d
ZdefddZdefddZ	dd Z
dS )WeatherPoller.c                 C   s6   || _ tj|d| _t | _| jj	ddi d S )Nzweather.jsonz
User-Agentz
WashOS/1.0)

output_dirospathjoinoutput_filerequestsSessionsessionheadersupdate)selfrC   r>   r>   r?   __init__M   s   
zWeatherPoller.__init__c              
   C   s   t  tdd }|ttd d }tt| | dg dtd}z| j	j
d|dd	}|jd
kr8| W S W dS  tyT } ztd|  W Y d}~dS d}~ww )z!Historische Daten bis vorgestern.r   )daysr
   ,
weather_codetemperature_2m_maxtemperature_2m_mintemperature_2m_meanprecipitation_sumrain_sumsnowfall_sumprecipitation_hourssunshine_durationwind_speed_10m_max)latitude	longitude
start_dateend_datedailyr   z-https://archive-api.open-meteo.com/v1/archive   paramstimeout   z  [Weather] History-Fehler: N)r   todayr   HISTORY_DAYSLATLON	isoformatrF   TZrJ   r7   status_codejson	Exceptionprint)rM   endstartrc   rer>   r>   r?   _fetch_historyS   s.   

zWeatherPoller._fetch_historyc              
   C   s~   t tdg dtdtd}z| jjd|dd}|jdkr"| W S W d
S  t	y> } zt
d	|  W Y d
}~d
S d
}~ww )zHeute + 7 Tage Vorhersage.rP   rQ   r   )r\   r]   r`   r   	past_daysforecast_daysz&https://api.open-meteo.com/v1/forecastra   rb   re   z  [Weather] Forecast-Fehler: N)rh   ri   rF   rk   FORECAST_DAYSrJ   r7   rl   rm   rn   ro   )rM   rc   rr   rs   r>   r>   r?   _fetch_forecastu   s*   

zWeatherPoller._fetch_forecastFc                 C   s  |rd|vrg S |d }g }t  }t|dg D ]\}}zt |}W n	 ty.   Y qw |ddg| }	|ddg| }
|ddg| }|ddg| }|ddg| }|d	dg| }|d
dg| }|ddg| }|ddg| }|ddg| }t|durt|ndd\}}t|||	}|	|||k||k||||	durt
|	dnd|
durt
|
dnd|durt
|dnd|durt
|dnd|durt
|dnd|durt
|dnd|durt
|dnd|rt
|d dnd|durt
|dndd q|S )zTageswerte parsen.r`   timerS   NrT   rU   rV   rW   rX   rY   rZ   r[   rR   r1   r
   i  )r   	is_futureis_todayr9   r<   categorytmaxtmintmeanr:   rain_mmsnow_cmprecip_h
sunshine_hwind_kmh)r   rf   	enumerater7   fromisoformatrn   r6   r8   r@   appendround)rM   rawis_forecastdoutrf   idsdtr~   r   r   preciprainsnowprec_hsun_swindr9   r<   cat_rawr=   r>   r>   r?   _parse   sX   
zWeatherPoller._parsereturnc                 C   s   |   }|  }| j|dd}| j|dd}dd |D }|D ]}|||d < qt| dd d	}ttj	 d
t
ttdt|t|t|d|dS )z%Historie + Forecast holen und mergen.F)r   Tc                 S   s   i | ]}|d  |qS )r   r>   .0r   r>   r>   r?   
<dictcomp>   s    z+WeatherPoller.poll_once.<locals>.<dictcomp>r   c                 S   s   | d S )Nr   r>   )xr>   r>   r?   <lambda>   s    z)WeatherPoller.poll_once.<locals>.<lambda>)keyz
open-meteo)namelatlon)last_updatesourcelocationhistory_daysrv   
total_days)metarO   )rt   rx   r   sortedvaluesr   nowr   utcrj   LOCATION_NAMErh   ri   len)rM   histfc	hist_daysfc_daysby_dater   all_daysr>   r>   r?   	poll_once   s"   
zWeatherPoller.poll_oncedatac                 C   s  | j d }t|ddd}tj||ddd W d   n1 s w   Y  z	t|| j  W n tyB   d	dl}||| j  Y nw t	
 d
}|dg }tdd |D d}|rztd| dt| d|d  d|d  d|d  d dS td| dt| d dS )zSchreibe weather.json (atomar).z.tmpwzutf-8)encodingFr   )ensure_asciiindentNr   z%H:%M:%SrO   c                 s   s    | ]
}| d r|V  qdS )r|   N)r7   r   r>   r>   r?   	<genexpr>   s    z-WeatherPoller.write_output.<locals>.<genexpr>[z] WEATHER | z Tage | Heute: r<    r~   u   °C / r:   mmz Tage geladen)rG   openrm   dumprD   replaceOSErrorshutilmover   r   strftimer7   nextro   r   )rM   r   tmpfr   tsrO   today_entryr>   r>   r?   write_output   s4   
zWeatherPoller.write_outputc              
   C   st   t d 	 z|  }|dr| | nt d W n ty3 } zt d|  W Y d}~nd}~ww tt q)zEndlos-Polling alle 6 Stunden.z  [Weather] Starte Poller...TrO   z   [Weather] Keine Daten erhaltenz  [Weather] Fehler: N)ro   r   r7   r   rn   ry   sleepPOLL_INTERVAL)rM   r   rs   r>   r>   r?   
run_poller   s   

zWeatherPoller.run_pollerNrB   )F)__name__
__module____qualname__rN   rt   rx   r   dictr   r   r   r>   r>   r>   r?   rA   L   s    
"
 .rA   rB   c                 C   s(   t | d}tj|jddd}|  |S )z-Startet den Weather-Poller als Daemon-Thread.)rC   TrA   )targetdaemonr   )rA   	threadingThreadr   rq   )rC   pollertr>   r>   r?   start_weather_thread  s   
r   __main__u-   Open-Meteo Weather Poller — Standalone-TestF)r   r   i  r   )__doc__rm   rD   ry   r   rH   r   r   r   r   rh   ri   r   rk   rg   rw   r   r6   r@   rA   r   r   ro   r   r   r   r   dumpsr>   r>   r>   r?   <module>   s   (	
! 
=
 