<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pahenning</id>
	<title>FHEMWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pahenning"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Pahenning"/>
	<updated>2026-04-15T13:44:50Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEMWEB/VoiceControl:_Web-STT_%26_Hardware-Wakeword&amp;diff=40942</id>
		<title>FHEMWEB/VoiceControl: Web-STT &amp; Hardware-Wakeword</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEMWEB/VoiceControl:_Web-STT_%26_Hardware-Wakeword&amp;diff=40942"/>
		<updated>2026-04-06T07:18:37Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Datei:Voicecontrol.png|mini]]&lt;br /&gt;
&lt;br /&gt;
== VoiceControl – Sprachsteuerung via Browser und Atom Echo s3r ==&lt;br /&gt;
&lt;br /&gt;
Diese Lösung ermöglicht eine flexible Sprachsteuerung für [[FHEM]]. Sprache wird in Text (Speech-to-Text) umgewandelt und als Reading &amp;lt;code&amp;gt;STT&amp;lt;/code&amp;gt; im Device &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; bereitgestellt. Dieses Reading kann anschließend zentral (z. B. über &amp;lt;code&amp;gt;notify&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;DOIF&amp;lt;/code&amp;gt;) ausgewertet werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unterstützt werden nur Chromium-basierte Browser (Chrome, Edge, Fully Browser). Firefox hat leider kein Backend.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es gibt zwei unterschiedliche Wege zur Spracherfassung:&lt;br /&gt;
&lt;br /&gt;
* Weg 1️⃣ (Software): Browser-basierte Komplettlösung&lt;br /&gt;
* Weg 2️⃣ (Hybrid): Hardware-Wakeword + Browser-Spracherkennung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hilfe ===&lt;br /&gt;
* Forenthread zum {{Link2Forum|Topic=144147|LinkText=VoiceControl Sprachsteuerung}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Funktionen ===&lt;br /&gt;
&lt;br /&gt;
==== Grundprinzip ====&lt;br /&gt;
* Sprache → Speech-to-Text&lt;br /&gt;
* Ergebnis → Reading &amp;lt;code&amp;gt;STT&amp;lt;/code&amp;gt; im Device &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt;&lt;br /&gt;
* Zentrale Logik verarbeitet Befehle&lt;br /&gt;
&lt;br /&gt;
==== Betriebsarten ====&lt;br /&gt;
* Push-to-Talk (nur Browser)&lt;br /&gt;
* Always-On mit Wakeword&lt;br /&gt;
* Hardware-Wakeword (Hybrid)&lt;br /&gt;
&lt;br /&gt;
==== Rückmeldungen ====&lt;br /&gt;
* Sprachausgabe (TTS)&lt;br /&gt;
* Visuelle Bubble im Browser&lt;br /&gt;
* Optional gezielte Rückmeldung per Client-ID&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Weg 1️⃣: Browser-Lösung (voicecontrol.js) ==&lt;br /&gt;
&lt;br /&gt;
Das Script nutzt die Google Web Speech API. Unterstützt werden Chromium-basierte Browser (Chrome, Edge, Fully Browser). Firefox wird aktuell nicht unterstützt.&lt;br /&gt;
&lt;br /&gt;
=== Bedienung ===&lt;br /&gt;
&lt;br /&gt;
==== Push-to-Talk ====&lt;br /&gt;
* Button gedrückt halten&lt;br /&gt;
* Wakeword erforderlich (Standard: „James“)&lt;br /&gt;
* Nach Aktivierung ca.6sek Zeit für Befehl&lt;br /&gt;
&lt;br /&gt;
==== Always-On ====&lt;br /&gt;
* Kurzer Klick aktiviert Dauerbetrieb&lt;br /&gt;
* Wakeword erforderlich (Standard: „James“)&lt;br /&gt;
* Nach Aktivierung ca.6sek Zeit für Befehl&lt;br /&gt;
* JS wird neu gestartet udn Schleife fängt von vorne an&lt;br /&gt;
&lt;br /&gt;
==== Wakeword ====&lt;br /&gt;
* Standard: &amp;lt;code&amp;gt;james&amp;lt;/code&amp;gt;&lt;br /&gt;
* Anpassbar im Script:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const wakewords = [&amp;quot;james&amp;quot;];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
==== Datei kopieren ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
{ Svn_GetFile(&#039;contrib/voicecontrol.js&#039;, &#039;www/pgm2/voicecontrol.js&#039;) }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Einbindung ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr WEBphone JavaScripts www/pgm2/voicecontrol.js&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Hinweis (HTTP ohne HTTPS) ====&lt;br /&gt;
Chrome benötigt Freigabe für Mikrofon:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;chrome://flags/#unsafely-treat-insecure-origin-as-secure&amp;lt;/code&amp;gt;&lt;br /&gt;
* Eigene URL hinzufügen&lt;br /&gt;
* Auf &amp;lt;code&amp;gt;Enabled&amp;lt;/code&amp;gt; setzen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Weg 2️⃣: Hybrid-Lösung mit Browser + Atom Echo (voicecontrol_echo.js) ==&lt;br /&gt;
&lt;br /&gt;
Diese Variante kombiniert Hardware und Software:&lt;br /&gt;
&lt;br /&gt;
* Wakeword-Erkennung erfolgt auf dem ESP (Atom Echo s3r)&lt;br /&gt;
* Die eigentliche Sprachverarbeitung (Speech-to-Text) erfolgt im Browser&lt;br /&gt;
&lt;br /&gt;
=== Funktionsweise ===&lt;br /&gt;
&lt;br /&gt;
# Wakeword wird auf dem ESP erkannt&lt;br /&gt;
# FHEM erzeugt Event (z. B. &amp;lt;code&amp;gt;james_detected&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Browser empfängt Event via WebSocket&lt;br /&gt;
# Speech-to-Text startet im Browser&lt;br /&gt;
# Ergebnis wird an FHEM übertragen&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung ===&lt;br /&gt;
&lt;br /&gt;
* Kurzer Klick auf Button aktiviert/deaktiviert System&lt;br /&gt;
* Baut WebSocket-Verbindung zu FHEM auf&lt;br /&gt;
* Kein Push-to-Talk-Modus&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
==== Datei kopieren ====&lt;br /&gt;
&lt;br /&gt;
Die Datei voicecontrol_echo.js ist hier zu finden:&lt;br /&gt;
{{Link2Forum|Topic=144147|LinkText=VoiceControl Sprachsteuerung}}&lt;br /&gt;
und muss nach www/pgm2/voicecontrol_echo.js kopiert werden.&lt;br /&gt;
&lt;br /&gt;
Die echo_s3r.yaml ist für den Atom Echo s3r. Die Konfuguration ist weiter unten beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== Einbindung ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr WEBtablet JavaScripts www/pgm2/voicecontrol_echo.js&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration im Javascript ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const DEVICE  = &amp;quot;atom_echos3r_9888e00f4280&amp;quot;;&lt;br /&gt;
const TRIGGER = &amp;quot;james_detected&amp;quot;;&lt;br /&gt;
const FHEM_IP = &amp;quot;192.168.1.76:8085&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;DEVICE&amp;lt;/code&amp;gt; → FHEM-Device des ESP&lt;br /&gt;
* &amp;lt;code&amp;gt;TRIGGER&amp;lt;/code&amp;gt; → Event bei Wakeword&lt;br /&gt;
* &amp;lt;code&amp;gt;FHEM_IP&amp;lt;/code&amp;gt; → FHEM-Server&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration in der Yaml ===&lt;br /&gt;
&lt;br /&gt;
Damit sich der ESP mit eurem MQTT-Server und WLAN verbindet, müssen folgende Stellen angepasst werden.&lt;br /&gt;
&lt;br /&gt;
   wifi:&lt;br /&gt;
     ssid: &amp;quot;YOUR_SSID&amp;quot;&lt;br /&gt;
     password: &amp;quot;YOUR_PW&amp;quot;&lt;br /&gt;
     fast_connect: true&lt;br /&gt;
&lt;br /&gt;
   mqtt:&lt;br /&gt;
     broker: 192.168.1.76&lt;br /&gt;
     port: 1884&lt;br /&gt;
     username: &amp;quot;YOUR_USERNAME&amp;quot;&lt;br /&gt;
     password: &amp;quot;YOUR_PW&amp;quot;&lt;br /&gt;
     topic_prefix: atom_echo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wakeword (ESP / ESPHome) ===&lt;br /&gt;
&lt;br /&gt;
Das Wakeword wird direkt auf dem ESP definiert:&lt;br /&gt;
&lt;br /&gt;
* Umsetzung über ESPHome&lt;br /&gt;
* Eine große Auswahl an Wakewords sind hier zu finden:&lt;br /&gt;
   https://github.com/TaterTotterson/microWakeWords&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel, wie das Wakeword definiert wird.&lt;br /&gt;
&lt;br /&gt;
   micro_wake_word:&lt;br /&gt;
     id: mww&lt;br /&gt;
     microphone: echo_mic&lt;br /&gt;
     models:&lt;br /&gt;
       - model: &amp;quot;https://github.com/TaterTotterson/microWakeWords/raw/main/microWakeWordsV2/james.json&amp;quot;&lt;br /&gt;
         id: james_model&lt;br /&gt;
         probability_cutoff: 0.6   &lt;br /&gt;
&lt;br /&gt;
=== Kommunikation ===&lt;br /&gt;
&lt;br /&gt;
* WebSocket-Verbindung zu FHEM&lt;br /&gt;
* Lauscht auf Device-Events&lt;br /&gt;
* Automatischer Reconnect bei Abbruch&lt;br /&gt;
&lt;br /&gt;
=== Ablauf nach Wakeword ===&lt;br /&gt;
&lt;br /&gt;
# System sagt „Ja?“&lt;br /&gt;
# Browser startet SpeechRecognition&lt;br /&gt;
# Nutzer spricht Befehl&lt;br /&gt;
# Befehl wird verarbeitet&lt;br /&gt;
# Rückmeldung „Erledigt“&lt;br /&gt;
&lt;br /&gt;
== Zentrale Auswertung (Logik) ==&lt;br /&gt;
&lt;br /&gt;
Beide Wege schreiben in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;global:STT&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Verarbeitung erfolgt zentral über ein &amp;lt;code&amp;gt;notify&amp;lt;/code&amp;gt;. Ein Device wird in der Mappingtabelle eingetragen.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;esszimmer:licht|lampe|deckenlampe&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;Lampe01_Ez&amp;quot;, label =&amp;gt; &amp;quot;Licht Esszimmer&amp;quot;,  cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aufschlüsselung:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;hauptkeyword:Filter1|Filter3|Filter3&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;Devicename&amp;quot;, label =&amp;gt; &amp;quot;Übersichtname&amp;quot;,  cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispiel: notify ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod n_VoiceControl notify global:STT:.* {\&lt;br /&gt;
    # --- VORBEREITUNG ---\&lt;br /&gt;
    my ($cleanEvent, $clientId) = $EVENT =~ /^(.*)\s\[(.*)\]$/;;\&lt;br /&gt;
    $cleanEvent //= $EVENT;;\&lt;br /&gt;
    $clientId   //= &amp;quot;unknown&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
    # --- KONFIGURATION: Zentrales Mapping ---\&lt;br /&gt;
    my %smartHomeDevices = (\&lt;br /&gt;
        &amp;quot;esszimmer:licht|lampe|deckenlampe&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;Lampe01_Ez&amp;quot;, label =&amp;gt; &amp;quot;Licht Esszimmer&amp;quot;,  cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; },\&lt;br /&gt;
        &amp;quot;esszimmer:aquarium&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;Aquarium_Aktor&amp;quot;, label =&amp;gt; &amp;quot;Aquarium&amp;quot;, cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; },\&lt;br /&gt;
        &amp;quot;küche&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;Deckenlampe_Kue&amp;quot;, label =&amp;gt; &amp;quot;Licht Küche&amp;quot;, cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; },\&lt;br /&gt;
        &amp;quot;wohnzimmer&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;Lampe06_Dek&amp;quot;, label =&amp;gt; &amp;quot;Licht Wohnzimmer&amp;quot;, cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; },\&lt;br /&gt;
        &amp;quot;fernseher|tv&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;VuPlus&amp;quot;, label =&amp;gt; &amp;quot;Fernseher&amp;quot;, cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; },\&lt;br /&gt;
        &amp;quot;rechner|pc&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;PC_Aktor&amp;quot;, label =&amp;gt; &amp;quot;PC&amp;quot;, cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; },\&lt;br /&gt;
        &amp;quot;garage|tor&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;Garagentor_Aktor&amp;quot;, label =&amp;gt; &amp;quot;Garagentor öffnen/schließen&amp;quot;, cmdOn =&amp;gt; &amp;quot;open&amp;quot;, cmdOff =&amp;gt; &amp;quot;close&amp;quot; },\&lt;br /&gt;
        &amp;quot;kaffee&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;Kaffeemaschine&amp;quot;, label =&amp;gt; &amp;quot;Kaffeemaschine&amp;quot;, cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; },\&lt;br /&gt;
        &amp;quot;roberto&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;MQTT2_valetudo_FlusteredUnequaledFish&amp;quot;, label =&amp;gt; &amp;quot;Lade Roberto&amp;quot;, cmdOn =&amp;gt; &amp;quot;charge&amp;quot; },\&lt;br /&gt;
        &amp;quot;ambiente&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;LampeSzeneAlle&amp;quot;, label =&amp;gt; &amp;quot;Zentrales Licht&amp;quot;, type =&amp;gt; &amp;quot;dimmer&amp;quot;, cmdOn =&amp;gt; &amp;quot;on&amp;quot;, cmdOff =&amp;gt; &amp;quot;off&amp;quot; },\&lt;br /&gt;
        &amp;quot;sauge|reinige|putze|staubsauger|roboter&amp;quot; =&amp;gt; { dev =&amp;gt; &amp;quot;MQTT2_valetudo_FlusteredUnequaledFish&amp;quot;, label =&amp;gt; &amp;quot;Staubsauger&amp;quot;, type =&amp;gt; &amp;quot;vacuum&amp;quot; },\&lt;br /&gt;
         &amp;quot;ambilight&amp;quot; =&amp;gt; { label =&amp;gt; &amp;quot;Ambilight&amp;quot;, type =&amp;gt; &amp;quot;system&amp;quot;, cmd =&amp;gt; &amp;quot;sshpass -p &#039;GEHEIMESPASSWORD&#039; ssh -o StrictHostKeyChecking=no root\@192.168.1.46 &#039;/usr/share/hyperhdr/scripts/hyperhdr_toggle.sh&#039;&amp;quot; }\&lt;br /&gt;
    );;\&lt;br /&gt;
\&lt;br /&gt;
    my %vacRooms = (&amp;quot;arbeitszimmer&amp;quot; =&amp;gt; &amp;quot;Arbeitszimmer&amp;quot;, &amp;quot;badezimmer&amp;quot; =&amp;gt; &amp;quot;Badezimmer&amp;quot;, &amp;quot;esszimmer&amp;quot; =&amp;gt; &amp;quot;Esszimmer&amp;quot;, &amp;quot;flur&amp;quot; =&amp;gt; &amp;quot;Flur&amp;quot;, &amp;quot;küche&amp;quot; =&amp;gt; &amp;quot;Küche&amp;quot;, &amp;quot;wohnzimmer&amp;quot; =&amp;gt; &amp;quot;Wohnzimmer&amp;quot;);;\&lt;br /&gt;
\&lt;br /&gt;
    my $onRegEx  = &#039;\b(an|ein|einschalten|starte|aktivier|aktiviere|öffne|öffnen|auf|hoch|lade)\b&#039;;;\&lt;br /&gt;
    my $offRegEx = &#039;\b(aus|ausschalten|stop|stoppe|beende|deaktivier|deaktiviere|schließe|schließen|zu|runter)\b&#039;;;\&lt;br /&gt;
\&lt;br /&gt;
    my @commands = split(/\s*(?:und|dann|,)\s*/, lc($cleanEvent));;\&lt;br /&gt;
\&lt;br /&gt;
    # --- DER BEFEHLS-LOOP ---\&lt;br /&gt;
    foreach my $cmd_part (@commands) {\&lt;br /&gt;
        $cmd_part =~ s/^\s+|\s+$//g;;\&lt;br /&gt;
        my $is_on  = ($cmd_part =~ /$onRegEx/) ? 1 : 0;;\&lt;br /&gt;
        my $is_off = ($cmd_part =~ /$offRegEx/) ? 1 : 0;;\&lt;br /&gt;
        $cmd_part =~ s/\b(ich|brauche|mach|bitte|kannst du|würdest du|mal|doch|den|das|die|im|in der)\b//g;;\&lt;br /&gt;
\&lt;br /&gt;
        # --- GENERISCHE STEUERUNG ---\&lt;br /&gt;
        my $match = 0;;\&lt;br /&gt;
        # Sortierung stellt sicher, dass &#039;dimmer/vacuum&#039; Vorrang haben\&lt;br /&gt;
        foreach my $key (sort { ($smartHomeDevices{$b}{type}//&amp;quot;&amp;quot;) cmp ($smartHomeDevices{$a}{type}//&amp;quot;&amp;quot;) } keys %smartHomeDevices) {\&lt;br /&gt;
            \&lt;br /&gt;
            my ($main, $must) = split(/:/, $key);;\&lt;br /&gt;
            \&lt;br /&gt;
            # Prüfe Hauptwort\&lt;br /&gt;
            if ($cmd_part =~ /\b($main)\b/i) {\&lt;br /&gt;
                # Prüfe Pflichtwort falls vorhanden\&lt;br /&gt;
                next if ($must &amp;amp;&amp;amp; $cmd_part !~ /\b($must)\b/i);;\&lt;br /&gt;
                \&lt;br /&gt;
                my $d = $smartHomeDevices{$key};;\&lt;br /&gt;
\&lt;br /&gt;
                # A) System\&lt;br /&gt;
                if (($d-&amp;gt;{type} // &amp;quot;&amp;quot;) eq &amp;quot;system&amp;quot;) {\&lt;br /&gt;
                    system($d-&amp;gt;{cmd});;\&lt;br /&gt;
                }\&lt;br /&gt;
                \&lt;br /&gt;
                # B) Staubsauger\&lt;br /&gt;
                if (($d-&amp;gt;{type} // &amp;quot;&amp;quot;) eq &amp;quot;vacuum&amp;quot;) {\&lt;br /&gt;
                    my @found = grep { $cmd_part =~ /\b$_\b/ } keys %vacRooms;;\&lt;br /&gt;
                    fhem(@found ? &amp;quot;set $d-&amp;gt;{dev} clean_segment &amp;quot;.join(&amp;quot;,&amp;quot;, map { $vacRooms{$_} } @found) : &amp;quot;set $d-&amp;gt;{dev} start&amp;quot;);;\&lt;br /&gt;
                }\&lt;br /&gt;
                # C) Dimmer (Kompakt &amp;amp; korrigiert)\&lt;br /&gt;
                elsif (($d-&amp;gt;{type} // &amp;quot;&amp;quot;) eq &amp;quot;dimmer&amp;quot;) {\&lt;br /&gt;
                    $cmd_part =~ /(\d+)/ \&lt;br /&gt;
                        ? fhem(&amp;quot;set $d-&amp;gt;{dev} brightness &amp;quot; . int(($1 &amp;gt; 100 ? 100 : $1) * 2.55)) \&lt;br /&gt;
                        : ($is_on || $is_off) &amp;amp;&amp;amp; fhem(&amp;quot;set $d-&amp;gt;{dev} &amp;quot; . ($is_off ? &amp;quot;off&amp;quot; : &amp;quot;on&amp;quot;));;\&lt;br /&gt;
                }\&lt;br /&gt;
                # D) Standard An/Aus\&lt;br /&gt;
                else {\&lt;br /&gt;
                    my $fhem_cmd = $is_off ? ($d-&amp;gt;{cmdOff} // &amp;quot;off&amp;quot;) : ($d-&amp;gt;{cmdOn} // &amp;quot;on&amp;quot;);;\&lt;br /&gt;
                    fhem(&amp;quot;set $d-&amp;gt;{dev} $fhem_cmd&amp;quot;) if ($is_on || $is_off);;\&lt;br /&gt;
                }\&lt;br /&gt;
                \&lt;br /&gt;
                $match = 1;; last;;\&lt;br /&gt;
            }\&lt;br /&gt;
        }\&lt;br /&gt;
        next if $match;;\&lt;br /&gt;
\&lt;br /&gt;
        # --- HILFE ---\&lt;br /&gt;
        if ($cmd_part =~ /(hilfe|kommandos|übersicht)/) {\&lt;br /&gt;
            my $h = &#039;&amp;lt;div style=&amp;quot;text-align:left;;min-width:250px;;font-family:sans-serif;;&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Befehlsübersicht:&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;;;\&lt;br /&gt;
            my %seen;;\&lt;br /&gt;
            for my $k (sort keys %smartHomeDevices) {\&lt;br /&gt;
                my $d = $smartHomeDevices{$k};;\&lt;br /&gt;
                next if $seen{$d-&amp;gt;{label}}++;; \&lt;br /&gt;
                my $suffix = ($d-&amp;gt;{cmdOn} &amp;amp;&amp;amp; $d-&amp;gt;{cmdOff} &amp;amp;&amp;amp; $d-&amp;gt;{label} !~ /(an\/aus|öffnen\/schließen)/i) ? &amp;quot; (an/aus)&amp;quot; : &amp;quot;&amp;quot;;;\&lt;br /&gt;
                $suffix = &amp;quot; [0-100%]&amp;quot; if ($d-&amp;gt;{type} // &amp;quot;&amp;quot;) eq &amp;quot;dimmer&amp;quot;;;\&lt;br /&gt;
                $h .= &amp;quot;• $d-&amp;gt;{label}$suffix&amp;lt;br&amp;gt;&amp;quot;;;\&lt;br /&gt;
            }\&lt;br /&gt;
            $h .= &#039;&amp;lt;br&amp;gt;&amp;lt;u&amp;gt;Staubsauger Räume&amp;lt;/u&amp;gt;&amp;lt;br&amp;gt;• &#039;.join(&amp;quot;, &amp;quot;, map { ucfirst($_) } sort keys %vacRooms).&#039;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&#039;;;\&lt;br /&gt;
            $h =~ s/&#039;/\\&amp;quot;/g;;\&lt;br /&gt;
            my $js = &amp;quot;if((document.querySelector(&#039;input[name=\&amp;quot;fw_id\&amp;quot;]&#039;)||{}).value===&#039;$clientId&#039;){FW_okDialog(&#039;$h&#039;)}&amp;quot;;;\&lt;br /&gt;
            FW_directNotify(&amp;quot;#FHEMWEB:$_&amp;quot;, $js, &amp;quot;&amp;quot;) for devspec2array(&amp;quot;TYPE=FHEMWEB&amp;quot;);;\&lt;br /&gt;
        }\&lt;br /&gt;
    }\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Unterschiede der Wege ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Feature&lt;br /&gt;
! Browser&lt;br /&gt;
! Hybrid (Atom Echo S3)&lt;br /&gt;
|-&lt;br /&gt;
| Wakeword&lt;br /&gt;
| Browser&lt;br /&gt;
| ESP (Hardware)&lt;br /&gt;
|-&lt;br /&gt;
| Push-to-Talk&lt;br /&gt;
| Ja&lt;br /&gt;
| Nein&lt;br /&gt;
|-&lt;br /&gt;
| Always-On&lt;br /&gt;
| Ja (bedingt)&lt;br /&gt;
| Ja&lt;br /&gt;
|-&lt;br /&gt;
| Architektur&lt;br /&gt;
| Software&lt;br /&gt;
| Software + Hardware&lt;br /&gt;
|-&lt;br /&gt;
| Stabilität&lt;br /&gt;
| Sehr stabil&lt;br /&gt;
| Sehr stabil (Wakeword extern)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FireOS mit Fully Browser (Plus) ==&lt;br /&gt;
&lt;br /&gt;
Damit die Spracherkennung funktioniert:&lt;br /&gt;
&lt;br /&gt;
* Apps installieren:&lt;br /&gt;
   Google&lt;br /&gt;
   Speech Recognition &amp;amp; Synthesis&lt;br /&gt;
* FireOS:&lt;br /&gt;
   „Tastatur und Sprache“ → „Text-to-Speech“&lt;br /&gt;
* Fully Browser:&lt;br /&gt;
   &amp;lt;code&amp;gt;Enable JavaScriptInterface (PLUS)&amp;lt;/code&amp;gt; aktivieren&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:FHEM Frontends]]&lt;br /&gt;
[[Kategorie:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40941</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40941"/>
		<updated>2026-04-05T14:34:30Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Dieser Artikel soll mittelfristig die eher summarische Darstellung [[Ertragsprognose PV]] ersetzen}}&lt;br /&gt;
Für Fotovoltaikanlagen (PV), die mindestens teilweise dem Eigenverbrauch dienen, wird eine Ertragsprognose immer wichtiger. Nur dadurch kann man den Eigenverbrauch optimieren und die Netze signifikant entlasten.&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel erläutert die grundlegenden Berechnungen, um aus einer Angabe der Globalstrahlung auf einer horizontalen Fläche die Strahlungskomponenten der direkten Strahlung B, der diffusen Strahlung D und der durch Bodenreflexion hinzukommenden Strahlung R zu erhalten.&lt;br /&gt;
&lt;br /&gt;
== Vorarbeiten ==&lt;br /&gt;
Einer der wichtigsten Schritte für eine gute Ertragsprognose ist die Bestimmung der Lage und Ausrichtung der PV-Anlage.&lt;br /&gt;
* Die Werte für geografische Breite und Länge sowie Höhe über Meeresspiegel sollten in die Attribute latitude, longitude und altitude des global-Devices von FHEM eingetragen werden. Breite und Länge im dezimalen Format kann man in Google Maps einfach ablesen, die Höhenlage ist meistens im Wikipedia_Eintrag des Ortes zu finden.&lt;br /&gt;
* Für die vertikale Ausrichtung sollte die Neigung der Module bekannt sein, auch als Elevation bezeichnet, ggf. ist das einfach die Dachneigung. Konvention ist: 0°=horizontale Anordnung, 90°=vertikale Anordnung.&lt;br /&gt;
* Die horizontale Ausrichtung, manchmal als Azimut bezeichnet, kann man ebenfalls in Google Maps ablesen, wenn man ein Geodreieck an den Bildschirm hält. Konvention für die Himmelsrichtungen ist: 0°=Nord, 90°=Ost, 180°=Süd, 270°=West  &lt;br /&gt;
&lt;br /&gt;
== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche in W/m². &#039;&#039;&#039;Achtung&#039;&#039;&#039;: Die Vorhersagedaten des DWD sind in der Einheit kJ/m²h angegeben und müssen durch 3.6 dividiert werden, um die Intensität in W/m² zu erhalten&lt;br /&gt;
* γs = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* α = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* γ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* β = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(α)&lt;br /&gt;
für α &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(α)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(α)*cos(β)+cos(α)*sin(β)*cos(γs − γ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(α)&lt;br /&gt;
für α &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn α &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(β))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-α, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-α) = F/sin(α)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(α) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(β)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(β)) + C3*sin(β))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzeit nicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(β))&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Einfluss der Moduloberfläche ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf. Formal wird dies über so genannte &#039;Incident Angle Modifier&#039; IAM berücksichtigt, die jeweils Funktionen des oben berechneten Einfallswinkels θ sind. Das gebräuchlichste Modell dafür stammt von der &#039;&#039;American Society of Heating, Refrigerating and Air-Conditioning Engineers&#039;&#039; ASHRAE und lautet&lt;br /&gt;
 IAM(θ) = 1 - b0*(1/cos(θ) - 1)&lt;br /&gt;
mit einem modulabhängigen Parameter b0 = 0.05 .. 0.2 je nach Glasoberfläche der Module. Bei θ=0 ist dieser Faktor also 1 und fällt bei größeren Einfallswinkeln ab. Wichtig: IAM darf nicht negativ werden.&lt;br /&gt;
&lt;br /&gt;
Diesen IAM kann man für die direkte Strahlung verwenden. Bei diffuser Strahlung und Bodenreflexion kommen prinzipiell alle Einfallswinkel vor, so dass man zwar dieselbe Funktion verwenden kann, allerdings mit jeweils einem effektiven Einfallswinkel. Gebräuchliche Näherungen für diese effektiven Einfallswinkel sind&lt;br /&gt;
 θd = 59.7° − 0.1388*β + 0.001497*β²&lt;br /&gt;
 θr = 90° − 0.5788*β + 0.002693*β²&lt;br /&gt;
mit β in Grad.&lt;br /&gt;
&lt;br /&gt;
Die tatsächlich in elektrische Energie umsetzbare Strahlung ist also &lt;br /&gt;
 Ieff = IAM(θ)*B + IAM(θd)*D + IAM(θr)*R&lt;br /&gt;
Eine brauchbare Näherung ergibt sich bereits, wenn sowohl IAM(θd) als auch IAM(θr) auf 1 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Berechnung des Ertrags ==&lt;br /&gt;
Die elektrische Leistung aus der PV-Anlage ergibt sich, indem die berechnet effektive Einstrahlung Ieff mit der Modulfläche Am und dem Wirkungsgrad η multipliziert wird. Dieser Wirkungsgrad hängt stark von der Temperatur Tm der Module ab, er sinkt gegenüber dem Referenzwert η0 bei 25 °C um jeweils ca. 1% pro Kelvin ab.&lt;br /&gt;
&lt;br /&gt;
Die zu erwartende elektrische Leistung ist also &lt;br /&gt;
 P = Ieff * Am * η0 * (1 - 0.01*(Tc - 25))&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 8 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche. &#039;&#039;&#039;Achtung&#039;&#039;&#039;: Die vom DWD angegebenen Daten haben die Einheit kJ/m²h. Um diese in W/m² umzurechnen, müssen sie durch 3.6 dividiert werden.&lt;br /&gt;
* sunazi =&amp;gt; γs = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; α = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; γ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; β = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
* b0 =&amp;gt; b0 Materialfaktor für IAM, 0.05 .. 0.2 (Startwert für eine Vorhersage sollte 0.05 sein)&lt;br /&gt;
Rückgabewert ist die effektive Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model, $b0) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
&lt;br /&gt;
  $model = 0    if !defined($model);&lt;br /&gt;
  $b0    = 0.05 if !defined($b0);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  # IAM nur für Direktstrahlung (ASHRAE)&lt;br /&gt;
  my $IAMb = 1.0;&lt;br /&gt;
  if ($B_tilt &amp;gt; 0.0 &amp;amp;&amp;amp; $cos_thetai_pos &amp;gt; 0.0) {&lt;br /&gt;
    $IAMb = 1.0 - $b0 * (1.0 / $cos_thetai_pos - 1.0);&lt;br /&gt;
    $IAMb = 0.0 if $IAMb &amp;lt; 0.0;&lt;br /&gt;
    $IAMb = 1.0 if $IAMb &amp;gt; 1.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $B_eff = $B_tilt * $IAMb;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_eff + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Ertragsprognose_PV&amp;diff=40940</id>
		<title>Ertragsprognose PV</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Ertragsprognose_PV&amp;diff=40940"/>
		<updated>2026-04-05T14:29:07Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Die vorliegende Wiki-Seite ist nicht mehr aktuell. Eine genauere Berechnung findet man im Wiki-Artikel [[Von der Globalstrahlung zur Ertragsvorhersage]]. }}&lt;br /&gt;
Für Fotovoltaikanlagen (PV), die mindestens teilweise dem Eigenverbrauch dienen, wird eine Ertragsprognose immer wichtiger. Nur dadurch kann man den Eigenverbrauch optimieren und die Netze signifikant entlasten.&lt;br /&gt;
&lt;br /&gt;
== Vorarbeiten ==&lt;br /&gt;
Einer der wichtigsten Schritte für eine gute Ertragsprognose ist die Bestimmung der Lage und Ausrichtung der PV-Anlage.&lt;br /&gt;
* Die Werte für geografische Breite und Länge sowie Höhe über Meeresspiegel sollten in die Attribute latitude, longitude und altitude des global-Devices von FHEM eingetragen werden. Breite und Länge im dezimalen Format kann man in Google Maps einfach ablesen, die Höhenlage ist meistens im Wikipedia_Eintrag des Ortes zu finden.&lt;br /&gt;
* Für die vertikale Ausrichtung sollte die Neigung der Module bekannt sein, auch als Elevation bezeichnet, ggf. ist das einfach die Dachneigung. Konvention ist: 0°=horizontale Anordnung, 90°=vertikale Anordnung.&lt;br /&gt;
* Die horizontale Ausrichtung, manchmal als Azimut bezeichnet, kann man ebenfalls in Google Maps ablesen, wenn man ein Geodreieck an den Bildschirm hält. Konvention für die Himmelsrichtungen ist: 0°=Nord, 90°=Ost, 180°=Süd, 270°=West  &lt;br /&gt;
&lt;br /&gt;
== Jährliche Ertragsvorhersage ==&lt;br /&gt;
Für die Planung einer PV-Anlage ist es wichtig, den Jahresertrag zu prognostizieren. Dafür kann man von zwei Größen ausgehen:&lt;br /&gt;
* Dem kumulierten Energieeintrag auf eine horizontale Fläche von einem Quadratmeter durch die so genannte Globalstrahlung. Darin ist die die direkte Sonneneinstrahlung ebenso wie der mittlere Einfluss der Bewölkung enthalten - eben typisch für eine Region, also durchaus ganz unterschiedlich für unterschiedliche Orte selbst in Deutschland. Ein typischer Wert für München ist 1100 kWh/m²a.&lt;br /&gt;
* Einem Korrekturfaktor, der den Jahresertrag mit einem empirischen Wert multipliziert, der wiederum von der Flächenneigung der Anlage und der horizontalen Ausrichtung abhängt. Auch dieser so genannte Flächenfaktor ist aber regional beeinflusst, denn möglicherweise wird sich an einem durchschnittlichen Tag die Bewölkung in Hamburg anders verhalten als in München.Im unten aufgeführten Link des Ingenieurbüros Junge wird eine Tabelle dieser Korrekturfaktoren angegeben, deren Wert zwischen 33% und 118% schwankt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery widths=300px heights=300px&amp;gt;&lt;br /&gt;
File:PVProg_HFF.png|Interpolierte Tabelle&lt;br /&gt;
File:PVProg_GFF.png|Näherungsfunktion&lt;br /&gt;
File:PVProg diff.png|Absolute Abweichung zwischen Tabelle und Näherungsfunktion&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
Da die Interpolation in der Tabelle reichlich ungenau ist, wurde eine Näherungsfunktion bestimmt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
#  Flächenfaktor Photovoltaik&lt;br /&gt;
#&lt;br /&gt;
#  Prof. Dr. Peter A. Henning, September 2024&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
sub PV_hff($$){&lt;br /&gt;
&lt;br /&gt;
  my ($neigung,$ausrichtung) = @_;&lt;br /&gt;
  my $pi180  = 0.0174532918889;&lt;br /&gt;
  &lt;br /&gt;
  return undef&lt;br /&gt;
    if( $neigung&amp;lt;0.0 || $neigung&amp;gt;90.0 || $ausrichtung&amp;lt;0.0 || $ausrichtung&amp;gt;360. );&lt;br /&gt;
    &lt;br /&gt;
  my $x=$neigung*sin($ausrichtung*$pi180);&lt;br /&gt;
  my $y=$neigung*cos($ausrichtung*$pi180);&lt;br /&gt;
  &lt;br /&gt;
  my $x2 = $x**2;&lt;br /&gt;
  my $x4 = $x2**2;&lt;br /&gt;
  &lt;br /&gt;
  my $res = 3.808301895960147E-7 - 8.650170178954599E-11 * $x2 + 5.50016483344622E-15 * $x4;&lt;br /&gt;
  $res = $res*$y + 0.00007319316326291892- 3.604294916743569E-9 * $x2 - 2.343747951073022E-13 * $x4;&lt;br /&gt;
  $res = $res*$y - 0.00785953342909065  + 1.1197340251684106E-6 * $x2 - 8.99915952119488E-11 * $x4;&lt;br /&gt;
  $res = $res*$y - 0.8432627150525525 + 0.00010392051567819936 * $x2 - 3.979206287671085E-9 * $x4;&lt;br /&gt;
  $res = $res*$y +  99.49627151067648 - 0.006340200119196879 * $x2 + 2.052575360270524E-7 * $x4; &lt;br /&gt;
  &lt;br /&gt;
  return  $res&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Diese Näherungsfunktion gibt die Tabelle mit einer Genauigkeit von 2% wieder, siehe rechte Grafik&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung&#039;&#039;&#039;: Sowohl der kumulierte Energieertrag eines Jahres, als auch die Korrekturfaktoren sind einerseits standortabhängig. Andererseits aber auch zeitabhängig, denn der Klimawandel wirkt sich deutlich auf beide Werte aus.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40939</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40939"/>
		<updated>2026-04-05T14:05:21Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel erläutert die grundlegenden Berechnungen, um aus einer Angabe der Globalstrahlung auf einer horizontalen Fläche die Strahlungskomponenten der direkten Strahlung B, der diffusen Strahlung D und der durch Bodenreflexion hinzukommenden Strahlung R zu erhalten.&lt;br /&gt;
&lt;br /&gt;
== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche in W/m². &#039;&#039;&#039;Achtung&#039;&#039;&#039;: Die Vorhersagedaten des DWD sind in der Einheit kJ/m²h angegeben und müssen durch 3.6 dividiert werden, um die Intensität in W/m² zu erhalten&lt;br /&gt;
* γs = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* α = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* γ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* β = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(α)&lt;br /&gt;
für α &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(α)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(α)*cos(β)+cos(α)*sin(β)*cos(γs − γ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(α)&lt;br /&gt;
für α &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn α &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(β))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-α, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-α) = F/sin(α)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(α) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(β)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(β)) + C3*sin(β))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzeit nicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(β))&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Einfluss der Moduloberfläche ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf. Formal wird dies über so genannte &#039;Incident Angle Modifier&#039; IAM berücksichtigt, die jeweils Funktionen des oben berechneten Einfallswinkels θ sind. Das gebräuchlichste Modell dafür stammt von der &#039;&#039;American Society of Heating, Refrigerating and Air-Conditioning Engineers&#039;&#039; ASHRAE und lautet&lt;br /&gt;
 IAM(θ) = 1 - b0*(1/cos(θ) - 1)&lt;br /&gt;
mit einem modulabhängigen Parameter b0 = 0.05 .. 0.2 je nach Glasoberfläche der Module. Bei θ=0 ist dieser Faktor also 1 und fällt bei größeren Einfallswinkeln ab. Wichtig: IAM darf nicht negativ werden.&lt;br /&gt;
&lt;br /&gt;
Diesen IAM kann man für die direkte Strahlung verwenden. Bei diffuser Strahlung und Bodenreflexion kommen prinzipiell alle Einfallswinkel vor, so dass man zwar dieselbe Funktion verwenden kann, allerdings mit jeweils einem effektiven Einfallswinkel. Gebräuchliche Näherungen für diese effektiven Einfallswinkel sind&lt;br /&gt;
 θd = 59.7° − 0.1388*β + 0.001497*β²&lt;br /&gt;
 θr = 90° − 0.5788*β + 0.002693*β²&lt;br /&gt;
mit β in Grad.&lt;br /&gt;
&lt;br /&gt;
Die tatsächlich in elektrische Energie umsetzbare Strahlung ist also &lt;br /&gt;
 Ieff = IAM(θ)*B + IAM(θd)*D + IAM(θr)*R&lt;br /&gt;
Eine brauchbare Näherung ergibt sich bereits, wenn sowohl IAM(θd) als auch IAM(θr) auf 1 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Berechnung des Ertrags ==&lt;br /&gt;
Die elektrische Leistung aus der PV-Anlage ergibt sich, indem die berechnet effektive Einstrahlung Ieff mit der Modulfläche Am und dem Wirkungsgrad η multipliziert wird. Dieser Wirkungsgrad hängt stark von der Temperatur Tm der Module ab, er sinkt gegenüber dem Referenzwert η0 bei 25 °C um jeweils ca. 1% pro Kelvin ab.&lt;br /&gt;
&lt;br /&gt;
Die zu erwartende elektrische Leistung ist also &lt;br /&gt;
 P = Ieff * Am * η0 * (1 - 0.01*(Tc - 25))&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 8 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche. &#039;&#039;&#039;Achtung&#039;&#039;&#039;: Die vom DWD angegebenen Daten haben die Einheit kJ/m²h. Um diese in W/m² umzurechnen, müssen sie durch 3.6 dividiert werden.&lt;br /&gt;
* sunazi =&amp;gt; γs = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; α = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; γ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; β = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
* b0 =&amp;gt; b0 Materialfaktor für IAM, 0.05 .. 0.2 (Startwert für eine Vorhersage sollte 0.05 sein)&lt;br /&gt;
Rückgabewert ist die effektive Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model, $b0) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
&lt;br /&gt;
  $model = 0    if !defined($model);&lt;br /&gt;
  $b0    = 0.05 if !defined($b0);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  # IAM nur für Direktstrahlung (ASHRAE)&lt;br /&gt;
  my $IAMb = 1.0;&lt;br /&gt;
  if ($B_tilt &amp;gt; 0.0 &amp;amp;&amp;amp; $cos_thetai_pos &amp;gt; 0.0) {&lt;br /&gt;
    $IAMb = 1.0 - $b0 * (1.0 / $cos_thetai_pos - 1.0);&lt;br /&gt;
    $IAMb = 0.0 if $IAMb &amp;lt; 0.0;&lt;br /&gt;
    $IAMb = 1.0 if $IAMb &amp;gt; 1.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $B_eff = $B_tilt * $IAMb;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_eff + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40938</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40938"/>
		<updated>2026-04-05T14:04:05Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel erläutert die grundlegenden Berechnungen, um aus einer Angabe der Globalstrahlung auf einer horizontalen Fläche die Strahlungskomponenten der direkten Strahlung B, der diffusen Strahlung D und der durch Bodenreflexion hinzukommenden Strahlung R zu erhalten.&lt;br /&gt;
&lt;br /&gt;
== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche in W/m². &#039;&#039;&#039;Achtung&#039;&#039;&#039;: Die Vorhersagedaten des DWD sind in der Einheit kJ/m²h angegeben und müssen durch 3.6 dividiert werden, um die Intensität in W/m² zu erhalten&lt;br /&gt;
* γs = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* α = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* β = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(α)&lt;br /&gt;
für α &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(α)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(α)*cos(β)+cos(α)*sin(β)*cos(γs − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(α)&lt;br /&gt;
für α &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn α &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(β))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-α, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-α) = F/sin(α)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(α) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(β)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(β)) + C3*sin(β))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzeit nicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(β))&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Einfluss der Moduloberfläche ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf. Formal wird dies über so genannte &#039;Incident Angle Modifier&#039; IAM berücksichtigt, die jeweils Funktionen des oben berechneten Einfallswinkels θ sind. Das gebräuchlichste Modell dafür stammt von der &#039;&#039;American Society of Heating, Refrigerating and Air-Conditioning Engineers&#039;&#039; ASHRAE und lautet&lt;br /&gt;
 IAM(θ) = 1 - b0*(1/cos(θ) - 1)&lt;br /&gt;
mit einem modulabhängigen Parameter b0 = 0.05 .. 0.2 je nach Glasoberfläche der Module. Bei θ=0 ist dieser Faktor also 1 und fällt bei größeren Einfallswinkeln ab. Wichtig: IAM darf nicht negativ werden.&lt;br /&gt;
&lt;br /&gt;
Diesen IAM kann man für die direkte Strahlung verwenden. Bei diffuser Strahlung und Bodenreflexion kommen prinzipiell alle Einfallswinkel vor, so dass man zwar dieselbe Funktion verwenden kann, allerdings mit jeweils einem effektiven Einfallswinkel. Gebräuchliche Näherungen für diese effektiven Einfallswinkel sind&lt;br /&gt;
 θd = 59.7° − 0.1388*β + 0.001497*β²&lt;br /&gt;
 θr = 90° − 0.5788*β + 0.002693*β²&lt;br /&gt;
mit β in Grad.&lt;br /&gt;
&lt;br /&gt;
Die tatsächlich in elektrische Energie umsetzbare Strahlung ist also &lt;br /&gt;
 Ieff = IAM(θ)*B + IAM(θd)*D + IAM(θr)*R&lt;br /&gt;
Eine brauchbare Näherung ergibt sich bereits, wenn sowohl IAM(θd) als auch IAM(θr) auf 1 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Berechnung des Ertrags ==&lt;br /&gt;
Die elektrische Leistung aus der PV-Anlage ergibt sich, indem die berechnet effektive Einstrahlung Ieff mit der Modulfläche Am und dem Wirkungsgrad η multipliziert wird. Dieser Wirkungsgrad hängt stark von der Temperatur Tm der Module ab, er sinkt gegenüber dem Referenzwert η0 bei 25 °C um jeweils ca. 1% pro Kelvin ab.&lt;br /&gt;
&lt;br /&gt;
Die zu erwartende elektrische Leistung ist also &lt;br /&gt;
 P = Ieff * Am * η0 * (1 - 0.01*(Tc - 25))&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 8 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche. &#039;&#039;&#039;Achtung&#039;&#039;&#039;: Die vom DWD angegebenen Daten haben die Einheit kJ/m²h. Um diese in W/m² umzurechnen, müssen sie durch 3.6 dividiert werden.&lt;br /&gt;
* sunazi =&amp;gt; γs = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; α = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; β = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
* b0 =&amp;gt; b0 Materialfaktor für IAM, 0.05 .. 0.2 (Startwert für eine Vorhersage sollte 0.05 sein)&lt;br /&gt;
Rückgabewert ist die effektive Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model, $b0) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
&lt;br /&gt;
  $model = 0    if !defined($model);&lt;br /&gt;
  $b0    = 0.05 if !defined($b0);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  # IAM nur für Direktstrahlung (ASHRAE)&lt;br /&gt;
  my $IAMb = 1.0;&lt;br /&gt;
  if ($B_tilt &amp;gt; 0.0 &amp;amp;&amp;amp; $cos_thetai_pos &amp;gt; 0.0) {&lt;br /&gt;
    $IAMb = 1.0 - $b0 * (1.0 / $cos_thetai_pos - 1.0);&lt;br /&gt;
    $IAMb = 0.0 if $IAMb &amp;lt; 0.0;&lt;br /&gt;
    $IAMb = 1.0 if $IAMb &amp;gt; 1.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $B_eff = $B_tilt * $IAMb;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_eff + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Solar-/PV-%C3%9Cbersicht&amp;diff=40937</id>
		<title>Solar-/PV-Übersicht</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Solar-/PV-%C3%9Cbersicht&amp;diff=40937"/>
		<updated>2026-04-05T13:41:35Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Monitoring/Auswertung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right;margin-left:10px&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
Die Seite [[Solar-/PV-Übersicht]] soll einen schnellen Einstieg in die für Solar-/Photovoltaik-Betreiber relevanten Seiten und Threads ermöglichen. Bitte bei Bedarf selbständig ergänzen.&lt;br /&gt;
&lt;br /&gt;
==Forum==&lt;br /&gt;
Der Forenbereich {{Link2Forum|Area=Solaranlagen}} enthält Themen rund um Solaranlagen zur Wärme- oder Stromgewinnung.&lt;br /&gt;
&lt;br /&gt;
Unter der Überschrift {{Link2Forum|Topic=116747|LinkText=&amp;quot;Frevel: Die Idee einheitlicher Devicenamen und Readings&amp;quot;}} findet gerade eine Diskussion zum Thema Namenskonventionen für Readings statt.&lt;br /&gt;
&lt;br /&gt;
== Allgemein ==&lt;br /&gt;
* [[Fotovoltaikanlage]]&lt;br /&gt;
* Viele Seiten der Kategorie [[:Kategorie:Energieerzeugungsmessung|Energieerzeugungsmessung]]&lt;br /&gt;
&lt;br /&gt;
==Wechselrichter==&lt;br /&gt;
===Kostal===&lt;br /&gt;
* [[KostalPiko]]&lt;br /&gt;
* [[Kostal Plenticore 10 Plus]]&lt;br /&gt;
&lt;br /&gt;
===SMA===&lt;br /&gt;
* [[SMAWechselrichter]]&lt;br /&gt;
&lt;br /&gt;
===Solar Edge===&lt;br /&gt;
* [[SolarEdge Wechselrichter]]&lt;br /&gt;
&lt;br /&gt;
===Sunways===&lt;br /&gt;
* [[NT5000]]&lt;br /&gt;
&lt;br /&gt;
==Speicher==&lt;br /&gt;
* [[Sonnenspeicher]]&lt;br /&gt;
* [[Tesla Powerwall]]&lt;br /&gt;
&lt;br /&gt;
==Monitoring/Auswertung==&lt;br /&gt;
* [[Enecsys Monitoring System]]&lt;br /&gt;
* [[SunnyHomeManager]]&lt;br /&gt;
* [[Datenbankgestützte Erstellung der Energiebilanz einer SMA PV-Anlage mit Überschusseinspeisung]]&lt;br /&gt;
* [[SolarLog]]&lt;br /&gt;
* [[SolarForecast - Solare Prognose (PV Erzeugung) und Verbrauchersteuerung]]&lt;br /&gt;
* [[Von_der_Globalstrahlung_zur_Ertragsvorhersage]]&lt;br /&gt;
* [[Solaranlage Komplettbeispiel Fronius BYD]]&lt;br /&gt;
* [[Kostal_Plenticore_10_Plus#Wetter-/Leistungs-Prognose|Wetter-/Leistungs-Prognose - KI_Prognose mit DbLog/DbRep und RandomForestRegressor]]&lt;br /&gt;
&lt;br /&gt;
==Angrenzende Themen==&lt;br /&gt;
Verwandte Themen, &amp;quot;gern verwendete&amp;quot; oder erforderliche Module, etc.:&lt;br /&gt;
* [[ModbusAttr]]&lt;br /&gt;
* [[HTTPMOD]]&lt;br /&gt;
* [[SMLUSB]]&lt;br /&gt;
* [[EBUS-ECMD]]&lt;br /&gt;
* [[Stromzähler auslesen]]&lt;br /&gt;
* Externer Link [https://www.photovoltaikforum.com/ Photovoltaik-Forum]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40936</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40936"/>
		<updated>2026-04-05T13:35:15Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Perl-Programm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(γ)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(γ)) + C3*sin(γ))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzeit nicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Einfluss der Moduloberfläche ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf. Formal wird dies über so genannte &#039;Incident Angle Modifier&#039; IAM berücksichtigt, die jeweils Funktionen des oben berechneten Einfallswinkels θ sind. Das gebräuchlichste Modell dafür stammt von der &#039;&#039;American Society of Heating, Refrigerating and Air-Conditioning Engineers&#039;&#039; ASHRAE und lautet&lt;br /&gt;
 IAM(θ) = 1 - b0*(1/cos(θ) - 1)&lt;br /&gt;
mit einem modulabhängigen Parameter b0 = 0.05 .. 0.2 je nach Glasoberfläche der Module. Bei θ=0 ist dieser Faktor also 1 und fällt bei größeren Einfallswinkeln ab. Wichtig: IAM darf nicht negative werden.&lt;br /&gt;
&lt;br /&gt;
Diesen IAM kann man für die direkte Strahlung verwenden. Bei diffuser Strahlung und Bodenreflexion kommen prinzipiell alle Einfallswinkel vor, so dass man zwar dieselbe Funktion verwenden kann, allerdings mit jeweils einem effektiven Einfallswinkel. Gebräuchliche Näherungen für diese effektiven Einfallswinkel sind&lt;br /&gt;
 θd = 59.7° − 0.1388*γ + 0.001497*γ²&lt;br /&gt;
 θr = 90° − 0.5788*γ + 0.002693*γ²&lt;br /&gt;
mit γ in Grad.&lt;br /&gt;
&lt;br /&gt;
Die tatsächlich in elektrische Energie umsetzbare Strahlung ist also &lt;br /&gt;
 Ieff = IAM(θ)*B + IAM(θd)*D + IAM(θr)*R&lt;br /&gt;
Eine brauchbare Näherung ergibt sich bereits, wenn sowohl IAM(θd) als auch IAM(θr) auf 1 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Berechnung des Ertrags ==&lt;br /&gt;
Die elektrische Leistung aus der PV-Anlage ergibt sich, indem die berechnet effektive Einstrahlung Ieff mit der Modulfläche Am und dem Wirkungsgrad η multipliziert wird. Dieser Wirkungsgrad hängt stark von der Temperatur Tm der Module ab, er sinkt gegenüber dem Referenzwert η0 bei 25 °C um jeweils ca. 1% pro Kelvin ab.&lt;br /&gt;
&lt;br /&gt;
Die zu erwartende elektrische Leistung ist also &lt;br /&gt;
 P = Ieff * Am * η0 * (1 - 0.01*(Tc - 25))&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 8 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche. &#039;&#039;&#039;Achtung&#039;&#039;&#039;: Die vom DWD angegebenen Daten haben die Einheit kJ/m²h. Um diese in W/m² umzurechnen, müssen sie durch 3.6 dividiert werden.&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
* b0 =&amp;gt; b0 Materialfaktor für IAM, 0.05 .. 0.2 (Startwert für eine Vorhersage sollte 0.05 sein)&lt;br /&gt;
Rückgabewert ist die effektive Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model, $b0) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
&lt;br /&gt;
  $model = 0    if !defined($model);&lt;br /&gt;
  $b0    = 0.05 if !defined($b0);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  # IAM nur für Direktstrahlung (ASHRAE)&lt;br /&gt;
  my $IAMb = 1.0;&lt;br /&gt;
  if ($B_tilt &amp;gt; 0.0 &amp;amp;&amp;amp; $cos_thetai_pos &amp;gt; 0.0) {&lt;br /&gt;
    $IAMb = 1.0 - $b0 * (1.0 / $cos_thetai_pos - 1.0);&lt;br /&gt;
    $IAMb = 0.0 if $IAMb &amp;lt; 0.0;&lt;br /&gt;
    $IAMb = 1.0 if $IAMb &amp;gt; 1.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $B_eff = $B_tilt * $IAMb;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_eff + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40935</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40935"/>
		<updated>2026-04-05T09:21:14Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Perl-Programm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(γ)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(γ)) + C3*sin(γ))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzeit nicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Einfluss der Moduloberfläche ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf. Formal wird dies über so genannte &#039;Incident Angle Modifier&#039; IAM berücksichtigt, die jeweils Funktionen des oben berechneten Einfallswinkels θ sind. Das gebräuchlichste Modell dafür stammt von der &#039;&#039;American Society of Heating, Refrigerating and Air-Conditioning Engineers&#039;&#039; ASHRAE und lautet&lt;br /&gt;
 IAM(θ) = 1 - b0*(1/cos(θ) - 1)&lt;br /&gt;
mit einem modulabhängigen Parameter b0 = 0.05 .. 0.2 je nach Glasoberfläche der Module. Bei θ=0 ist dieser Faktor also 1 und fällt bei größeren Einfallswinkeln ab. Wichtig: IAM darf nicht negative werden.&lt;br /&gt;
&lt;br /&gt;
Diesen IAM kann man für die direkte Strahlung verwenden. Bei diffuser Strahlung und Bodenreflexion kommen prinzipiell alle Einfallswinkel vor, so dass man zwar dieselbe Funktion verwenden kann, allerdings mit jeweils einem effektiven Einfallswinkel. Gebräuchliche Näherungen für diese effektiven Einfallswinkel sind&lt;br /&gt;
 θd = 59.7° − 0.1388*γ + 0.001497*γ²&lt;br /&gt;
 θr = 90° − 0.5788*γ + 0.002693*γ²&lt;br /&gt;
mit γ in Grad.&lt;br /&gt;
&lt;br /&gt;
Die tatsächlich in elektrische Energie umsetzbare Strahlung ist also &lt;br /&gt;
 Ieff = IAM(θ)*B + IAM(θd)*D + IAM(θr)*R&lt;br /&gt;
Eine brauchbare Näherung ergibt sich bereits, wenn sowohl IAM(θd) als auch IAM(θr) auf 1 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Berechnung des Ertrags ==&lt;br /&gt;
Die elektrische Leistung aus der PV-Anlage ergibt sich, indem die berechnet effektive Einstrahlung Ieff mit der Modulfläche Am und dem Wirkungsgrad η multipliziert wird. Dieser Wirkungsgrad hängt stark von der Temperatur Tm der Module ab, er sinkt gegenüber dem Referenzwert η0 bei 25 °C um jeweils ca. 1% pro Kelvin ab.&lt;br /&gt;
&lt;br /&gt;
Die zu erwartende elektrische Leistung ist also &lt;br /&gt;
 P = Ieff * Am * η0 * (1 - 0.01*(Tc - 25))&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 8 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
* b0 =&amp;gt; b0 Materialfaktor für IAM, 0.05 .. 0.2 (Startwert für eine Vorhersage sollte 0.05 sein)&lt;br /&gt;
Rückgabewert ist die effektive Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model, $b0) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
&lt;br /&gt;
  $model = 0    if !defined($model);&lt;br /&gt;
  $b0    = 0.05 if !defined($b0);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  # IAM nur für Direktstrahlung (ASHRAE)&lt;br /&gt;
  my $IAMb = 1.0;&lt;br /&gt;
  if ($B_tilt &amp;gt; 0.0 &amp;amp;&amp;amp; $cos_thetai_pos &amp;gt; 0.0) {&lt;br /&gt;
    $IAMb = 1.0 - $b0 * (1.0 / $cos_thetai_pos - 1.0);&lt;br /&gt;
    $IAMb = 0.0 if $IAMb &amp;lt; 0.0;&lt;br /&gt;
    $IAMb = 1.0 if $IAMb &amp;gt; 1.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $B_eff = $B_tilt * $IAMb;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_eff + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40934</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40934"/>
		<updated>2026-04-05T08:55:00Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Einfluss der Moduloberfläche */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(γ)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(γ)) + C3*sin(γ))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzeit nicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Einfluss der Moduloberfläche ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf. Formal wird dies über so genannte &#039;Incident Angle Modifier&#039; IAM berücksichtigt, die jeweils Funktionen des oben berechneten Einfallswinkels θ sind. Das gebräuchlichste Modell dafür stammt von der &#039;&#039;American Society of Heating, Refrigerating and Air-Conditioning Engineers&#039;&#039; ASHRAE und lautet&lt;br /&gt;
 IAM(θ) = 1 - b0*(1/cos(θ) - 1)&lt;br /&gt;
mit einem modulabhängigen Parameter b0 = 0.05 .. 0.2 je nach Glasoberfläche der Module. Bei θ=0 ist dieser Faktor also 1 und fällt bei größeren Einfallswinkeln ab. Wichtig: IAM darf nicht negative werden.&lt;br /&gt;
&lt;br /&gt;
Diesen IAM kann man für die direkte Strahlung verwenden. Bei diffuser Strahlung und Bodenreflexion kommen prinzipiell alle Einfallswinkel vor, so dass man zwar dieselbe Funktion verwenden kann, allerdings mit jeweils einem effektiven Einfallswinkel. Gebräuchliche Näherungen für diese effektiven Einfallswinkel sind&lt;br /&gt;
 θd = 59.7° − 0.1388*γ + 0.001497*γ²&lt;br /&gt;
 θr = 90° − 0.5788*γ + 0.002693*γ²&lt;br /&gt;
mit γ in Grad.&lt;br /&gt;
&lt;br /&gt;
Die tatsächlich in elektrische Energie umsetzbare Strahlung ist also &lt;br /&gt;
 Ieff = IAM(θ)*B + IAM(θd)*D + IAM(θr)*R&lt;br /&gt;
Eine brauchbare Näherung ergibt sich bereits, wenn sowohl IAM(θd) als auch IAM(θr) auf 1 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Berechnung des Ertrags ==&lt;br /&gt;
Die elektrische Leistung aus der PV-Anlage ergibt sich, indem die berechnet effektive Einstrahlung Ieff mit der Modulfläche Am und dem Wirkungsgrad η multipliziert wird. Dieser Wirkungsgrad hängt stark von der Temperatur Tm der Module ab, er sinkt gegenüber dem Referenzwert η0 bei 25 °C um jeweils ca. 1% pro Kelvin ab.&lt;br /&gt;
&lt;br /&gt;
Die zu erwartende elektrische Leistung ist also &lt;br /&gt;
 P = Ieff * Am * η0 * (1 - 0.01*(Tc - 25))&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40933</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40933"/>
		<updated>2026-04-05T08:41:31Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Einfluss der Moduloberfläche */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(γ)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(γ)) + C3*sin(γ))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzeit nicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Einfluss der Moduloberfläche ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf. Formal wird dies über so genannte &#039;Incident Angle Modifier&#039; IAM berücksichtigt, die jeweils Funktionen des oben berechneten Einfallswinkels θ sind. Das gebräuchlichste Modell dafür stammt von der &#039;&#039;American Society of Heating, Refrigerating and Air-Conditioning Engineers&#039;&#039; ASHRAE und lautet&lt;br /&gt;
 IAM(θ) = 1 - b0*(1/cos(θ) - 1)&lt;br /&gt;
mit einem modulabhängigen Parameter b0 = 0.05 .. 0.2 je nach Glasoberfläche der Module. Bei θ=0 ist dieser Faktor also 1 und fällt bei größeren Einfallswinkeln ab. Wichtig: IAM darf nicht negative werden.&lt;br /&gt;
&lt;br /&gt;
Diesen IAM kann man für die direkte Strahlung verwenden. Bei diffuser Strahlung und Bodenreflexion kommen prinzipiell alle Einfallswinkel vor, so dass man zwar dieselbe Funktion verwenden kann, allerdings mit jeweils einem effektiven Einfallswinkel. Gebräuchliche Näherungen für diese effektiven Einfallswinkel sind&lt;br /&gt;
 θd = 59.7° − 0.1388*γ + 0.001497*γ²&lt;br /&gt;
 θr = 90° − 0.5788*γ + 0.002693*γ²&lt;br /&gt;
Die tatsächlich in elektrische Energie umgesetzte Strahlung ist also &lt;br /&gt;
 Igs = IAM(θ)*B + IAM(θd)*D + IAM(θr)*R&lt;br /&gt;
Eine brauchbare Näherung ergibt sich bereits, wenn sowohl IAM(θd) als auch IAM(θr) auf 1 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40932</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40932"/>
		<updated>2026-04-05T08:35:06Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(γ)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(γ)) + C3*sin(γ))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzeit nicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Einfluss der Moduloberfläche ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf. Formal wird dies über so genannte &#039;Incident Angle Modifier&#039; IAM berücksichtigt, die jeweils Funktionen des oben berechneten Einfallswinkels θ sind. Das gebräuchlichste Modell dafür lautet&lt;br /&gt;
 IAM(θ) = 1 - b0*(1/cos(θ) - 1)&lt;br /&gt;
mit einem modulabhängigen Parameter b0 = 0.05 .. 0.2 je nach Glasoberfläche der Module. Bei θ=0 ist dieser Faktor also 1 und fällt bei größeren Einfallswinkeln ab. Wichtig: IAM darf nicht negative werden.&lt;br /&gt;
&lt;br /&gt;
Diesen IAM kann man für die direkte Strahlung verwenden. Bei diffuser Strahlung und Bodenreflexion kommen prinzipiell alle Einfallswinkel vor, so dass man zwar dieselbe Funktion verwenden kann, allerdings mit jeweils einem effektiven Einfallswinkel. Gebräuchliche Näherungen für diese effektiven Einfallswinkel sind&lt;br /&gt;
 θd = 59.7° − 0.1388*γ + 0.001497*γ²&lt;br /&gt;
 θr = 90° − 0.5788*γ + 0.002693*γ²&lt;br /&gt;
Die tatsächlich in elektrische Energie umgesetzte Strahlung ist also &lt;br /&gt;
 Igs = IAM(θ)*B + IAM(θd)*D + IAM(θr)*R&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40931</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40931"/>
		<updated>2026-04-05T08:14:10Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Gesamtergebnis für die Einstrahlung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(γ)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(γ)) + C3*sin(γ))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzei tnicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 Ig = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Ertragsvorhersage ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf.&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40930</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40930"/>
		<updated>2026-04-05T08:12:45Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Diffuse Einstrahlung auf die PV-Fläche */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
==== Hay-Davies ====&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage. Allerdings muss man ggf. berücksichtigen, dass direkte Strahlung nur von &amp;quot;vorne&amp;quot; kommt, diffuse Strahlung aber ggf. auch von der anderen Seite. &lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​)*0.5*(1+cos(γ)))&lt;br /&gt;
==== Perez ====&lt;br /&gt;
Das Modell von Perez ist deutlich komplizierter, weil es die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt, aber zusätzlich eine Horizontaufhellung berücksichtigt. Im Endeffekt wird die diffuse Einstrahlung auf die PV-Fläche nach Perez berechnet als&lt;br /&gt;
 D = Sf * (C1 ​+ (1−C2)*0.5*(1+cos(γ)) + C3*sin(γ))&lt;br /&gt;
Allerdings ist die Berechnung der Koeffizienten C1..C3 sehr kompliziert, erfordert u.a. eine Wertetabelle. Außerdem ist für PV-Anlagen am Horizont mit Bebauung etc. zu rechnen, so dass die Verwendung dieses Modells derzei tnicht sinnvoll scheint.&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 I = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Ertragsvorhersage ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf.&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40929</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40929"/>
		<updated>2026-04-05T07:27:44Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Berechnung der Einstrahlung ==&lt;br /&gt;
Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage.&lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​) * 0.5*(1+cos(γ)))&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis für die Einstrahlung===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 I = B + D + R&lt;br /&gt;
&lt;br /&gt;
== Ertragsvorhersage ==&lt;br /&gt;
Bis zur Ertragsvorhersage sind noch mehrere Schritte zu unternehmen. Denn Solarmodule weisen unterschiedliche Empfindlichkeiten für die verschiedenen Strahlungsarten auf.&lt;br /&gt;
&lt;br /&gt;
== Perl-Programm ==&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40928</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40928"/>
		<updated>2026-04-04T18:05:48Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Bodenreflexion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage.&lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​) * 0.5*(1+cos(γ)))&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Gesamtergebnis ===&lt;br /&gt;
Die Einstrahlung auf die PV-Anlage ist also&lt;br /&gt;
 I = B + D + R&lt;br /&gt;
&lt;br /&gt;
=== Perl-Programm ===&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40927</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40927"/>
		<updated>2026-04-04T16:49:17Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Direkte Einstahlung auf die PV-Fläche */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β)*cos(γ)+cos(β)*sin(γ)*cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage.&lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​) * 0.5*(1+cos(γ)))&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Perl-Programm ===&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40926</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40926"/>
		<updated>2026-04-04T16:02:33Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β) * cos(γ)+cos(β)* sin(γ) * cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage.&lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​) * 0.5*(1+cos(γ)))&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Perl-Programm ===&lt;br /&gt;
Ein einfaches Perl-Programm zur Berechnung folgt hier. Es bekommt 7 Parameter übergeben:&lt;br /&gt;
* sg =&amp;gt; Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* sunazi =&amp;gt; α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* sunele =&amp;gt; β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* day =&amp;gt; n = Tag des Jahres, 1..365&lt;br /&gt;
* strazi =&amp;gt; φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* strtilt =&amp;gt; γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* model =&amp;gt; 0: Berechnung mit isotropem Himmelsmodell, 1: Berechnung nach Hay-Davies&lt;br /&gt;
&lt;br /&gt;
Rückgabewert ist die Einstrahlung auf die PV-Anlage in W/m²&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub pfx_PVforecast($$$$$$$) {&lt;br /&gt;
  my ($sg, $sunazi, $sunele, $day, $strazi, $strtilt, $model) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $rho = 0.2;          # Bodenalbedo&lt;br /&gt;
  my $pi  = 4 * atan2(1,1);&lt;br /&gt;
  my $deg = $pi / 180.0;&lt;br /&gt;
  my $Isc = 1367.0;       # Solarkonstante W/m²&lt;br /&gt;
&lt;br /&gt;
  return 0 if !defined($sg)     || $sg &amp;lt;= 0;&lt;br /&gt;
  return 0 if !defined($sunele) || $sunele &amp;lt;= 0;&lt;br /&gt;
  $model = 0 if !defined($model);&lt;br /&gt;
&lt;br /&gt;
  my $sunazi_r  = $sunazi  * $deg;&lt;br /&gt;
  my $sunele_r  = $sunele  * $deg;&lt;br /&gt;
  my $strazi_r  = $strazi  * $deg;&lt;br /&gt;
  my $strtilt_r = $strtilt * $deg;&lt;br /&gt;
&lt;br /&gt;
  my $sin_ele = sin($sunele_r);&lt;br /&gt;
  my $cos_ele = cos($sunele_r);&lt;br /&gt;
&lt;br /&gt;
  return 0 if $sin_ele &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $I0n = $Isc * (1.0 + 0.033 * cos(2.0 * $pi * $day / 365.0));&lt;br /&gt;
  my $I0h = $I0n * $sin_ele;&lt;br /&gt;
  return 0 if $I0h &amp;lt;= 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $Kt = $sg / $I0h;&lt;br /&gt;
  $Kt = 0.0 if $Kt &amp;lt; 0.0;&lt;br /&gt;
  $Kt = 1.0 if $Kt &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $kd;&lt;br /&gt;
  if ($Kt &amp;lt;= 0.22) {&lt;br /&gt;
    $kd = 1.0 - 0.09 * $Kt;&lt;br /&gt;
  }&lt;br /&gt;
  elsif ($Kt &amp;lt;= 0.80) {&lt;br /&gt;
    $kd = 0.9511&lt;br /&gt;
        - 0.1604  * $Kt&lt;br /&gt;
        + 4.388   * $Kt**2&lt;br /&gt;
        - 16.638  * $Kt**3&lt;br /&gt;
        + 12.336  * $Kt**4;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $kd = 0.165;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $kd = 0.0 if $kd &amp;lt; 0.0;&lt;br /&gt;
  $kd = 1.0 if $kd &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
  my $sf = $kd * $sg;      # diffuse horizontale Strahlung = DHI&lt;br /&gt;
  my $si = $sg - $sf;      # direkte horizontale Strahlung = BHI&lt;br /&gt;
  $si = 0.0 if $si &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai =&lt;br /&gt;
        $sin_ele * cos($strtilt_r)&lt;br /&gt;
      + $cos_ele * sin($strtilt_r) * cos($sunazi_r - $strazi_r);&lt;br /&gt;
&lt;br /&gt;
  my $cos_thetai_pos = $cos_thetai;&lt;br /&gt;
  $cos_thetai_pos = 0.0 if $cos_thetai_pos &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $dni = ($sin_ele &amp;gt; 0.01) ? ($si / $sin_ele) : 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $B_tilt = $dni * $cos_thetai_pos;&lt;br /&gt;
  $B_tilt = 0.0 if $B_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $D_tilt;&lt;br /&gt;
&lt;br /&gt;
  if ($model == 1) {&lt;br /&gt;
    my $Ai = ($sg &amp;gt; 0.0) ? (($si / $sg) * $Kt) : 0.0;&lt;br /&gt;
    $Ai = 0.0 if $Ai &amp;lt; 0.0;&lt;br /&gt;
    $Ai = 1.0 if $Ai &amp;gt; 1.0;&lt;br /&gt;
&lt;br /&gt;
    my $Rb = ($sin_ele &amp;gt; 0.01) ? ($cos_thetai_pos / $sin_ele) : 0.0;&lt;br /&gt;
    $Rb = 0.0 if $Rb &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
    $D_tilt = $sf * (&lt;br /&gt;
      $Ai * $Rb&lt;br /&gt;
      + (1.0 - $Ai) * (1.0 + cos($strtilt_r)) / 2.0&lt;br /&gt;
    );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    $D_tilt = $sf * (1.0 + cos($strtilt_r)) / 2.0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $D_tilt = 0.0 if $D_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $R_tilt = $rho * $sg * (1.0 - cos($strtilt_r)) / 2.0;&lt;br /&gt;
  $R_tilt = 0.0 if $R_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  my $G_tilt = $B_tilt + $D_tilt + $R_tilt;&lt;br /&gt;
  $G_tilt = 0.0 if $G_tilt &amp;lt; 0.0;&lt;br /&gt;
&lt;br /&gt;
  return $G_tilt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40925</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40925"/>
		<updated>2026-04-04T14:40:15Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Die direkte Normalstrahlung auf horizontaler Fläche ist&lt;br /&gt;
 DNI = Si * 1/sin(β)&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β) * cos(γ)+cos(β)* sin(γ) * cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F/sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
&lt;br /&gt;
Besser geeignet ist ein Modell nach Hay-Davies, in welchem die diffuse Einstrahlung in einen Anteil in Sonnennähe und einen isotropen Anteil zerlegt wird. Dafür benötigen wir den Zenitwinkel des Sonnenstandes, dieser ist gleich 90°-β, um einen geometrischen Faktor r zu berechnen&lt;br /&gt;
 r = F/cos(90°-β) = F/sin(β)&lt;br /&gt;
Darin ist F der im vorigen Abschnitt berechnete Faktor, also in der Regel der Kosinus des Einfallswinkels der direkten Strahlung auf die PV-Anlage.&lt;br /&gt;
&lt;br /&gt;
Desweiteren bestimmen wir einen Anisotropiefaktor A&lt;br /&gt;
 A =  DNI/I0n = Si/I0n * 1/sin(β) = Si/I0h = Si/Sg * Kt = (1 - kd)* Kt&lt;br /&gt;
Damit ergibt sich dann als diffuse Einstrahlung auf die PV-Fläche nach Hay-Davies&lt;br /&gt;
 D = Sf * (A*r ​+ (1−A​) * 0.5*(1+cos(γ)))&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstrahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40924</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40924"/>
		<updated>2026-04-04T13:51:25Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Diffuse Einstrahlung auf die PV-Fläche */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β) * cos(γ)+cos(β)* sin(γ) * cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F / sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
&lt;br /&gt;
Besser geeignet ist&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40923</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40923"/>
		<updated>2026-04-04T13:49:19Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Direkte Einstahlung auf die PV-Fläche */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β) * cos(γ)+cos(β)* sin(γ) * cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F / sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung gegen nummerische Instabilität sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 3°, ansonsten hart auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40922</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40922"/>
		<updated>2026-04-04T13:38:45Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
* n = Tag des Jahres, 1..365&lt;br /&gt;
Die Aufgabe besteht nun darin, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β) * cos(γ)+cos(β)* sin(γ) * cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F / sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 0.05.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;br /&gt;
Das so genannte isotrope Himmelsmodell ergibt für die diffuse Einstrahlung auf die PV-Fläche&lt;br /&gt;
 D = Sf * 0.5*(1+cos(γ))​&lt;br /&gt;
&lt;br /&gt;
=== Bodenreflexion ===&lt;br /&gt;
Bei geeigneter Anlage kann man noch die Bodenreflexion hinzufügen, mit einer Albedo&lt;br /&gt;
* ρ = 0.2 für &amp;quot;normalen&amp;quot; Boden&lt;br /&gt;
* ρ = 0.6 .. 0.8 bei Schnee&lt;br /&gt;
ergibt sich die Einstahlung aus Bodenreflexion als&lt;br /&gt;
 R = ρ * Sg * 0.5*(1-cos(γ))​&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40921</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40921"/>
		<updated>2026-04-04T13:29:57Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* γ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
=== Klarheitsindex und diffuser Anteil ===&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;br /&gt;
Um Instabilitäten bei kleinen Sonnenwinkeln zu vermeiden, sollte dieser Wert auf das Intervall [0,0.85] geclippt werden.&lt;br /&gt;
&lt;br /&gt;
Der diffuse Anteil nach Erbs ist dann&lt;br /&gt;
 Sf = kd * Sg&lt;br /&gt;
wobei der Wert kd sich wie folgt aus Kt ergibt:&lt;br /&gt;
* Für Kt &amp;lt;= 0.22 =&amp;gt; kd = 1-0.09*Kt&lt;br /&gt;
* Für 0.22 &amp;lt; Kt &amp;lt;= 0.80 =&amp;gt; kd = 0.9511−0.1604*Kt​+4.388*Kt²​−16.638*Kt³​+12.336*Kt⁴&lt;br /&gt;
* Für 0.80 &amp;lt;= Kt =&amp;gt; kd = 0.165&lt;br /&gt;
Der direkte Strahlungsanteil auf der horizontalen Fläche ist also&lt;br /&gt;
 Si = (1 - kd) * Sg &lt;br /&gt;
&lt;br /&gt;
=== Direkte Einstahlung auf die PV-Fläche ===&lt;br /&gt;
Der Kosinus des Einfallswinkels auf die Modulfläche ergibt sich als&lt;br /&gt;
 cos(θ)=sin(β) * cos(γ)+cos(β)* sin(γ) * cos(α − φ)&lt;br /&gt;
Dieser Wert wird negativ, wenn sich die Sonne hinter der PV-Fläche befindet. &lt;br /&gt;
* Wenn es ältere Module mit undurchsichtiger Rückseite sind, entfällt in diesem Fall die direkte Einstrahlung. Als Faktor für die weitere Rechnung ist also zu verwenden&lt;br /&gt;
 F = max(0,cos(θ))​&lt;br /&gt;
* Wenn es sich um eine Anlage mit modernen Glas-Glas-Modulen handelt, ist die direkte Einstrahlung auch dann noch vorhanden. Als Faktor für die weitere Rechnung ist bei gleicher Empfindlichkeit aus beiden Richtungen also zu verwenden&lt;br /&gt;
 F = abs(cos(θ))​&lt;br /&gt;
* Im Zweifelsfall ist hier ein Korrekturfaktor anzubringen, wenn cos(θ) &amp;lt; 0&lt;br /&gt;
&lt;br /&gt;
Die direkte Strahlung auf die PV-Anlage ergibt sich damit als&lt;br /&gt;
 B = Si * F / sin(β)&lt;br /&gt;
für β &amp;gt; 0. Zur besseren Absicherung sollte das aber tatsächlich nur verwendet werden wenn β &amp;gt; 0.05.&lt;br /&gt;
&lt;br /&gt;
=== Diffuse Einstrahlung auf die PV-Fläche ===&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40920</id>
		<title>Von der Globalstrahlung zur Ertragsvorhersage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Von_der_Globalstrahlung_zur_Ertragsvorhersage&amp;diff=40920"/>
		<updated>2026-04-04T12:54:35Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: Die Seite wurde neu angelegt: „Gegeben seien die folgenden Größen * Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche * α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung * β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht * φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn * θ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht Die Aufgabe…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gegeben seien die folgenden Größen&lt;br /&gt;
* Sg = Intensität der Globalstrahlung (diffuse und direkte Strahlung) auf einer horizontalen Fläche&lt;br /&gt;
* α = Azimutwinkel des Sonnenstandes, 180° = Südrichtung&lt;br /&gt;
* β = Höhenwinkel des Sonnenstandes, 0° = waagerecht, 90° = senkrecht&lt;br /&gt;
* φ = Azimutwinkel der PV-Anlage, 0° = Nordrichtung, 180° = Südrichtung, gemessen im Uhrzeigersinn&lt;br /&gt;
* θ = Neigungswinkel der PV-Anlage, 0° = horizontal, 90° = senkrecht&lt;br /&gt;
Die Aufgabe besteht nun, aus diesen Daten die Globalstrahlung und damit den Ertrag auf der geneigten PV-Anlage zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Als Zwischengrößen benötigen wir&lt;br /&gt;
* Si = Intensität der direkten Strahlung auf einer horizontalen Fläche&lt;br /&gt;
* Sf = Intensität der diffusen Strahlung auf einer horizontalen Fläche&lt;br /&gt;
womit also gilt&lt;br /&gt;
 Sg = Sf + Si&lt;br /&gt;
Die direkte Normalstahlung DNI ergibt sich aus&lt;br /&gt;
 DNI = Si/sin(β)&lt;br /&gt;
für β &amp;gt; 0.&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt schätzen wir aus der Globalstrahlung einen Klarheitsindex Kt ab, indem wir zunächst mit der Solarkonstante&lt;br /&gt;
 I0 = 1367 W/m²&lt;br /&gt;
die außeratmosphärische normale Einstrahlung I0n modellieren. Diese beträgt am  n-ten Tag des Jahres ungefähr&lt;br /&gt;
 I0n = I0 * ( 1 + 0.033 * cos( 360° * n/365))&lt;br /&gt;
Horizontal ergibt sich damit&lt;br /&gt;
 I0h = I0n*sin(β)&lt;br /&gt;
für β &amp;gt; 0. Der Klarheitsindex ergibt sich als&lt;br /&gt;
 Kt = Sg/I0h&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40859</id>
		<title>Tapo Kameras</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40859"/>
		<updated>2026-03-24T16:42:55Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Stream und Snapshot */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verifiziert für Tapo C530WS&lt;br /&gt;
&lt;br /&gt;
== Cloud-Installation ==&lt;br /&gt;
Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Wichtig: In der Tapo-App unter &amp;quot;Ich&amp;quot; unbedingt &amp;quot;Dienste von Drittanbietern&amp;quot; aufrufen und &amp;quot;Kompatibilität mit Drittanbietern&amp;quot; auf EIN stellen!&lt;br /&gt;
&lt;br /&gt;
== Stream und Snapshot ==&lt;br /&gt;
Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera angelegt werden, unter Einstellungen-&amp;gt;Erweiterte Einstellungen.&lt;br /&gt;
Dabei werden ein Username und ein Passwort festgelegt, die im Folgenden als &amp;lt;USERKAMERA&amp;gt; und &amp;lt;PWKAMERA&amp;gt; abgekürzt werden.&lt;br /&gt;
&lt;br /&gt;
Auf dem FHEM-Server (oder einem anderen System zum Testen) muss dann die ffmpeg-Suite installiert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Kamera eingeschaltet ist, lässt sich dann der Stream der Kamera abgreifen mit&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&lt;br /&gt;
in voller Auflösung, sowie mit reduzierter Auflösung als&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream2&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;: Beschreibung RSTPtoWeb nachziehen&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Snapshots wird über ein Shellskript gesteuert, das man unter https://github.com/pahenning/TapoCam_for_FHEM/tapo_snapshot.sh findet. Für das Weitere gehen wir davon aus, dass dieses Shellskript unter /opt/fhem/tapo liegt und durch den FHEM-Prozess ausführbar ist. Wir definieren ein Dummy-Device mit zunächst minimalen Eigenschaften&lt;br /&gt;
 defmod TapoCam dummy&lt;br /&gt;
 attr TapoCam readingList snapshot&lt;br /&gt;
 attr TapoCam setList getPhoto:noArg &lt;br /&gt;
sowie ein DOIF&lt;br /&gt;
 defmod TapoCam.N DOIF ([TapoCam:state] =~ /^getPhoto$/) \&lt;br /&gt;
 ({my $res = qx(/opt/fhem/tapo/tapo_snapshot.sh);;\&lt;br /&gt;
  chomp($res);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam snapshot $res&amp;quot;);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam state ready&amp;quot;)\&lt;br /&gt;
 }\&lt;br /&gt;
 )&lt;br /&gt;
mit Attribut&lt;br /&gt;
 attr TapoCam.N do always&lt;br /&gt;
Dann sorgt der FHEM-Befehl&lt;br /&gt;
 set TapoCam getPhoto&lt;br /&gt;
dafür, dass ein Snapshot unter /opt/fhem/www/images gespeichert wird. Im FHEMWEB Frontend ist er dann unter /fhem/images/Tapo.jpg ansehbar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: Komfortabler machen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Kamerasteuerung mit Python==&lt;br /&gt;
=== FHEM-Device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod TapoCam dummy&lt;br /&gt;
attr TapoCam devStateIcon stream_running:it_camera@green stream_stopped:it_camera@black&lt;br /&gt;
attr TapoCam readingList snapshot motor_action motor_result motor_presets error&lt;br /&gt;
attr TapoCam setList getPhoto:noArg getClip getEvents privacy:on,off light:on,off light_intensity light_duration light_night:ir,white,auto led:on,off moveLeft moveRight moveUp moveDown calibrate:noArg preset_goto:1,2,3,4,5,6,7,8 preset_save preset_delete getPresets detection_motion detection_person detection_pet detection_tamper detection_vehicle detection_linecrossing alarm:on,off alarm_light:on,off alarm_sound:on,off alarm_duration alarm_volume:low,medium,high&lt;br /&gt;
attr TapoCam stateFormat {my $x=ReadingsAge(&amp;quot;TapoCam&amp;quot;,&amp;quot;snapshot&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $v=ReadingsVal(&amp;quot;TapoCam&amp;quot;,&amp;quot;event_dl_link&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $w=ReadingsAge(&amp;quot;TapoCam&amp;quot;,&amp;quot;event_dl&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $y=(ReadingsVal(&amp;quot;TapoCam&amp;quot;,&amp;quot;privacy&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;off&amp;quot;)?&amp;quot;&amp;lt;a href=\&amp;quot;http://192.168.0.94:8085/pages/player/webrtc/stream1/0\&amp;quot;&amp;gt;\nstream_running\n&amp;lt;/a&amp;gt;&amp;quot;:&amp;quot;stream_stopped&amp;quot;;;\&lt;br /&gt;
 sprintf(&amp;quot;&amp;lt;p style=\&amp;quot;text-align:left;;font-weight:normal\&amp;quot;&amp;gt;\n%s\n&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;a href=\&amp;quot;http://192.168.0.94:8083/fhem/images/Tapo.jpg\&amp;quot;&amp;gt;Tapo.jpg&amp;lt;/a&amp;gt; (%s)\n&amp;lt;br/&amp;gt;&amp;lt;a href=\&amp;quot;%s\&amp;quot;&amp;gt;TapoClip.mp4&amp;lt;/a&amp;gt; (%s)\n&amp;lt;/p&amp;gt;&amp;quot;,$y,$x,$v,$w)}&lt;br /&gt;
attr TapoCam webCmd getPhoto:moveLeft:moveRight:moveUp:moveDown&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== DOIF ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod TapoCam.N DOIF ([TapoCam:state] ne &amp;quot;ready&amp;quot;)&lt;br /&gt;
({TapoCamHandler(&amp;quot;$DEVICE&amp;quot;,&amp;quot;$EVENT&amp;quot;)})&lt;br /&gt;
(setreading TapoCam state ready)&lt;br /&gt;
DOELSEIF&lt;br /&gt;
([+00:05:00])&lt;br /&gt;
({TapoCamHandler(&amp;quot;TapoCam&amp;quot;,&amp;quot;status_update&amp;quot;)})&lt;br /&gt;
attr TapoCam.N do always&lt;br /&gt;
attr TapoCam.N wait 0,3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Handler ===&lt;br /&gt;
In der Datei https://github.com/pahenning/TapoCam_for_FHEM/99_TapoCamUtils.pm findet man zwei Funktionen:&lt;br /&gt;
* &#039;&#039;&#039;TapoCamHelper&#039;&#039;&#039; - nimmt als Parameter den Namen eines FHEM_Devices für die Kamera und ein Event entgegen und ruft dann eines der Python-Skripte auf. Dieses läuft asynchron ab, d.h. die Rückmeldung an FHEM kann bis zu 10 Sekunden dauern.&lt;br /&gt;
* &#039;&#039;&#039;TapoReturnHelper&#039;&#039;&#039; - wird aus dem Python-Skript gerufen und mit einer JSON-Struktur befüllt. Die Inhalte dieser JSON-Struktur werden auf Readings in dem FHEM-Device verteilt.&lt;br /&gt;
=== Python Vorbereitung ===&lt;br /&gt;
Zur Vorbereitung folgende Schritte ggf. mit root-Rechten unternehmen:&lt;br /&gt;
 mkdir -p /opt/fhem/tapo&lt;br /&gt;
 cd /opt/fhem/tapo&lt;br /&gt;
 python3 -m venv .venv&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install --upgrade pip&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install pytapo&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install aiofiles&lt;br /&gt;
 chown -R fhem:dialout /opt/fhem/tapo&lt;br /&gt;
 chmod -R u+rwX /opt/fhem/tapo&lt;br /&gt;
Dadurch wird im Verzeichnis /opt/fhem/tapo eine virtuelle Umgebung für die TapoCam angelegt. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Falls mit den nachfolgend aufgeführten Skripten irgendwelche Laufzeitfehler auftauchen, kann dies an einer veralteten Version von Python liegen. Aktuell ist eigentlich die Version 3.13 erforderlich.&lt;br /&gt;
&lt;br /&gt;
In dieses Verzeichnis können nun die Python-Skripte aus https://github.com/pahenning/TapoCam_for_FHEM hineinkopiert werden.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tapo_credentials.py&#039;&#039;&#039; - enthält &amp;lt;IPKAMERA&amp;gt; und &amp;lt;PWCLOUD&amp;gt;, sowie IP-Adresse, Port des FHEM-Servers, dessen statischen (!) csrf-Parameter und den Devicenamen des TapoCam-Devices.&lt;br /&gt;
* &#039;&#039;&#039;tapo_helper.py&#039;&#039;&#039; - diverse Hilfsfunktionen, die von den anderen Skripten importiert werden.&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_privacy.py&#039;&#039;&#039; - Kontrollprogramm für den &amp;quot;PRIVAT&amp;quot;-Modus der Kamera - d.h. das Ausschalten der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_privacy.py&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_privacy.py on|off&amp;lt;/code&amp;gt; -&amp;gt; setzt den &amp;quot;PRIVAT&amp;quot;-Modus (Kamera aus), oder hebt ihn auf (Kamera eingeschaltet)&lt;br /&gt;
=== Bewegung ===&lt;br /&gt;
* &#039;&#039;&#039; tapo_control_motor.py&#039;&#039;&#039; - Kontrollprogramm für die Bewegungen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py left [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach links. Ohne Parameter wird um den in der Kamera eingestellten Wert, typisch 10°, bewegt. Wenn ein Parameter angegeben wird, ist das der Winkel für die Bewegung.&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py right [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach rechts. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py up [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach oben. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py down [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach unten. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py calibrate&amp;lt;/code&amp;gt;  -&amp;gt; Kalibrierung der Kamerabewegung&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py presets&amp;lt;/code&amp;gt;  -&amp;gt; Hole die definierten Positionen &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py goto &amp;lt;preset&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Gehe zur definierten Position (Zahlenangabe) &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py save &amp;lt;preset&amp;gt; &amp;lt;name&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Speichere die gegenwärtige Position (Zahlenangabe und Name)&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py delete &amp;lt;preset&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Lösche die definierte Position (Zahlenangabe) &lt;br /&gt;
=== Beleuchtung ===&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_light.py&#039;&#039;&#039; - Kontrollprogramm für die Lichtfunktionen der Kamera. Kann wie folgt gerufen werden: &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py status&amp;lt;/code&amp;gt;  -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py led on|off&amp;lt;/code&amp;gt; -&amp;gt; Schaltet die Kamera-LED an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py light on|off&amp;lt;/code&amp;gt; -&amp;gt; Schaltet das Kameralicht an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py intensity &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Helligkeit des Kameralichtss&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py time &amp;lt;0-3600&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Dauer des Kameralichts&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py night ir|white|auto&amp;lt;/code&amp;gt; -&amp;gt; Modus des Kameralichts bei Nacht&lt;br /&gt;
=== Kamera-Events ===&lt;br /&gt;
Events werden ausgelöst, wenn eine bestimmte Detektion erfolgt ist. Dafür gibt es &lt;br /&gt;
* &#039;&#039;&#039;tapo_control_detection.py&#039;&#039;&#039; - Kontrollprogramm für die Erkennungsfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_detection.py status&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_detection.py motion &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Bewegungserkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py person &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Personenserkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py vehicle &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Fahrzeugerkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py pet &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Haustiererkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py tamper &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Sabotageerkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py linecrossing &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Erkennung des Übertretens einer virtuellen Linie. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
&lt;br /&gt;
Diese Events werden nur gespeichert, wenn in der Kamera eine SD-Karte eingesetzt wurde. Empfohlen werden mindesten 16 GByte, diese Karte wird als Ringpuffer mit den Erkennungsevents beschrieben. Dabei werden jeweils kurze Videoclips aufgenommen (1 min Dauer). Welche Events vorhanden sind, kann man abfragen mit&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_events.py&#039;&#039;&#039; - Kontrollprogramm für die Eventfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_events.py &amp;lt;seconds&amp;gt;&amp;lt;/code&amp;gt; - Hole die während der vergangenen &amp;lt;seconds&amp;gt; Sekunden detektierten Events von der Kamera und meldet sie an FHEM. Diese Clips werden dabei durchnummeriert. Die Liste der im Zeitfenster vorhandenen Events wird in der Datei /tmp/tapo_control_events.json zwischengespeichert.&lt;br /&gt;
&lt;br /&gt;
Das Programm zum Download ist&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_download.py&#039;&#039;&#039; - Kontrollprogramm zum Download eines Event-Videoclips auf den FHEM-Server. Kann wie folgt gerufen werden:&lt;br /&gt;
*** &amp;lt;code&amp;gt;tapo_control_download.py clip &amp;lt;number&amp;gt; [DEBUG]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;number&amp;gt; ist die aus der o.a. Nummerierung abzulesende Nummer des Events. DEBUG: 0 oder 1, default 0. Wenn DEBUG eingeschaltet ist, werden auf STDOUT Kontrollnachrichten ausgegeben.&lt;br /&gt;
&lt;br /&gt;
Bei diesem Download laufen etliche Dinge im Hintergrund ab, insbesondere ist das Linux-Paket ffmpeg nötig, um die Umwandlung des Kameravideos in eine MP4-Datei durchzuführen. Diese wird in /tmp/tapo_recordings/clips gespeichert, und ein Link von /opt/fhem/www/images/TapoClip.mp4 auf diese Datei angelegt.&lt;br /&gt;
&lt;br /&gt;
=== Alarmierung ===&lt;br /&gt;
Bei entsprechend detektierten Events kann auch ein lokaler Alarm in der Kamera ausgelöst werden (blinkende Beleuchtung = light und/oder Sirene=sound). Achtung: light und sound dürfen nicht beide off sein.&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_alarm.py&#039;&#039;&#039;- Kontrollprogramm für die Alarmfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py status&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py on|off&amp;lt;/code&amp;gt; -&amp;gt; schaltet die Alarmfunktionen an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py light on|off&amp;lt;/code&amp;gt; -&amp;gt; bei Alarm wird das Licht eingeschaltet, oder nicht&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py sound on|off&amp;lt;/code&amp;gt; -&amp;gt; bei Alarm wird die Sirene eingeschaltet, oder nicht.&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py volume low|medium|high&amp;lt;/code&amp;gt; -&amp;gt; Lautstärke der Sirene&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py duration &amp;lt;zahl&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Dauer eines Alarms in Sekunden&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40858</id>
		<title>Tapo Kameras</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40858"/>
		<updated>2026-03-24T16:42:09Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Stream und Snapshot */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verifiziert für Tapo C530WS&lt;br /&gt;
&lt;br /&gt;
== Cloud-Installation ==&lt;br /&gt;
Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Wichtig: In der Tapo-App unter &amp;quot;Ich&amp;quot; unbedingt &amp;quot;Dienste von Drittanbietern&amp;quot; aufrufen und &amp;quot;Kompatibilität mit Drittanbietern&amp;quot; auf EIN stellen!&lt;br /&gt;
&lt;br /&gt;
== Stream und Snapshot ==&lt;br /&gt;
Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera angelegt werden, unter Einstellungen-&amp;gt;Erweiterte Einstellungen.&lt;br /&gt;
Dabei werden ein Username und ein Passwort festgelegt, die im Folgenden als &amp;lt;USERKAMERA&amp;gt; und &amp;lt;PWKAMERA&amp;gt; abgekürzt werden.&lt;br /&gt;
&lt;br /&gt;
Auf dem FHEM-Server (oder einem anderen System zum Testen) muss dann die ffmpeg-Suite installiert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Kamera eingeschaltet ist, lässt sich dann der Stream der Kamera abgreifen mit&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&lt;br /&gt;
in voller Auflösung, sowie mit reduzierter Auflösung als&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream2&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Snapshots wird über ein Shellskript gesteuert, das man unter https://github.com/pahenning/TapoCam_for_FHEM/tapo_snapshot.sh findet. Für das Weitere gehen wir davon aus, dass dieses Shellskript unter /opt/fhem/tapo liegt und durch den FHEM-Prozess ausführbar ist. Wir definieren ein Dummy-Device mit zunächst minimalen Eigenschaften&lt;br /&gt;
 defmod TapoCam dummy&lt;br /&gt;
 attr TapoCam readingList snapshot&lt;br /&gt;
 attr TapoCam setList getPhoto:noArg &lt;br /&gt;
sowie ein DOIF&lt;br /&gt;
 defmod TapoCam.N DOIF ([TapoCam:state] =~ /^getPhoto$/) \&lt;br /&gt;
 ({my $res = qx(/opt/fhem/tapo/tapo_snapshot.sh);;\&lt;br /&gt;
  chomp($res);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam snapshot $res&amp;quot;);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam state ready&amp;quot;)\&lt;br /&gt;
 }\&lt;br /&gt;
 )&lt;br /&gt;
mit Attribut&lt;br /&gt;
 attr TapoCam.N do always&lt;br /&gt;
Dann sorgt der FHEM-Befehl&lt;br /&gt;
 set TapoCam getPhoto&lt;br /&gt;
dafür, dass ein Snapshot unter /opt/fhem/www/images gespeichert wird. Im FHEMWEB Frontend ist er dann unter /fhem/images/Tapo.jpg ansehbar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: Komfortabler machen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Kamerasteuerung mit Python==&lt;br /&gt;
=== FHEM-Device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod TapoCam dummy&lt;br /&gt;
attr TapoCam devStateIcon stream_running:it_camera@green stream_stopped:it_camera@black&lt;br /&gt;
attr TapoCam readingList snapshot motor_action motor_result motor_presets error&lt;br /&gt;
attr TapoCam setList getPhoto:noArg getClip getEvents privacy:on,off light:on,off light_intensity light_duration light_night:ir,white,auto led:on,off moveLeft moveRight moveUp moveDown calibrate:noArg preset_goto:1,2,3,4,5,6,7,8 preset_save preset_delete getPresets detection_motion detection_person detection_pet detection_tamper detection_vehicle detection_linecrossing alarm:on,off alarm_light:on,off alarm_sound:on,off alarm_duration alarm_volume:low,medium,high&lt;br /&gt;
attr TapoCam stateFormat {my $x=ReadingsAge(&amp;quot;TapoCam&amp;quot;,&amp;quot;snapshot&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $v=ReadingsVal(&amp;quot;TapoCam&amp;quot;,&amp;quot;event_dl_link&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $w=ReadingsAge(&amp;quot;TapoCam&amp;quot;,&amp;quot;event_dl&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $y=(ReadingsVal(&amp;quot;TapoCam&amp;quot;,&amp;quot;privacy&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;off&amp;quot;)?&amp;quot;&amp;lt;a href=\&amp;quot;http://192.168.0.94:8085/pages/player/webrtc/stream1/0\&amp;quot;&amp;gt;\nstream_running\n&amp;lt;/a&amp;gt;&amp;quot;:&amp;quot;stream_stopped&amp;quot;;;\&lt;br /&gt;
 sprintf(&amp;quot;&amp;lt;p style=\&amp;quot;text-align:left;;font-weight:normal\&amp;quot;&amp;gt;\n%s\n&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;a href=\&amp;quot;http://192.168.0.94:8083/fhem/images/Tapo.jpg\&amp;quot;&amp;gt;Tapo.jpg&amp;lt;/a&amp;gt; (%s)\n&amp;lt;br/&amp;gt;&amp;lt;a href=\&amp;quot;%s\&amp;quot;&amp;gt;TapoClip.mp4&amp;lt;/a&amp;gt; (%s)\n&amp;lt;/p&amp;gt;&amp;quot;,$y,$x,$v,$w)}&lt;br /&gt;
attr TapoCam webCmd getPhoto:moveLeft:moveRight:moveUp:moveDown&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== DOIF ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod TapoCam.N DOIF ([TapoCam:state] ne &amp;quot;ready&amp;quot;)&lt;br /&gt;
({TapoCamHandler(&amp;quot;$DEVICE&amp;quot;,&amp;quot;$EVENT&amp;quot;)})&lt;br /&gt;
(setreading TapoCam state ready)&lt;br /&gt;
DOELSEIF&lt;br /&gt;
([+00:05:00])&lt;br /&gt;
({TapoCamHandler(&amp;quot;TapoCam&amp;quot;,&amp;quot;status_update&amp;quot;)})&lt;br /&gt;
attr TapoCam.N do always&lt;br /&gt;
attr TapoCam.N wait 0,3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Handler ===&lt;br /&gt;
In der Datei https://github.com/pahenning/TapoCam_for_FHEM/99_TapoCamUtils.pm findet man zwei Funktionen:&lt;br /&gt;
* &#039;&#039;&#039;TapoCamHelper&#039;&#039;&#039; - nimmt als Parameter den Namen eines FHEM_Devices für die Kamera und ein Event entgegen und ruft dann eines der Python-Skripte auf. Dieses läuft asynchron ab, d.h. die Rückmeldung an FHEM kann bis zu 10 Sekunden dauern.&lt;br /&gt;
* &#039;&#039;&#039;TapoReturnHelper&#039;&#039;&#039; - wird aus dem Python-Skript gerufen und mit einer JSON-Struktur befüllt. Die Inhalte dieser JSON-Struktur werden auf Readings in dem FHEM-Device verteilt.&lt;br /&gt;
=== Python Vorbereitung ===&lt;br /&gt;
Zur Vorbereitung folgende Schritte ggf. mit root-Rechten unternehmen:&lt;br /&gt;
 mkdir -p /opt/fhem/tapo&lt;br /&gt;
 cd /opt/fhem/tapo&lt;br /&gt;
 python3 -m venv .venv&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install --upgrade pip&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install pytapo&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install aiofiles&lt;br /&gt;
 chown -R fhem:dialout /opt/fhem/tapo&lt;br /&gt;
 chmod -R u+rwX /opt/fhem/tapo&lt;br /&gt;
Dadurch wird im Verzeichnis /opt/fhem/tapo eine virtuelle Umgebung für die TapoCam angelegt. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Falls mit den nachfolgend aufgeführten Skripten irgendwelche Laufzeitfehler auftauchen, kann dies an einer veralteten Version von Python liegen. Aktuell ist eigentlich die Version 3.13 erforderlich.&lt;br /&gt;
&lt;br /&gt;
In dieses Verzeichnis können nun die Python-Skripte aus https://github.com/pahenning/TapoCam_for_FHEM hineinkopiert werden.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tapo_credentials.py&#039;&#039;&#039; - enthält &amp;lt;IPKAMERA&amp;gt; und &amp;lt;PWCLOUD&amp;gt;, sowie IP-Adresse, Port des FHEM-Servers, dessen statischen (!) csrf-Parameter und den Devicenamen des TapoCam-Devices.&lt;br /&gt;
* &#039;&#039;&#039;tapo_helper.py&#039;&#039;&#039; - diverse Hilfsfunktionen, die von den anderen Skripten importiert werden.&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_privacy.py&#039;&#039;&#039; - Kontrollprogramm für den &amp;quot;PRIVAT&amp;quot;-Modus der Kamera - d.h. das Ausschalten der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_privacy.py&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_privacy.py on|off&amp;lt;/code&amp;gt; -&amp;gt; setzt den &amp;quot;PRIVAT&amp;quot;-Modus (Kamera aus), oder hebt ihn auf (Kamera eingeschaltet)&lt;br /&gt;
=== Bewegung ===&lt;br /&gt;
* &#039;&#039;&#039; tapo_control_motor.py&#039;&#039;&#039; - Kontrollprogramm für die Bewegungen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py left [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach links. Ohne Parameter wird um den in der Kamera eingestellten Wert, typisch 10°, bewegt. Wenn ein Parameter angegeben wird, ist das der Winkel für die Bewegung.&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py right [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach rechts. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py up [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach oben. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py down [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach unten. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py calibrate&amp;lt;/code&amp;gt;  -&amp;gt; Kalibrierung der Kamerabewegung&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py presets&amp;lt;/code&amp;gt;  -&amp;gt; Hole die definierten Positionen &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py goto &amp;lt;preset&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Gehe zur definierten Position (Zahlenangabe) &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py save &amp;lt;preset&amp;gt; &amp;lt;name&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Speichere die gegenwärtige Position (Zahlenangabe und Name)&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py delete &amp;lt;preset&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Lösche die definierte Position (Zahlenangabe) &lt;br /&gt;
=== Beleuchtung ===&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_light.py&#039;&#039;&#039; - Kontrollprogramm für die Lichtfunktionen der Kamera. Kann wie folgt gerufen werden: &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py status&amp;lt;/code&amp;gt;  -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py led on|off&amp;lt;/code&amp;gt; -&amp;gt; Schaltet die Kamera-LED an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py light on|off&amp;lt;/code&amp;gt; -&amp;gt; Schaltet das Kameralicht an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py intensity &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Helligkeit des Kameralichtss&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py time &amp;lt;0-3600&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Dauer des Kameralichts&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py night ir|white|auto&amp;lt;/code&amp;gt; -&amp;gt; Modus des Kameralichts bei Nacht&lt;br /&gt;
=== Kamera-Events ===&lt;br /&gt;
Events werden ausgelöst, wenn eine bestimmte Detektion erfolgt ist. Dafür gibt es &lt;br /&gt;
* &#039;&#039;&#039;tapo_control_detection.py&#039;&#039;&#039; - Kontrollprogramm für die Erkennungsfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_detection.py status&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_detection.py motion &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Bewegungserkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py person &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Personenserkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py vehicle &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Fahrzeugerkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py pet &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Haustiererkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py tamper &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Sabotageerkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py linecrossing &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Erkennung des Übertretens einer virtuellen Linie. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
&lt;br /&gt;
Diese Events werden nur gespeichert, wenn in der Kamera eine SD-Karte eingesetzt wurde. Empfohlen werden mindesten 16 GByte, diese Karte wird als Ringpuffer mit den Erkennungsevents beschrieben. Dabei werden jeweils kurze Videoclips aufgenommen (1 min Dauer). Welche Events vorhanden sind, kann man abfragen mit&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_events.py&#039;&#039;&#039; - Kontrollprogramm für die Eventfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_events.py &amp;lt;seconds&amp;gt;&amp;lt;/code&amp;gt; - Hole die während der vergangenen &amp;lt;seconds&amp;gt; Sekunden detektierten Events von der Kamera und meldet sie an FHEM. Diese Clips werden dabei durchnummeriert. Die Liste der im Zeitfenster vorhandenen Events wird in der Datei /tmp/tapo_control_events.json zwischengespeichert.&lt;br /&gt;
&lt;br /&gt;
Das Programm zum Download ist&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_download.py&#039;&#039;&#039; - Kontrollprogramm zum Download eines Event-Videoclips auf den FHEM-Server. Kann wie folgt gerufen werden:&lt;br /&gt;
*** &amp;lt;code&amp;gt;tapo_control_download.py clip &amp;lt;number&amp;gt; [DEBUG]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;number&amp;gt; ist die aus der o.a. Nummerierung abzulesende Nummer des Events. DEBUG: 0 oder 1, default 0. Wenn DEBUG eingeschaltet ist, werden auf STDOUT Kontrollnachrichten ausgegeben.&lt;br /&gt;
&lt;br /&gt;
Bei diesem Download laufen etliche Dinge im Hintergrund ab, insbesondere ist das Linux-Paket ffmpeg nötig, um die Umwandlung des Kameravideos in eine MP4-Datei durchzuführen. Diese wird in /tmp/tapo_recordings/clips gespeichert, und ein Link von /opt/fhem/www/images/TapoClip.mp4 auf diese Datei angelegt.&lt;br /&gt;
&lt;br /&gt;
=== Alarmierung ===&lt;br /&gt;
Bei entsprechend detektierten Events kann auch ein lokaler Alarm in der Kamera ausgelöst werden (blinkende Beleuchtung = light und/oder Sirene=sound). Achtung: light und sound dürfen nicht beide off sein.&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_alarm.py&#039;&#039;&#039;- Kontrollprogramm für die Alarmfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py status&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py on|off&amp;lt;/code&amp;gt; -&amp;gt; schaltet die Alarmfunktionen an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py light on|off&amp;lt;/code&amp;gt; -&amp;gt; bei Alarm wird das Licht eingeschaltet, oder nicht&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py sound on|off&amp;lt;/code&amp;gt; -&amp;gt; bei Alarm wird die Sirene eingeschaltet, oder nicht.&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py volume low|medium|high&amp;lt;/code&amp;gt; -&amp;gt; Lautstärke der Sirene&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py duration &amp;lt;zahl&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Dauer eines Alarms in Sekunden&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40857</id>
		<title>Tapo Kameras</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40857"/>
		<updated>2026-03-24T16:38:54Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Kamerasteuerung mit Python */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verifiziert für Tapo C530WS&lt;br /&gt;
&lt;br /&gt;
== Cloud-Installation ==&lt;br /&gt;
Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Wichtig: In der Tapo-App unter &amp;quot;Ich&amp;quot; unbedingt &amp;quot;Dienste von Drittanbietern&amp;quot; aufrufen und &amp;quot;Kompatibilität mit Drittanbietern&amp;quot; auf EIN stellen!&lt;br /&gt;
&lt;br /&gt;
== Stream und Snapshot ==&lt;br /&gt;
Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera angelegt werden, unter Einstellungen-&amp;gt;Erweiterte Einstellungen.&lt;br /&gt;
Dabei werden ein Username und ein Passwort festgelegt, die im Folgenden als &amp;lt;USERKAMERA&amp;gt; und &amp;lt;PWKAMERA&amp;gt; abgekürzt werden.&lt;br /&gt;
&lt;br /&gt;
Auf dem FHEM-Server (oder einem anderen System zum Testen) muss dann die ffmpeg-Suite installiert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Kamera eingeschaltet ist, lässt sich dann der Stream der Kamera abgreifen mit&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&lt;br /&gt;
in voller Auflösung, sowie mit reduzierter Auflösung als&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream2&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Snapshots wird über ein Shellskript gesteuert, mit folgendem Inhalt&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 OUT=&amp;quot;/opt/fhem/www/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 URL=&amp;quot;/fhem/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 ffmpeg -rtsp_transport tcp -y \&lt;br /&gt;
   -i &amp;quot;rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&amp;quot; \&lt;br /&gt;
   -frames:v 1 &amp;quot;$OUT&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;br /&gt;
 if [ $? -eq 0 ] &amp;amp;&amp;amp; [ -s &amp;quot;$OUT&amp;quot; ]; then&lt;br /&gt;
   echo &amp;quot;$URL&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
   echo &amp;quot;error creating image&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
Für das Weitere gehen wir davon aus, dass dieses Shellskript unter /opt/fhem/tapo liegt und durch den FHEM-Prozess ausführbar ist.&lt;br /&gt;
Wir definieren ein Dummy-Device mit zunächst minimalen Eigenschaften&lt;br /&gt;
 defmod TapoCam dummy&lt;br /&gt;
 attr TapoCam readingList snapshot&lt;br /&gt;
 attr TapoCam setList takePhoto:noArg &lt;br /&gt;
sowie ein DOIF&lt;br /&gt;
 defmod TapoCam.move.N DOIF ([TapoCam:state] =~ /^takePhoto$/) \&lt;br /&gt;
 ({my $res = qx(/opt/fhem/tapo/tapo_snapshot.sh);;\&lt;br /&gt;
  chomp($res);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam snapshot $res&amp;quot;);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam state ready&amp;quot;)\&lt;br /&gt;
 }\&lt;br /&gt;
 )&lt;br /&gt;
mit Attribut&lt;br /&gt;
 attr TapoCam.move.N do always&lt;br /&gt;
Dann sorgt der FHEM-Befehl&lt;br /&gt;
 set TapoCam takePhoto&lt;br /&gt;
dafür, dass ein Snapshot unter /opt/fhem/www/images gespeichert wird. Im FHEMWEB Frontend ist er dann unter /fhem/images/Tapo.jpg ansehbar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: Komfortabler machen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Kamerasteuerung mit Python==&lt;br /&gt;
=== FHEM-Device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod TapoCam dummy&lt;br /&gt;
attr TapoCam devStateIcon stream_running:it_camera@green stream_stopped:it_camera@black&lt;br /&gt;
attr TapoCam readingList snapshot motor_action motor_result motor_presets error&lt;br /&gt;
attr TapoCam setList getPhoto:noArg getClip getEvents privacy:on,off light:on,off light_intensity light_duration light_night:ir,white,auto led:on,off moveLeft moveRight moveUp moveDown calibrate:noArg preset_goto:1,2,3,4,5,6,7,8 preset_save preset_delete getPresets detection_motion detection_person detection_pet detection_tamper detection_vehicle detection_linecrossing alarm:on,off alarm_light:on,off alarm_sound:on,off alarm_duration alarm_volume:low,medium,high&lt;br /&gt;
attr TapoCam stateFormat {my $x=ReadingsAge(&amp;quot;TapoCam&amp;quot;,&amp;quot;snapshot&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $v=ReadingsVal(&amp;quot;TapoCam&amp;quot;,&amp;quot;event_dl_link&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $w=ReadingsAge(&amp;quot;TapoCam&amp;quot;,&amp;quot;event_dl&amp;quot;,&amp;quot;&amp;quot;);;\&lt;br /&gt;
 my $y=(ReadingsVal(&amp;quot;TapoCam&amp;quot;,&amp;quot;privacy&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;off&amp;quot;)?&amp;quot;&amp;lt;a href=\&amp;quot;http://192.168.0.94:8085/pages/player/webrtc/stream1/0\&amp;quot;&amp;gt;\nstream_running\n&amp;lt;/a&amp;gt;&amp;quot;:&amp;quot;stream_stopped&amp;quot;;;\&lt;br /&gt;
 sprintf(&amp;quot;&amp;lt;p style=\&amp;quot;text-align:left;;font-weight:normal\&amp;quot;&amp;gt;\n%s\n&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;a href=\&amp;quot;http://192.168.0.94:8083/fhem/images/Tapo.jpg\&amp;quot;&amp;gt;Tapo.jpg&amp;lt;/a&amp;gt; (%s)\n&amp;lt;br/&amp;gt;&amp;lt;a href=\&amp;quot;%s\&amp;quot;&amp;gt;TapoClip.mp4&amp;lt;/a&amp;gt; (%s)\n&amp;lt;/p&amp;gt;&amp;quot;,$y,$x,$v,$w)}&lt;br /&gt;
attr TapoCam webCmd getPhoto:moveLeft:moveRight:moveUp:moveDown&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== DOIF ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod TapoCam.N DOIF ([TapoCam:state] ne &amp;quot;ready&amp;quot;)&lt;br /&gt;
({TapoCamHandler(&amp;quot;$DEVICE&amp;quot;,&amp;quot;$EVENT&amp;quot;)})&lt;br /&gt;
(setreading TapoCam state ready)&lt;br /&gt;
DOELSEIF&lt;br /&gt;
([+00:05:00])&lt;br /&gt;
({TapoCamHandler(&amp;quot;TapoCam&amp;quot;,&amp;quot;status_update&amp;quot;)})&lt;br /&gt;
attr TapoCam.N do always&lt;br /&gt;
attr TapoCam.N wait 0,3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Handler ===&lt;br /&gt;
In der Datei https://github.com/pahenning/TapoCam_for_FHEM/99_TapoCamUtils.pm findet man zwei Funktionen:&lt;br /&gt;
* &#039;&#039;&#039;TapoCamHelper&#039;&#039;&#039; - nimmt als Parameter den Namen eines FHEM_Devices für die Kamera und ein Event entgegen und ruft dann eines der Python-Skripte auf. Dieses läuft asynchron ab, d.h. die Rückmeldung an FHEM kann bis zu 10 Sekunden dauern.&lt;br /&gt;
* &#039;&#039;&#039;TapoReturnHelper&#039;&#039;&#039; - wird aus dem Python-Skript gerufen und mit einer JSON-Struktur befüllt. Die Inhalte dieser JSON-Struktur werden auf Readings in dem FHEM-Device verteilt.&lt;br /&gt;
=== Python Vorbereitung ===&lt;br /&gt;
Zur Vorbereitung folgende Schritte ggf. mit root-Rechten unternehmen:&lt;br /&gt;
 mkdir -p /opt/fhem/tapo&lt;br /&gt;
 cd /opt/fhem/tapo&lt;br /&gt;
 python3 -m venv .venv&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install --upgrade pip&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install pytapo&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install aiofiles&lt;br /&gt;
 chown -R fhem:dialout /opt/fhem/tapo&lt;br /&gt;
 chmod -R u+rwX /opt/fhem/tapo&lt;br /&gt;
Dadurch wird im Verzeichnis /opt/fhem/tapo eine virtuelle Umgebung für die TapoCam angelegt. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Falls mit den nachfolgend aufgeführten Skripten irgendwelche Laufzeitfehler auftauchen, kann dies an einer veralteten Version von Python liegen. Aktuell ist eigentlich die Version 3.13 erforderlich.&lt;br /&gt;
&lt;br /&gt;
In dieses Verzeichnis können nun die Python-Skripte aus https://github.com/pahenning/TapoCam_for_FHEM hineinkopiert werden.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tapo_credentials.py&#039;&#039;&#039; - enthält &amp;lt;IPKAMERA&amp;gt; und &amp;lt;PWCLOUD&amp;gt;, sowie IP-Adresse, Port des FHEM-Servers, dessen statischen (!) csrf-Parameter und den Devicenamen des TapoCam-Devices.&lt;br /&gt;
* &#039;&#039;&#039;tapo_helper.py&#039;&#039;&#039; - diverse Hilfsfunktionen, die von den anderen Skripten importiert werden.&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_privacy.py&#039;&#039;&#039; - Kontrollprogramm für den &amp;quot;PRIVAT&amp;quot;-Modus der Kamera - d.h. das Ausschalten der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_privacy.py&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_privacy.py on|off&amp;lt;/code&amp;gt; -&amp;gt; setzt den &amp;quot;PRIVAT&amp;quot;-Modus (Kamera aus), oder hebt ihn auf (Kamera eingeschaltet)&lt;br /&gt;
=== Bewegung ===&lt;br /&gt;
* &#039;&#039;&#039; tapo_control_motor.py&#039;&#039;&#039; - Kontrollprogramm für die Bewegungen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py left [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach links. Ohne Parameter wird um den in der Kamera eingestellten Wert, typisch 10°, bewegt. Wenn ein Parameter angegeben wird, ist das der Winkel für die Bewegung.&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py right [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach rechts. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py up [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach oben. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py down [0-359]&amp;lt;/code&amp;gt;  -&amp;gt;  Bewege die Kamera nach unten. Parameter wie oben&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py calibrate&amp;lt;/code&amp;gt;  -&amp;gt; Kalibrierung der Kamerabewegung&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py presets&amp;lt;/code&amp;gt;  -&amp;gt; Hole die definierten Positionen &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py goto &amp;lt;preset&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Gehe zur definierten Position (Zahlenangabe) &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py save &amp;lt;preset&amp;gt; &amp;lt;name&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Speichere die gegenwärtige Position (Zahlenangabe und Name)&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_motor.py delete &amp;lt;preset&amp;gt;&amp;lt;/code&amp;gt;  -&amp;gt; Lösche die definierte Position (Zahlenangabe) &lt;br /&gt;
=== Beleuchtung ===&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_light.py&#039;&#039;&#039; - Kontrollprogramm für die Lichtfunktionen der Kamera. Kann wie folgt gerufen werden: &lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py status&amp;lt;/code&amp;gt;  -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py led on|off&amp;lt;/code&amp;gt; -&amp;gt; Schaltet die Kamera-LED an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py light on|off&amp;lt;/code&amp;gt; -&amp;gt; Schaltet das Kameralicht an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py intensity &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Helligkeit des Kameralichtss&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py time &amp;lt;0-3600&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Dauer des Kameralichts&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_light.py night ir|white|auto&amp;lt;/code&amp;gt; -&amp;gt; Modus des Kameralichts bei Nacht&lt;br /&gt;
=== Kamera-Events ===&lt;br /&gt;
Events werden ausgelöst, wenn eine bestimmte Detektion erfolgt ist. Dafür gibt es &lt;br /&gt;
* &#039;&#039;&#039;tapo_control_detection.py&#039;&#039;&#039; - Kontrollprogramm für die Erkennungsfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_detection.py status&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_detection.py motion &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Bewegungserkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py person &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Personenserkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py vehicle &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Fahrzeugerkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py pet &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Haustiererkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py tamper &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Sabotageerkennung. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
** &amp;lt;code&amp;gt;  tapo_control_detection.py linecrossing &amp;lt;0-100&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; setzt die Empfindlichkeit der Erkennung des Übertretens einer virtuellen Linie. 0 =&amp;gt; ausgeschaltet.&lt;br /&gt;
&lt;br /&gt;
Diese Events werden nur gespeichert, wenn in der Kamera eine SD-Karte eingesetzt wurde. Empfohlen werden mindesten 16 GByte, diese Karte wird als Ringpuffer mit den Erkennungsevents beschrieben. Dabei werden jeweils kurze Videoclips aufgenommen (1 min Dauer). Welche Events vorhanden sind, kann man abfragen mit&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_events.py&#039;&#039;&#039; - Kontrollprogramm für die Eventfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_events.py &amp;lt;seconds&amp;gt;&amp;lt;/code&amp;gt; - Hole die während der vergangenen &amp;lt;seconds&amp;gt; Sekunden detektierten Events von der Kamera und meldet sie an FHEM. Diese Clips werden dabei durchnummeriert. Die Liste der im Zeitfenster vorhandenen Events wird in der Datei /tmp/tapo_control_events.json zwischengespeichert.&lt;br /&gt;
&lt;br /&gt;
Das Programm zum Download ist&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_download.py&#039;&#039;&#039; - Kontrollprogramm zum Download eines Event-Videoclips auf den FHEM-Server. Kann wie folgt gerufen werden:&lt;br /&gt;
*** &amp;lt;code&amp;gt;tapo_control_download.py clip &amp;lt;number&amp;gt; [DEBUG]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;number&amp;gt; ist die aus der o.a. Nummerierung abzulesende Nummer des Events. DEBUG: 0 oder 1, default 0. Wenn DEBUG eingeschaltet ist, werden auf STDOUT Kontrollnachrichten ausgegeben.&lt;br /&gt;
&lt;br /&gt;
Bei diesem Download laufen etliche Dinge im Hintergrund ab, insbesondere ist das Linux-Paket ffmpeg nötig, um die Umwandlung des Kameravideos in eine MP4-Datei durchzuführen. Diese wird in /tmp/tapo_recordings/clips gespeichert, und ein Link von /opt/fhem/www/images/TapoClip.mp4 auf diese Datei angelegt.&lt;br /&gt;
&lt;br /&gt;
=== Alarmierung ===&lt;br /&gt;
Bei entsprechend detektierten Events kann auch ein lokaler Alarm in der Kamera ausgelöst werden (blinkende Beleuchtung = light und/oder Sirene=sound). Achtung: light und sound dürfen nicht beide off sein.&lt;br /&gt;
* &#039;&#039;&#039;tapo_control_alarm.py&#039;&#039;&#039;- Kontrollprogramm für die Alarmfunktionen der Kamera. Kann wie folgt gerufen werden:&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py status&amp;lt;/code&amp;gt; -&amp;gt; Statusmeldung an FHEM&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py on|off&amp;lt;/code&amp;gt; -&amp;gt; schaltet die Alarmfunktionen an oder aus&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py light on|off&amp;lt;/code&amp;gt; -&amp;gt; bei Alarm wird das Licht eingeschaltet, oder nicht&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py sound on|off&amp;lt;/code&amp;gt; -&amp;gt; bei Alarm wird die Sirene eingeschaltet, oder nicht.&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py volume low|medium|high&amp;lt;/code&amp;gt; -&amp;gt; Lautstärke der Sirene&lt;br /&gt;
** &amp;lt;code&amp;gt;tapo_control_alarm.py duration &amp;lt;zahl&amp;gt;&amp;lt;/code&amp;gt; -&amp;gt; Dauer eines Alarms in Sekunden&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40841</id>
		<title>Tapo Kameras</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40841"/>
		<updated>2026-03-18T14:19:19Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Kontrollprogramm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verifiziert für Tapo C530WS&lt;br /&gt;
&lt;br /&gt;
== Cloud-Installation ==&lt;br /&gt;
Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
== Stream und Snapshot ==&lt;br /&gt;
Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera angelegt werden, unter Einstellungen-&amp;gt;Erweiterte Einstellungen.&lt;br /&gt;
Dabei werden ein Username und ein Passwort festgelegt, die im Folgenden als &amp;lt;USERKAMERA&amp;gt; und &amp;lt;PWKAMERA&amp;gt; abgekürzt werden.&lt;br /&gt;
&lt;br /&gt;
Auf dem FHEM-Server (oder einem anderen System zum Testen) muss dann die ffmpeg-Suite installiert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Kamera eingeschaltet ist, lässt sich dann der Stream der Kamera abgreifen mit&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&lt;br /&gt;
in voller Auflösung, sowie mit reduzierter Auflösung als&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream2&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Snapshots wird über ein Shellskript gesteuert, mit folgendem Inhalt&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 OUT=&amp;quot;/opt/fhem/www/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 URL=&amp;quot;/fhem/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 ffmpeg -rtsp_transport tcp -y \&lt;br /&gt;
   -i &amp;quot;rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&amp;quot; \&lt;br /&gt;
   -frames:v 1 &amp;quot;$OUT&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;br /&gt;
 if [ $? -eq 0 ] &amp;amp;&amp;amp; [ -s &amp;quot;$OUT&amp;quot; ]; then&lt;br /&gt;
   echo &amp;quot;$URL&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
   echo &amp;quot;error creating image&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
Für das Weitere gehen wir davon aus, dass dieses Shellskript unter /opt/fhem/tapo liegt und durch den FHEM-Prozess ausführbar ist.&lt;br /&gt;
Wir definieren ein Dummy-Device mit zunächst minimalen Eigenschaften&lt;br /&gt;
 defmod TapoCam dummy&lt;br /&gt;
 attr TapoCam readingList snapshot&lt;br /&gt;
 attr TapoCam setList takePhoto:noArg &lt;br /&gt;
sowie ein DOIF&lt;br /&gt;
 defmod TapoCam.move.N DOIF ([TapoCam:state] =~ /^takePhoto$/) \&lt;br /&gt;
 ({my $res = qx(/opt/fhem/tapo/tapo_snapshot.sh);;\&lt;br /&gt;
  chomp($res);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam snapshot $res&amp;quot;);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam state ready&amp;quot;)\&lt;br /&gt;
 }\&lt;br /&gt;
 )&lt;br /&gt;
mit Attribut&lt;br /&gt;
 attr TapoCam.N do always&lt;br /&gt;
Dann sorgt der FHEM-Befehl&lt;br /&gt;
 set TapoCam takePhoto&lt;br /&gt;
dafür, dass ein Snapshot unter /opt/fhem/www/images gespeichert wird. Im FHEMWEB Frontend ist er dann unter /fhem/images/Tapo.jpg ansehbar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: Komfortabler machen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Kamerasteuerung mit Python==&lt;br /&gt;
Zur Vorbereitung folgende Schritte ggf. mit root-Rechten unternehmen:&lt;br /&gt;
 mkdir -p /opt/fhem/tapo&lt;br /&gt;
 cd /opt/fhem/tapo&lt;br /&gt;
 python3 -m venv .venv&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install --upgrade pip&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install pytapo&lt;br /&gt;
 chown -R fhem:dialout /opt/fhem/tapo&lt;br /&gt;
 chmod -R u+rwX /opt/fhem/tapo&lt;br /&gt;
Dadurch wird im Verzeichnis /opt/fhem/tapo eine virtuelle Umgebung für die TapoCam angelegt. Danach eine Datei /opt/fhem/tapo/tapo_testmethod.py anlegen, mit dem Inhalt&lt;br /&gt;
 #!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
 from pytapo import Tapo&lt;br /&gt;
 tapo = Tapo(&amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;, &amp;quot;admin&amp;quot;, &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;)&lt;br /&gt;
 for m in dir(tapo):&lt;br /&gt;
    ml = m.lower()&lt;br /&gt;
    if any(x in ml for x in [&lt;br /&gt;
        &amp;quot;light&amp;quot;, &amp;quot;spot&amp;quot;, &amp;quot;privacy&amp;quot;, &amp;quot;mask&amp;quot;, &amp;quot;alarm&amp;quot;, &amp;quot;siren&amp;quot;,&lt;br /&gt;
        &amp;quot;speaker&amp;quot;, &amp;quot;micro&amp;quot;, &amp;quot;audio&amp;quot;, &amp;quot;talk&amp;quot;, &amp;quot;voice&amp;quot;, &amp;quot;ring&amp;quot;&lt;br /&gt;
    ]):&lt;br /&gt;
        print(m)&lt;br /&gt;
Wichtig: Für die Kamerasteuerung verlangt Tapo inzwischen das Cloud-Passwort und den Usernamen admin.&lt;br /&gt;
Dieses Python-Skript ausführbar machen und ausführen:&lt;br /&gt;
 chmod +x tapo_testmethod.py&lt;br /&gt;
 ./tapo_testmethod.py&lt;br /&gt;
Man erhält auf diese Weise eine unstrukturierte Liste alle Methode, die von der Kamera akzeptiert werden.&lt;br /&gt;
=== Kontrollprogramm ===&lt;br /&gt;
Das zentrale Python-Skript zur Kamerasteuerung liegt in der Datei /opt/fhem/tapo/tapo_controlpy und hat den Inhalt&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
#!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys &lt;br /&gt;
import json&lt;br /&gt;
from pytapo import Tapo&lt;br /&gt;
HOST = &amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;&lt;br /&gt;
USER = &amp;quot;admin&amp;quot;&lt;br /&gt;
PASSWORD = &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
STEP = 10&lt;br /&gt;
&lt;br /&gt;
def out(obj):&lt;br /&gt;
    if isinstance(obj, (dict, list)):&lt;br /&gt;
        print(json.dumps(obj, ensure_ascii=False))&lt;br /&gt;
    else:&lt;br /&gt;
        print(str(obj))&lt;br /&gt;
&lt;br /&gt;
def ok(msg):&lt;br /&gt;
    print(msg)&lt;br /&gt;
    sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
def err(msg):&lt;br /&gt;
    print(msg)&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def safe_call(label, func):&lt;br /&gt;
    try:def safe_call(label, func):&lt;br /&gt;
    try:&lt;br /&gt;
        return func()&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        return f&amp;quot;error: {e}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    tapo = Tapo(HOST, USER, PASSWORD)&lt;br /&gt;
except Exception as e:&lt;br /&gt;
    err(f&amp;quot;login error: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
cmd = sys.argv[1] if len(sys.argv) &amp;gt; 1 else &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    if cmd == &amp;quot;left&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(-STEP, 0)&lt;br /&gt;
        ok(&amp;quot;ok left&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;right&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(STEP, 0)&lt;br /&gt;
        ok(&amp;quot;ok right&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;up&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(0, STEP)&lt;br /&gt;
        ok(&amp;quot;ok up&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;down&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(0, -STEP)&lt;br /&gt;
        ok(&amp;quot;ok down&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_on&amp;quot;:&lt;br /&gt;
        res = tapo.setPrivacyMode(True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_off&amp;quot;:&lt;br /&gt;
        res = tapo.setPrivacyMode(False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_light_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=False, lightEnabled=True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_sound_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=True, lightEnabled=False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_both_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=True, lightEnabled=True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_off&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;status&amp;quot;:&lt;br /&gt;
        status = {&lt;br /&gt;
            &amp;quot;privacy&amp;quot;: safe_call(&amp;quot;privacy&amp;quot;, lambda: tapo.getPrivacyMode()),&lt;br /&gt;
            &amp;quot;alarm&amp;quot;: safe_call(&amp;quot;alarm&amp;quot;, lambda: tapo.getAlarm()),&lt;br /&gt;
            &amp;quot;audio&amp;quot;: safe_call(&amp;quot;audio&amp;quot;, lambda: tapo.getAudioConfig()),&lt;br /&gt;
            &amp;quot;floodlight_status&amp;quot;: safe_call(&amp;quot;floodlight_status&amp;quot;, lambda: tapo.getFloodlightStatus()),&lt;br /&gt;
            &amp;quot;floodlight_config&amp;quot;: safe_call(&amp;quot;floodlight_config&amp;quot;, lambda: tapo.getFloodlightConfig()),&lt;br /&gt;
            &amp;quot;floodlight_capability&amp;quot;: safe_call(&amp;quot;floodlight_capability&amp;quot;, lambda: tapo.getFloodlightCapability()),&lt;br /&gt;
        }&lt;br /&gt;
        out(status)&lt;br /&gt;
&lt;br /&gt;
    else:&lt;br /&gt;
        err(&amp;quot;unknown command&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
except Exception as e:&lt;br /&gt;
    err(f&amp;quot;command error: {e}&amp;quot;)&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40840</id>
		<title>Tapo Kameras</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40840"/>
		<updated>2026-03-18T14:18:53Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Kontrollprogramm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verifiziert für Tapo C530WS&lt;br /&gt;
&lt;br /&gt;
== Cloud-Installation ==&lt;br /&gt;
Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
== Stream und Snapshot ==&lt;br /&gt;
Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera angelegt werden, unter Einstellungen-&amp;gt;Erweiterte Einstellungen.&lt;br /&gt;
Dabei werden ein Username und ein Passwort festgelegt, die im Folgenden als &amp;lt;USERKAMERA&amp;gt; und &amp;lt;PWKAMERA&amp;gt; abgekürzt werden.&lt;br /&gt;
&lt;br /&gt;
Auf dem FHEM-Server (oder einem anderen System zum Testen) muss dann die ffmpeg-Suite installiert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Kamera eingeschaltet ist, lässt sich dann der Stream der Kamera abgreifen mit&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&lt;br /&gt;
in voller Auflösung, sowie mit reduzierter Auflösung als&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream2&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Snapshots wird über ein Shellskript gesteuert, mit folgendem Inhalt&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 OUT=&amp;quot;/opt/fhem/www/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 URL=&amp;quot;/fhem/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 ffmpeg -rtsp_transport tcp -y \&lt;br /&gt;
   -i &amp;quot;rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&amp;quot; \&lt;br /&gt;
   -frames:v 1 &amp;quot;$OUT&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;br /&gt;
 if [ $? -eq 0 ] &amp;amp;&amp;amp; [ -s &amp;quot;$OUT&amp;quot; ]; then&lt;br /&gt;
   echo &amp;quot;$URL&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
   echo &amp;quot;error creating image&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
Für das Weitere gehen wir davon aus, dass dieses Shellskript unter /opt/fhem/tapo liegt und durch den FHEM-Prozess ausführbar ist.&lt;br /&gt;
Wir definieren ein Dummy-Device mit zunächst minimalen Eigenschaften&lt;br /&gt;
 defmod TapoCam dummy&lt;br /&gt;
 attr TapoCam readingList snapshot&lt;br /&gt;
 attr TapoCam setList takePhoto:noArg &lt;br /&gt;
sowie ein DOIF&lt;br /&gt;
 defmod TapoCam.move.N DOIF ([TapoCam:state] =~ /^takePhoto$/) \&lt;br /&gt;
 ({my $res = qx(/opt/fhem/tapo/tapo_snapshot.sh);;\&lt;br /&gt;
  chomp($res);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam snapshot $res&amp;quot;);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam state ready&amp;quot;)\&lt;br /&gt;
 }\&lt;br /&gt;
 )&lt;br /&gt;
mit Attribut&lt;br /&gt;
 attr TapoCam.N do always&lt;br /&gt;
Dann sorgt der FHEM-Befehl&lt;br /&gt;
 set TapoCam takePhoto&lt;br /&gt;
dafür, dass ein Snapshot unter /opt/fhem/www/images gespeichert wird. Im FHEMWEB Frontend ist er dann unter /fhem/images/Tapo.jpg ansehbar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: Komfortabler machen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Kamerasteuerung mit Python==&lt;br /&gt;
Zur Vorbereitung folgende Schritte ggf. mit root-Rechten unternehmen:&lt;br /&gt;
 mkdir -p /opt/fhem/tapo&lt;br /&gt;
 cd /opt/fhem/tapo&lt;br /&gt;
 python3 -m venv .venv&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install --upgrade pip&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install pytapo&lt;br /&gt;
 chown -R fhem:dialout /opt/fhem/tapo&lt;br /&gt;
 chmod -R u+rwX /opt/fhem/tapo&lt;br /&gt;
Dadurch wird im Verzeichnis /opt/fhem/tapo eine virtuelle Umgebung für die TapoCam angelegt. Danach eine Datei /opt/fhem/tapo/tapo_testmethod.py anlegen, mit dem Inhalt&lt;br /&gt;
 #!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
 from pytapo import Tapo&lt;br /&gt;
 tapo = Tapo(&amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;, &amp;quot;admin&amp;quot;, &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;)&lt;br /&gt;
 for m in dir(tapo):&lt;br /&gt;
    ml = m.lower()&lt;br /&gt;
    if any(x in ml for x in [&lt;br /&gt;
        &amp;quot;light&amp;quot;, &amp;quot;spot&amp;quot;, &amp;quot;privacy&amp;quot;, &amp;quot;mask&amp;quot;, &amp;quot;alarm&amp;quot;, &amp;quot;siren&amp;quot;,&lt;br /&gt;
        &amp;quot;speaker&amp;quot;, &amp;quot;micro&amp;quot;, &amp;quot;audio&amp;quot;, &amp;quot;talk&amp;quot;, &amp;quot;voice&amp;quot;, &amp;quot;ring&amp;quot;&lt;br /&gt;
    ]):&lt;br /&gt;
        print(m)&lt;br /&gt;
Wichtig: Für die Kamerasteuerung verlangt Tapo inzwischen das Cloud-Passwort und den Usernamen admin.&lt;br /&gt;
Dieses Python-Skript ausführbar machen und ausführen:&lt;br /&gt;
 chmod +x tapo_testmethod.py&lt;br /&gt;
 ./tapo_testmethod.py&lt;br /&gt;
Man erhält auf diese Weise eine unstrukturierte Liste alle Methode, die von der Kamera akzeptiert werden.&lt;br /&gt;
=== Kontrollprogramm ===&lt;br /&gt;
Das zentrale Python-Skript zur Kamerasteuerung liegt in der Datei /opt/fhem7tapo/tapo_controlpy und hat den Inhalt&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
#!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys &lt;br /&gt;
import json&lt;br /&gt;
from pytapo import Tapo&lt;br /&gt;
HOST = &amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;&lt;br /&gt;
USER = &amp;quot;admin&amp;quot;&lt;br /&gt;
PASSWORD = &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
STEP = 10&lt;br /&gt;
&lt;br /&gt;
def out(obj):&lt;br /&gt;
    if isinstance(obj, (dict, list)):&lt;br /&gt;
        print(json.dumps(obj, ensure_ascii=False))&lt;br /&gt;
    else:&lt;br /&gt;
        print(str(obj))&lt;br /&gt;
&lt;br /&gt;
def ok(msg):&lt;br /&gt;
    print(msg)&lt;br /&gt;
    sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
def err(msg):&lt;br /&gt;
    print(msg)&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def safe_call(label, func):&lt;br /&gt;
    try:def safe_call(label, func):&lt;br /&gt;
    try:&lt;br /&gt;
        return func()&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        return f&amp;quot;error: {e}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    tapo = Tapo(HOST, USER, PASSWORD)&lt;br /&gt;
except Exception as e:&lt;br /&gt;
    err(f&amp;quot;login error: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
cmd = sys.argv[1] if len(sys.argv) &amp;gt; 1 else &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    if cmd == &amp;quot;left&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(-STEP, 0)&lt;br /&gt;
        ok(&amp;quot;ok left&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;right&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(STEP, 0)&lt;br /&gt;
        ok(&amp;quot;ok right&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;up&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(0, STEP)&lt;br /&gt;
        ok(&amp;quot;ok up&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;down&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(0, -STEP)&lt;br /&gt;
        ok(&amp;quot;ok down&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_on&amp;quot;:&lt;br /&gt;
        res = tapo.setPrivacyMode(True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_off&amp;quot;:&lt;br /&gt;
        res = tapo.setPrivacyMode(False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_light_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=False, lightEnabled=True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_sound_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=True, lightEnabled=False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_both_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=True, lightEnabled=True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_off&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;status&amp;quot;:&lt;br /&gt;
        status = {&lt;br /&gt;
            &amp;quot;privacy&amp;quot;: safe_call(&amp;quot;privacy&amp;quot;, lambda: tapo.getPrivacyMode()),&lt;br /&gt;
            &amp;quot;alarm&amp;quot;: safe_call(&amp;quot;alarm&amp;quot;, lambda: tapo.getAlarm()),&lt;br /&gt;
            &amp;quot;audio&amp;quot;: safe_call(&amp;quot;audio&amp;quot;, lambda: tapo.getAudioConfig()),&lt;br /&gt;
            &amp;quot;floodlight_status&amp;quot;: safe_call(&amp;quot;floodlight_status&amp;quot;, lambda: tapo.getFloodlightStatus()),&lt;br /&gt;
            &amp;quot;floodlight_config&amp;quot;: safe_call(&amp;quot;floodlight_config&amp;quot;, lambda: tapo.getFloodlightConfig()),&lt;br /&gt;
            &amp;quot;floodlight_capability&amp;quot;: safe_call(&amp;quot;floodlight_capability&amp;quot;, lambda: tapo.getFloodlightCapability()),&lt;br /&gt;
        }&lt;br /&gt;
        out(status)&lt;br /&gt;
&lt;br /&gt;
    else:&lt;br /&gt;
        err(&amp;quot;unknown command&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
except Exception as e:&lt;br /&gt;
    err(f&amp;quot;command error: {e}&amp;quot;)&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40839</id>
		<title>Tapo Kameras</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40839"/>
		<updated>2026-03-18T14:18:34Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Kontrollprogramm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verifiziert für Tapo C530WS&lt;br /&gt;
&lt;br /&gt;
== Cloud-Installation ==&lt;br /&gt;
Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
== Stream und Snapshot ==&lt;br /&gt;
Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera angelegt werden, unter Einstellungen-&amp;gt;Erweiterte Einstellungen.&lt;br /&gt;
Dabei werden ein Username und ein Passwort festgelegt, die im Folgenden als &amp;lt;USERKAMERA&amp;gt; und &amp;lt;PWKAMERA&amp;gt; abgekürzt werden.&lt;br /&gt;
&lt;br /&gt;
Auf dem FHEM-Server (oder einem anderen System zum Testen) muss dann die ffmpeg-Suite installiert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Kamera eingeschaltet ist, lässt sich dann der Stream der Kamera abgreifen mit&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&lt;br /&gt;
in voller Auflösung, sowie mit reduzierter Auflösung als&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream2&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Snapshots wird über ein Shellskript gesteuert, mit folgendem Inhalt&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 OUT=&amp;quot;/opt/fhem/www/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 URL=&amp;quot;/fhem/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 ffmpeg -rtsp_transport tcp -y \&lt;br /&gt;
   -i &amp;quot;rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&amp;quot; \&lt;br /&gt;
   -frames:v 1 &amp;quot;$OUT&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;br /&gt;
 if [ $? -eq 0 ] &amp;amp;&amp;amp; [ -s &amp;quot;$OUT&amp;quot; ]; then&lt;br /&gt;
   echo &amp;quot;$URL&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
   echo &amp;quot;error creating image&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
Für das Weitere gehen wir davon aus, dass dieses Shellskript unter /opt/fhem/tapo liegt und durch den FHEM-Prozess ausführbar ist.&lt;br /&gt;
Wir definieren ein Dummy-Device mit zunächst minimalen Eigenschaften&lt;br /&gt;
 defmod TapoCam dummy&lt;br /&gt;
 attr TapoCam readingList snapshot&lt;br /&gt;
 attr TapoCam setList takePhoto:noArg &lt;br /&gt;
sowie ein DOIF&lt;br /&gt;
 defmod TapoCam.move.N DOIF ([TapoCam:state] =~ /^takePhoto$/) \&lt;br /&gt;
 ({my $res = qx(/opt/fhem/tapo/tapo_snapshot.sh);;\&lt;br /&gt;
  chomp($res);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam snapshot $res&amp;quot;);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam state ready&amp;quot;)\&lt;br /&gt;
 }\&lt;br /&gt;
 )&lt;br /&gt;
mit Attribut&lt;br /&gt;
 attr TapoCam.N do always&lt;br /&gt;
Dann sorgt der FHEM-Befehl&lt;br /&gt;
 set TapoCam takePhoto&lt;br /&gt;
dafür, dass ein Snapshot unter /opt/fhem/www/images gespeichert wird. Im FHEMWEB Frontend ist er dann unter /fhem/images/Tapo.jpg ansehbar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: Komfortabler machen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Kamerasteuerung mit Python==&lt;br /&gt;
Zur Vorbereitung folgende Schritte ggf. mit root-Rechten unternehmen:&lt;br /&gt;
 mkdir -p /opt/fhem/tapo&lt;br /&gt;
 cd /opt/fhem/tapo&lt;br /&gt;
 python3 -m venv .venv&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install --upgrade pip&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install pytapo&lt;br /&gt;
 chown -R fhem:dialout /opt/fhem/tapo&lt;br /&gt;
 chmod -R u+rwX /opt/fhem/tapo&lt;br /&gt;
Dadurch wird im Verzeichnis /opt/fhem/tapo eine virtuelle Umgebung für die TapoCam angelegt. Danach eine Datei /opt/fhem/tapo/tapo_testmethod.py anlegen, mit dem Inhalt&lt;br /&gt;
 #!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
 from pytapo import Tapo&lt;br /&gt;
 tapo = Tapo(&amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;, &amp;quot;admin&amp;quot;, &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;)&lt;br /&gt;
 for m in dir(tapo):&lt;br /&gt;
    ml = m.lower()&lt;br /&gt;
    if any(x in ml for x in [&lt;br /&gt;
        &amp;quot;light&amp;quot;, &amp;quot;spot&amp;quot;, &amp;quot;privacy&amp;quot;, &amp;quot;mask&amp;quot;, &amp;quot;alarm&amp;quot;, &amp;quot;siren&amp;quot;,&lt;br /&gt;
        &amp;quot;speaker&amp;quot;, &amp;quot;micro&amp;quot;, &amp;quot;audio&amp;quot;, &amp;quot;talk&amp;quot;, &amp;quot;voice&amp;quot;, &amp;quot;ring&amp;quot;&lt;br /&gt;
    ]):&lt;br /&gt;
        print(m)&lt;br /&gt;
Wichtig: Für die Kamerasteuerung verlangt Tapo inzwischen das Cloud-Passwort und den Usernamen admin.&lt;br /&gt;
Dieses Python-Skript ausführbar machen und ausführen:&lt;br /&gt;
 chmod +x tapo_testmethod.py&lt;br /&gt;
 ./tapo_testmethod.py&lt;br /&gt;
Man erhält auf diese Weise eine unstrukturierte Liste alle Methode, die von der Kamera akzeptiert werden.&lt;br /&gt;
=== Kontrollprogramm ===&lt;br /&gt;
Das zentrale Python-Skript zur Kamerasteuerung liegt in der Datei /opt/fhem7tapo/tapo_controlpy und hat den Inhalt&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
#!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys import json&lt;br /&gt;
from pytapo import Tapo&lt;br /&gt;
HOST = &amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;&lt;br /&gt;
USER = &amp;quot;admin&amp;quot;&lt;br /&gt;
PASSWORD = &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
STEP = 10&lt;br /&gt;
&lt;br /&gt;
def out(obj):&lt;br /&gt;
    if isinstance(obj, (dict, list)):&lt;br /&gt;
        print(json.dumps(obj, ensure_ascii=False))&lt;br /&gt;
    else:&lt;br /&gt;
        print(str(obj))&lt;br /&gt;
&lt;br /&gt;
def ok(msg):&lt;br /&gt;
    print(msg)&lt;br /&gt;
    sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
def err(msg):&lt;br /&gt;
    print(msg)&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def safe_call(label, func):&lt;br /&gt;
    try:def safe_call(label, func):&lt;br /&gt;
    try:&lt;br /&gt;
        return func()&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        return f&amp;quot;error: {e}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    tapo = Tapo(HOST, USER, PASSWORD)&lt;br /&gt;
except Exception as e:&lt;br /&gt;
    err(f&amp;quot;login error: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
cmd = sys.argv[1] if len(sys.argv) &amp;gt; 1 else &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    if cmd == &amp;quot;left&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(-STEP, 0)&lt;br /&gt;
        ok(&amp;quot;ok left&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;right&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(STEP, 0)&lt;br /&gt;
        ok(&amp;quot;ok right&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;up&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(0, STEP)&lt;br /&gt;
        ok(&amp;quot;ok up&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;down&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(0, -STEP)&lt;br /&gt;
        ok(&amp;quot;ok down&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_on&amp;quot;:&lt;br /&gt;
        res = tapo.setPrivacyMode(True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_off&amp;quot;:&lt;br /&gt;
        res = tapo.setPrivacyMode(False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_light_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=False, lightEnabled=True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_sound_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=True, lightEnabled=False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_both_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=True, lightEnabled=True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_off&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;status&amp;quot;:&lt;br /&gt;
        status = {&lt;br /&gt;
            &amp;quot;privacy&amp;quot;: safe_call(&amp;quot;privacy&amp;quot;, lambda: tapo.getPrivacyMode()),&lt;br /&gt;
            &amp;quot;alarm&amp;quot;: safe_call(&amp;quot;alarm&amp;quot;, lambda: tapo.getAlarm()),&lt;br /&gt;
            &amp;quot;audio&amp;quot;: safe_call(&amp;quot;audio&amp;quot;, lambda: tapo.getAudioConfig()),&lt;br /&gt;
            &amp;quot;floodlight_status&amp;quot;: safe_call(&amp;quot;floodlight_status&amp;quot;, lambda: tapo.getFloodlightStatus()),&lt;br /&gt;
            &amp;quot;floodlight_config&amp;quot;: safe_call(&amp;quot;floodlight_config&amp;quot;, lambda: tapo.getFloodlightConfig()),&lt;br /&gt;
            &amp;quot;floodlight_capability&amp;quot;: safe_call(&amp;quot;floodlight_capability&amp;quot;, lambda: tapo.getFloodlightCapability()),&lt;br /&gt;
        }&lt;br /&gt;
        out(status)&lt;br /&gt;
&lt;br /&gt;
    else:&lt;br /&gt;
        err(&amp;quot;unknown command&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
except Exception as e:&lt;br /&gt;
    err(f&amp;quot;command error: {e}&amp;quot;)&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40838</id>
		<title>Tapo Kameras</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40838"/>
		<updated>2026-03-18T14:16:49Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verifiziert für Tapo C530WS&lt;br /&gt;
&lt;br /&gt;
== Cloud-Installation ==&lt;br /&gt;
Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
== Stream und Snapshot ==&lt;br /&gt;
Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera angelegt werden, unter Einstellungen-&amp;gt;Erweiterte Einstellungen.&lt;br /&gt;
Dabei werden ein Username und ein Passwort festgelegt, die im Folgenden als &amp;lt;USERKAMERA&amp;gt; und &amp;lt;PWKAMERA&amp;gt; abgekürzt werden.&lt;br /&gt;
&lt;br /&gt;
Auf dem FHEM-Server (oder einem anderen System zum Testen) muss dann die ffmpeg-Suite installiert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Kamera eingeschaltet ist, lässt sich dann der Stream der Kamera abgreifen mit&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&lt;br /&gt;
in voller Auflösung, sowie mit reduzierter Auflösung als&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream2&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Snapshots wird über ein Shellskript gesteuert, mit folgendem Inhalt&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 OUT=&amp;quot;/opt/fhem/www/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 URL=&amp;quot;/fhem/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 ffmpeg -rtsp_transport tcp -y \&lt;br /&gt;
   -i &amp;quot;rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&amp;quot; \&lt;br /&gt;
   -frames:v 1 &amp;quot;$OUT&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;br /&gt;
 if [ $? -eq 0 ] &amp;amp;&amp;amp; [ -s &amp;quot;$OUT&amp;quot; ]; then&lt;br /&gt;
   echo &amp;quot;$URL&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
   echo &amp;quot;error creating image&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
Für das Weitere gehen wir davon aus, dass dieses Shellskript unter /opt/fhem/tapo liegt und durch den FHEM-Prozess ausführbar ist.&lt;br /&gt;
Wir definieren ein Dummy-Device mit zunächst minimalen Eigenschaften&lt;br /&gt;
 defmod TapoCam dummy&lt;br /&gt;
 attr TapoCam readingList snapshot&lt;br /&gt;
 attr TapoCam setList takePhoto:noArg &lt;br /&gt;
sowie ein DOIF&lt;br /&gt;
 defmod TapoCam.move.N DOIF ([TapoCam:state] =~ /^takePhoto$/) \&lt;br /&gt;
 ({my $res = qx(/opt/fhem/tapo/tapo_snapshot.sh);;\&lt;br /&gt;
  chomp($res);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam snapshot $res&amp;quot;);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam state ready&amp;quot;)\&lt;br /&gt;
 }\&lt;br /&gt;
 )&lt;br /&gt;
mit Attribut&lt;br /&gt;
 attr TapoCam.N do always&lt;br /&gt;
Dann sorgt der FHEM-Befehl&lt;br /&gt;
 set TapoCam takePhoto&lt;br /&gt;
dafür, dass ein Snapshot unter /opt/fhem/www/images gespeichert wird. Im FHEMWEB Frontend ist er dann unter /fhem/images/Tapo.jpg ansehbar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: Komfortabler machen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Kamerasteuerung mit Python==&lt;br /&gt;
Zur Vorbereitung folgende Schritte ggf. mit root-Rechten unternehmen:&lt;br /&gt;
 mkdir -p /opt/fhem/tapo&lt;br /&gt;
 cd /opt/fhem/tapo&lt;br /&gt;
 python3 -m venv .venv&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install --upgrade pip&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install pytapo&lt;br /&gt;
 chown -R fhem:dialout /opt/fhem/tapo&lt;br /&gt;
 chmod -R u+rwX /opt/fhem/tapo&lt;br /&gt;
Dadurch wird im Verzeichnis /opt/fhem/tapo eine virtuelle Umgebung für die TapoCam angelegt. Danach eine Datei /opt/fhem/tapo/tapo_testmethod.py anlegen, mit dem Inhalt&lt;br /&gt;
 #!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
 from pytapo import Tapo&lt;br /&gt;
 tapo = Tapo(&amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;, &amp;quot;admin&amp;quot;, &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;)&lt;br /&gt;
 for m in dir(tapo):&lt;br /&gt;
    ml = m.lower()&lt;br /&gt;
    if any(x in ml for x in [&lt;br /&gt;
        &amp;quot;light&amp;quot;, &amp;quot;spot&amp;quot;, &amp;quot;privacy&amp;quot;, &amp;quot;mask&amp;quot;, &amp;quot;alarm&amp;quot;, &amp;quot;siren&amp;quot;,&lt;br /&gt;
        &amp;quot;speaker&amp;quot;, &amp;quot;micro&amp;quot;, &amp;quot;audio&amp;quot;, &amp;quot;talk&amp;quot;, &amp;quot;voice&amp;quot;, &amp;quot;ring&amp;quot;&lt;br /&gt;
    ]):&lt;br /&gt;
        print(m)&lt;br /&gt;
Wichtig: Für die Kamerasteuerung verlangt Tapo inzwischen das Cloud-Passwort und den Usernamen admin.&lt;br /&gt;
Dieses Python-Skript ausführbar machen und ausführen:&lt;br /&gt;
 chmod +x tapo_testmethod.py&lt;br /&gt;
 ./tapo_testmethod.py&lt;br /&gt;
Man erhält auf diese Weise eine unstrukturierte Liste alle Methode, die von der Kamera akzeptiert werden.&lt;br /&gt;
=== Kontrollprogramm ===&lt;br /&gt;
Das zentrale Python-Skript zur Kamerasteuerung liegt in der Datei /opt/fhem7tapo/tapo_controlpy und hat den Inhalt&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
#!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys import json&lt;br /&gt;
from pytapo import Tapo&lt;br /&gt;
HOST = &amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;&lt;br /&gt;
USER = &amp;quot;admin&amp;quot;&lt;br /&gt;
PASSWORD = &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
STEP = 10&lt;br /&gt;
&lt;br /&gt;
def out(obj):&lt;br /&gt;
    if isinstance(obj, (dict, list)):&lt;br /&gt;
        print(json.dumps(obj, ensure_ascii=False))&lt;br /&gt;
    else:&lt;br /&gt;
        print(str(obj))&lt;br /&gt;
&lt;br /&gt;
def ok(msg):&lt;br /&gt;
    print(msg)&lt;br /&gt;
    sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
def err(msg):&lt;br /&gt;
    print(msg)&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def safe_call(label, func):&lt;br /&gt;
    try:def safe_call(label, func):&lt;br /&gt;
    try:&lt;br /&gt;
        return func()&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        return f&amp;quot;error: {e}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    tapo = Tapo(HOST, USER, PASSWORD)&lt;br /&gt;
except Exception as e:&lt;br /&gt;
    err(f&amp;quot;login error: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
cmd = sys.argv[1] if len(sys.argv) &amp;gt; 1 else &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    if cmd == &amp;quot;left&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(-STEP, 0)&lt;br /&gt;
        ok(&amp;quot;ok left&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;right&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(STEP, 0)&lt;br /&gt;
        ok(&amp;quot;ok right&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;up&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(0, STEP)&lt;br /&gt;
        ok(&amp;quot;ok up&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;down&amp;quot;:&lt;br /&gt;
        tapo.moveMotor(0, -STEP)&lt;br /&gt;
        ok(&amp;quot;ok down&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_on&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
        return func()&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_on&amp;quot;:&lt;br /&gt;
        res = tapo.setPrivacyMode(True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;privacy_off&amp;quot;:&lt;br /&gt;
        res = tapo.setPrivacyMode(False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_light_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=False, lightEnabled=True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_sound_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=True, lightEnabled=False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_both_enable&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(True, soundEnabled=True, lightEnabled=True)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;alarm_off&amp;quot;:&lt;br /&gt;
        res = tapo.setAlarm(False)&lt;br /&gt;
        out(res)&lt;br /&gt;
&lt;br /&gt;
    elif cmd == &amp;quot;status&amp;quot;:&lt;br /&gt;
        status = {&lt;br /&gt;
            &amp;quot;privacy&amp;quot;: safe_call(&amp;quot;privacy&amp;quot;, lambda: tapo.getPrivacyMode()),&lt;br /&gt;
           &amp;quot;alarm&amp;quot;: safe_call(&amp;quot;alarm&amp;quot;, lambda: tapo.getAlarm()),&lt;br /&gt;
            &amp;quot;audio&amp;quot;: safe_call(&amp;quot;audio&amp;quot;, lambda: tapo.getAudioConfig()),&lt;br /&gt;
            &amp;quot;floodlight_status&amp;quot;: safe_call(&amp;quot;floodlight_status&amp;quot;, lambda: tapo.getFloodlightStatus()),&lt;br /&gt;
            &amp;quot;floodlight_config&amp;quot;: safe_call(&amp;quot;floodlight_config&amp;quot;, lambda: tapo.getFloodlightConfig()),&lt;br /&gt;
            &amp;quot;floodlight_capability&amp;quot;: safe_call(&amp;quot;floodlight_capability&amp;quot;, lambda: tapo.getFloodlightCapability()),&lt;br /&gt;
        }&lt;br /&gt;
        out(status)&lt;br /&gt;
&lt;br /&gt;
    else:&lt;br /&gt;
        err(&amp;quot;unknown command&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
except Exception as e:&lt;br /&gt;
    err(f&amp;quot;command error: {e}&amp;quot;)&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40837</id>
		<title>Tapo Kameras</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Tapo_Kameras&amp;diff=40837"/>
		<updated>2026-03-18T14:09:29Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: Die Seite wurde neu angelegt: „Verifiziert für Tapo C530WS  == Cloud-Installation == Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.  Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.  == Stream und Snapshot == Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera ang…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Verifiziert für Tapo C530WS&lt;br /&gt;
&lt;br /&gt;
== Cloud-Installation ==&lt;br /&gt;
Die Kamera zunächst mit der von Tapo angegebenen App installieren und testen. Dafür muss ein Konto angelegt werden, mit Mailadresse und einem Passwort, das im Folgenden als &amp;lt;PWCLOUD&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
Die Kamera erhält im internen Netz eine IP-Adresse, die im Folgenden als &amp;lt;IPKAMERA&amp;gt; abgekürzt wird.&lt;br /&gt;
&lt;br /&gt;
== Stream und Snapshot ==&lt;br /&gt;
Hierfür muss zunächst ein so genanntes Kamera-Konto auf der Kamera angelegt werden, unter Einstellungen-&amp;gt;Erweiterte Einstellungen.&lt;br /&gt;
Dabei werden ein Username und ein Passwort festgelegt, die im Folgenden als &amp;lt;USERKAMERA&amp;gt; und &amp;lt;PWKAMERA&amp;gt; abgekürzt werden.&lt;br /&gt;
&lt;br /&gt;
Auf dem FHEM-Server (oder einem anderen System zum Testen) muss dann die ffmpeg-Suite installiert werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Kamera eingeschaltet ist, lässt sich dann der Stream der Kamera abgreifen mit&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&lt;br /&gt;
in voller Auflösung, sowie mit reduzierter Auflösung als&lt;br /&gt;
 ffplay rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream2&lt;br /&gt;
&lt;br /&gt;
Die Erstellung eines Snapshots wird über ein Shellskript gesteuert, mit folgendem Inhalt&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 OUT=&amp;quot;/opt/fhem/www/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 URL=&amp;quot;/fhem/images/Tapo.jpg&amp;quot;&lt;br /&gt;
 ffmpeg -rtsp_transport tcp -y \&lt;br /&gt;
   -i &amp;quot;rtsp://&amp;lt;USERKAMERA&amp;gt;:&amp;lt;PWKAMERA&amp;gt;@&amp;lt;IPKAMERA&amp;gt;:554/stream1&amp;quot; \&lt;br /&gt;
   -frames:v 1 &amp;quot;$OUT&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;br /&gt;
 if [ $? -eq 0 ] &amp;amp;&amp;amp; [ -s &amp;quot;$OUT&amp;quot; ]; then&lt;br /&gt;
   echo &amp;quot;$URL&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
   echo &amp;quot;error creating image&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
Für das Weitere gehen wir davon aus, dass dieses Shellskript unter /opt/fhem/tapo liegt und durch den FHEM-Prozess ausführbar ist.&lt;br /&gt;
Wir definieren ein Dummy-Device mit zunächst minimalen Eigenschaften&lt;br /&gt;
 defmod TapoCam dummy&lt;br /&gt;
 attr TapoCam readingList snapshot&lt;br /&gt;
 attr TapoCam setList takePhoto:noArg &lt;br /&gt;
sowie ein DOIF&lt;br /&gt;
 defmod TapoCam.move.N DOIF ([TapoCam:state] =~ /^takePhoto$/) \&lt;br /&gt;
 ({my $res = qx(/opt/fhem/tapo/tapo_snapshot.sh);;\&lt;br /&gt;
  chomp($res);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam snapshot $res&amp;quot;);;\&lt;br /&gt;
  fhem(&amp;quot;setreading TapoCam state ready&amp;quot;)\&lt;br /&gt;
 }\&lt;br /&gt;
 )&lt;br /&gt;
mit Attribut&lt;br /&gt;
 attr TapoCam.N do always&lt;br /&gt;
Dann sorgt der FHEM-Befehl&lt;br /&gt;
 set TapoCam takePhoto&lt;br /&gt;
dafür, dass ein Snapshot unter /opt/fhem/www/images gespeichert wird. Im FHEMWEB Frontend ist er dann unter /fhem/images/Tapo.jpg ansehbar&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: Komfortabler machen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Kamerasteuerung mit Python==&lt;br /&gt;
Zur Vorbereitung folgende Schritte ggf. mit root-Rechten unternehmen:&lt;br /&gt;
 mkdir -p /opt/fhem/tapo&lt;br /&gt;
 cd /opt/fhem/tapo&lt;br /&gt;
 python3 -m venv .venv&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install --upgrade pip&lt;br /&gt;
 /opt/fhem/tapo/.venv/bin/pip install pytapo&lt;br /&gt;
 chown -R fhem:dialout /opt/fhem/tapo&lt;br /&gt;
 chmod -R u+rwX /opt/fhem/tapo&lt;br /&gt;
Dadurch wird im Verzeichnis /opt/fhem/tapo eine virtuelle Umgebung für die TapoCam angelegt. Danach eine Datei /opt/fhem/tapo/tapo_testmethod.py anlegen, mit dem Inhalt&lt;br /&gt;
 #!/opt/fhem/tapo/.venv/bin/python3&lt;br /&gt;
 from pytapo import Tapo&lt;br /&gt;
 tapo = Tapo(&amp;quot;&amp;lt;IPKAMERA&amp;gt;&amp;quot;, &amp;quot;admin&amp;quot;, &amp;quot;&amp;lt;PWCLOUD&amp;gt;&amp;quot;)&lt;br /&gt;
 for m in dir(tapo):&lt;br /&gt;
    ml = m.lower()&lt;br /&gt;
    if any(x in ml for x in [&lt;br /&gt;
        &amp;quot;light&amp;quot;, &amp;quot;spot&amp;quot;, &amp;quot;privacy&amp;quot;, &amp;quot;mask&amp;quot;, &amp;quot;alarm&amp;quot;, &amp;quot;siren&amp;quot;,&lt;br /&gt;
        &amp;quot;speaker&amp;quot;, &amp;quot;micro&amp;quot;, &amp;quot;audio&amp;quot;, &amp;quot;talk&amp;quot;, &amp;quot;voice&amp;quot;, &amp;quot;ring&amp;quot;&lt;br /&gt;
    ]):&lt;br /&gt;
        print(m)&lt;br /&gt;
Wichtig: Für die Kamerasteuerung verlangt Tapo inzwischen das Cloud-Passwort und den Usernamen admin.&lt;br /&gt;
Dieses Python-Skript ausführbar machen und ausführen:&lt;br /&gt;
 chmod +x tapo_testmethod.py&lt;br /&gt;
 ./tapo_testmethod.py&lt;br /&gt;
Man erhält auf diese Weise eine unstrukturierte Liste alle Methode, die von der Kamera akzeptiert werden.&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40786</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40786"/>
		<updated>2026-02-12T17:18:52Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im spätestens im Mai 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt:&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung allgemein===&lt;br /&gt;
In der Regel werden für den cloudfreien Betrieb der Boxen sowohl die Device-ID, als auch die ID des BOSE-Accounts benötigt. Dazu greift man mit einem Browser auf das API der Box zu, und ruft die Adresse&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
auf. Die Rückgabe sieht etwa so aus:&lt;br /&gt;
 &amp;lt;info deviceID=&amp;quot;{Device-ID}&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;name&amp;gt;{Name des Geräts in der BOSE Apps}&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;SoundTouch 300&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;margeAccountUUID&amp;gt;{ID des BOSE-Accounts}&amp;lt;/margeAccountUUID&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
Diese beiden Codes bitte notieren. Außerdem die drei Dateien&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/recents &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/preset&lt;br /&gt;
lokal abspeichern mit den Namen DeviceInfo.xml, Recents.xml, Presets.xml (Achtung, XML-Header nicht vergessen).&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken, die Taste kann losgelassen werden.&lt;br /&gt;
&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services&#039; erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
Während das für die Umstellung auf cloudfreien Betrieb ganz komfortabel ist, sollte man diese Datei nach erfolgreich getester Umstellung wieder löschen, denn sonst ist die Box komplett ungesichert!&lt;br /&gt;
&lt;br /&gt;
===Holen weiterer Daten===&lt;br /&gt;
Nach einem Wechsel in das korrekte Verzeichnis&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
findet man dort auch die schon oben erwähnten Dateien Recents.xml und Presets.xml, sie können auch von hier auf den USB-Stick herunterkopiert werden.&lt;br /&gt;
&lt;br /&gt;
Ebenfalls in diesem Verzeichnis liegt die Datei Sources.xml, dies muss ebenfalls entweder kopiert werden. Entweder lokal auf den USB-Stick oder, z.B. mit dem Befehl&lt;br /&gt;
 scp Sources.xml {username}@{irgendein computer}&lt;br /&gt;
via Netz übertragen werden.&lt;br /&gt;
&lt;br /&gt;
===Umbiegen===&lt;br /&gt;
Die Konfiguration der BOSE-Server kann jetzt geändert werden, dazu muss man das richtige Verzeichnis auf der Box kennen, das Dateisystem beschreibbar machen und die entsprechende Datei ändern&lt;br /&gt;
 cd /opt/Bose/etc/&lt;br /&gt;
 rw&lt;br /&gt;
 cp SoundTouchSdkPrivateCfg.xml STSPC.backup&lt;br /&gt;
 vi SoundTouchSdkPrivateCfg.xml&lt;br /&gt;
Für Nicht-Linux-Nutzer ist der vi Editor etwas gewöhnungsbedürftig, hier findet man eine [https://sits.de/vi.html Mini-Anleitung].&lt;br /&gt;
&lt;br /&gt;
Die Datei enthält im BOSE-Urzustand folgende Informationen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
 &amp;lt;margeServerUrl&amp;gt;https://streaming.bose.com&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;statsServerUrl&amp;gt;https://events.api.bosecm.com&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;swUpdateUrl&amp;gt;https://worldwide.bose.com/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
 &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
 &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
 &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
 &amp;lt;bmxRegistryUrl&amp;gt;https://content.api.bose.io/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Um die Box auf einen anderen Server umzubiegen, der unter dem Namen oder der IP-adresse &amp;lt;code&amp;gt;&#039;{NeuerServer}:{Port}&#039;&amp;lt;/code&amp;gt; erreichbar ist, bitte den Inhalt wie folgt ändern:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
  &amp;lt;margeServerUrl&amp;gt;http://{NeuerServer}:{Port}/marge&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;statsServerUrl&amp;gt;http://{NeuerServer}:{Port}&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;swUpdateUrl&amp;gt;http://{NeuerServer}:{Port}/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
  &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
  &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
  &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
  &amp;lt;bmxRegistryUrl&amp;gt;http://{NeuerServer}:{Port}/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das Gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
&lt;br /&gt;
== ST10 zum Stereopaar verbinden ==&lt;br /&gt;
Zwei ST10-Boxen können auch ohne BOSE App und BOSE Server zu einem Stereopaar verbunden werden.&lt;br /&gt;
*Beide ST10 für den telnet-Zugang vorbereiten, so wie oben beschrieben&lt;br /&gt;
*Auswählen, welche Box künftig den LINKEN Stereokanal wiedergeben soll, einloggen als root&lt;br /&gt;
**Auf dieser Box in das korrekte Verzeichnis wechseln&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
** Hier liegt eine Datei &#039;&#039;GroupService.xml&#039;&#039;. Im normalen (ungepaarten) Zustand hat diese den Inhalt&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;group /&amp;gt;&lt;br /&gt;
**Den Inhalt dieser Datei ersetzen durch&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;group id=&amp;quot;1234567&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;{NAME DES PAARS, z.B. &amp;quot;ST10-1 und ST10-2&amp;quot;}&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;masterDeviceId&amp;gt;{BOSE-ID des Master-Devices, z.B. 50338B343905}&amp;lt;/masterDeviceId&amp;gt;&lt;br /&gt;
    &amp;lt;roles&amp;gt;&lt;br /&gt;
        &amp;lt;groupRole&amp;gt;&lt;br /&gt;
            &amp;lt;deviceId&amp;gt;{BOSE-ID des Master-Devices, z.B. 50338B343905}&amp;lt;/deviceId&amp;gt;&lt;br /&gt;
            &amp;lt;role&amp;gt;LEFT&amp;lt;/role&amp;gt;&lt;br /&gt;
            &amp;lt;ipAddress&amp;gt;{IP-Adresse des Master-Devices}&amp;lt;/ipAddress&amp;gt;&lt;br /&gt;
        &amp;lt;/groupRole&amp;gt;&lt;br /&gt;
        &amp;lt;groupRole&amp;gt;&lt;br /&gt;
            &amp;lt;deviceId&amp;gt;{BOSE-ID des Slave-Devices, z.B. 458790343905}&amp;lt;/deviceId&amp;gt;&lt;br /&gt;
            &amp;lt;role&amp;gt;RIGHT&amp;lt;/role&amp;gt;&lt;br /&gt;
            &amp;lt;ipAddress&amp;gt;{IP-Adresse des Slave-Devices}&amp;lt;/ipAddress&amp;gt;&lt;br /&gt;
        &amp;lt;/groupRole&amp;gt;&lt;br /&gt;
    &amp;lt;/roles&amp;gt;&lt;br /&gt;
    &amp;lt;senderIPAddress&amp;gt;{IP-Adresse des Master-Devices}&amp;lt;/senderIPAddress&amp;gt;&lt;br /&gt;
 &amp;lt;/group&amp;gt;&lt;br /&gt;
** Datei sichern und die Box neu booten&lt;br /&gt;
*Auswählen, welche Box künftig den RECHTEN Stereokanal wiedergeben soll, einloggen als root&lt;br /&gt;
**Auf dieser Box in das korrekte Verzeichnis wechseln&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
** Hier liegt eine Datei &#039;&#039;GroupService.xml&#039;&#039;. Im normalen (ungepaarten) Zustand hat diese den Inhalt&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;group /&amp;gt;&lt;br /&gt;
**Den Inhalt dieser Datei ersetzen durch&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;group id=&amp;quot;1234567&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;{NAME DES PAARS, z.B. &amp;quot;ST10-1 und ST10-2&amp;quot;}&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;masterDeviceId&amp;gt;{BOSE-ID des Master-Devices, z.B. 50338B343905}&amp;lt;/masterDeviceId&amp;gt;&lt;br /&gt;
    &amp;lt;roles&amp;gt;&lt;br /&gt;
        &amp;lt;groupRole&amp;gt;&lt;br /&gt;
            &amp;lt;deviceId&amp;gt;{BOSE-ID des Master-Devices, z.B. 50338B343905}&amp;lt;/deviceId&amp;gt;&lt;br /&gt;
            &amp;lt;role&amp;gt;LEFT&amp;lt;/role&amp;gt;&lt;br /&gt;
            &amp;lt;ipAddress&amp;gt;{IP-Adresse des Master-Devices}&amp;lt;/ipAddress&amp;gt;&lt;br /&gt;
        &amp;lt;/groupRole&amp;gt;&lt;br /&gt;
        &amp;lt;groupRole&amp;gt;&lt;br /&gt;
            &amp;lt;deviceId&amp;gt;{BOSE-ID des Slave-Devices, z.B. 458790343905}&amp;lt;/deviceId&amp;gt;&lt;br /&gt;
            &amp;lt;role&amp;gt;RIGHT&amp;lt;/role&amp;gt;&lt;br /&gt;
            &amp;lt;ipAddress&amp;gt;{IP-Adresse des Slave-Devices}&amp;lt;/ipAddress&amp;gt;&lt;br /&gt;
        &amp;lt;/groupRole&amp;gt;&lt;br /&gt;
    &amp;lt;/roles&amp;gt;&lt;br /&gt;
    &amp;lt;senderIPAddress&amp;gt;{IP-Adresse des Master-Devices}&amp;lt;/senderIPAddress&amp;gt;&lt;br /&gt;
    &amp;lt;status&amp;gt;GROUP_OK&amp;lt;/status&amp;gt;&lt;br /&gt;
 &amp;lt;/group&amp;gt;&lt;br /&gt;
** Achtung: Der einzige Unterschied zur Datei auf der LINKEN Box ist die vorletzte Zeile mit dem &#039;&#039;status&#039;&#039;&lt;br /&gt;
**Datei sichern und die Box neu booten&lt;br /&gt;
Abspielbefehle werden dann nur an die Master-Box gesendet, diese synchronisiert sich automatisch mit der anderen Box&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40783</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40783"/>
		<updated>2026-02-10T09:25:00Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt:&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung allgemein===&lt;br /&gt;
In der Regel werden für den cloudfreien Betrieb der Boxen sowohl die Device-ID, als auch die ID des BOSE-Accounts benötigt. Dazu greift man mit einem Browser auf das API der Box zu, und ruft die Adresse&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
auf. Die Rückgabe sieht etwa so aus:&lt;br /&gt;
 &amp;lt;info deviceID=&amp;quot;{Device-ID}&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;name&amp;gt;{Name des Geräts in der BOSE Apps}&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;SoundTouch 300&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;margeAccountUUID&amp;gt;{ID des BOSE-Accounts}&amp;lt;/margeAccountUUID&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
Diese beiden Codes bitte notieren. Außerdem die drei Dateien&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/recents &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/preset&lt;br /&gt;
lokal abspeichern mit den Namen DeviceInfo.xml, Recents.xml, Presets.xml (Achtung, XML-Header nicht vergessen).&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken, die Taste kann losgelassen werden.&lt;br /&gt;
&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services&#039; erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
Während das für die Umstellung auf cloudfreien Betrieb ganz komfortabel ist, sollte man diese Datei nach erfolgreich getester Umstellung wieder löschen, denn sonst ist die Box komplett ungesichert!&lt;br /&gt;
&lt;br /&gt;
===Holen weiterer Daten===&lt;br /&gt;
Nach einem Wechsel in das korrekte Verzeichnis&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
findet man dort auch die schon oben erwähnten Dateien Recents.xml und Presets.xml, sie können auch von hier auf den USB-Stick herunterkopiert werden.&lt;br /&gt;
&lt;br /&gt;
Ebenfalls in diesem Verzeichnis liegt die Datei Sources.xml, dies muss ebenfalls entweder kopiert werden. Entweder lokal auf den USB-Stick oder, z.B. mit dem Befehl&lt;br /&gt;
 scp Sources.xml {username}@{irgendein computer}&lt;br /&gt;
via Netz übertragen werden.&lt;br /&gt;
&lt;br /&gt;
===Umbiegen===&lt;br /&gt;
Die Konfiguration der BOSE-Server kann jetzt geändert werden, dazu muss man das richtige Verzeichnis auf der Box kennen, das Dateisystem beschreibbar machen und die entsprechende Datei ändern&lt;br /&gt;
 cd /opt/Bose/etc/&lt;br /&gt;
 rw&lt;br /&gt;
 cp SoundTouchSdkPrivateCfg.xml STSPC.backup&lt;br /&gt;
 vi SoundTouchSdkPrivateCfg.xml&lt;br /&gt;
Für Nicht-Linux-Nutzer ist der vi Editor etwas gewöhnungsbedürftig, hier findet man eine [https://sits.de/vi.html Mini-Anleitung].&lt;br /&gt;
&lt;br /&gt;
Die Datei enthält im BOSE-Urzustand folgende Informationen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
 &amp;lt;margeServerUrl&amp;gt;https://streaming.bose.com&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;statsServerUrl&amp;gt;https://events.api.bosecm.com&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;swUpdateUrl&amp;gt;https://worldwide.bose.com/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
 &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
 &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
 &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
 &amp;lt;bmxRegistryUrl&amp;gt;https://content.api.bose.io/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Um die Box auf einen anderen Server umzubiegen, der unter dem Namen oder der IP-adresse &amp;lt;code&amp;gt;&#039;{NeuerServer}:{Port}&#039;&amp;lt;/code&amp;gt; erreichbar ist, bitte den Inhalt wie folgt ändern:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
  &amp;lt;margeServerUrl&amp;gt;http://{NeuerServer}:{Port}/marge&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;statsServerUrl&amp;gt;http://{NeuerServer}:{Port}&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;swUpdateUrl&amp;gt;http://{NeuerServer}:{Port}/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
  &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
  &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
  &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
  &amp;lt;bmxRegistryUrl&amp;gt;http://{NeuerServer}:{Port}/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das Gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
&lt;br /&gt;
== ST10 zum Stereopaar verbinden ==&lt;br /&gt;
Zwei ST10-Boxen können auch ohne BOSE App und BOSE Server zu einem Stereopaar verbunden werden.&lt;br /&gt;
*Beide ST10 für den telnet-Zugang vorbereiten, so wie oben beschrieben&lt;br /&gt;
*Auswählen, welche Box künftig den LINKEN Stereokanal wiedergeben soll, einloggen als root&lt;br /&gt;
**Auf dieser Box in das korrekte Verzeichnis wechseln&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
** Hier liegt eine Datei &#039;&#039;GroupService.xml&#039;&#039;. Im normalen (ungepaarten) Zustand hat diese den Inhalt&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;group /&amp;gt;&lt;br /&gt;
**Den Inhalt dieser Datei ersetzen durch&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;group id=&amp;quot;1234567&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;{NAME DES PAARS, z.B. &amp;quot;ST10-1 und ST10-2&amp;quot;}&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;masterDeviceId&amp;gt;{BOSE-ID des Master-Devices, z.B. 50338B343905}&amp;lt;/masterDeviceId&amp;gt;&lt;br /&gt;
    &amp;lt;roles&amp;gt;&lt;br /&gt;
        &amp;lt;groupRole&amp;gt;&lt;br /&gt;
            &amp;lt;deviceId&amp;gt;{BOSE-ID des Master-Devices, z.B. 50338B343905}&amp;lt;/deviceId&amp;gt;&lt;br /&gt;
            &amp;lt;role&amp;gt;LEFT&amp;lt;/role&amp;gt;&lt;br /&gt;
            &amp;lt;ipAddress&amp;gt;{IP-Adresse des Master-Devices}&amp;lt;/ipAddress&amp;gt;&lt;br /&gt;
        &amp;lt;/groupRole&amp;gt;&lt;br /&gt;
        &amp;lt;groupRole&amp;gt;&lt;br /&gt;
            &amp;lt;deviceId&amp;gt;{BOSE-ID des Slave-Devices, z.B. 458790343905}&amp;lt;/deviceId&amp;gt;&lt;br /&gt;
            &amp;lt;role&amp;gt;RIGHT&amp;lt;/role&amp;gt;&lt;br /&gt;
            &amp;lt;ipAddress&amp;gt;{IP-Adresse des Slave-Devices}&amp;lt;/ipAddress&amp;gt;&lt;br /&gt;
        &amp;lt;/groupRole&amp;gt;&lt;br /&gt;
    &amp;lt;/roles&amp;gt;&lt;br /&gt;
    &amp;lt;senderIPAddress&amp;gt;{IP-Adresse des Master-Devices}&amp;lt;/senderIPAddress&amp;gt;&lt;br /&gt;
 &amp;lt;/group&amp;gt;&lt;br /&gt;
** Datei sichern und die Box neu booten&lt;br /&gt;
*Auswählen, welche Box künftig den RECHTEN Stereokanal wiedergeben soll, einloggen als root&lt;br /&gt;
**Auf dieser Box in das korrekte Verzeichnis wechseln&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
** Hier liegt eine Datei &#039;&#039;GroupService.xml&#039;&#039;. Im normalen (ungepaarten) Zustand hat diese den Inhalt&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;group /&amp;gt;&lt;br /&gt;
**Den Inhalt dieser Datei ersetzen durch&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
 &amp;lt;group id=&amp;quot;1234567&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;{NAME DES PAARS, z.B. &amp;quot;ST10-1 und ST10-2&amp;quot;}&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;masterDeviceId&amp;gt;{BOSE-ID des Master-Devices, z.B. 50338B343905}&amp;lt;/masterDeviceId&amp;gt;&lt;br /&gt;
    &amp;lt;roles&amp;gt;&lt;br /&gt;
        &amp;lt;groupRole&amp;gt;&lt;br /&gt;
            &amp;lt;deviceId&amp;gt;{BOSE-ID des Master-Devices, z.B. 50338B343905}&amp;lt;/deviceId&amp;gt;&lt;br /&gt;
            &amp;lt;role&amp;gt;LEFT&amp;lt;/role&amp;gt;&lt;br /&gt;
            &amp;lt;ipAddress&amp;gt;{IP-Adresse des Master-Devices}&amp;lt;/ipAddress&amp;gt;&lt;br /&gt;
        &amp;lt;/groupRole&amp;gt;&lt;br /&gt;
        &amp;lt;groupRole&amp;gt;&lt;br /&gt;
            &amp;lt;deviceId&amp;gt;{BOSE-ID des Slave-Devices, z.B. 458790343905}&amp;lt;/deviceId&amp;gt;&lt;br /&gt;
            &amp;lt;role&amp;gt;RIGHT&amp;lt;/role&amp;gt;&lt;br /&gt;
            &amp;lt;ipAddress&amp;gt;{IP-Adresse des Slave-Devices}&amp;lt;/ipAddress&amp;gt;&lt;br /&gt;
        &amp;lt;/groupRole&amp;gt;&lt;br /&gt;
    &amp;lt;/roles&amp;gt;&lt;br /&gt;
    &amp;lt;senderIPAddress&amp;gt;{IP-Adresse des Master-Devices}&amp;lt;/senderIPAddress&amp;gt;&lt;br /&gt;
    &amp;lt;status&amp;gt;GROUP_OK&amp;lt;/status&amp;gt;&lt;br /&gt;
 &amp;lt;/group&amp;gt;&lt;br /&gt;
** Achtung: Der einzige Unterschied zur Datei auf der LINKEN Box ist die vorletzte Zeile mit dem &#039;&#039;status&#039;&#039;&lt;br /&gt;
**Datei sichern und die Box neu booten&lt;br /&gt;
Abspielbefehle werden dann nur an die Master-Box gesendet, diese synchronisiert sich automatisch mit der anderen Box&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI3_Label&amp;diff=40780</id>
		<title>FTUI3 Label</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI3_Label&amp;diff=40780"/>
		<updated>2026-02-07T09:54:25Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Zeilenumbruch im Label */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Zeilenumbruch im Label==&lt;br /&gt;
Wenn der Inhalt des Labels nur aus Text besteht, kann ein Zeilenumbruch durch das Einfügen des Strings &amp;lt;code&amp;gt;&amp;amp;lt;br&amp;gt;&amp;lt;/code&amp;gt; erzwungen werden.&lt;br /&gt;
&lt;br /&gt;
Wenn allerdings komplexere HTML-Inhalte enthalten sind, z.B.  &amp;lt;code&amp;gt;&amp;lt;img ...&amp;gt;&amp;lt;/code&amp;gt;-Elemente, werden solche Zeilenumbrüche ignoriert. Mittels eines einfachen Tricks kann allerdings Abhilfe geschaffen werden. Dazu definiert man im Seitenheader etwas JavaScript-Code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;script&amp;gt;&lt;br /&gt;
  const ftui_linebreaker = () =&amp;gt; input =&amp;gt; linebreaker(input);&lt;br /&gt;
  ...&lt;br /&gt;
  //-- helper function for linebreak&lt;br /&gt;
  function linebreaker(lines){&lt;br /&gt;
  let linea = lines.split(&#039;&amp;lt;br&amp;gt;&#039;);&lt;br /&gt;
  let num=linea.length;&lt;br /&gt;
  let ret=&#039;&amp;lt;ul style=&amp;quot;list-style-type:none;margin-left:0px;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
  for (var i = 0; i &amp;lt; num; i++) {&lt;br /&gt;
       ret+=&#039;&amp;lt;li&amp;gt;&#039;+linea[i]+&#039;&amp;lt;/li&amp;gt;&#039;;&lt;br /&gt;
  }&lt;br /&gt;
  ret+=&#039;&amp;lt;/ul&amp;gt;&#039;;&lt;br /&gt;
  return ret;&lt;br /&gt;
 }&lt;br /&gt;
 &amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Mit dieser Funktion wird der in der Variablen &amp;lt;code&amp;gt;input&amp;lt;/code&amp;gt; übergebene Label-Text an den eingefügten Zeilenumbrüchen &amp;lt;code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/code&amp;gt; aufgespalten und in eine so genannte ungeordnete Liste (unordered list &amp;lt;code&amp;gt;&amp;amp;lt;ul&amp;gt;&amp;lt;/code&amp;gt;) umzuwandeln und zurückzugeben. In einem &amp;lt;code&amp;gt;&amp;amp;lt;ftui-label&amp;gt;&amp;lt;/code&amp;gt;-Element wird dies angewendet als &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;ftui-label [text]=&amp;quot;DEVICE:READING | ftui_linebreaker()&amp;quot; scroll&amp;gt;&amp;lt;/ftui-label&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und resultiert in einer sauberen Ausrichtung der einzelnen Zeilen.&lt;br /&gt;
[[Kategorie:FHEM Tablet UI V3]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40773</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40773"/>
		<updated>2026-01-28T09:51:00Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Umbiegen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt:&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung allgemein===&lt;br /&gt;
In der Regel werden für den cloudfreien Betrieb der Boxen sowohl die Device-ID, als auch die ID des BOSE-Accounts benötigt. Dazu greift man mit einem Browser auf das API der Box zu, und ruft die Adresse&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
auf. Die Rückgabe sieht etwa so aus:&lt;br /&gt;
 &amp;lt;info deviceID=&amp;quot;{Device-ID}&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;name&amp;gt;{Name des Geräts in der BOSE Apps}&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;SoundTouch 300&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;margeAccountUUID&amp;gt;{ID des BOSE-Accounts}&amp;lt;/margeAccountUUID&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
Diese beiden Codes bitte notieren. Außerdem die drei Dateien&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/recents &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/preset&lt;br /&gt;
lokal abspeichern mit den Namen DeviceInfo.xml, Recents.xml, Presets.xml (Achtung, XML-Header nicht vergessen).&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken, die Taste kann losgelassen werden.&lt;br /&gt;
&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services&#039; erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
Während das für die Umstellung auf cloudfreien Betrieb ganz komfortabel ist, sollte man diese Datei nach erfolgreich getester Umstellung wieder löschen, denn sonst ist die Box komplett ungesichert!&lt;br /&gt;
&lt;br /&gt;
===Holen weiterer Daten===&lt;br /&gt;
Nach einem Wechsel in das korrekte Verzeichnis&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
findet man dort auch die schon oben erwähnten Dateien Recents.xml und Presets.xml, sie können auch von hier auf den USB-Stick herunterkopiert werden.&lt;br /&gt;
&lt;br /&gt;
Ebenfalls in diesem Verzeichnis liegt die Datei Sources.xml, dies muss ebenfalls entweder kopiert werden. Entweder lokal auf den USB-Stick oder, z.B. mit dem Befehl&lt;br /&gt;
 scp Sources.xml {username}@{irgendein computer}&lt;br /&gt;
via Netz übertragen werden.&lt;br /&gt;
&lt;br /&gt;
===Umbiegen===&lt;br /&gt;
Die Konfiguration der BOSE-Server kann jetzt geändert werden, dazu muss man das richtige Verzeichnis auf der Box kennen, das Dateisystem beschreibbar machen und die entsprechende Datei ändern&lt;br /&gt;
 cd /opt/Bose/etc/&lt;br /&gt;
 rw&lt;br /&gt;
 cp SoundTouchSdkPrivateCfg.xml STSPC.backup&lt;br /&gt;
 vi SoundTouchSdkPrivateCfg.xml&lt;br /&gt;
Für Nicht-Linux-Nutzer ist der vi Editor etwas gewöhnungsbedürftig, hier findet man eine [https://sits.de/vi.html Mini-Anleitung].&lt;br /&gt;
&lt;br /&gt;
Die Datei enthält im BOSE-Urzustand folgende Informationen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
 &amp;lt;margeServerUrl&amp;gt;https://streaming.bose.com&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;statsServerUrl&amp;gt;https://events.api.bosecm.com&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;swUpdateUrl&amp;gt;https://worldwide.bose.com/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
 &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
 &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
 &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
 &amp;lt;bmxRegistryUrl&amp;gt;https://content.api.bose.io/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Um die Box auf einen anderen Server umzubiegen, der unter dem Namen oder der IP-adresse &amp;lt;code&amp;gt;&#039;{NeuerServer}:{Port}&#039;&amp;lt;/code&amp;gt; erreichbar ist, bitte den Inhalt wie folgt ändern:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
  &amp;lt;margeServerUrl&amp;gt;http://{NeuerServer}:{Port}/marge&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;statsServerUrl&amp;gt;http://{NeuerServer}:{Port}&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;swUpdateUrl&amp;gt;http://{NeuerServer}:{Port}/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
  &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
  &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
  &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
  &amp;lt;bmxRegistryUrl&amp;gt;http://{NeuerServer}:{Port}/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das Gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40772</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40772"/>
		<updated>2026-01-28T09:30:46Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Holen weiterer Daten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt:&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung allgemein===&lt;br /&gt;
In der Regel werden für den cloudfreien Betrieb der Boxen sowohl die Device-ID, als auch die ID des BOSE-Accounts benötigt. Dazu greift man mit einem Browser auf das API der Box zu, und ruft die Adresse&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
auf. Die Rückgabe sieht etwa so aus:&lt;br /&gt;
 &amp;lt;info deviceID=&amp;quot;{Device-ID}&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;name&amp;gt;{Name des Geräts in der BOSE Apps}&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;SoundTouch 300&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;margeAccountUUID&amp;gt;{ID des BOSE-Accounts}&amp;lt;/margeAccountUUID&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
Diese beiden Codes bitte notieren. Außerdem die drei Dateien&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/recents &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/preset&lt;br /&gt;
lokal abspeichern mit den Namen DeviceInfo.xml, Recents.xml, Presets.xml (Achtung, XML-Header nicht vergessen).&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken, die Taste kann losgelassen werden.&lt;br /&gt;
&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services&#039; erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
Während das für die Umstellung auf cloudfreien Betrieb ganz komfortabel ist, sollte man diese Datei nach erfolgreich getester Umstellung wieder löschen, denn sonst ist die Box komplett ungesichert!&lt;br /&gt;
&lt;br /&gt;
===Holen weiterer Daten===&lt;br /&gt;
Nach einem Wechsel in das korrekte Verzeichnis&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
findet man dort auch die schon oben erwähnten Dateien Recents.xml und Presets.xml, sie können auch von hier auf den USB-Stick herunterkopiert werden.&lt;br /&gt;
&lt;br /&gt;
Ebenfalls in diesem Verzeichnis liegt die Datei Sources.xml, dies muss ebenfalls entweder kopiert werden. Entweder lokal auf den USB-Stick oder, z.B. mit dem Befehl&lt;br /&gt;
 scp Sources.xml {username}@{irgendein computer}&lt;br /&gt;
via Netz übertragen werden.&lt;br /&gt;
&lt;br /&gt;
===Umbiegen===&lt;br /&gt;
Die Konfiguration der BOSE-Server kann jetzt geändert werden, dazu muss man das richtige Verzeichnis auf der Box kennen, das Dateisystem beschreibbar machen und die entsprechende Datei ändern&lt;br /&gt;
 cd /opt/Bose/etc/&lt;br /&gt;
 rw&lt;br /&gt;
 vi SoundTouchSdkPrivateCfg.xml&lt;br /&gt;
Für Nicht-Linux-Nutzer ist der vi Editor etwas gewöhnungsbedürftig, hier findet man eine [https://sits.de/vi.html Mini-Anleitung].&lt;br /&gt;
&lt;br /&gt;
Die Datei enthält im BOSE-Urzustand folgende Informationen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
 &amp;lt;margeServerUrl&amp;gt;https://streaming.bose.com&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;statsServerUrl&amp;gt;https://events.api.bosecm.com&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;swUpdateUrl&amp;gt;https://worldwide.bose.com/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
 &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
 &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
 &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
 &amp;lt;bmxRegistryUrl&amp;gt;https://content.api.bose.io/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Um die Box auf einen anderen Server umzubiegen, der unter dem Namen oder der IP-adresse &amp;lt;code&amp;gt;&#039;{NeuerServer}:{Port}&#039;&amp;lt;/code&amp;gt; erreichbar ist, bitte den Inhalt wie folgt ändern:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
  &amp;lt;margeServerUrl&amp;gt;http://{NeuerServer}:{Port}/marge&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;statsServerUrl&amp;gt;http://{NeuerServer}:{Port}&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;swUpdateUrl&amp;gt;http://{NeuerServer}:{Port}/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
  &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
  &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
  &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
  &amp;lt;bmxRegistryUrl&amp;gt;http://{NeuerServer}:{Port}/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das Gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40771</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40771"/>
		<updated>2026-01-28T09:28:54Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Vorbereitung ST300 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt:&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung allgemein===&lt;br /&gt;
In der Regel werden für den cloudfreien Betrieb der Boxen sowohl die Device-ID, als auch die ID des BOSE-Accounts benötigt. Dazu greift man mit einem Browser auf das API der Box zu, und ruft die Adresse&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
auf. Die Rückgabe sieht etwa so aus:&lt;br /&gt;
 &amp;lt;info deviceID=&amp;quot;{Device-ID}&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;name&amp;gt;{Name des Geräts in der BOSE Apps}&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;SoundTouch 300&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;margeAccountUUID&amp;gt;{ID des BOSE-Accounts}&amp;lt;/margeAccountUUID&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
Diese beiden Codes bitte notieren. Außerdem die drei Dateien&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/recents &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/preset&lt;br /&gt;
lokal abspeichern mit den Namen DeviceInfo.xml, Recents.xml, Presets.xml (Achtung, XML-Header nicht vergessen).&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken, die Taste kann losgelassen werden.&lt;br /&gt;
&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services&#039; erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
Während das für die Umstellung auf cloudfreien Betrieb ganz komfortabel ist, sollte man diese Datei nach erfolgreich getester Umstellung wieder löschen, denn sonst ist die Box komplett ungesichert!&lt;br /&gt;
&lt;br /&gt;
===Holen weiterer Daten===&lt;br /&gt;
Nach einem Wechsel in das korrekte Verzeichnis&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
findet man dort auch die schon oben erwähnten Dateien Recents.xml und Presets.xml, sie können auch von hier auf den USB-Stick herunterkopiert werden.&lt;br /&gt;
&lt;br /&gt;
Ebenfalls in diesem Verzeichnis liegt die Datei Sources.xml, dies muss ebenfalls entweder kopiert werden. Entweder local auf den USB-Stick oder, z.B. mit dem Befehl&lt;br /&gt;
 scp Sources.xml {username}@{irgendein computer}&lt;br /&gt;
Via Netz übertragen werden.&lt;br /&gt;
===Umbiegen===&lt;br /&gt;
Die Konfiguration der BOSE-Server kann jetzt geändert werden, dazu muss man das richtige Verzeichnis auf der Box kennen, das Dateisystem beschreibbar machen und die entsprechende Datei ändern&lt;br /&gt;
 cd /opt/Bose/etc/&lt;br /&gt;
 rw&lt;br /&gt;
 vi SoundTouchSdkPrivateCfg.xml&lt;br /&gt;
Für Nicht-Linux-Nutzer ist der vi Editor etwas gewöhnungsbedürftig, hier findet man eine [https://sits.de/vi.html Mini-Anleitung].&lt;br /&gt;
&lt;br /&gt;
Die Datei enthält im BOSE-Urzustand folgende Informationen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
 &amp;lt;margeServerUrl&amp;gt;https://streaming.bose.com&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;statsServerUrl&amp;gt;https://events.api.bosecm.com&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;swUpdateUrl&amp;gt;https://worldwide.bose.com/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
 &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
 &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
 &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
 &amp;lt;bmxRegistryUrl&amp;gt;https://content.api.bose.io/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Um die Box auf einen anderen Server umzubiegen, der unter dem Namen oder der IP-adresse &amp;lt;code&amp;gt;&#039;{NeuerServer}:{Port}&#039;&amp;lt;/code&amp;gt; erreichbar ist, bitte den Inhalt wie folgt ändern:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;XML&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
  &amp;lt;margeServerUrl&amp;gt;http://{NeuerServer}:{Port}/marge&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;statsServerUrl&amp;gt;http://{NeuerServer}:{Port}&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;swUpdateUrl&amp;gt;http://{NeuerServer}:{Port}/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
  &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
  &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
  &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
  &amp;lt;bmxRegistryUrl&amp;gt;http://{NeuerServer}:{Port}/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das Gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40769</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40769"/>
		<updated>2026-01-27T11:24:36Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* De-clouding */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung allgemein===&lt;br /&gt;
In der Regel werden für den cloudfreien Betrieb der Boxen sowohl die Device-ID, als auch die ID des BOSE-Accounts benötigt. Dazu greift man mit einem Browser auf das API der Box zu, und ruft die Adresse&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
auf. Die Rückgabe sieht etwa so aus:&lt;br /&gt;
 &amp;lt;info deviceID=&amp;quot;{Device-ID}&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;name&amp;gt;{Name des Geräts in der BOSE Apps}&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;SoundTouch 300&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;margeAccountUUID&amp;gt;{ID des BOSE-Accounts}&amp;lt;/margeAccountUUID&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
Diese beiden Codes bitte notieren. Außerdem die drei Dateien&lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/info &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/recents &lt;br /&gt;
 http://&amp;lt;IP-Adresse der Box&amp;gt;:8090/preset&lt;br /&gt;
lokal abspeichern mit den Namen DeviceInfo.xml, Recents.xml, Presets.xml (Achtung, XML-Header nicht vergessen).&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services&#039; erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
Während das für die Umstellung auf cloudfreien betrieb ganz komfortabel ist, sollte man diese Datei nach erfolgreich getester Umstellung wieder löschen, denn sonst ist die Box komplett ungesichert !&lt;br /&gt;
===Holen weiterer Daten===&lt;br /&gt;
Nach einem Wechsel in das korrekte Verzeichnis&lt;br /&gt;
 cd /mnt/nv/BoseApp-Persistence/1/&lt;br /&gt;
findet man dort auch die schon oben erwähnten Dateien Recents.xml und Presets.xml, sie können auch von hier auf den USB-Stick herunterkopiert werden.&lt;br /&gt;
&lt;br /&gt;
Ebenfalls in diesem Verzeichnis liegt die Datei Sources.xml, dies muss ebenfalls entweder kopiert werden. Entweder local auf den USB-Stick oder, z.B. mit dem Befehl&lt;br /&gt;
 scp Sources.xml {username}@{irgendein computer}&lt;br /&gt;
Via Netz übertragen werden.&lt;br /&gt;
===Umbiegen===&lt;br /&gt;
Die Konfiguration der BOSE-Server kann jetzt geändert werden, dazu muss man das richtige Verzeichnis auf der Box kennen, das Dateisystem beschreibbar machen und die entsprechende Datei ändern&lt;br /&gt;
 cd /opt/Bose/etc/&lt;br /&gt;
 rw&lt;br /&gt;
 vi SoundTouchSdkPrivateCfg.xml&lt;br /&gt;
Für Nicht-Linux-Nutzer ist der vi Editor etwas gewöhnungsbedürftig, hier findet man eine [https://sits.de/vi.html Mini-Anleitung].&lt;br /&gt;
&lt;br /&gt;
Die Datei enthält im BOSE-Urzustand folgende Informationen&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
 &amp;lt;margeServerUrl&amp;gt;https://streaming.bose.com&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;statsServerUrl&amp;gt;https://events.api.bosecm.com&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;swUpdateUrl&amp;gt;https://worldwide.bose.com/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
 &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
 &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
 &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
 &amp;lt;bmxRegistryUrl&amp;gt;https://content.api.bose.io/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&amp;gt;&lt;br /&gt;
Um die Box auf einen anderen Server umzubiegen, der unter dem Namen oder der IP-adresse &#039;{NeuerServer}:{Port}&#039; erreichbar ist, bitte den Inhalt wie folgt ändern:&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
  &amp;lt;margeServerUrl&amp;gt;http://{NeuerServer}:{Port}/marge&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;statsServerUrl&amp;gt;http://{NeuerServer}:{Port}&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;swUpdateUrl&amp;gt;http://{NeuerServer}:{Port}/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
  &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
  &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
  &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
  &amp;lt;bmxRegistryUrl&amp;gt;http://{NeuerServer}:{Port}/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40768</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40768"/>
		<updated>2026-01-27T11:02:25Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Zugang */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services&#039; erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
Während das für die Umstellung auf cloudfreien betrieb ganz komfortabel ist, sollte man diese Datei nach erfolgreich getester Umstellung wieder löschen, denn sonst ist die Box komplett ungesichert !&lt;br /&gt;
===Umbiegen===&lt;br /&gt;
Die Konfiguration der BOSE-Server kann jetzt geändert werden, dazu muss man das richtige Verzeichnis auf der Box kennen, das Dateisystem beschreibbar machen und die entsprechende Datei ändern&lt;br /&gt;
 cd /opt/Bose/etc/&lt;br /&gt;
 rw&lt;br /&gt;
 vi SoundTouchSdkPrivateCfg.xml&lt;br /&gt;
Für Nicht-Linux-Nutzer ist der vi Editor etwas gewöhnungsbedürftig, hier findet man eine [https://sits.de/vi.html Mini-Anleitung].&lt;br /&gt;
&lt;br /&gt;
Die Datei enthält im BOSE-Urzustand folgende Informationen&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
 &amp;lt;margeServerUrl&amp;gt;https://streaming.bose.com&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;statsServerUrl&amp;gt;https://events.api.bosecm.com&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
 &amp;lt;swUpdateUrl&amp;gt;https://worldwide.bose.com/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
 &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
 &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
 &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
 &amp;lt;bmxRegistryUrl&amp;gt;https://content.api.bose.io/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&amp;gt;&lt;br /&gt;
Um die Box auf einen anderen Server umzubiegen, der unter dem Namen oder der IP-adresse &#039;{NeuerServer}:{Port}&#039; erreichbar ist, bitte den Inhalt wie folgt ändern:&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
  &amp;lt;margeServerUrl&amp;gt;http://{NeuerServer}:{Port}/marge&amp;lt;/margeServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;statsServerUrl&amp;gt;http://{NeuerServer}:{Port}&amp;lt;/statsServerUrl&amp;gt;&lt;br /&gt;
  &amp;lt;swUpdateUrl&amp;gt;http://{NeuerServer}:{Port}/updates/soundtouch&amp;lt;/swUpdateUrl&amp;gt;&lt;br /&gt;
  &amp;lt;usePandoraProductionServer&amp;gt;true&amp;lt;/usePandoraProductionServer&amp;gt;&lt;br /&gt;
  &amp;lt;isZeroconfEnabled&amp;gt;true&amp;lt;/isZeroconfEnabled&amp;gt;&lt;br /&gt;
  &amp;lt;saveMargeCustomerReport&amp;gt;false&amp;lt;/saveMargeCustomerReport&amp;gt;&lt;br /&gt;
  &amp;lt;bmxRegistryUrl&amp;gt;http://{NeuerServer}:{Port}/bmx/registry/v1/services&amp;lt;/bmxRegistryUrl&amp;gt;&lt;br /&gt;
 &amp;lt;/SoundTouchSdkPrivateCfg&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_offline_vermeiden&amp;diff=40767</id>
		<title>BOSE SoundTouch offline vermeiden</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_offline_vermeiden&amp;diff=40767"/>
		<updated>2026-01-26T14:28:36Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Lösung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Verbindungsabbrüche werden automatisch geheilt.&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
Aus unbekannten Gründen gibt es häufig (ca. 1x pro Stunde) einen Verbindungsabbruch der BOSE SoundTouch-Geräte zum SoundTouch-Modul.&lt;br /&gt;
&lt;br /&gt;
== Lösung ==&lt;br /&gt;
Die Aktivierung eines Suchprozesses im LAN/WLAN wird durch den Aufruf einer modulinternen Funktion erreicht. Diese modulinterne Funktion wandelt man durch die Definition&lt;br /&gt;
 define c_Bose_Find cmdalias Bose_Find AS {my $hash=$defs{&amp;lt;NAME DES BOSEST-HAUPTDEVICES&amp;gt;};;delete($hash-&amp;gt;{helper}{DISCOVERY_PID});;BOSEST_startDiscoveryProcess($hash)}&lt;br /&gt;
in ein FHEM-Kommando &#039;&#039;&#039;bose_find&#039;&#039;&#039; um. Dieses Kommando wird dann durch &lt;br /&gt;
 define Bose_Finder DOIF ([&amp;lt;NAME DES BOSE-GERÄTEDEVICES&amp;gt;:state] eq &amp;quot;offline&amp;quot;) (Bose_Find)&lt;br /&gt;
ausgerufen, wann immer das betreffende Device weg ist. Da &#039;&#039;&#039;Bose_Find&#039;&#039;&#039; alle Geräte-Devices findet und diese meist gleichzeitig offline gehen, reicht es in der Regel, einen der möglicherweise verschiedenen Gerätenamen anzugeben. &lt;br /&gt;
 &lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40766</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40766"/>
		<updated>2026-01-26T13:47:07Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Zugang */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services&#039; erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSEST&amp;diff=40765</id>
		<title>BOSEST</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSEST&amp;diff=40765"/>
		<updated>2026-01-26T13:43:48Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anbindung des BOSE SoundTouch Systems&lt;br /&gt;
|ModType=d&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=&lt;br /&gt;
|ModForumArea=Multimedia&lt;br /&gt;
|ModTechName=98_BOSEST.pm&lt;br /&gt;
|ModOwner=dominik&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SoundTouch ist ein Multiroom-Musiksystem der Firma [http://www.bose.com BOSE].&lt;br /&gt;
Es bietet die Möglichkeit der verteilten Musikabspielung und Steuerung, sowie der Verknüpfung von mehreren Playern, um diese dasselbe abspielen zu lassen.  &lt;br /&gt;
&lt;br /&gt;
Weitere wichtige Hinweise:&lt;br /&gt;
*[[BOSE_SoundTouch_de-clouding]], um die Boxen nach dem Abschalten der BOSE-Server weiter zu betreiben&lt;br /&gt;
*[[BOSE SoundTouch offline vermeiden]], um &#039;&#039;offline&#039;&#039; gegangene Boxen automatisch wieder zu aktivieren&lt;br /&gt;
*[[BOSE SoundTouch App stabilisieren]] - obsolet nach Abschaltung der Server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Work in Progress &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:BOSE]]&lt;br /&gt;
[[Category:Unterhaltungselektronik]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_offline_vermeiden&amp;diff=40764</id>
		<title>BOSE SoundTouch offline vermeiden</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_offline_vermeiden&amp;diff=40764"/>
		<updated>2026-01-26T13:42:27Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Verbindungsabbrüche werden automatisch geheilt.&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
Aus unbekannten Gründen gibt es häufig (ca. 1x pro Stunde) einen Verbindungsabbruch der BOSE SoundTouch-Geräte zum SoundTouch-Modul.&lt;br /&gt;
&lt;br /&gt;
== Lösung ==&lt;br /&gt;
Die Aktivierung eines Suchprozesses im LAN/WLAN wird durch den Aufruf einer modulinternen Funktion erreicht. Diese modulinterne Funktion wandelt man durch die Definition&lt;br /&gt;
 define c_Bose_Find cmdalias Bose_Find AS {my $hash=$defs{&amp;lt;NAME DES BOSEST-HAUPTDEVICES&amp;gt;};;delete($hash-&amp;gt;{helper}{DISCOVERY_PID});;BOSEST_startDiscoveryProcess($hash)}&lt;br /&gt;
in ein FHEM-Kommando &#039;&#039;&#039;bose_find&#039;&#039;&#039; um. Dieses Kommando wird dann durch &lt;br /&gt;
 define Bose_Finder DOIF ([&amp;lt;NAME DES BOSE-GERÄTEDEVICES&amp;gt;:state] eq &amp;quot;offline&amp;quot;) (bose_find)&lt;br /&gt;
ausgerufen, wann immer das betreffende Device weg ist. Da &#039;&#039;&#039;Bose_Find&#039;&#039;&#039; alle Geräte-Devices findet und diese meist gleichzeitig offline gehen, reicht es in der Regel, einen der möglicherweise verschiedenen Gerätenamen anzugeben. &lt;br /&gt;
 &lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40763</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40763"/>
		<updated>2026-01-26T13:36:00Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Zugang */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
Alternativ kann man auch verwenden&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent haben, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40762</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40762"/>
		<updated>2026-01-26T13:35:07Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* Zugang */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
===Zugang===&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
oder&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent habe, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40761</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40761"/>
		<updated>2026-01-26T13:34:45Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* ST300 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
==Zugang==&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
 telnet &amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Auf die Rückgabe &#039;rhino login&#039; einfach &#039;root&#039; eingeben, ein Passwort ist nicht erforderlich.&lt;br /&gt;
oder&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der Box&amp;gt;&lt;br /&gt;
Möchte man diesen Zugang permanent habe, um ggf. weitere Änderungen einfacher auszuführen, muss man eine leere Datei &#039;remote_services erzeugen mit dem Kommando&lt;br /&gt;
 touch /mnt/nv/remote_services&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40760</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40760"/>
		<updated>2026-01-26T13:31:29Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* ST20 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===Vorbereitung ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
&lt;br /&gt;
Auf einem Computer im Netzwerk ausführen&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der ST300&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40759</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40759"/>
		<updated>2026-01-26T13:31:15Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* ST10 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===Vorbereitung ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
&lt;br /&gt;
Auf einem Computer im Netzwerk ausführen&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der ST300&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40758</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40758"/>
		<updated>2026-01-26T13:28:53Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* ST10 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
Der Zugang ist jetzt möglich mit &lt;br /&gt;
 telnet &amp;lt;IP-Adresse&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
&lt;br /&gt;
Auf einem Computer im Netzwerk ausführen&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der ST300&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40757</id>
		<title>BOSE SoundTouch de-clouding</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=BOSE_SoundTouch_de-clouding&amp;diff=40757"/>
		<updated>2026-01-26T11:57:05Z</updated>

		<summary type="html">&lt;p&gt;Pahenning: /* ST10 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Zielgruppe ==&lt;br /&gt;
Benutzer von BOSE SoundTouch-Systemen&lt;br /&gt;
&lt;br /&gt;
== Lösungsübersicht ==&lt;br /&gt;
Cloudfreier Betrieb der BOSE-Boxen, De-bricking nach fehlerhaften Installationen&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
BOSE wird im Februar 2026 seine Server aus dem Netz nehmen. Damit wird die Funktionalität der BOSE-Boxen drastisch eingeschränkt, das Abspielen von netzbasierten Radiostreams ist ohne Modifikation der Boxen nicht möglich.&lt;br /&gt;
&lt;br /&gt;
== De-clouding ==&lt;br /&gt;
Um einen root-Zugang zum Linux-Betriebssystem der Boxen zu erhalten, wird benötigt&lt;br /&gt;
* USB-Stick, formatiert FAT32, mit einer leeren Datei &#039;remote_services&#039;. Achtung: Das bootable-Flag des Dateisystems muss gesetzt sein.&lt;br /&gt;
* Für BOSE ST10 und ST300 zusätzlich ein USB-OTG-Adapter. Das ist ein Adapter, der eine Buchse vom Typ USB A (in den wird der o.a. Stick gesteckt) mit einem Stecker vom Type USB Micro (Typ Micro B, trapezförmig) verbindet. Darin ist offenbar das 5. (ID-)Pin des Micro USB-Steckers mit GND verbunden. Diese Adapter gibt es für ca. 8 € im Handel, sie werden gerne benutzt, um Smartphones in den USB-Host-Modus zu bringen. &lt;br /&gt;
===ST10===&lt;br /&gt;
Achtung: Vorher unbedingt die Einbindung der ST10 in ein Stereopaar aufheben! Sonst ist das Gerät nach der Änderung der internen Dateien nur noch ein teurer Ziegelstein (&#039;Brick&#039;) und man muss erst die gesamte Firmware neu installieren, siehe unten.&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===ST20===&lt;br /&gt;
*USB-Stick mit dem USB-Port der ST20 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST20 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
&lt;br /&gt;
===ST300===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST300 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Infrarot-Fernbedienung der ST300 auf das Gerät richten, den &#039;&#039;SoundTouch&#039;&#039;-Button drücken und &#039;&#039;&#039;halten&#039;&#039;&#039; (2. Button in der 2. Reihe)&lt;br /&gt;
*Währenddessen das Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST300 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an.&lt;br /&gt;
*LEDs der ST300 sollten jetzt gelb blinken&lt;br /&gt;
&lt;br /&gt;
Auf einem Computer im Netzwerk ausführen&lt;br /&gt;
 ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa  root@&amp;lt;IP-Adresse der ST300&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== De-bricking ==&lt;br /&gt;
Für den Fall, dass die BOSE Box nach irgendwelchen Änderungen nicht mehr ins lokale WLAN findet, aber auch keinen eigenen Access Point anbietet, kann man das gerät dennoch retten. Dazu muss die Firmware komplett neu installiert werden. Zunächst die passende Firmware suchen&lt;br /&gt;
&lt;br /&gt;
[https://archive.org/download/bose-soundtouch-software-and-firmware/ Archiv mit BOSE Firmware]&lt;br /&gt;
&lt;br /&gt;
Die Zip-Datei muss entpackt werden die darin enthaltene Datei mit der Endung &#039;&#039;.stu&#039;&#039; muss auf einen bootfähigen USB-Stick geschrieben werden, siehe oben.&lt;br /&gt;
&lt;br /&gt;
TODO: Unterabschnitte für die anderen Systeme schreiben, da nicht bekannt ist, wie lange [https://downloads.bose.com/ced/soundtouch/soundtouch_usb/index.html?l=de BOSE die Informationen noch zur Verfügung stellt].&lt;br /&gt;
===ST10===&lt;br /&gt;
*USB-Stick durch den OTG-Adapter mit dem USB-Port der ST10 verbinden.&lt;br /&gt;
*Stromversorgungskabel abziehen.&lt;br /&gt;
*Auf dem Tastenfeld die Taste „4“ und die „Lautstärke leiser“-Taste drücken und &#039;&#039;&#039;halten&#039;&#039;&#039;&lt;br /&gt;
*Stromversorgungskabel wieder einstecken&lt;br /&gt;
*Die ST10 bootet jetzt vom USB-Stick, ggf. zeigt dessen Signal-LED den Zugriff an. Die Buttons können nun losgelassen werden.&lt;br /&gt;
Die Installation dauert ca. 5 Minuten.&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:BOSE]]&lt;/div&gt;</summary>
		<author><name>Pahenning</name></author>
	</entry>
</feed>