Frost und Schnee Warnung

<!DOCTYPE html>
<html lang="de">
<head>
 <meta charset="UTF-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
 <title>Frost- & Schneewarnung – Kitzbühel & Ingolstadt</title>
 <style>
   body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; max-width: 750px; margin: 30px auto; padding: 20px; background: #f8fafc; color: #2d3748; }
   h1 { text-align: center; color: #1a202c; margin-bottom: 10px; }
   .subtitle { text-align: center; color: #718096; margin-bottom: 30px; }
   .ort { background: white; border-radius: 12px; padding: 20px; margin-bottom: 25px; box-shadow: 0 4px 6px rgba(0,0,0,0.05); }
   .ort h2 { margin: 0 0 15px 0; color: #2d3748; font-size: 1.3em; }
   table { width: 100%; border-collapse: collapse; font-size: 0.95em; }
   th, td { padding: 10px 8px; text-align: center; border-bottom: 1px solid #e2e8f0; }
   th { background: #edf2f7; color: #4a5568; font-weight: 600; }
   .frost { background: #fee2e2 !important; color: #991b1b; font-weight: bold; }
   .schnee { background: #dbeafe !important; color: #1e40af; font-weight: bold; }
   .beides { background: #f3e8ff !important; color: #6b21a8; font-weight: bold; }
   .ok { color: #166534; }
   .footer { text-align: center; margin-top: 40px; font-size: 0.85em; color: #718096; }
   .loading { color: #4299e1; font-style: italic; }
   .cron-box { background: #e6f3ff; border: 1px solid #90cdf4; border-radius: 8px; padding: 15px; margin: 25px 0; font-family: monospace; font-size: 0.9em; text-align: left; overflow-x: auto; }
   .cron-box strong { color: #2b6cb0; }
   @media (max-width: 600px) { table { font-size: 0.85em; } th, td { padding: 8px 4px; } }
 </style>
</head>
<body>

 <h1>Frost- & Schneewarnung: 7-Tage</h1>
 <p class="subtitle">
   <strong>Orte:</strong> Kitzbühel & Ingolstadt<br>
   <strong>Frost:</strong> ≤ 1 °C | <strong>Schnee:</strong> ≥ 1 cm | <strong>E-Mail bei beidem</strong>
 </p>

 <div id="kitzbuehel" class="ort">
   <h2>Kitzbühel</h2>
   <div class="loading">Lade Vorhersage…</div>
 </div>

 <div id="ingolstadt" class="ort">
   <h2>Ingolstadt</h2>
   <div class="loading">Lade Vorhersage…</div>
 </div>

 <!-- === AUTOMATISCHE E-MAIL BEI FROST ODER SCHNEE === -->
 <div class="cron-box">
   <strong>Automatische E-Mail bei Frost (≤1°C) ODER Schnee (≥1cm):</strong><br><br>
   <code>
0 18 * * * curl -s https://deine-domain.de/frostalarm.html | grep -q -E 'class="frost"|class="schnee"|class="beides"' && echo "WETTERWARNUNG! Frost oder Schnee erwartet. Siehe: https://deine-domain.de/frostalarm.html" | mail -s "FROST- ODER SCHNEE-WARNUNG" meine@email.de
   </code>
   <br><br>
   <small>E-Mail wird gesendet bei <strong>roten</strong> (Frost), <strong>blauen</strong> (Schnee) oder <strong>lila</strong> (beides) Zeilen.</small>
 </div>

 <div class="footer">
   Daten: <a href="https://open-meteo.com" target="_blank">Open-Meteo API</a> – kostenlos, keine Registrierung<br>
   Aktualisiert bei jedem Aufruf
 </div>

 <script>
   // === ORTE ===
   const orte = {
     kitzbuehel: { name: "Kitzbühel", lat: 47.4464, lon: 12.3912 },
     ingolstadt: { name: "Ingolstadt", lat: 48.7665, lon: 11.4258 }
   };

   // === SCHWELLEN ===
   const FROST_SCHWELLE = 1.9;   // ≤ 1.0 °C → Frost
   const SCHNEE_SCHWELLE = 1.0;  // ≥ 1.0 cm → Schnee

   // === 7-TAGE-TABELLE ===
   async function zeigeVorhersage(ortId, name, lat, lon) {

     try {
       const res = await fetch(url);
       if (!res.ok) throw new Error("API-Fehler: " + res.status);

       const data = await res.json();
       const temps = data.daily.temperature_2m_min;
       const schnee = data.daily.snowfall_sum;  // in cm
       const daten = data.daily.time;

       let tableHTML = `
         <table>
           <thead>
             <tr>
               <th>Datum</th>
               <th>Tag</th>
               <th>Min. Temp.</th>
               <th>Schnee (cm)</th>
             </tr>
           </thead>
           <tbody>`;

       const tageNamen = ["Heute", "Morgen", "+2 Tage", "+3 Tage", "+4 Tage", "+5 Tage", "+6 Tage"];

       for (let i = 0; i < temps.length; i++) {
         const temp = temps[i];
         const schneeCm = (schnee[i] || 0).toFixed(1);
         const datum = daten[i];
         const tagLabel = tageNamen[i];
         const tempStr = temp.toFixed(1) + " °C";
         const schneeStr = schneeCm + " cm";

         let klasse = "ok";
         let frost = temp <= FROST_SCHWELLE;
         let schneefall = parseFloat(schneeCm) >= SCHNEE_SCHWELLE;

         if (frost && schneefall) {
           klasse = "beides";
         } else if (frost) {
           klasse = "frost";
         } else if (schneefall) {
           klasse = "schnee";
         }

         tableHTML += `
           <tr class="${klasse}">
             <td><strong>${datum}</strong></td>
             <td>${tagLabel}</td>
             <td>${tempStr}</td>
             <td>${schneeStr}</td>
           </tr>`;
       }

       tableHTML += `</tbody></table>`;
       document.getElementById(ortId).innerHTML = `<h2>${name}</h2>` + tableHTML;

     } catch (e) {
       document.getElementById(ortId).innerHTML = `<h2>${name}</h2>
         <p style="color:#e53e3e">Fehler: ${e.message}</p>`;
     }
   }

   // === START ===
   zeigeVorhersage("kitzbuehel", orte.kitzbuehel.name, orte.kitzbuehel.lat, orte.kitzbuehel.lon);
   zeigeVorhersage("ingolstadt", orte.ingolstadt.name, orte.ingolstadt.lat, orte.ingolstadt.lon);
 </script>

</body>
</html>

anhängende Datei(en)
frostalarm3.html
404kb