├── .github
└── FUNDING.yml
├── DOKU
├── 00_DOKU_Install_Arduino_IDE.md
├── 01_DOKU_Vorbereitung_ARDUINO_IDE.md
├── 02_DOKU_Bord_Auswahl.md
├── 03_DOKU_Sketch.md
├── 04_DOKU_Aufbau.md
├── 05_Bedienungsanleitung.md
├── 05_Bedienungsanleitung.pdf
├── Alarm_Screen_Raster.svg
├── Cheap
│ ├── Fritzing_Schaltplan.png
│ ├── Fritzing_Steckplatine.png
│ └── cheap_radiowecker.fzz
├── Config_Screen_Raster.svg
├── Main_Screen_Raster.svg
├── Min
│ ├── Fritzing_Schaltplan.png
│ ├── Fritzing_Steckplatine.png
│ └── min_radiowecker.fzz
└── plan.png
├── README.md
├── radiowecker
├── 00_librarys.h
├── 00_pin_settings.h
├── 00_settings.h
├── 00_texte.h
├── 01_ziffern.ino
├── ArduinoJson.h
├── audio.ino
├── fonts.h
├── index.h
├── knoepfe.h
├── num_64_44.h
├── ota.ino
├── radiowecker.ino
├── stations.ino
├── symbole.h
├── tft_color_setting.h
├── tft_display.ino
├── weather.h
├── weather_icons.h
├── webserver.ino
└── wlan.ino
└── screenshot
├── alarm.jpg
├── info_tab.png
├── radio.jpg
├── result.jpg
├── settings.jpg
├── settings_color.png
├── website.png
├── website_2.png
├── website_3.png
├── website_4.png
└── wetter.jpg
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
12 | polar: # Replace with a single Polar username
13 | buy_me_a_coffee: kunigunde
14 | thanks_dev: beabel
15 | custom: [paypal.me/pleissa]
16 |
--------------------------------------------------------------------------------
/DOKU/00_DOKU_Install_Arduino_IDE.md:
--------------------------------------------------------------------------------
1 | # Arduino IDE Installation Guide
2 |
3 | ## Voraussetzungen
4 | Bevor du die Arduino IDE installierst, stelle sicher, dass du die folgenden Voraussetzungen erfüllst:
5 | - Ein kompatibles Betriebssystem: Windows, macOS oder Linux.
6 | - Eine Internetverbindung für den Download.
7 |
8 | ## Installation unter Windows
9 |
10 | 1. **Download der Arduino IDE**
11 | - Gehe zur offiziellen [Arduino Website](https://www.arduino.cc/en/software).
12 | - Wähle die **Windows Installer** Version aus und klicke auf **Download**.
13 |
14 | 2. **Installation**
15 | - Öffne die heruntergeladene `.exe`-Datei.
16 | - Akzeptiere die Lizenzbedingungen.
17 | - Klicke auf **Installieren** und warte, bis der Vorgang abgeschlossen ist.
18 |
19 | 3. **Abschluss**
20 | - Nach der Installation kannst du die Arduino IDE starten und dein erstes Projekt erstellen!
21 |
--------------------------------------------------------------------------------
/DOKU/01_DOKU_Vorbereitung_ARDUINO_IDE.md:
--------------------------------------------------------------------------------
1 | # Arduino IDE Setup für ESP32 und benötigte Bibliotheken
2 |
3 | Nachdem die Arduino IDE installiert ist, folgen die Schritte zur Integration des ESP32 Boards und der benötigten Bibliotheken.
4 |
5 | ## 1. ESP32 Boardverwalter-URL hinzufügen
6 |
7 | 1. Öffne die **Arduino IDE**.
8 | 2. Gehe zu `Datei` > `Voreinstellungen` (oder drücke `Strg + ,`).
9 | 3. Im Fenster **Voreinstellungen** findest du das Feld **Zusätzliche Boardverwalter-URLs**. Füge die folgende URL in dieses Feld ein:
10 | ```
11 | https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
12 | ```
13 | 4. Falls bereits andere URLs vorhanden sind, trenne sie mit einem Komma.
14 | 5. Klicke auf **OK**, um die Einstellungen zu speichern.
15 |
16 | ## 2. ESP32 Board installieren
17 |
18 | 1. Gehe zu `Werkzeuge` > `Board` > `Boardverwalter`.
19 | 2. Suche nach **ESP32** im Suchfeld.
20 | 3. Wähle **ESP32 by Espressif Systems** aus und klicke auf **Installieren**.
21 |
22 | > [!IMPORTANT]
23 | > **Hinweis:** Stelle sicher, dass du **Version 2.0.17** auswählst, da es zu Problemen mit größeren Versionen ab 3.x kommen kann.~~
24 |
25 | |Boardverwalter Version|Sketchgröße|
26 | | ------------- | ------------- |
27 | |2.0.17|:white_check_mark: 1113105|
28 | |3.0.0|:x: 1288101|
29 | |3.0.5|:x: 1312869|
30 |
31 | Das Maximum sind 1310720 Bytes
32 |
33 | 4. Warte, bis die Installation abgeschlossen ist.
34 |
35 | Nach der Installation sollte **ESP32** unter `Werkzeuge` > `Board` auswählbar sein.
36 |
37 |
38 | ## 3. Benötigte Bibliotheken installieren
39 |
40 | Um die benötigten Bibliotheken zu installieren, befolge diese Schritte:
41 |
42 | ### 3.1 Adafruit_ILI9341 by Adafruit (Version 1.6.1)
43 |
44 | 1. Gehe zu `Sketch` > `Include Library` > `Library Manager`.
45 | 2. Suche nach **Adafruit_ILI9341**.
46 | 3. Wähle die **Version 1.6.1** aus dem Dropdown-Menü und klicke auf **Installieren**.
47 |
48 | ### 3.2 Adafruit_GFX by Adafruit (Version 1.12.00)
49 |
50 | 1. Im selben **Library Manager** suche nach **Adafruit_GFX**.
51 | 2. Wähle die **Version 1.12.00** und klicke auf **Installieren**.
52 |
53 | ### 3.3 XPT2046_Touchscreen by Paul Stoffregen (Version 1.4.0)
54 |
55 | 1. Im **Library Manager** suche nach **XPT2046_Touchscreen**.
56 | 2. Wähle die **Version 1.4.0** und klicke auf **Installieren**.
57 |
58 | ### 3.4 Touchevent by Gerald-Lechner (Version 1.3.0)
59 |
60 | 1. Im **Library Manager** suche nach **Touchevent**.
61 | 2. Wähle die **Version 1.3.0** und klicke auf **Installieren**.
62 |
63 | ### 3.5 ESP8266Audio by Earle F. Philhower (Version 2.0.0)
64 |
65 | 1. Im **Library Manager** suche nach **ESP8266Audio**.
66 | 2. Wähle die **Version 2.0.0** und klicke auf **Installieren**.
67 |
68 | ## 4. Abschluss
69 |
70 | Nach der Installation der Board-Verwaltung und Bibliotheken kannst du nun dein ESP32-Projekt starten. Wähle unter `Werkzeuge` > `Board` das ESP32-Board aus, das du verwendest, und beginne mit der Entwicklung!
71 |
72 | ---
73 |
74 | Für weitere Informationen und Unterstützung kannst du die offiziellen Dokumentationen der jeweiligen Bibliotheken oder das Arduino-Forum besuchen.
75 |
--------------------------------------------------------------------------------
/DOKU/02_DOKU_Bord_Auswahl.md:
--------------------------------------------------------------------------------
1 | # Konfiguration der Arduino IDE für ESP32
2 |
3 | Nachdem alle Vorbereitungen abgeschlossen sind, folgt die Anleitung zur Auswahl des Boards, zum Finden des richtigen Ports und zur Installation des CH341-Treibers, falls notwendig.
4 |
5 | ## 1. Auswahl des ESP32-Boards
6 |
7 | 1. Öffne die **Arduino IDE**.
8 | 2. Gehe zu `Werkzeuge` > `Board` > `ESP32 Arduino`.
9 | 3. Wähle aus der Liste **"ESP32 Dev Module"** aus.
10 |
11 | Dies ist das Standard-Board, das für die meisten ESP32-Entwicklungsboards verwendet wird.
12 |
13 | ## 2. Den richtigen Port herausfinden
14 |
15 | Um den richtigen COM-Port zu finden, an dem dein ESP32-Board angeschlossen ist, folge diesen Schritten:
16 |
17 | 1. **COM-Port identifizieren:**
18 | - Gehe in der Arduino IDE zu `Werkzeuge` > `Port`.
19 | - Notiere dir die angezeigten Ports, bevor du dein Board anschließt.
20 | - Schließe dein ESP32-Board an und öffne das Menü `Werkzeuge` > `Port` erneut. Ein neuer Eintrag sollte erscheinen.
21 | - Wähle den neuen Port aus (dies ist der COM-Port deines ESP32-Boards).
22 |
23 | **Hinweis:** Wenn du unsicher bist, welcher Port korrekt ist, kannst du den Port im Gerätemanager überprüfen:
24 | - Öffne den **Gerätemanager** (Rechtsklick auf das Windows-Startsymbol > **Gerätemanager**).
25 | - Unter **Anschlüsse (COM & LPT)** siehst du den neuen Port, der erscheint, wenn du das ESP32-Board anschließt. Dies ist der richtige COM-Port.
26 |
27 | ## 3. Installation des CH341-Treibers (falls benötigt)
28 |
29 | Wenn dein ESP32-Board nach dem Anschließen keinen COM-Port anzeigt oder im Gerätemanager nicht erkannt wird, könnte es sein, dass du den CH341-Treiber installieren musst. Dies ist insbesondere für Boards notwendig, die den CH340/CH341-USB-zu-Seriell-Konverter verwenden.
30 |
31 | ### 3.1 CH341-Treiber herunterladen
32 |
33 | 1. Besuche die [offizielle CH341-Treiber-Seite](http://www.wch.cn/download/CH341SER_ZIP.html) oder lade den Treiber von einer vertrauenswürdigen Quelle herunter.
34 |
35 | 2. Lade die `.zip`-Datei herunter und entpacke sie.
36 |
37 | ### 3.2 Treiber installieren
38 |
39 | 1. Öffne die entpackte Datei und starte die `SETUP.exe`.
40 | 2. Folge den Anweisungen auf dem Bildschirm, um den Treiber zu installieren.
41 | 3. Nachdem die Installation abgeschlossen ist, verbinde das ESP32-Board erneut mit dem Computer.
42 |
43 | ### 3.3 Überprüfen der Installation
44 |
45 | 1. Öffne den **Gerätemanager** und überprüfe unter **Anschlüsse (COM & LPT)**, ob der CH340/CH341-Port korrekt angezeigt wird.
46 | 2. Gehe zurück zur Arduino IDE und wähle unter `Werkzeuge` > `Port` den entsprechenden COM-Port aus.
47 |
48 | ## 4. Abschluss
49 |
50 | Nun sollte dein ESP32-Board einsatzbereit sein:
51 |
52 | 1. Stelle sicher, dass unter `Werkzeuge` > `Board` das **ESP32 Dev Module** ausgewählt ist.
53 | 2. Wähle unter `Werkzeuge` > `Port` den richtigen COM-Port.
54 | 3. Du kannst nun mit der Programmierung deines ESP32-Boards beginnen und das erste Programm hochladen.
55 |
56 | ---
57 |
58 | Falls du auf Probleme stößt, überprüfe, ob alle Treiber korrekt installiert sind, und konsultiere die [offizielle Arduino-Hilfe](https://www.arduino.cc/en/Guide/Troubleshooting) für weitere Unterstützung.
59 |
--------------------------------------------------------------------------------
/DOKU/03_DOKU_Sketch.md:
--------------------------------------------------------------------------------
1 | # Arduino Projekt "Radiowecker" aus GitHub herunterladen und öffnen
2 |
3 | Nachdem alle Vorbereitungen getroffen sind, folgt hier die Anleitung, wie du das Projekt aus dem GitHub-Repository herunterlädst und in der Arduino IDE öffnest.
4 |
5 | ## 1. GitHub-Repository herunterladen
6 |
7 | 1. **Besuche das GitHub-Repository:**
8 | - Gehe in deinem Browser auf die Seite des Repositories: [https://github.com/beabel/radiowecker](https://github.com/beabel/radiowecker).
9 |
10 | 2. **Projekt herunterladen:**
11 | - Klicke auf den grünen Button **Code**.
12 | - Wähle **Download ZIP** aus. Dies lädt das gesamte Repository als ZIP-Datei auf deinen Computer herunter.
13 |
14 | 3. **ZIP-Datei entpacken:**
15 | - Navigiere zu dem Ordner, in dem die ZIP-Datei heruntergeladen wurde.
16 | - Entpacke die ZIP-Datei, indem du mit der rechten Maustaste darauf klickst und **Alle extrahieren...** auswählst oder ein entsprechendes Entpack-Tool verwendest.
17 | - Der entpackte Ordner sollte denselben Namen wie das Repository haben (z.B. `radiowecker-main`).
18 |
19 | ## 2. Sketch in der Arduino IDE öffnen
20 |
21 | 1. **Sketch öffnen:**
22 | - Starte die **Arduino IDE**.
23 | - Gehe zu `Datei` > `Öffnen...`.
24 | - Navigiere zu dem entpackten Ordner `radiowecker-main/radiowecker`.
25 | - Wähle die Datei `radiowecker.ino` aus und klicke auf **Öffnen**.
26 |
27 | 2. **Überprüfung des Projekts:**
28 | - Sobald der Sketch in der Arduino IDE geöffnet ist, überprüfe, ob alle Bibliotheken, die im Sketch verwendet werden, bereits installiert sind (du kannst dies durch Kompilieren des Sketches prüfen, indem du auf das Häkchen-Symbol oben links klickst).
29 | - Falls Fehler auftreten, stelle sicher, dass alle benötigten Bibliotheken, die in den vorherigen Schritten installiert wurden, korrekt integriert sind.
30 |
31 | ## 3. Sketch hochladen
32 |
33 | 1. **Board und Port überprüfen:**
34 | - Stelle sicher, dass unter `Werkzeuge` > `Board` das **ESP32 Dev Module** ausgewählt ist.
35 | - Wähle unter `Werkzeuge` > `Port` den richtigen COM-Port aus, an dem dein ESP32-Board angeschlossen ist.
36 |
37 | 2. **Sketch hochladen:**
38 | - Klicke auf den **Hochladen**-Button (Pfeil-Symbol) in der Arduino IDE, um den Sketch auf dein ESP32-Board zu übertragen.
39 |
40 | ## 4. Abschluss
41 |
42 | Nachdem der Sketch erfolgreich hochgeladen wurde, sollte das Radiowecker-Projekt auf deinem ESP32-Board laufen. Du kannst jetzt den seriellen Monitor in der Arduino IDE öffnen, um Ausgaben zu beobachten und sicherzustellen, dass alles wie erwartet funktioniert.
43 |
44 | ---
45 |
46 | Für weitere Anpassungen oder Informationen zum Projekt kannst du das GitHub-Repository durchsuchen oder die Dokumentation des Projekts lesen.
47 |
--------------------------------------------------------------------------------
/DOKU/04_DOKU_Aufbau.md:
--------------------------------------------------------------------------------
1 | # Aufbau des Radiowecker-Projekts
2 |
3 | Es gibt mehrere Möglichkeiten, das Radiowecker-Projekt aufzubauen. Hier sind die verschiedenen Optionen beschrieben, einschließlich der benötigten Komponenten und Schritte.
4 |
5 | ## 1. Option 1: Verwenden des AZ-Touch Sets von AZ-Delivery
6 |
7 | ### Komponenten:
8 | - **AZ-Touch Set** (inkl. ESP32 Dev Kit v4, 2.8" TFT-Display, Max98357A, Lautsprecher)
9 | - Dieses Set enthält alle notwendigen Komponenten und eine vorgefertigte Platine, sodass keine zusätzlichen Teile benötigt werden.
10 |
11 | ### Aufbau:
12 |
13 | 1. **Bestellen des Sets:**
14 | - Das AZ-Touch Set kann über diesen [Link](https://www.az-delivery.de/products/radiowecker-mit-dem-az-touch?_pos=2&_psq=az-touch&_ss=e&_v=1.0) erworben werden.
15 |
16 | 2. **Zusammenbau:**
17 | - Folge den Anweisungen, die im [hier](https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/internet-radiowecker-mit-touchscreen) enthalten sind.
18 | - Löte die Verbindungen, wie in der Anleitung beschrieben, um die Komponenten zu verbinden
19 | - Montiere das Display und die Lautsprecher in das Gehäuse des AZ-Touch.
20 | - Verbinde den ESP32 Dev Kit v4 mit der Platine im Gehäuse.
21 |
22 | 3. **Software hochladen:**
23 | - Nachdem der Aufbau abgeschlossen ist, lade den Sketch wie in den vorherigen Anleitungen beschrieben auf das ESP32-Board.
24 |
25 | 4. **Test:**
26 | - Stelle sicher, dass das Display, die Lautsprecher und alle anderen Komponenten ordnungsgemäß funktionieren.
27 |
28 | ---
29 |
30 | ## 2. Option 2: Verwenden einer fertigen Platine
31 |
32 | ### Komponenten:
33 | - **ESP32 Dev Kit v4**
34 | - **2.8" TFT-Display**
35 | - **2x Max98357A I2S Digital-Analog-Wandler**
36 | - **Lautsprecher**
37 | - **Fertige Platine nach dem Schaltplan auf EasyEDA**
38 |
39 | ### Aufbau:
40 |
41 | 1. **Platinenlayout:**
42 | - Besuche den Schaltplan auf EasyEDA: [EasyEDA Schaltplan](https://easyeda.com/editor#project_id=b7c90a5cbe554e4dbcf25dbf78662e11).
43 | - Du kannst die Platine entweder selbst herstellen oder bei einem PCB-Hersteller in Auftrag geben.
44 |
45 | 2. **Zusammenbau:**
46 | - Sobald die Platine fertig ist, montiere die Komponenten auf der Platine.
47 | - Löte die Verbindungen gemäß dem Schaltplan.
48 |
49 | 3. **Software hochladen:**
50 | - Nach dem Zusammenbau der Platine lade den Sketch wie zuvor beschrieben auf das ESP32-Board.
51 |
52 | 4. **Test:**
53 | - Prüfe, ob die Verbindungen korrekt sind und alle Komponenten funktionieren.
54 |
55 | ---
56 |
57 | ## 3. Option 3: Aufbau auf einem Steckbrett
58 |
59 | ### Komponenten:
60 | - **ESP32 Dev Kit v4**
61 | - **2.8" TFT-Display**
62 | - **2x Max98357A I2S Digital-Analog-Wandler**
63 | - **Lautsprecher**
64 | - **Steckbrett und Jumper-Kabel**
65 |
66 | ### Aufbau:
67 |
68 | 1. **Bestellen der Komponenten:**
69 | - Besorge dir die notwendigen Komponenten:
70 | - ESP32 Dev Kit v4
71 | - 2.8" TFT-Display
72 | - 2x Max98357A
73 | - Lautsprecher
74 | - Steckbrett und Jumper-Kabel
75 |
76 | 2. **Schaltplan und Verdrahtung:**
77 | - Verwende den Schaltplan auf [Github](https://github.com/beabel/radiowecker/blob/main/DOKU/Cheap/Fritzing_Steckplatine.png) als Referenz für die Verdrahtung.
78 | - Platziere die Komponenten auf dem Steckbrett und verbinde sie mit den Jumper-Kabeln.
79 |
80 | 3. **Verbindungen herstellen:**
81 | - **TFT-Display**: Verbinde die Pins des Displays entsprechend mit dem ESP32 Dev Kit.
82 | - **Max98357A**: Verbinde die zwei Max98357A-Module mit dem ESP32 für die Audio-Ausgabe.
83 | - **Lautsprecher**: Schließe die Lautsprecher an die Ausgänge der Max98357A-Module an.
84 |
85 | 4. **Software hochladen:**
86 | - Lade den Sketch auf das ESP32-Board hoch, wie in den vorherigen Anleitungen beschrieben.
87 |
88 | 5. **Test:**
89 | - Überprüfe die Verbindungen und teste die Funktionalität des Radioweckers.
90 |
91 | ---
92 |
93 | ## Abschluss
94 |
95 | Egal für welche Option du dich entscheidest, nach dem Aufbau und Hochladen der Software sollte dein Radiowecker funktionieren. Bei Problemen überprüfe alle Verbindungen und stelle sicher, dass alle Komponenten korrekt installiert sind. Viel Spaß beim Bauen und Programmieren!
96 |
--------------------------------------------------------------------------------
/DOKU/05_Bedienungsanleitung.md:
--------------------------------------------------------------------------------
1 | # Bedienungsanleitung
2 |
3 | ## Erste Schritte und Verbindung zum WLAN
4 |
5 | 1. **Gerät einschalten**
6 | Nach dem ersten Start des DIY-Webradios oder wenn das Gerät kein bekanntes WLAN-Netzwerk findet, zeigt das Display die Meldung:
7 |
8 | 
9 |
10 | 2. **Verbindung mit dem Konfigurations-WLAN herstellen**
11 | Auf deinem Smartphone, Tablet oder Computer öffnest du die WLAN-Einstellungen und suchst nach verfügbaren Netzwerken. Wähle das Netzwerk mit der SSID (Netzwerkname) `radioweckerconf` aus, um dich mit dem Radiowecker zu verbinden. Dies ist ein temporäres Netzwerk, das das Radio erstellt, um die Konfiguration zu ermöglichen.
12 |
13 | 3. **Zugriff auf das Einstellungsmenü**
14 | Sobald die Verbindung hergestellt ist, öffne einen Webbrowser (z. B. Chrome, Firefox, Safari) und gib in der Adressleiste die IP-Adresse `192.168.4.1` ein. Diese IP-Adresse führt dich zur Einstellungsseite des Radios.
15 |
16 | 
17 |
18 | 4. **WLAN-Konfiguration**
19 | Auf der Einstellungsseite wirst du aufgefordert, das WLAN-Netzwerk auszuwählen, mit dem das Radio dauerhaft verbunden werden soll. Wähle dein gewünschtes WLAN-Netzwerk aus und gib das entsprechende Passwort ein. Speichere die Einstellungen.
20 |
21 | 5. **Neustart des Geräts**
22 | Nach der erfolgreichen Konfiguration wird der Radiowecker das temporäre Netzwerk `radioweckerconf` beenden und sich mit dem neu konfigurierten WLAN-Netzwerk verbinden. Das Radio sollte nun betriebsbereit sein und du kannst Sender auswählen und abspielen.
23 |
24 | ## Fehlerbehebung
25 |
26 | - **Verbindung fehlgeschlagen**
27 | Falls das DIY-Webradio nach der Konfiguration keine Verbindung zum gewünschten WLAN herstellen kann, wird erneut die Meldung "Nicht verbunden" angezeigt. In diesem Fall wiederhole den Verbindungsprozess.
28 |
29 | - **WLAN-Netzwerkwechsel**
30 | Solltest du das WLAN-Netzwerk wechseln müssen, kannst du das Gerät zurücksetzen oder einen ähnlichen Prozess durchlaufen, um das temporäre Netzwerk wiederherzustellen und eine neue Konfiguration vorzunehmen.
31 |
32 | 
33 |
34 | ## Anzeige auf dem TFT-Display
35 |
36 | 1. **Statusleiste (oben im Display):**
37 | - **Weckerstatus**: Ein Symbol zeigt an, ob der Wecker aktiviert oder deaktiviert ist. Ein Glockensymbol, das bei aktivem Wecker orange ist und die nächste Weckzeit anzeigt. Bei deaktiviertem Wecker ist ein rotes, durchgestrichenes Symbol sichtbar.
38 | - **Einschlaftimer**: Ein weiteres Symbol zeigt den Status des Einschlaftimers an. Ist der Timer aktiv, erscheint ein "Bett"-Symbol. Wenn der Timer nicht aktiv ist, ist dieses Symbol ausgeblendet.
39 | - **IP-Adresse**: Die aktuelle IP-Adresse des Geräts wird angezeigt, um bei Bedarf eine direkte Verbindung oder weitere Einstellungen zu ermöglichen.
40 | - **WLAN-Signalstärke**: Die Signalstärke des WLANs wird sowohl als numerischer Wert als auch als farbiges Symbol dargestellt:
41 | - **Grün**: Starkes Signal
42 | - **Gelb**: Mittelmäßiges Signal
43 | - **Rot**: Schwaches Signal
44 |
45 | 2. **Hauptanzeige (mittig im Display):**
46 | - **Aktuelle Uhrzeit**: Die aktuelle Uhrzeit wird prominent angezeigt, damit sie leicht ablesbar ist.
47 | - **Aktuelles Datum**: Unter der Uhrzeit wird das aktuelle Datum angezeigt, damit du sowohl die Zeit als auch das Datum im Blick hast.
48 |
49 | 3. **Lautstärkeregler (unten im Display):**
50 | - Ein Schieberegler für die Lautstärke befindet sich am unteren Rand des Displays. Du kannst den Regler nach links oder rechts schieben, um die Lautstärke des Webradios anzupassen.
51 |
52 | 4. **Radio:**
53 | - **Sendername und Titel**: Wenn ein Sender gerade läuft, werden hier die Informationen des Senders und des Titels angezeigt.
54 | - **Senderwechsel**: Ab Version 3.0.5 ist es möglich, rechts und links zum nächsten aktivierten Sender zu springen, ohne erst auf eine Unterseite schalten zu müssen. Dies erfolgt durch Berührung an den Seiten, 40px jeweils von den Rändern.
55 |
56 | 5. **Anzeige Einstellungs-Seiten:**
57 | - **Unterseiten**: Durch eine Berührung in die Mitte des Touchscreens wird die Unterseite Radio-Einstellungen angezeigt. Wenn keine Berührung mehr registriert wird, schaltet es automatisch zurück zur Hauptanzeige.
58 |
59 | 
60 |
61 |
--------------------------------------------------------------------------------
/DOKU/05_Bedienungsanleitung.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/DOKU/05_Bedienungsanleitung.pdf
--------------------------------------------------------------------------------
/DOKU/Alarm_Screen_Raster.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
37 |
53 |
54 |
56 |
62 |
63 |
67 |
75 |
83 |
91 |
99 |
107 |
111 |
115 |
123 |
131 |
139 |
147 |
155 |
163 |
164 |
168 |
176 |
184 |
192 |
200 |
208 |
216 |
224 |
232 |
233 |
237 |
245 |
253 |
261 |
269 |
277 |
285 |
286 |
290 |
298 |
306 |
314 |
322 |
330 |
338 |
346 |
354 |
355 |
356 |
357 |
--------------------------------------------------------------------------------
/DOKU/Cheap/Fritzing_Schaltplan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/DOKU/Cheap/Fritzing_Schaltplan.png
--------------------------------------------------------------------------------
/DOKU/Cheap/Fritzing_Steckplatine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/DOKU/Cheap/Fritzing_Steckplatine.png
--------------------------------------------------------------------------------
/DOKU/Cheap/cheap_radiowecker.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/DOKU/Cheap/cheap_radiowecker.fzz
--------------------------------------------------------------------------------
/DOKU/Config_Screen_Raster.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
37 |
53 |
54 |
56 |
62 |
63 |
67 |
75 |
83 |
91 |
99 |
107 |
111 |
115 |
123 |
132 |
141 |
150 |
151 |
155 |
163 |
171 |
180 |
183 |
191 |
199 |
207 |
208 |
209 |
213 |
221 |
229 |
238 |
241 |
249 |
257 |
265 |
266 |
267 |
271 |
279 |
287 |
296 |
299 |
307 |
315 |
323 |
324 |
325 |
326 |
327 |
--------------------------------------------------------------------------------
/DOKU/Main_Screen_Raster.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
36 |
52 |
53 |
55 |
61 |
62 |
66 |
70 |
78 |
86 |
94 |
99 |
107 |
115 |
123 |
124 |
128 |
136 |
144 |
152 |
160 |
168 |
176 |
184 |
192 |
200 |
208 |
216 |
224 |
232 |
240 |
248 |
249 |
257 |
261 |
269 |
277 |
285 |
293 |
301 |
302 |
305 |
313 |
321 |
329 |
337 |
345 |
353 |
354 |
355 |
356 |
--------------------------------------------------------------------------------
/DOKU/Min/Fritzing_Schaltplan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/DOKU/Min/Fritzing_Schaltplan.png
--------------------------------------------------------------------------------
/DOKU/Min/Fritzing_Steckplatine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/DOKU/Min/Fritzing_Steckplatine.png
--------------------------------------------------------------------------------
/DOKU/Min/min_radiowecker.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/DOKU/Min/min_radiowecker.fzz
--------------------------------------------------------------------------------
/DOKU/plan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/DOKU/plan.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | |[:skull:ISSUE](https://github.com/beabel/radiowecker/issues?q=is%3Aissue)|[:speech_balloon: Forum /Discussion](https://github.com/beabel/radiowecker/discussions?discussions_q=)|[:grey_question:WiKi](https://github.com/beabel/radiowecker/wiki)|
7 | |--|--|--|
8 | |||
9 |
10 |
11 |
12 |
13 |
14 | |This project is based on the blog article "[Internet clock radio with touchscreen](https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/internet-radiowecker-mit-touchscreen)" by Gerald Lechner / Az-Delivery. | Dieses Projekt basiert auf dem Blogartikel "[Internet Radiowecker mit Touchscreen](https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/internet-radiowecker-mit-touchscreen)" von Gerald Lechner / Az-Delivery. |
15 | |--|--|
16 |
17 | > [!NOTE]
18 | > **Instruction / Anleitung**
19 | > Eine detailierte Anleitung befindet sich [hier](https://github.com/beabel/radiowecker/wiki).
20 |
21 | **Parts required: / Benötigte Teile:**
22 |
23 | ||Pro|Cheap|Minimal|
24 | |--|--|--|--|
25 | |[1 x AZ-Touch MOD mit 2,8" Touchscreen](https://amzn.to/3srKxjE)|:white_check_mark:|:ballot_box_with_check:[1xTFT](https://amzn.to/3MEtdyy)|:x:|
26 | |[1 x ESP-32 Dev Kit C V4](https://amzn.to/40ApxUA)|:white_check_mark:|:white_check_mark:|:white_check_mark:|
27 | |[2 x I2S 3W MAX98357A](https://amzn.to/3QSHtGF)|:white_check_mark:|:white_check_mark:|:white_check_mark:(1x)|
28 | |[1 x Lautsprecher Set](https://amzn.to/3SSyQNR)|:white_check_mark:|:white_check_mark:|:white_check_mark:|
29 | |[1 x Widerstand 470 kOhm](https://amzn.to/3Sw17cL)|:white_check_mark:|:white_check_mark:|:white_check_mark:(1x470kOhm)|
30 | |[DC Einbaubuchse](https://amzn.to/47it0ZY)|:white_check_mark:|:x:|:x:|
31 | |[1 x LDR](https://amzn.to/3FQYCKq)|:white_check_mark:|:x:|:x:|
32 | ||~95,-|~54,-|~37,-|
33 |
34 | [German Version below / Deutsche Version unten:point_down:](#german-version)
35 | ----
36 | # Clock radio
37 |
38 | I have extended and adapted this project.
39 |
40 |
41 | At the time of publishing this blog article, a complete set was available for purchase from AZ-Delivery. Currently this is not offered, but all required parts can be ordered individually.
42 |
43 |
44 | **[Additional information::point_down:](#informationen)**
45 |
46 | ## [Screenshots:point_down:](#screenshots)
47 |
48 | ## German Version
49 |
50 | # Radiowecker
51 |
52 | Ich habe dieses Projekt erweitert und angepasst.
53 |
54 | Zum Zeitpunkt der Veröffentlichung des Blogartikels gab es ein vollständiges Set bei AZ-Delivery zu kaufen. Aktuell wird dies nicht angeboten, aber alle benötigten Teile können einzeln bestellt werden.
55 |
56 | # Informationen
57 |
58 | **Boardverwalter URL:**
59 | [https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json](https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json)
60 | - ESP32 von Espressif Systems
61 |
62 | > [!IMPORTANT]
63 | > **Hinweis:** Stelle sicher, dass du **Version 2.0.17** auswählst, da es zu Problemen mit größeren Versionen ab 3.x kommen kann.~~
64 |
65 | |Boardverwalter Version|Sketchgröße|
66 | | ------------- | ------------- |
67 | |2.0.17|:white_check_mark: 1113105|
68 | |3.0.0|:x: 1288101|
69 | |3.0.5|:x: 1312869|
70 |
71 | **Bibliotheken:**
72 | - [Adafruit_ILI9341 by Adafruit Version 1.6.1](https://github.com/adafruit/Adafruit_ILI9341)
73 | - [Adafruit_GFX by Adafruit Version 1.12.00](https://github.com/adafruit/Adafruit-GFX-Library)
74 | - [XPT2046_Touchscreen by Paul Stoffregen Version 1.4.0](https://github.com/PaulStoffregen/XPT2046_Touchscreen)
75 | - [Touchevent by Gerald-Lechner Version 1.3.0](https://github.com/GerLech/TouchEvent)
76 | - [ESP8266Audio by Earle F. Philhower Version 2.0.0](https://github.com/earlephilhower/ESP8266Audio)
77 |
78 | # Screenshots
79 |
80 | 
81 |
82 | 
83 |
84 | 
85 |
86 | 
87 |
88 | 
89 |
90 | 
91 |
92 | 
93 |
94 | 
95 |
96 | 
97 |
98 | 
99 |
100 | 
101 |
102 | # Bedienungsanleitung
103 |
104 | ## Erste Schritte und Verbindung zum WLAN
105 |
106 | 1. **Gerät einschalten**
107 | Nach dem ersten Start des DIY-Webradios oder wenn das Gerät kein bekanntes WLAN-Netzwerk findet, zeigt das Display die Meldung:
108 |
109 | 
110 |
111 | 2. **Verbindung mit dem Konfigurations-WLAN herstellen**
112 | Auf deinem Smartphone, Tablet oder Computer öffnest du die WLAN-Einstellungen und suchst nach verfügbaren Netzwerken. Wähle das Netzwerk mit der SSID (Netzwerkname) `radioweckerconf` aus, um dich mit dem Radiowecker zu verbinden. Dies ist ein temporäres Netzwerk, das das Radio erstellt, um die Konfiguration zu ermöglichen.
113 |
114 | 3. **Zugriff auf das Einstellungsmenü**
115 | Sobald die Verbindung hergestellt ist, öffne einen Webbrowser (z. B. Chrome, Firefox, Safari) und gib in der Adressleiste die IP-Adresse `192.168.4.1` ein. Diese IP-Adresse führt dich zur Einstellungsseite des Radios.
116 |
117 | 
118 |
119 | 4. **WLAN-Konfiguration**
120 | Auf der Einstellungsseite wirst du aufgefordert, das WLAN-Netzwerk auszuwählen, mit dem das Radio dauerhaft verbunden werden soll. Wähle dein gewünschtes WLAN-Netzwerk aus und gib das entsprechende Passwort ein. Speichere die Einstellungen.
121 |
122 | 5. **Neustart des Geräts**
123 | Nach der erfolgreichen Konfiguration wird der Radiowecker das temporäre Netzwerk `radioweckerconf` beenden und sich mit dem neu konfigurierten WLAN-Netzwerk verbinden. Das Radio sollte nun betriebsbereit sein und du kannst Sender auswählen und abspielen.
124 |
125 | ## Fehlerbehebung
126 |
127 | - **Verbindung fehlgeschlagen**
128 | Falls das DIY-Webradio nach der Konfiguration keine Verbindung zum gewünschten WLAN herstellen kann, wird erneut die Meldung "Nicht verbunden" angezeigt. In diesem Fall wiederhole den Verbindungsprozess.
129 |
130 | - **WLAN-Netzwerkwechsel**
131 | Solltest du das WLAN-Netzwerk wechseln müssen, kannst du das Gerät zurücksetzen oder einen ähnlichen Prozess durchlaufen, um das temporäre Netzwerk wiederherzustellen und eine neue Konfiguration vorzunehmen.
132 |
133 | 
134 |
135 | ## Anzeige auf dem TFT-Display
136 |
137 | 1. **Statusleiste (oben im Display):**
138 | - **Weckerstatus**: Ein Symbol zeigt an, ob der Wecker aktiviert oder deaktiviert ist. Ein Glockensymbol, das bei aktivem Wecker orange ist und die nächste Weckzeit anzeigt. Bei deaktiviertem Wecker ist ein rotes, durchgestrichenes Symbol sichtbar.
139 | - **Einschlaftimer**: Ein weiteres Symbol zeigt den Status des Einschlaftimers an. Ist der Timer aktiv, erscheint ein "Bett"-Symbol. Wenn der Timer nicht aktiv ist, ist dieses Symbol ausgeblendet.
140 | - **IP-Adresse**: Die aktuelle IP-Adresse des Geräts wird angezeigt, um bei Bedarf eine direkte Verbindung oder weitere Einstellungen zu ermöglichen.
141 | - **WLAN-Signalstärke**: Die Signalstärke des WLANs wird sowohl als numerischer Wert als auch als farbiges Symbol dargestellt:
142 | - **Grün**: Starkes Signal
143 | - **Gelb**: Mittelmäßiges Signal
144 | - **Rot**: Schwaches Signal
145 |
146 | 2. **Hauptanzeige (mittig im Display):**
147 | - **Aktuelle Uhrzeit**: Die aktuelle Uhrzeit wird prominent angezeigt, damit sie leicht ablesbar ist.
148 | - **Aktuelles Datum**: Unter der Uhrzeit wird das aktuelle Datum angezeigt, damit du sowohl die Zeit als auch das Datum im Blick hast.
149 |
150 | 3. **Lautstärkeregler (unten im Display):**
151 | - Ein Schieberegler für die Lautstärke befindet sich am unteren Rand des Displays. Du kannst den Regler nach links oder rechts schieben, um die Lautstärke des Webradios anzupassen.
152 |
153 | 4. **Radio:**
154 | - **Sendername und Titel**: Wenn ein Sender gerade läuft, werden hier die Informationen des Senders und des Titels angezeigt.
155 | - **Senderwechsel**: Ab Version 3.0.5 ist es möglich, rechts und links zum nächsten aktivierten Sender zu springen, ohne erst auf eine Unterseite schalten zu müssen. Dies erfolgt durch Berührung an den Seiten, 40px jeweils von den Rändern.
156 |
157 | 5. **Anzeige Einstellungs-Seiten:**
158 | - **Unterseiten**: Durch eine Berührung in die Mitte des Touchscreens wird die Unterseite Radio-Einstellungen angezeigt. Wenn keine Berührung mehr registriert wird, schaltet es automatisch zurück zur Hauptanzeige.
159 |
160 | 
161 |
162 | ---
163 |
164 | [](https://www.pulse107.com)
165 | [](https://www.pulse107.com/pulse-107)
166 | [](https://www.pulse107.com/the-strobe-radio)
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/radiowecker/00_librarys.h:
--------------------------------------------------------------------------------
1 | // Bibliotheken für WiFi und Over-the-Air (OTA) Updates
2 | #include
3 | #include
4 |
5 | // TFT & Touchscreen Bibliotheken
6 | #include // Basisbibliothek für Grafikanzeige
7 | #include // Treiberbibliothek für das ILI9341 TFT-Display
8 | #include // Treiberbibliothek für das XPT2046 Touchscreen
9 | #include // Bibliothek zur Analyse von Touchscreen-Ereignissen
10 |
11 | // ESP32 Bibliothek zum Speichern von Einstellungen im Flash-Speicher
12 | #include
13 |
14 | // Bibliothek für den eingebauten Webserver
15 | #include
16 |
17 | // Bibliotheken für Audio-Funktionen
18 | // Enthält Klassen für die Audiowiedergabe und -verarbeitung
19 | #include // Klasse für den Eingabestream von ICY (Internet Radio) Streams
20 | #include // Klasse für das Puffern von Audio-Daten
21 | #include // MP3-Decoder Klasse
22 | #include // Klasse für die Audioausgabe über I2S (Inter-IC Sound) Schnittstelle
--------------------------------------------------------------------------------
/radiowecker/00_pin_settings.h:
--------------------------------------------------------------------------------
1 | // Pin-Definitionen für verschiedene Komponenten des Projekts
2 |
3 | // Pin für den Lichtsensor (LDR)
4 | #define LDR 36
5 |
6 | // Pin für den Buzzer auf dem originalen Az-Delivery TouchMod
7 | #define BEEPER 21
8 |
9 | // Audio-Pins
10 | #define LRCLK 25 // Left-Right Clock für die Audioausgabe
11 | #define BCLK 26 // Bit Clock für die Audioausgabe
12 | #define DOUT 33 // Daten-Ausgang für die Audioausgabe
13 |
14 | // Pins für den Touchscreen
15 | #define TOUCH_CS 14 // Chip Select für den Touchscreen
16 | #define TOUCH_IRQ 27 // Interrupt-Anschluss für den Touchscreen
17 |
18 | // Pins für das TFT-Display
19 | #define TFT_CS 5 // Chip Select für das TFT-Display
20 | #define TFT_DC 4 // Data/Command Pin für das TFT-Display
21 | #define TFT_RST 22 // Reset-Pin für das TFT-Display
22 | #define TFT_LED 15 // Hintergrundbeleuchtung des TFT-Displays
23 | #define LED_ON 0 // Logikpegel für die Hintergrundbeleuchtung (0 = Ein)
--------------------------------------------------------------------------------
/radiowecker/00_settings.h:
--------------------------------------------------------------------------------
1 | // Instanzen der Preferences-Klasse für die Speicherung von Einstellungen
2 | Preferences pref; // Allgemeine Instanz für die Nutzung der Preferences
3 | Preferences sender; // Zusätzliche Instanz, möglicherweise für spezielle Konfigurationen
4 |
5 | // Struktur zur Speicherung der Stationsdaten
6 | typedef struct {
7 | char url[150]; // URL des Streams der Station
8 | char name[32]; // Name der Station
9 | uint8_t enabled; // Flag zur Aktivierung der Station (1 = aktiv, 0 = inaktiv)
10 | } Station;
11 |
12 | // Konstanten
13 | #define STATIONS 30 // Anzahl der Stationen in der Liste
14 | #define MINUTES_PER_DAY 1440 // Anzahl der Minuten in einem Tag (24 Stunden * 60 Minuten)
15 |
16 | // Globale Variablen
17 | Station stationlist[STATIONS]; // Liste der verfügbaren Stationen
18 |
19 | // Variablen zur Speicherung von Konfigurationsdaten
20 | String ssid = ""; // SSID für die WLAN-Verbindung
21 | String pkey = ""; // Passwort für die WLAN-Verbindung
22 | String ntp = "de.pool.ntp.org"; // URL des NTP-Servers zur Zeitabgleich
23 | uint8_t curStation = 0; // Index der aktuell ausgewählten Station in der stationlist
24 | uint8_t curGain = 200; // Aktuelle Lautstärke (Gain)
25 | uint8_t snoozeTime = 30; // Schlummerzeit in Minuten
26 | uint16_t alarm1 = 390; // Erste Alarmzeit (6:30 Uhr in Minuten nach Mitternacht)
27 | uint8_t alarmday1 = 0B00111110; // Gültige Wochentage für den ersten Alarm (Beispiel: 00111110 = Montag bis Freitag)
28 | uint16_t alarm2 = 480; // Zweite Alarmzeit (8:00 Uhr in Minuten nach Mitternacht)
29 | uint8_t alarmday2 = 0B01000001; // Gültige Wochentage für den zweiten Alarm (Beispiel: 01000001 = Sonntag und Samstag)
30 | uint8_t actStation = 0; // Index der aktuellen Station in der Liste, verwendet für das Streaming
31 | uint8_t bright = 25; // Helligkeit in Prozent. 0 bedeutet, dass der LDR die Helligkeit regelt
32 |
33 | // Weitere globale Variablen
34 | uint32_t lastchange = 0; // Zeitpunkt der letzten Auswahländerung
35 | uint32_t snoozeTimeEnd = 0; // Zeitpunkt zum Beenden des Schlummermodus
36 | uint16_t alarmtime = 0; // Nächste relevante Alarmzeit
37 | uint8_t alarmday = 8; // Wochentag für den nächsten relevanten Alarm oder 8 bedeutet Alarm deaktiviert
38 | char title[64]; // Zeichenarray zur Speicherung der Metadaten-Nachricht
39 | bool newTitle = false; // Flag zum Signalisieren eines neuen Titels
40 | uint32_t tick = 0; // Letzter Wert des Tick-Counters zur Auslösung zeitgesteuerter Ereignisse
41 | uint32_t discon = 0; // Tick-Counter-Wert zur Berechnung der Zeit der Trennung
42 | uint16_t minutes; // Aktuelle Anzahl der Minuten seit Mitternacht
43 | uint8_t weekday; // Aktueller Wochentag
44 | struct tm ti; // Zeitstruktur mit der aktuellen Zeit
45 | int16_t lastldr; // Letzter Wert vom LDR-Sensor zur Erkennung von Änderungen
46 | uint32_t start_conf; // Zeitpunkt des Betretens des Konfigurationsbildschirms
47 | boolean connected; // Flag zum Signalisieren einer aktiven Verbindung
48 | boolean reconnected = false; // Flag zum Signalisieren einer erfolgreichen Wiederverbindung
49 | boolean radio = false; // Flag zum Signalisieren der Radiowiedergabe
50 | boolean clockmode = true; // Flag zum Signalisieren, dass die Uhrzeit auf dem Bildschirm angezeigt wird
51 | boolean configpage = false; // Flag zum Signalisieren, dass die Konfigurationsseite angezeigt wird
52 | boolean radiopage = false; // Flag zum Signalisieren, dass die Radioauswahlseite angezeigt wird
53 | boolean alarmpage = false; // Flag zum Signalisieren, dass die Alarm-Einstellseite angezeigt wird
54 | unsigned long lastUpdate = 0; // Variable, um die letzte Anzeigeaktualisierung zu verfolgen
55 | uint16_t lastLedb = 0; // Globale Variable, um den zuletzt eingestellten Helligkeitswert zu speichern
56 | // Definitionen für die Textausrichtung
57 | #define ALIGNLEFT 0 // Textausrichtung: linksbündig
58 | #define ALIGNCENTER 1 // Textausrichtung: zentriert
59 | #define ALIGNRIGHT 2 // Textausrichtung: rechtsbündig
60 |
61 | // Definitionen für Schriftarten
62 | #define FNT9 &AT_Standard9pt7b // Schriftart 9pt
63 | #define FNT12 &AT_Bold12pt7b // Schriftart 12pt
64 | #define LS 23 // Zeilenabstand
65 |
66 | // WLAN-Konfiguration
67 | #define NETWORK_NAME "radioweckerlanname" // Definiert den Hostnamen
68 | #define AP_NAME "radioweckerconf" // Definiert den SSID-Namen des Soft-AP
69 |
70 | // Zeitzonen-Definition für Mitteleuropa (Deutschland, Frankreich, Italien, Spanien, etc.)
71 | #define TIME_ZONE "CET-1CEST,M3.5.0/02,M10.5.0/03" // Zeitzone für Mitteleuropa mit Sommerzeitregelung
72 |
73 | // OTA-Konfiguration
74 | #define OTA_HOSTNAME "radiowecker" // Definiert den Hostnamen für OTA Update
75 | #define OTA_PASSWORD "weckerupdate" // Definiert das Passwort für OTA Update
76 | //############## WETTER ##############################################################
77 | // Globale Variable, um den Zeitpunkt des letzten Wetterupdates zu speichern
78 | unsigned long lastWeatherUpdate = 0;
79 | const unsigned long weatherUpdateInterval = 60000; // 60 Sekunden
80 | // Definiere Latitude, Longitude und Zeitzone
81 | float LATITUDE = 52.520645;
82 | float LONGITUDE = 13.409779;
83 | String TIME_ZONE_IANA = "Europe/Berlin"; // Zeitzone dynamisch setzen
--------------------------------------------------------------------------------
/radiowecker/00_texte.h:
--------------------------------------------------------------------------------
1 | #ifndef TEXTE_H
2 | #define TEXTE_H
3 |
4 | #define TXT_DISCONNECT "Disconnect"
5 | #define TXT_SOFT_AP_DISCONNECT "Soft AP disconnect"
6 | #define TXT_SET_WLAN_MODE "Set WLAN Mode"
7 | #define TXT_CONNECTING_TO "Verbindung zu "
8 | #define TXT_CONNECTING_ESTABLISH " herstellen"
9 | #define TXT_NO_CONNECTION "Keine Verbindung! \nStarte Access-Point."
10 | #define TXT_IP_ADDRESS "IP-Adresse = "
11 |
12 | #define TXT_RECONNECTED "Reconnected"
13 | #define TXT_NOT_CONNECTED "Nicht verbunden"
14 | #define TXT_CONNECT_TO_AP "Verbinde dich mit SSID "
15 | #define TXT_CONFIG_IP "Einstellung auf IP: "
16 |
17 | #define TXT_OK "OK"
18 |
19 | //day and month names
20 | const char* const PROGMEM days[] = { "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag" };
21 | const char* const PROGMEM days_short[] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" };
22 | const char* PROGMEM months[] = { "Jan.", "Feb.", "März", "April", "Mai", "Juni", "Juli", "Aug.", "Sept.", "Okt.", "Nov.", "Dez." };
23 |
24 | #define TXT_NOW "Jetzt"
25 | #define TXT_TODAY "Heute"
26 | #define TXT_TOMMORROW "Morgen"
27 |
28 | #define TXT_TEMP "Temp:"
29 | #define TXT_FEELS "wie:"
30 | #define TXT_MIN "Min"
31 | #define TXT_MAX "Max"
32 | #endif // TEXTE_H
--------------------------------------------------------------------------------
/radiowecker/audio.ino:
--------------------------------------------------------------------------------
1 | // Puffergröße für das Stream-Buffern
2 | const int preallocateBufferSize = 82 * 1024; // Größe des vorab zugewiesenen Puffers in Bytes
3 | const int preallocateCodecSize = 29192; // Maximal benötigter Speicher für den MP3-Codec in Bytes
4 |
5 | // Zeiger auf vorab zugewiesenen Speicher
6 | void *preallocateBuffer = NULL; // Zeiger auf den vorab zugewiesenen Puffer für die Daten
7 | void *preallocateCodec = NULL; // Zeiger auf den vorab zugewiesenen Puffer für den Codec
8 |
9 | // Instanzen für Audio-Komponenten
10 | AudioGenerator *decoder = NULL; // MP3-Decoder
11 | AudioFileSourceICYStream *file = NULL; // Eingabemodul für ICY-Streams aus dem Web
12 | AudioFileSourceBuffer *buff = NULL; // Puffer für den Eingabestream
13 | AudioOutputI2S *out; // Ausgabemodul zum Erzeugen von I2S-Signalen
14 |
15 | // Funktion für die gesamte erforderliche Einrichtung
16 | void setup_audio() {
17 | // Speicher für Decoder und Stream reservieren
18 | preallocateBuffer = malloc(preallocateBufferSize); // Speicher für den Stream-Dateipuffer anfordern
19 | preallocateCodec = malloc(preallocateCodecSize); // Speicher für den Decoder-Puffer anfordern
20 | delay(1000); // Warte 1 Sekunde, um sicherzustellen, dass der Speicher zugewiesen wurde
21 |
22 | // Überprüfen, ob der Speicher erfolgreich zugewiesen wurde
23 | if (!preallocateBuffer || !preallocateCodec) {
24 | Serial.printf_P(PSTR("FATAL ERROR: Unable to preallocate %d bytes for app\n"), preallocateBufferSize + preallocateCodecSize);
25 | while (1) {
26 | yield(); // Endlosschleife zur Behebung des Fehlers
27 | }
28 | }
29 |
30 | // I2S-Ausgabe erstellen, um sie mit dem Decoder zu verwenden
31 | out = new AudioOutputI2S(); // Neues AudioOutputI2S-Objekt erstellen
32 | out->SetPinout(BCLK, LRCLK, DOUT); // Pin-Konfiguration für I2S-Ausgabe festlegen
33 | }
34 |
35 | // Diese Funktion überprüft, ob der Decoder läuft
36 | void audio_loop() {
37 | // Überprüfen, ob der Decoder läuft
38 | if (decoder->isRunning()) {
39 | // Wenn der Decoder läuft, überprüfen, ob der Loop noch läuft
40 | if (!decoder->loop()) {
41 | // Wenn der Loop nicht mehr läuft, stoppen Sie den Decoder
42 | decoder->stop();
43 | }
44 | } else {
45 | // Der Decoder hat gestoppt, was auf einen Fehler hindeutet
46 | Serial.printf("MP3 done\n");
47 | // Um zu vermeiden, dass das gleiche Problem nach einem Neustart erneut auftritt,
48 | // wird die Station auf den ersten Eintrag in der Liste gesetzt.
49 | // Der erste Eintrag sollte eine stabile, funktionierende URL sein.
50 | // Verwenden Sie diesen ersten Eintrag nicht für Experimente.
51 | pref.putUShort("station", 0);
52 |
53 | // Warten Sie 10 Sekunden, bevor Sie das ESP neu starten
54 | delay(10000);
55 |
56 | // Neustart des ESP
57 | ESP.restart();
58 | }
59 | }
60 |
61 | // Callback-Funktion, die aufgerufen wird, wenn Metadaten im Eingabestream gefunden werden
62 | void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string) {
63 | // Sicherstellen, dass die Zeiger gültig sind
64 | if (type == nullptr || string == nullptr) {
65 | Serial.println("Error: Null pointer encountered in MDCallback.");
66 | return;
67 | }
68 |
69 | // Hinweis: Der Typ und der String können im PROGMEM sein, daher Kopie ins RAM für printf
70 | char s1[32], s2[64];
71 | strncpy_P(s1, type, sizeof(s1) - 1);
72 | s1[sizeof(s1) - 1] = 0;
73 | strncpy_P(s2, string, sizeof(s2) - 1);
74 | s2[sizeof(s2) - 1] = 0;
75 |
76 | // Verarbeiten von Metadaten-Typ "Title"
77 | if (strstr_P(s1, PSTR("Title"))) {
78 | strncpy(title, s2, sizeof(title));
79 | title[sizeof(title) - 1] = 0;
80 | Serial.printf("Title: %s\n", title);
81 | // Zeige die Nachricht auf dem Display an
82 | newTitle = true;
83 | } else {
84 | // Nur den Typ und den String für generische Metadaten anzeigen
85 | Serial.printf("METADATA '%s' = '%s'\n", s1, s2);
86 | }
87 |
88 | // Serial.flush(); // Optional: Zum Flushing der Serial-Ausgabe, falls notwendig
89 | }
90 |
91 | // Stoppt das Abspielen des Eingabestreams, gibt den Speicher frei und löscht die Instanzen
92 | void stopPlaying() {
93 | if (decoder) {
94 | decoder->stop(); // Stoppt das Abspielen
95 | delete decoder; // Gibt den Decoder und seinen Speicher frei
96 | decoder = NULL; // Setzt den Zeiger auf NULL, um darauf hinzuweisen, dass der Speicher freigegeben wurde
97 | }
98 |
99 | if (buff) {
100 | buff->close(); // Schließt den Puffer
101 | delete buff; // Gibt den Puffer und seinen Speicher frei
102 | buff = NULL; // Setzt den Zeiger auf NULL
103 | }
104 |
105 | if (file) { // Und schließlich für den Stream
106 | file->close(); // Schließt den Stream
107 | delete file; // Gibt den Stream und seinen Speicher frei
108 | file = NULL; // Setzt den Zeiger auf NULL
109 | }
110 | }
111 |
112 | // Startet das Abspielen eines Streams von der angegebenen Station
113 | bool startUrl(String url) {
114 | bool ret = true;
115 | stopPlaying(); // Zuerst bestehende Streams schließen
116 |
117 | // Öffne die Eingabedatei für die ausgewählte URL
118 | Serial.printf("Active station %s\n", url.c_str());
119 | file = new AudioFileSourceICYStream();
120 | ret = file->open(url.c_str());
121 |
122 | if (ret) {
123 | // Registriere Callback für Metadaten
124 | file->RegisterMetadataCB(MDCallback, NULL);
125 |
126 | // Erstelle einen neuen Puffer, der den vorab zugewiesenen Speicher verwendet
127 | buff = new AudioFileSourceBuffer(file, preallocateBuffer, preallocateBufferSize);
128 | Serial.printf_P(PSTR("sourcebuffer created - Free mem=%d\n"), ESP.getFreeHeap());
129 |
130 | // Erstelle und starte einen neuen Decoder
131 | decoder = (AudioGenerator *)new AudioGeneratorMP3(preallocateCodec, preallocateCodecSize);
132 | Serial.printf_P(PSTR("created decoder\n"));
133 | Serial.printf_P("Decoder start...\n");
134 | delay(1000);
135 | decoder->begin(buff, out);
136 | } else {
137 | delete file; // Wenn kein Erfolg, lösche die Datei
138 | file = NULL;
139 | }
140 |
141 | return ret;
142 | }
143 |
144 | // Ändert die Lautstärke auf den aktuellen Gain-Wert
145 | void setGain(float gain) {
146 | float v = gain / 100 * 0.5; // Berechnet die Lautstärke als Prozentsatz von 0,5
147 | out->SetGain(v); // Setzt die Lautstärke
148 | Serial.printf("New volume = %4.2f\n", v); // Gibt den neuen Lautstärkewert aus
149 | }
150 |
--------------------------------------------------------------------------------
/radiowecker/knoepfe.h:
--------------------------------------------------------------------------------
1 | const unsigned char knopf_sym PROGMEM [9][512] = {
2 | {// [0] 'power_64', 64x64px
3 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5 | 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00,
6 | 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00,
7 | 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00,
8 | 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x0f, 0xf0, 0x07, 0x80, 0x00,
9 | 0x00, 0x03, 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x00, 0x00, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x00,
10 | 0x00, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x1f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf8, 0x00,
11 | 0x00, 0x3f, 0xf0, 0x0f, 0xf0, 0x0f, 0xfc, 0x00, 0x00, 0x7f, 0xe0, 0x0f, 0xf0, 0x07, 0xfe, 0x00,
12 | 0x00, 0x7f, 0xc0, 0x0f, 0xf0, 0x03, 0xfe, 0x00, 0x00, 0xff, 0x80, 0x0f, 0xf0, 0x01, 0xff, 0x00,
13 | 0x01, 0xff, 0x00, 0x0f, 0xf0, 0x00, 0xff, 0x80, 0x01, 0xff, 0x00, 0x0f, 0xf0, 0x00, 0x7f, 0x80,
14 | 0x01, 0xfe, 0x00, 0x0f, 0xf0, 0x00, 0x7f, 0x80, 0x03, 0xfc, 0x00, 0x0f, 0xf0, 0x00, 0x3f, 0xc0,
15 | 0x03, 0xfc, 0x00, 0x0f, 0xf0, 0x00, 0x3f, 0xc0, 0x03, 0xf8, 0x00, 0x0f, 0xf0, 0x00, 0x1f, 0xc0,
16 | 0x07, 0xf8, 0x00, 0x0f, 0xf0, 0x00, 0x1f, 0xe0, 0x07, 0xf8, 0x00, 0x0f, 0xf0, 0x00, 0x1f, 0xe0,
17 | 0x07, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x0f, 0xe0,
18 | 0x07, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x0f, 0xe0,
19 | 0x07, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x0f, 0xe0,
20 | 0x07, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x07, 0xc0, 0x00, 0x0f, 0xe0,
21 | 0x07, 0xf0, 0x00, 0x00, 0x80, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0,
22 | 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0,
23 | 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0,
24 | 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80,
25 | 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0x00,
26 | 0x00, 0xff, 0x80, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x03, 0xfe, 0x00,
27 | 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x1f, 0xfc, 0x00,
28 | 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x01, 0xff, 0xf0, 0x00,
29 | 0x00, 0x07, 0xff, 0xf0, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
30 | 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
31 | 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00,
32 | 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00,
33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
35 | },{// [1] 'bed_64', 64x64px
36 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 | 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 | 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 | 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 | 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x7c, 0x01, 0xff, 0xff, 0xfc, 0x00,
47 | 0x0f, 0xc1, 0xff, 0x03, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xc3, 0xff, 0x87, 0xff, 0xff, 0xff, 0x80,
48 | 0x0f, 0xc3, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xc7, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xe0,
49 | 0x0f, 0xc7, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xc7, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xe0,
50 | 0x0f, 0xc7, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xc7, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xf0,
51 | 0x0f, 0xc7, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xc3, 0xff, 0x87, 0xff, 0xff, 0xff, 0xf0,
52 | 0x0f, 0xc3, 0xff, 0x87, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xc0, 0xfe, 0x07, 0xff, 0xff, 0xff, 0xf0,
53 | 0x0f, 0xc0, 0x38, 0x07, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xff, 0xf0,
54 | 0x0f, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
55 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
56 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
57 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
58 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
59 | 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0,
60 | 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0,
61 | 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
68 | },{// [2] 'bell_64', 64x64px
69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
71 | 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00,
72 | 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00,
73 | 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00,
74 | 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00,
75 | 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00,
76 | 0x00, 0x00, 0x3f, 0xf8, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x03, 0xfc, 0x00, 0x00,
77 | 0x00, 0x00, 0x7f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x7f, 0x00, 0x00,
78 | 0x00, 0x00, 0xfc, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x1f, 0x80, 0x00,
79 | 0x00, 0x01, 0xf8, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x0f, 0x80, 0x00,
80 | 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00,
81 | 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00,
82 | 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00,
83 | 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00,
84 | 0x00, 0x03, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00,
85 | 0x00, 0x03, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00,
86 | 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00,
87 | 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00,
88 | 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00,
89 | 0x00, 0x1f, 0x80, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00,
90 | 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00,
91 | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
92 | 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
93 | 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00,
96 | 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00,
97 | 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00,
98 | 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00,
99 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
101 | },{// [3] 'bell_slash_64', 64x64px
102 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 | 0x07, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
108 | 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00,
109 | 0x03, 0xf8, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00,
110 | 0x00, 0x7f, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x81, 0xff, 0xff, 0x80, 0x00, 0x00,
111 | 0x00, 0x1f, 0xc3, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x07, 0xe7, 0xff, 0xff, 0xe0, 0x00, 0x00,
112 | 0x00, 0x03, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00,
113 | 0x00, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00,
114 | 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf8, 0x00, 0x00,
115 | 0x00, 0x00, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfc, 0x00, 0x00,
116 | 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7f, 0xff, 0xfc, 0x00, 0x00,
117 | 0x00, 0x00, 0x30, 0x1f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0f, 0xff, 0xfc, 0x00, 0x00,
118 | 0x00, 0x00, 0x3e, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x03, 0xff, 0xfc, 0x00, 0x00,
119 | 0x00, 0x00, 0x7f, 0x80, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x7f, 0xfe, 0x00, 0x00,
120 | 0x00, 0x00, 0xff, 0xf0, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x1f, 0xff, 0x80, 0x00,
121 | 0x00, 0x01, 0xff, 0xfc, 0x07, 0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x03, 0xff, 0xc0, 0x00,
122 | 0x00, 0x07, 0xff, 0xff, 0x81, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x7f, 0xe0, 0x00,
123 | 0x00, 0x07, 0xff, 0xff, 0xe0, 0x3f, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf8, 0x1f, 0xe0, 0x00,
124 | 0x00, 0x07, 0xff, 0xff, 0xfc, 0x0f, 0xf0, 0x00, 0x00, 0x03, 0xff, 0xff, 0xfe, 0x03, 0xf8, 0x00,
125 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00,
126 | 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x1f, 0xc0,
127 | 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x07, 0xe0,
128 | 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0xe0,
129 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
134 | },{// [4] 'radio_64', 64x64px
135 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0,
138 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xe0,
139 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xc0,
140 | 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x00,
141 | 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf8, 0x00, 0x00,
142 | 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfc, 0x00, 0x00, 0x00,
143 | 0x00, 0x01, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
144 | 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
145 | 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
146 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
147 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
148 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
149 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
150 | 0x0f, 0xfe, 0x00, 0x7f, 0xff, 0xe3, 0xff, 0xf0, 0x0f, 0xf8, 0x00, 0x1f, 0xff, 0x00, 0xff, 0xf0,
151 | 0x0f, 0xf8, 0x00, 0x1f, 0xfc, 0x00, 0x3f, 0xf0, 0x0f, 0xfe, 0x00, 0x7f, 0xf8, 0x00, 0x1f, 0xf0,
152 | 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0,
153 | 0x0f, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0, 0x0f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, 0x0f, 0xf0,
154 | 0x0f, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x07, 0xf0, 0x0f, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x07, 0xf0,
155 | 0x0f, 0xf8, 0x00, 0x1f, 0xf0, 0x00, 0x0f, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0,
156 | 0x0f, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xf0,
157 | 0x0f, 0xfc, 0x00, 0x3f, 0xfc, 0x00, 0x3f, 0xf0, 0x0f, 0xf8, 0x00, 0x1f, 0xfe, 0x00, 0x7f, 0xf0,
158 | 0x0f, 0xf8, 0x00, 0x1f, 0xff, 0x00, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
159 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
160 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
161 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
162 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
163 | 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
164 | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00,
165 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
167 | },{// [5] 'house_64', 64x64px
168 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
170 | 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00,
171 | 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00,
172 | 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
173 | 0x00, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00,
174 | 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00,
175 | 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00,
176 | 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
177 | 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
178 | 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00,
179 | 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
180 | 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
181 | 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
182 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
183 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
184 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
185 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
186 | 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
187 | 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
188 | 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
189 | 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x0f, 0xff, 0xfc, 0x00,
190 | 0x00, 0x3f, 0xff, 0xe0, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x07, 0xff, 0xfc, 0x00,
191 | 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00,
192 | 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00,
193 | 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00,
194 | 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00,
195 | 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00,
196 | 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x00,
197 | 0x00, 0x1f, 0xff, 0xc0, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xf8, 0x00,
198 | 0x00, 0x0f, 0xff, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
200 | },{// [6] 'gear_64', 64x64px
201 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00,
203 | 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00,
204 | 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x00,
205 | 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
206 | 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
207 | 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x3e, 0x0f, 0xff, 0xff, 0xf0, 0x7e, 0x00,
208 | 0x00, 0x7f, 0xdf, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
209 | 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
210 | 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
211 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
212 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xe0,
213 | 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xc0,
214 | 0x01, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xfe, 0x00,
215 | 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xfc, 0x00,
216 | 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xfc, 0x00,
217 | 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xfc, 0x00,
218 | 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0xff, 0xfe, 0x00,
219 | 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80,
220 | 0x03, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0,
221 | 0x07, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
222 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
223 | 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
224 | 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
225 | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
226 | 0x00, 0x7f, 0x0f, 0xff, 0xff, 0xf0, 0x7c, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00,
227 | 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
228 | 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
229 | 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00,
230 | 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00,
231 | 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
233 | },{// [7] 'clock_64', 64x64px
234 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00,
236 | 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00,
237 | 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
238 | 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xe0, 0x0f, 0xff, 0xc0, 0x00,
239 | 0x00, 0x0f, 0xff, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x3f, 0xf8, 0x00,
240 | 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x07, 0xfc, 0x00,
241 | 0x00, 0x7f, 0x80, 0x03, 0xc0, 0x03, 0xfe, 0x00, 0x00, 0xff, 0x00, 0x07, 0xe0, 0x00, 0xff, 0x00,
242 | 0x01, 0xfe, 0x00, 0x07, 0xe0, 0x00, 0x7f, 0x80, 0x01, 0xfc, 0x00, 0x07, 0xe0, 0x00, 0x7f, 0x80,
243 | 0x03, 0xf8, 0x00, 0x07, 0xe0, 0x00, 0x3f, 0xc0, 0x03, 0xf8, 0x00, 0x07, 0xe0, 0x00, 0x1f, 0xc0,
244 | 0x07, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x0f, 0xe0,
245 | 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xf0, 0x0f, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xf0,
246 | 0x0f, 0xc0, 0x00, 0x07, 0xe0, 0x00, 0x03, 0xf0, 0x0f, 0xc0, 0x00, 0x07, 0xe0, 0x00, 0x03, 0xf0,
247 | 0x1f, 0xc0, 0x00, 0x07, 0xe0, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x07, 0xe0, 0x00, 0x03, 0xf8,
248 | 0x1f, 0x80, 0x00, 0x07, 0xe0, 0x00, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x07, 0xe0, 0x00, 0x01, 0xf8,
249 | 0x1f, 0x80, 0x00, 0x07, 0xe0, 0x00, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x07, 0xf8, 0x00, 0x01, 0xf8,
250 | 0x1f, 0x80, 0x00, 0x07, 0xfc, 0x00, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x07, 0xff, 0x00, 0x01, 0xf8,
251 | 0x1f, 0x80, 0x00, 0x03, 0xff, 0x80, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x01, 0xff, 0xe0, 0x01, 0xf8,
252 | 0x1f, 0x80, 0x00, 0x00, 0x7f, 0xf0, 0x01, 0xf8, 0x1f, 0xc0, 0x00, 0x00, 0x3f, 0xf8, 0x03, 0xf8,
253 | 0x1f, 0xc0, 0x00, 0x00, 0x0f, 0xfc, 0x03, 0xf0, 0x0f, 0xc0, 0x00, 0x00, 0x07, 0xfc, 0x03, 0xf0,
254 | 0x0f, 0xe0, 0x00, 0x00, 0x01, 0xfc, 0x07, 0xf0, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf0,
255 | 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0,
256 | 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0,
257 | 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80,
258 | 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x01, 0xfe, 0x00,
259 | 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x0f, 0xfc, 0x00,
260 | 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0xff, 0xf0, 0x00,
261 | 0x00, 0x07, 0xff, 0xe0, 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
262 | 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00,
263 | 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00,
264 | 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
266 | },{// [8] 'floppy_disk_64', 64x64px
267 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00,
269 | 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
270 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00,
271 | 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00,
272 | 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xff, 0xfe, 0x00,
273 | 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xfb, 0xff, 0x00, 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xf9, 0xff, 0x80,
274 | 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xf8, 0xff, 0xc0, 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xf8, 0x7f, 0xe0,
275 | 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xf8, 0x3f, 0xf0, 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xf8, 0x1f, 0xf0,
276 | 0x1f, 0xc7, 0xf0, 0x00, 0x03, 0xf8, 0x0f, 0xf8, 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xf8,
277 | 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xf8, 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xf8,
278 | 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xf8, 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xf8,
279 | 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xf0, 0x03, 0xf8, 0x1f, 0xc3, 0xff, 0xff, 0xff, 0xe0, 0x03, 0xf8,
280 | 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8,
281 | 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8,
282 | 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8,
283 | 0x1f, 0xc0, 0x00, 0x0f, 0xf0, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x1f, 0xf8, 0x00, 0x03, 0xf8,
284 | 0x1f, 0xc0, 0x00, 0x3f, 0xfc, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x7f, 0xfe, 0x00, 0x03, 0xf8,
285 | 0x1f, 0xc0, 0x00, 0xff, 0xff, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0xff, 0xff, 0x00, 0x03, 0xf8,
286 | 0x1f, 0xc0, 0x00, 0xff, 0xff, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x03, 0xf8,
287 | 0x1f, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x03, 0xf8, 0x1f, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x03, 0xf8,
288 | 0x1f, 0xc0, 0x00, 0xff, 0xff, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0xff, 0xff, 0x00, 0x03, 0xf8,
289 | 0x1f, 0xc0, 0x00, 0xff, 0xfe, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x7f, 0xfe, 0x00, 0x03, 0xf8,
290 | 0x1f, 0xc0, 0x00, 0x3f, 0xfc, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x1f, 0xf8, 0x00, 0x03, 0xf8,
291 | 0x1f, 0xc0, 0x00, 0x07, 0xc0, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8,
292 | 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8,
293 | 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8,
294 | 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8,
295 | 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
296 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
297 | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
299 | }
300 | };
301 |
--------------------------------------------------------------------------------
/radiowecker/num_64_44.h:
--------------------------------------------------------------------------------
1 | const unsigned char num_64_44 PROGMEM [10][360] = {
2 | {// '1_64_44, 64x44px
3 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
4 | 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
5 | 0x80, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x01,
6 | 0x80, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0xff, 0xe0, 0x00, 0x00, 0x01,
7 | 0x80, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x01,
8 | 0x80, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x07, 0xe7, 0xe0, 0x00, 0x00, 0x01,
9 | 0x80, 0x00, 0x07, 0xc7, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
10 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
11 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
12 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
13 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
14 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
15 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
16 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
17 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
18 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
19 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
20 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01,
21 | 0x80, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01,
22 | 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01,
23 | 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01,
24 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
25 | },{// '2_64_44, 64x44px
26 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
27 | 0x80, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x01,
28 | 0x80, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x01, 0x80, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x01,
29 | 0x80, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x01,
30 | 0x80, 0x00, 0x1f, 0xe0, 0x7f, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xc0, 0x1f, 0xc0, 0x00, 0x01,
31 | 0x80, 0x00, 0x3f, 0x80, 0x0f, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x0f, 0xe0, 0x00, 0x01,
32 | 0x80, 0x00, 0x3e, 0x00, 0x07, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x01,
33 | 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x01,
34 | 0x80, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x01,
35 | 0x80, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x01,
36 | 0x80, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x01,
37 | 0x80, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x01,
38 | 0x80, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x01,
39 | 0x80, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x01,
40 | 0x80, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x01,
41 | 0x80, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01,
42 | 0x80, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x01,
43 | 0x80, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x01,
44 | 0x80, 0x00, 0x1f, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x01,
45 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x01,
46 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x01,
47 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
48 | },{// '3_64_44, 64x44px
49 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
50 | 0x80, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x01,
51 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x01,
52 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x01,
53 | 0x80, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x01,
54 | 0x80, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x01,
55 | 0x80, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x01,
56 | 0x80, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x01,
57 | 0x80, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x01,
58 | 0x80, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x01, 0x80, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x01,
59 | 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x01,
60 | 0x80, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x01,
61 | 0x80, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x01,
62 | 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01,
63 | 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01,
64 | 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01,
65 | 0x80, 0x00, 0x1c, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3e, 0x00, 0x01, 0xfc, 0x00, 0x01,
66 | 0x80, 0x00, 0x3f, 0x00, 0x03, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x80, 0x07, 0xf8, 0x00, 0x01,
67 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x1f, 0xff, 0xff, 0xf0, 0x00, 0x01,
68 | 0x80, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x01,
69 | 0x80, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x01,
70 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 | },{// '4_64_44, 64x44px
72 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
73 | 0x80, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01,
74 | 0x80, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01,
75 | 0x80, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x01,
76 | 0x80, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x01,
77 | 0x80, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0xf8, 0x01, 0xe0, 0x00, 0x01,
78 | 0x80, 0x00, 0x03, 0xf8, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x03, 0xf0, 0x03, 0xe0, 0x00, 0x01,
79 | 0x80, 0x00, 0x07, 0xf0, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x07, 0xe0, 0x03, 0xe0, 0x00, 0x01,
80 | 0x80, 0x00, 0x0f, 0xe0, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xc0, 0x03, 0xe0, 0x00, 0x01,
81 | 0x80, 0x00, 0x0f, 0xc0, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x1f, 0x80, 0x03, 0xe0, 0x00, 0x01,
82 | 0x80, 0x00, 0x1f, 0x80, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x03, 0xe0, 0x00, 0x01,
83 | 0x80, 0x00, 0x3f, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x7f, 0x00, 0x03, 0xe0, 0x00, 0x01,
84 | 0x80, 0x00, 0x7e, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0xfe, 0x00, 0x03, 0xe0, 0x00, 0x01,
85 | 0x80, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01,
86 | 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01,
87 | 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
88 | 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01,
89 | 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01,
90 | 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01,
91 | 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01,
92 | 0x80, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x01,
93 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
94 | },{// '5_64_44', 64x44px
95 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
96 | 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01,
97 | 0x80, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x01,
98 | 0x80, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x01,
99 | 0x80, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01,
100 | 0x80, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x01,
101 | 0x80, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x01,
102 | 0x80, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x01,
103 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x01,
104 | 0x80, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xff, 0x00, 0x00, 0x01,
105 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x00, 0x01,
106 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x01,
107 | 0x80, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x01,
108 | 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01,
109 | 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01,
110 | 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01,
111 | 0x80, 0x00, 0x1c, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3e, 0x00, 0x01, 0xfc, 0x00, 0x01,
112 | 0x80, 0x00, 0x3f, 0x00, 0x03, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x80, 0x07, 0xf8, 0x00, 0x01,
113 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x1f, 0xff, 0xff, 0xf0, 0x00, 0x01,
114 | 0x80, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x01,
115 | 0x80, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x01,
116 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
117 | },{// '6_64_44', 64x44px
118 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
119 | 0x80, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01,
120 | 0x80, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x01,
121 | 0x80, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x01,
122 | 0x80, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x01,
123 | 0x80, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x01,
124 | 0x80, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x01,
125 | 0x80, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0x01,
126 | 0x80, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01,
127 | 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xfc, 0x3f, 0xf0, 0x00, 0x01,
128 | 0x80, 0x00, 0x0f, 0xe0, 0x0f, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x1f, 0xc0, 0x03, 0xf8, 0x00, 0x01,
129 | 0x80, 0x00, 0x1f, 0x80, 0x01, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x00, 0x01,
130 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01,
131 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0x7c, 0x00, 0x01,
132 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01,
133 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x01, 0xfc, 0x00, 0x01,
134 | 0x80, 0x00, 0x1f, 0x80, 0x01, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x1f, 0xc0, 0x03, 0xf8, 0x00, 0x01,
135 | 0x80, 0x00, 0x1f, 0xe0, 0x07, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xf0, 0x1f, 0xf0, 0x00, 0x01,
136 | 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x01,
137 | 0x80, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01,
138 | 0x80, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x01,
139 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
140 | },{// '7_64_44', 64x44px
141 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
142 | 0x80, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x01,
143 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x01,
144 | 0x80, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xf8, 0x00, 0x01,
145 | 0x80, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x01,
146 | 0x80, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x01,
147 | 0x80, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x01,
148 | 0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x01,
149 | 0x80, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01,
150 | 0x80, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x01,
151 | 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x01,
152 | 0x80, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x01,
153 | 0x80, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x01,
154 | 0x80, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x01,
155 | 0x80, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x01,
156 | 0x80, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x01,
157 | 0x80, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01,
158 | 0x80, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x01,
159 | 0x80, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x01,
160 | 0x80, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x01,
161 | 0x80, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01,
162 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
163 | },{// '8_64_44', 64x44px
164 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
165 | 0x80, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x01,
166 | 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01,
167 | 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01,
168 | 0x80, 0x00, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x01,
169 | 0x80, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x1f, 0x80, 0x01, 0xf0, 0x00, 0x01,
170 | 0x80, 0x00, 0x1f, 0x80, 0x01, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x1f, 0x80, 0x01, 0xf8, 0x00, 0x01,
171 | 0x80, 0x00, 0x1f, 0x80, 0x01, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x0f, 0x80, 0x01, 0xf8, 0x00, 0x01,
172 | 0x80, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x01,
173 | 0x80, 0x00, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01,
174 | 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01,
175 | 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x01,
176 | 0x80, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x1f, 0xe0, 0x07, 0xf8, 0x00, 0x01,
177 | 0x80, 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x00, 0x01,
178 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01,
179 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01,
180 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x80, 0x00, 0xfc, 0x00, 0x01,
181 | 0x80, 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x1f, 0xc0, 0x07, 0xf8, 0x00, 0x01,
182 | 0x80, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x01,
183 | 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01,
184 | 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x01,
185 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
186 | },{// '9_64_44', 64x44px
187 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
188 | 0x80, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x01,
189 | 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x01,
190 | 0x80, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01,
191 | 0x80, 0x00, 0x0f, 0xf8, 0x1f, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x1f, 0xe0, 0x07, 0xf8, 0x00, 0x01,
192 | 0x80, 0x00, 0x1f, 0xc0, 0x03, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x80, 0x01, 0xf8, 0x00, 0x01,
193 | 0x80, 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01,
194 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01,
195 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01,
196 | 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x01,
197 | 0x80, 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x1f, 0x80, 0x01, 0xf8, 0x00, 0x01,
198 | 0x80, 0x00, 0x1f, 0xc0, 0x03, 0xf8, 0x00, 0x01, 0x80, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x01,
199 | 0x80, 0x00, 0x0f, 0xfc, 0x3f, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x01,
200 | 0x80, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x01,
201 | 0x80, 0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x01,
202 | 0x80, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x01,
203 | 0x80, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x01,
204 | 0x80, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x01,
205 | 0x80, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x01,
206 | 0x80, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x01,
207 | 0x80, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01,
208 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
209 | },{// '10_64_44', 64x44px
210 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
211 | 0x80, 0x00, 0x38, 0x00, 0x00, 0x7f, 0x00, 0x01, 0x80, 0x00, 0xfc, 0x00, 0x03, 0xff, 0xe0, 0x01,
212 | 0x80, 0x03, 0xfc, 0x00, 0x0f, 0xff, 0xf8, 0x01, 0x80, 0x07, 0xfc, 0x00, 0x1f, 0xff, 0xfc, 0x01,
213 | 0x80, 0x1f, 0xfc, 0x00, 0x3f, 0xff, 0xfe, 0x01, 0x80, 0x3f, 0xfc, 0x00, 0x7f, 0xff, 0xff, 0x01,
214 | 0x80, 0x7f, 0xfc, 0x00, 0xff, 0x80, 0xff, 0x81, 0x80, 0xff, 0xfc, 0x00, 0xff, 0x00, 0x7f, 0x81,
215 | 0x80, 0xff, 0xfc, 0x01, 0xfc, 0x00, 0x1f, 0xc1, 0x80, 0xfc, 0xfc, 0x01, 0xfc, 0x00, 0x1f, 0xc1,
216 | 0x80, 0x78, 0xfc, 0x01, 0xf8, 0x00, 0x0f, 0xc1, 0x80, 0x00, 0xfc, 0x03, 0xf8, 0x00, 0x0f, 0xc1,
217 | 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1, 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1,
218 | 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1, 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1,
219 | 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1, 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1,
220 | 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1, 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1,
221 | 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1, 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1,
222 | 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1, 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1,
223 | 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1, 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1,
224 | 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1, 0x80, 0x00, 0xfc, 0x03, 0xf0, 0x00, 0x07, 0xe1,
225 | 0x80, 0x00, 0xfc, 0x01, 0xf8, 0x00, 0x0f, 0xe1, 0x80, 0x00, 0xfc, 0x01, 0xf8, 0x00, 0x0f, 0xc1,
226 | 0x80, 0x00, 0xfc, 0x01, 0xfc, 0x00, 0x1f, 0xc1, 0x80, 0x00, 0xfc, 0x01, 0xfc, 0x00, 0x1f, 0xc1,
227 | 0x80, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x7f, 0x81, 0x80, 0x00, 0xfc, 0x00, 0xff, 0x80, 0xff, 0x81,
228 | 0x80, 0x3f, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xfe, 0x01,
229 | 0x80, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xfc, 0x01, 0x80, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xf8, 0x01,
230 | 0x80, 0xff, 0xff, 0xfc, 0x03, 0xff, 0xe0, 0x01, 0x80, 0x7f, 0xff, 0xf8, 0x00, 0x7f, 0x00, 0x01,
231 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
232 | }
233 | };
234 |
--------------------------------------------------------------------------------
/radiowecker/ota.ino:
--------------------------------------------------------------------------------
1 | // Variable zur Verfolgung des Fortschritts der OTA-Aktualisierung
2 | uint32_t oldprc;
3 |
4 | // Funktion zur Vorbereitung der OTA-Aktualisierung
5 | void setup_ota() {
6 | // Setze den Hostnamen und das Passwort für OTA-Updates
7 | ArduinoOTA.setHostname(OTA_HOSTNAME); // Setzt den Hostnamen für OTA
8 | ArduinoOTA.setPassword(OTA_PASSWORD); // Setzt das Passwort für OTA
9 |
10 | // Registriere Callback-Routinen für OTA-Ereignisse
11 | ArduinoOTA.onStart(ota_onStart); // Callback, wenn die OTA-Aktualisierung beginnt
12 | ArduinoOTA.onEnd(ota_onEnd); // Callback, wenn die OTA-Aktualisierung endet
13 | ArduinoOTA.onProgress(ota_onProgress); // Callback zur Anzeige des Fortschritts
14 | ArduinoOTA.onError(ota_onError); // Callback bei einem Fehler während der OTA-Aktualisierung
15 |
16 | // Starte die OTA-Verarbeitung
17 | ArduinoOTA.begin(); // Beginnt die OTA-Aktualisierung
18 | }
19 |
20 | // Callback-Funktion, die aufgerufen wird, wenn die OTA-Aktualisierung beginnt
21 | void ota_onStart() {
22 | displayClear(); // Löscht das Display
23 | setBGLight(100); // Setzt die Hintergrundbeleuchtung auf 100% Helligkeit
24 | oldprc = 0; // Setzt den alten Fortschrittswert zurück
25 | String type;
26 | // Bestimme den Typ der Aktualisierung (Sketch oder Dateisystem)
27 | if (ArduinoOTA.getCommand() == U_FLASH)
28 | type = "sketch"; // Programm-Aktualisierung
29 | else // U_SPIFFS
30 | type = "filesystem"; // Dateisystem-Aktualisierung
31 |
32 | // Zeige eine Nachricht auf dem Display an, dass das Sketch aktualisiert wird
33 | displayMessage(5, 10, 310, 30, "Updating Sketch", ALIGNCENTER, true, ILI9341_YELLOW, ILI9341_BLACK, 1);
34 | showProgress(0); // Zeigt den Fortschritt (beginnend bei 0%)
35 | }
36 |
37 | // Callback-Funktion, die aufgerufen wird, wenn die OTA-Aktualisierung endet
38 | void ota_onEnd() {
39 | // Zeigt eine Nachricht auf dem Display an, dass die Aktualisierung abgeschlossen ist
40 | displayMessage(5, 120, 310, 30, "Done", ALIGNLEFT, true, ILI9341_GREEN, ILI9341_BLACK, 1);
41 | }
42 |
43 | // Callback-Funktion, die aufgerufen wird, um den Fortschritt der OTA-Aktualisierung anzuzeigen
44 | void ota_onProgress(unsigned int progress, unsigned int total) {
45 | uint32_t prc = progress / (total / 100); // Berechne den Fortschritt in Prozent
46 | char tmp[20];
47 | // Wenn der Fortschritt gestiegen ist, aktualisiere die Fortschrittsanzeige
48 | if (prc > oldprc) {
49 | showProgress(prc); // Zeige den Fortschritt an
50 | oldprc = prc; // Speichere den aktuellen Fortschritt für die nächste Überprüfung
51 | }
52 | }
53 |
54 | // Callback-Funktion, die bei einem Fehler während der OTA-Aktualisierung aufgerufen wird
55 | void ota_onError(ota_error_t error) {
56 | char err[80];
57 | // Formatierte Fehlermeldung
58 | sprintf(err, "Error[%u]: ", error);
59 | // Bestimme die spezifische Fehlermeldung basierend auf dem Fehlercode
60 | if (error == OTA_AUTH_ERROR) sprintf(err, "Error[%u]: Auth Failed", error);
61 | else if (error == OTA_BEGIN_ERROR) sprintf(err, "Error[%u] Begin Failed", error);
62 | else if (error == OTA_CONNECT_ERROR) sprintf(err, "Error[%u] Connect Failed", error);
63 | else if (error == OTA_RECEIVE_ERROR) sprintf(err, "Error[%u] Receive Failed", error);
64 | else if (error == OTA_END_ERROR) sprintf(err, "Error[%u] End Failed", error);
65 |
66 | // Zeige die Fehlermeldung auf dem Display an
67 | displayMessage(5, 200, 310, 30, err, ALIGNLEFT, false, ILI9341_RED);
68 | }
--------------------------------------------------------------------------------
/radiowecker/radiowecker.ino:
--------------------------------------------------------------------------------
1 | #define RADIOVERSION "v4.0.2";
2 | #include "00_librarys.h" //Lade alle benötigten Bibliotheken
3 | #include "00_pin_settings.h" //Einstellungen der genutzten Pins
4 | #include "00_settings.h" //einstellungen
5 | #include "00_texte.h" //Strings
6 | #include "weather.h"
7 | //predefined function from modul tft_display.ino
8 | void displayMessage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const char* text, uint8_t align = ALIGNLEFT, boolean big = false, uint16_t fc = ILI9341_WHITE, uint16_t bg = ILI9341_BLACK, uint8_t lines = 1);
9 |
10 | // Berechnet das Datum und die Uhrzeit für den nächsten erwarteten Alarm
11 | // Setzt `alarmtime` auf die Zeit des Tages und `alarmday` auf den Wochentag für den Alarm
12 | // oder auf 8, wenn kein Alarm vorhanden ist
13 | void findNextAlarm() {
14 | Serial.println("Search next alarm time");
15 | int wd; // Variable für den aktuellen Wochentag
16 | uint8_t mask; // Maske zum Filtern von Wochentagen
17 |
18 | if (getLocalTime(&ti)) { // Hole das aktuelle Datum und die Uhrzeit
19 | wd = weekday; // Setze wd auf den aktuellen Wochentag
20 | alarmday = 8; // Setze alarmday auf 8, was bedeutet, dass kein Alarm vorhanden ist
21 | alarmtime = MINUTES_PER_DAY + 1; // Setze alarmtime auf einen Wert, der höher ist als der maximal mögliche Wert für Minuten pro Tag
22 |
23 | mask = 1 << wd; // Erstelle eine Maske für den aktuellen Wochentag
24 |
25 | // Überprüfe, ob die Alarmzeit 1 übereinstimmt und ob der Alarm vor der aktuellen Zeit liegt
26 | if (((alarmday1 & mask) != 0) && (alarm1 > minutes)) {
27 | alarmtime = alarm1; // Setze alarmtime auf alarm1
28 | alarmday = wd; // Setze alarmday auf den aktuellen Wochentag
29 | }
30 |
31 | // Überprüfe, ob die Alarmzeit 2 übereinstimmt und ob der Alarm vor alarm1 liegt
32 | if (((alarmday2 & mask) != 0) && (alarm2 > minutes) && (alarmtime > alarm2)) {
33 | alarmtime = alarm2; // Setze alarmtime auf alarm2
34 | alarmday = wd; // Setze alarmday auf den aktuellen Wochentag
35 | }
36 |
37 | // Wenn kein Alarm gefunden wurde, fahre fort mit der Suche nach dem nächsten Alarm in der kommenden Woche
38 | if (alarmday == 8) { // Wenn alarmday immer noch 8 ist (kein Alarm gefunden)
39 | do {
40 | wd++; // Gehe zum nächsten Wochentag
41 | if (wd > 7) wd = 0; // Wenn der Wochentag über 7 hinausgeht, setze ihn auf 0 (Sonntag)
42 |
43 | mask = 1 << wd; // Erstelle eine neue Maske für den aktuellen Wochentag
44 |
45 | // Überprüfe erneut Alarmzeit 1
46 | if ((alarmday1 & mask) != 0) {
47 | alarmtime = alarm1; // Setze alarmtime auf alarm1
48 | alarmday = wd; // Setze alarmday auf den aktuellen Wochentag
49 | }
50 |
51 | // Überprüfe erneut Alarmzeit 2
52 | if (((alarmday2 & mask) != 0) && (alarmtime > alarm2)) {
53 | alarmtime = alarm2; // Setze alarmtime auf alarm2
54 | alarmday = wd; // Setze alarmday auf den aktuellen Wochentag
55 | }
56 |
57 | } while ((alarmday == 8) && (wd != weekday)); // Wiederhole, bis ein gültiger Alarm gefunden wird oder eine Woche vorbei ist
58 | }
59 | Serial.printf("Next alarm %i on %i\n", alarmtime, alarmday); // Gib die nächste Alarmzeit und den Wochentag aus
60 | }
61 | }
62 |
63 | // Initialisierung des Systems
64 | void setup() {
65 | // Starte die serielle Kommunikation mit einer Baudrate von 115200
66 | Serial.begin(115200);
67 | Serial.println("Load preferences"); // Debug-Ausgabe: "Lade Einstellungen"
68 |
69 | title[0] = 0; // Setze das erste Zeichen des Titels auf 0 (leerer Titel)
70 |
71 | // Lade die gespeicherten Präferenzen aus dem EEPROM des ESP32
72 | // Die Präferenzen werden in zwei Themen gespeichert: "radio" und "senderliste"
73 | // Beide Themen werden hier geladen
74 | pref.begin("radio", false);
75 | sender.begin("senderlist", false);
76 |
77 | // Werte aus den gespeicherten Präferenzen abrufen, falls vorhanden
78 | if (pref.isKey("ssid")) ssid = pref.getString("ssid"); // SSID für WLAN-Verbindung
79 | if (pref.isKey("pkey")) pkey = pref.getString("pkey"); // Passkey für WLAN-Verbindung
80 | if (pref.isKey("ntp")) ntp = pref.getString("ntp"); // NTP-Server-URL für die Zeitabgleich
81 | if (pref.isKey("TIME_ZONE_IANA")) TIME_ZONE_IANA = pref.getString("TIME_ZONE_IANA"); // Zeitzone abrufen
82 | if (pref.isKey("LATITUDE")) LATITUDE = pref.getFloat("LATITUDE"); // Latitude für die Wetterdaten
83 | if (pref.isKey("LONGITUDE")) LONGITUDE = pref.getFloat("LONGITUDE"); // Longitude für die Wetterdaten
84 |
85 |
86 | curGain = 50; // Standardwert für Lautstärke
87 | if (pref.isKey("gain")) curGain = pref.getUShort("gain"); // Abrufen des Lautstärkewerts
88 |
89 | snoozeTime = 30; // Standardwert für Schlummerzeit in Minuten
90 | if (pref.isKey("snooze")) snoozeTime = pref.getUShort("snooze"); // Abrufen der Schlummerzeit
91 |
92 | bright = 80; // Standardwert für Helligkeit in Prozent
93 | if (pref.isKey("bright")) bright = pref.getUShort("bright"); // Abrufen des Helligkeitswerts
94 |
95 | alarm1 = 390; // Standardwert für die erste Alarmzeit (6:30)
96 | if (pref.isKey("alarm1")) alarm1 = pref.getUInt("alarm1"); // Abrufen der ersten Alarmzeit
97 |
98 | alarmday1 = 0B00111110; // Standardwert für die Tage (Mo-Fr)
99 | if (pref.isKey("alarmday1")) alarmday1 = pref.getUShort("alarmday1"); // Abrufen der Wochentage für den ersten Alarm
100 |
101 | alarm2 = 480; // Standardwert für die zweite Alarmzeit (8:00)
102 | if (pref.isKey("alarm2")) alarm2 = pref.getUInt("alarm2"); // Abrufen der zweiten Alarmzeit
103 |
104 | alarmday2 = 0B01000001; // Standardwert für die Tage (So, Sa)
105 | if (pref.isKey("alarmday2")) alarmday2 = pref.getUShort("alarmday2"); // Abrufen der Wochentage für den zweiten Alarm
106 |
107 | alarmtime = 0; // Startwert für die nächste Alarmzeit
108 | alarmday = 8; // Startwert für den nächsten Alarmtag (8 bedeutet, Alarm ist deaktiviert)
109 |
110 | curStation = 0; // Standardwert für die aktuelle Station
111 | // Setze die aktuelle Station auf den gespeicherten Wert, falls vorhanden
112 | if (pref.isKey("station")) curStation = pref.getUShort("station");
113 | // Überprüfe, ob die aktuelle Station innerhalb des gültigen Bereichs liegt
114 | if (curStation >= STATIONS) curStation = 0;
115 |
116 | actStation = curStation; // Setze die aktive Station auf die aktuelle Station
117 |
118 | // Debug-Ausgabe der aktuellen Station, Lautstärke, SSID und NTP-Server
119 | Serial.printf("station %i, gain %i, ssid %s, ntp %s\n", curStation, curGain, ssid.c_str(), ntp.c_str());
120 |
121 | // Führe die Setup-Funktionen für Audio, Display und Senderliste aus
122 | setup_audio(); // Initialisiere die Audio-Streams
123 | setup_display(); // Initialisiere die Display-Schnittstelle
124 | setup_senderList(); // Lade die Senderliste aus den Präferenzen
125 | setGain(0); // Setze die aktuelle Lautstärke
126 |
127 | // Versuche, eine WLAN-Verbindung herzustellen und zeige den Fortschritt auf dem Display an
128 | displayClear(); // Bildschirm löschen
129 | displayMessage(5, 10, 310, 30, TXT_CONNECTING_TO, ALIGNCENTER, true, ILI9341_YELLOW, ILI9341_BLACK, 1); // Zeige "Verbinden zu" auf dem Display an
130 | displayMessage(5, 50, 310, 30, ssid.c_str(), ALIGNCENTER, true, ILI9341_GREEN, ILI9341_BLACK, 1); // Zeige die SSID auf dem Display an
131 | Serial.println("Connect WiFi"); // Debug-Ausgabe: "Verbinde zu WiFi"
132 |
133 | // Versuche, sich mit dem WLAN zu verbinden
134 | connected = initWiFi(ssid, pkey);
135 |
136 | // Wenn die Verbindung erfolgreich war
137 | if (connected) {
138 | // Konfiguriere die Echtzeituhr mit der Zeitzone und dem NTP-Server
139 | configTzTime(TIME_ZONE, ntp.c_str());
140 |
141 | // Zeige Datum und Uhrzeit sowie den Namen der Station an
142 | delay(500); // Kurze Verzögerung für die Anzeige
143 | // Fülle die Zeitstruktur ti, Minuten und Wochentag mit der aktuellen Zeit
144 | getLocalTime(&ti);
145 | minutes = ti.tm_hour * 60 + ti.tm_min; // Berechne Minuten seit Mitternacht
146 | weekday = ti.tm_wday; // Wochentag (0 = Sonntag, 1 = Montag, usw.)
147 |
148 | Serial.println("Start"); // Debug-Ausgabe: "Start"
149 |
150 | // Wenn der Alarm aktiviert ist, berechne das Datum und die Uhrzeit für den nächsten Alarm
151 | if (pref.isKey("alarmon") && pref.getBool("alarmon")) findNextAlarm();
152 |
153 | // Zeige Uhrzeit und nächsten Alarm auf dem Display an
154 | showClock();
155 | } else { // Wenn die Verbindung nicht erfolgreich war
156 | // Es konnte keine Verbindung hergestellt werden. Eine entsprechende Nachricht wird auf dem Display angezeigt
157 | displayClear(); // Bildschirm löschen
158 | displayMessage(5, 10, 310, 30, TXT_NOT_CONNECTED, ALIGNCENTER, true, ILI9341_RED, ILI9341_BLACK, 1); // Zeige "Nicht verbunden" auf dem Display an
159 | displayMessage(5, 50, 310, 30, TXT_CONNECT_TO_AP, ALIGNCENTER, true, ILI9341_WHITE, ILI9341_BLACK, 1); // Zeige "Verbinden zu AP" auf dem Display an
160 | displayMessage(5, 100, 310, 30, AP_NAME, ALIGNCENTER, true, ILI9341_GREEN, ILI9341_BLACK, 1); // Zeige "Ap Name" auf dem Display an
161 | displayMessage(5, 150, 310, 30, TXT_CONFIG_IP, ALIGNCENTER, true, ILI9341_WHITE, ILI9341_BLACK, 1); // Zeige "IP konfigurieren" auf dem Display an
162 | displayMessage(5, 200, 310, 30, "192.168.4.1", ALIGNCENTER, true, ILI9341_GREEN, ILI9341_BLACK, 1); // Zeige "IP " auf dem Display an
163 |
164 | // Merke den aktuellen Zeitstempel, um später nach 5 Minuten einen Retry zu ermöglichen
165 | discon = millis();
166 | }
167 |
168 | Serial.println("Start webserver"); // Debug-Ausgabe: "Starte Webserver"
169 |
170 | // Initialisiere den Webserver und das OTA-Update
171 | setup_webserver(); // Initialisiere den Webserver
172 | setup_ota(); // Initialisiere das OTA-Update
173 |
174 | start_conf = 0; // Setze den Startwert für die Konfiguration
175 | }
176 |
177 | void loop() {
178 | long rssi = WiFi.RSSI(); // Hole das Signalstärke- (RSSI) Level des WiFi
179 |
180 | // Überprüfe und verarbeite mögliche OTA-Updates
181 | ArduinoOTA.handle();
182 |
183 | // Verarbeite HTTP-Anfragen
184 | webserver_loop();
185 |
186 | // Überprüfe Touch-Ereignisse
187 | touch_loop();
188 |
189 | // Nach 10 Sekunden im Konfigurationsmodus, zurück zum Uhrmodus wechseln
190 | if (!clockmode && ((millis() - start_conf) > 10000)) {
191 | showClock(); // Zeige die Uhrzeit an
192 | clockmode = true; // Setze den Modus auf Uhr
193 | }
194 |
195 | // Zeige Metadaten an, wenn das Radio aktiv ist und wir im Uhrmodus sind
196 | if (newTitle && radio && clockmode) {
197 | showTitle(); // Zeige den Titel des aktuellen Radiosenders an
198 | newTitle = false; // Setze das Flag zurück
199 | }
200 |
201 | // Erkenne einen Verbindungsabbruch
202 | if (connected && (WiFi.status() != WL_CONNECTED)) {
203 | connected = false; // Setze die Verbindung auf false
204 | discon = millis(); // Merke den aktuellen Zeitstempel für einen automatischen Retry
205 | displayClear(); // Bildschirm löschen
206 | // Zeige eine Nachricht an, dass die Verbindung verloren gegangen ist
207 | displayMessage(5, 10, 310, 30, TXT_NOT_CONNECTED, ALIGNCENTER, true, ILI9341_RED, ILI9341_BLACK, 1);
208 | }
209 |
210 | // Erkenne eine Wiederverbindung
211 | if (!connected && (WiFi.status() == WL_CONNECTED)) {
212 | connected = true; // Setze die Verbindung auf true
213 | displayClear(); // Bildschirm löschen
214 | // Zeige eine Nachricht an, dass die Verbindung wiederhergestellt wurde
215 | displayMessage(5, 10, 310, 30, TXT_RECONNECTED, ALIGNCENTER, true, ILI9341_GREEN, ILI9341_BLACK, 1);
216 | reconnected = true;
217 | }
218 |
219 | // Wenn das Radio eingeschaltet ist, hole neue Stream-Daten
220 | if (connected && radio) {
221 | audio_loop(); // Verarbeite Audiodaten
222 | }
223 |
224 | // Wenn die Helligkeit auf 0 gesetzt ist, wird die Helligkeit durch das Umgebungslicht gesteuert
225 | if (bright == 0) {
226 | int16_t tmp = analogRead(LDR); // Lese den Wert vom Lichtsensor (LDR)
227 | int16_t diff = lastldr - tmp; // Berechne die Differenz zum vorherigen Wert
228 | diff = abs(diff); // Nehme den absoluten Wert der Differenz
229 |
230 | // Setze die Hintergrundbeleuchtung, wenn die Uhr angezeigt wird und eine signifikante Änderung des Umgebungslichts erkannt wurde
231 | if (clockmode && (diff > 50)) {
232 | setBGLight(bright); // Setze die Hintergrundbeleuchtung
233 | Serial.printf("ldr %i letzter %i\n", tmp, lastldr); // Debug-Ausgabe der aktuellen und letzten LDR-Werte
234 | lastldr = tmp; // Merke den aktuellen LDR-Wert für die nächste Messung
235 | }
236 | }
237 |
238 | // Wetterdaten beim ersten Durchlauf sofort abrufen (wenn lastWeatherUpdate == 0) oder alle 60 Sekunden
239 | if (millis() - lastWeatherUpdate > weatherUpdateInterval || lastWeatherUpdate == 0) {
240 | if (!radio && clockmode) {
241 | String weatherData = getWeatherData(LATITUDE, LONGITUDE, TIME_ZONE_IANA);
242 | displayWeather(weatherData);
243 | }
244 | lastWeatherUpdate = millis(); // Zeitstempel für das nächste Update
245 | }
246 |
247 | // Zeitgesteuertes Ereignis: Update der Anzeige alle 1 Sekunde
248 | if ((millis() - lastUpdate) > 1000) {
249 | lastUpdate = millis(); // Aktualisiere den Zeitstempel
250 |
251 | // Regelmäßige Prüfung der Schlummerzeit
252 | if (millis() > snoozeTimeEnd && snoozeTimeEnd > 0) {
253 | snoozeTimeEnd = 0; // Setze den Schlummermodus zurück
254 | toggleRadio(true); // Schalte das Radio aus
255 | showRadio(); // Zeige Radio-Status an
256 | }
257 |
258 | // Hole das Datum und die Uhrzeit
259 | if (connected && getLocalTime(&ti)) {
260 | minutes = ti.tm_hour * 60 + ti.tm_min; // Berechne Minuten seit Mitternacht
261 | weekday = ti.tm_wday; // Wochentag (0 = Sonntag, 1 = Montag, usw.)
262 | }
263 | // Setze die Hintergrundbeleuchtung, wenn die Uhr angezeigt wird
264 | if (connected && clockmode) {
265 |
266 | if(!reconnected){
267 | setBGLight(bright); // Setze die Hintergrundbeleuchtung
268 | displayDateTime(); // Zeige Datum und Uhrzeit an ohne komplettes Display neu zu zeichnen
269 | }else{
270 | showClock(); // Zeige Datum und Uhrzeit mit komplett neu zu zeichnen
271 | reconnected = false;
272 | }
273 |
274 | }
275 |
276 | // Wenn ein Alarm aktiviert ist, überprüfe den Tag und die Zeit
277 | if ((alarmday < 8) && getLocalTime(&ti)) {
278 | // Wenn der Alarmtag und die Zeit erreicht sind, schalte das Radio ein und berechne die Werte für den nächsten erwarteten Alarm
279 | if ((alarmday == weekday) && ((minutes == alarmtime) || (minutes == (alarmtime + 1)))) {
280 | // Test Beeper#####################
281 |
282 | // Test Beeper#####################
283 | toggleRadio(false); // Schalte das Radio an
284 | showRadio(); // Zeige Radio-Informationen an
285 | findNextAlarm(); // Berechne den nächsten Alarm
286 | showNextAlarm(); // Zeige den nächsten Alarm an
287 | }
288 | }
289 | }
290 |
291 | // Starte einen Neustart, wenn das Gerät mehr als 5 Minuten getrennt war
292 | if (!connected && ((millis() - discon) > 300000)) ESP.restart();
293 | }
294 |
--------------------------------------------------------------------------------
/radiowecker/stations.ino:
--------------------------------------------------------------------------------
1 | // Anzahl der Standardstationen in der Liste
2 | #define DEFAULTSTATIONS 26
3 |
4 | // Definition eines Sets getesteter Standardstationen, gespeichert im Flash-Speicher (PROGMEM)
5 | Station defstations[DEFAULTSTATIONS] PROGMEM = {
6 | { "http://stream01.zogl.net:8906/stream", "Radino", 1 },
7 | { "http://radio.toggo.de/live/mp3-192/radio.toggo.de/", "Toggo", 1 },
8 | { "http://streams.radiobob.de/bob-national/mp3-192/mediaplayer", "BOB", 1 },
9 | { "http://stream.laut.fm/hoerspiel", "Hörspiele", 1 },
10 | { "http://stream.laut.fm/jugend_radio", "Jugend", 1 },
11 | { "http://646.cloudrad.io:8234", "Strobe", 1 },
12 | { "http://646.cloudrad.io:8276", "Pulse107", 1 },
13 | { "http://646.cloudrad.io:8314", "DJ Perry", 1 },
14 | { "http://dispatcher.rndfnk.com/hr/hr3/suedhessen/high", "HR3", 1 },
15 | { "http://stream.antenne.de/antenne", "Antenne Bayern", 1 },
16 | { "http://stream.1a-webradio.de/saw-deutsch/", "1A Deutsche Hits", 1 },
17 | { "http://1a-rock.radionetz.de:8000/1a-rock.mp3", "1A Rock", 1 },
18 | { "http://1a-ndw.radionetz.de/1a-ndw.mp3", "1A NDW", 1 },
19 | { "http://dispatcher.rndfnk.com/br/brklassik/live/mp3/low", "Bayern Klassik", 1 },
20 | { "http://mdr-284280-1.cast.mdr.de/mdr/284280/1/mp3/low/stream.mp3", "MDR", 1 },
21 | { "http://icecast.ndr.de/ndr/njoy/live/mp3/128/stream.mp3", "N-JOY", 1 },
22 | { "http://dispatcher.rndfnk.com/rbb/rbb888/live/mp3/mid", "RBB", 1 },
23 | { "http://dispatcher.rndfnk.com/rbb/antennebrandenburg/live/mp3/mid", "Antenne Brandenburg", 1 },
24 | { "http://wdr-wdr3-live.icecastssl.wdr.de/wdr/wdr3/live/mp3/128/stream.mp3", "WDR3", 1 },
25 | { "http://wdr-wdr2-aachenundregion.icecastssl.wdr.de/wdr/wdr2/aachenundregion/mp3/128/stream.mp3", "WDR 2", 1 },
26 | { "http://rnrw.cast.addradio.de/rnrw-0182/deinschlager/low/stream.mp3", "NRW Schlagerradio", 1 },
27 | { "http://rnrw.cast.addradio.de/rnrw-0182/deinrock/low/stream.mp3", "NRW Rockradio", 1 },
28 | { "http://rnrw.cast.addradio.de/rnrw-0182/dein90er/low/stream.mp3", "NRW 90er", 1 },
29 | { "http://rt1.radio/tu6h1", "RT1 Rock", 1 },
30 | { "https://s10.streamingcloud.online:13552/radioluz320.mp3", "Spitalradio LuZ", 1 },
31 | { "http://stream.streambase.ch/vrock/mp3-192/", "Virgin Radio", 1 }
32 | };
33 |
34 | // Füllt die Stationenliste aus den gespeicherten Präferenzen. Wenn ein Eintrag nicht existiert, wird die Standardliste verwendet
35 | void setup_senderList() {
36 | char nkey[4]; // Schlüssel für den Namen
37 | char ukey[4]; // Schlüssel für die URL
38 | char fkey[4]; // Schlüssel für den Aktivierungsstatus
39 |
40 | // Schleife über alle möglichen Stationen
41 | for (uint8_t i = 0; i < STATIONS; i++) {
42 | // Erzeuge die Schlüssel für die aktuellen Index-Station
43 | sprintf(nkey, "n%i", i);
44 | sprintf(ukey, "u%i", i);
45 | sprintf(fkey, "f%i", i);
46 |
47 | if (i < DEFAULTSTATIONS) {
48 | // Wenn der Index innerhalb der Standardstationen liegt, lade die Daten aus den Präferenzen oder verwende Standardwerte
49 | strlcpy(stationlist[i].name, sender.getString(nkey, defstations[i].name).c_str(), 32);
50 | strlcpy(stationlist[i].url, sender.getString(ukey, defstations[i].url).c_str(), 150);
51 | stationlist[i].enabled = sender.getUChar(fkey, defstations[i].enabled);
52 | } else {
53 | // Wenn der Index außerhalb der Standardstationen liegt, lade die Daten aus den Präferenzen oder verwende leere Standardwerte
54 | strlcpy(stationlist[i].name, sender.getString(nkey, nkey).c_str(), 32);
55 | strlcpy(stationlist[i].url, sender.getString(ukey, "").c_str(), 150);
56 | stationlist[i].enabled = sender.getUChar(fkey, 0);
57 | }
58 | }
59 | }
60 |
61 | // Füllt die Stationenliste mit den Standardstationen und speichert sie in den Präferenzen
62 | void restore() {
63 | char nkey[4]; // Schlüssel für den Namen
64 | char ukey[4]; // Schlüssel für die URL
65 | char fkey[4]; // Schlüssel für den Aktivierungsstatus
66 |
67 | // Schleife über alle möglichen Stationen
68 | for (uint8_t i = 0; i < STATIONS; i++) {
69 | // Lösche die vorherigen Einträge in den Präferenzen
70 | sender.clear();
71 |
72 | // Erzeuge die Schlüssel für den aktuellen Index
73 | sprintf(nkey, "n%i", i);
74 | sprintf(ukey, "u%i", i);
75 | sprintf(fkey, "f%i", i);
76 |
77 | if (i < DEFAULTSTATIONS) {
78 | // Wenn der Index innerhalb der Standardstationen liegt, verwende die Standardwerte
79 | strlcpy(stationlist[i].name, defstations[i].name, 32);
80 | sender.putString(nkey, defstations[i].name);
81 | strlcpy(stationlist[i].url, defstations[i].url, 150);
82 | sender.putString(ukey, defstations[i].url);
83 | stationlist[i].enabled = defstations[i].enabled;
84 | sender.putUChar(fkey, defstations[i].enabled);
85 | } else {
86 | // Wenn der Index außerhalb der Standardstationen liegt, speichere leere Werte
87 | strlcpy(stationlist[i].name, nkey, 32);
88 | sender.putString(nkey, nkey);
89 | strlcpy(stationlist[i].url, "", 150);
90 | sender.putString(ukey, "");
91 | stationlist[i].enabled = 0;
92 | sender.putUChar(fkey, 0);
93 | }
94 | }
95 | }
96 |
97 | // Speichert die Stationenliste in den Präferenzen
98 | void saveList() {
99 | char nkey[4]; // Schlüssel für den Namen
100 | char ukey[4]; // Schlüssel für die URL
101 | char fkey[4]; // Schlüssel für den Aktivierungsstatus
102 |
103 | // Schleife über alle möglichen Stationen
104 | for (uint8_t i = 0; i < STATIONS; i++) {
105 | // Erzeuge die Schlüssel für den aktuellen Index
106 | sprintf(nkey, "n%i", i);
107 | sprintf(ukey, "u%i", i);
108 | sprintf(fkey, "f%i", i);
109 |
110 | // Speichere die Stationen-Daten in den Präferenzen
111 | sender.putString(nkey, stationlist[i].name);
112 | sender.putString(ukey, stationlist[i].url);
113 | sender.putUChar(fkey, stationlist[i].enabled);
114 | }
115 | }
116 |
117 | // Verschiebt eine Station innerhalb der Stationenliste von der alten Position zur neuen Position
118 | void reorder(uint8_t oldpos, uint8_t newpos) {
119 | Station temp; // Temporäre Variable zum Speichern der Station während des Verschiebens
120 |
121 | // Überprüfe, ob die alten und neuen Positionen innerhalb der gültigen Grenzen liegen
122 | if ((oldpos < STATIONS) && (newpos < STATIONS)) {
123 | if (oldpos > newpos) {
124 | // Verschieben nach oben in der Liste
125 | memcpy(&temp, &stationlist[oldpos], sizeof(Station)); // Speichere die Station vorübergehend
126 | for (uint8_t i = oldpos; i > newpos; i--) {
127 | memcpy(&stationlist[i], &stationlist[i - 1], sizeof(Station)); // Verschiebe die Stationen nach oben
128 | }
129 | memcpy(&stationlist[newpos], &temp, sizeof(Station)); // Setze die Station an die neue Position
130 | } else {
131 | // Verschieben nach unten in der Liste
132 | memcpy(&temp, &stationlist[oldpos], sizeof(Station)); // Speichere die Station vorübergehend
133 | for (uint8_t i = oldpos; i < newpos; i++) {
134 | memcpy(&stationlist[i], &stationlist[i + 1], sizeof(Station)); // Verschiebe die Stationen nach unten
135 | }
136 | memcpy(&stationlist[newpos], &temp, sizeof(Station)); // Setze die Station an die neue Position
137 | }
138 | }
139 | }
--------------------------------------------------------------------------------
/radiowecker/symbole.h:
--------------------------------------------------------------------------------
1 | const unsigned char symbole PROGMEM [6][308] = {
2 | {// [0] 'wifi-solid_15, 17x17px
3 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x1f, 0xfc, 0x00, 0x70,
4 | 0x07, 0x00, 0x60, 0x03, 0x00, 0x03, 0xe0, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00,
5 | 0x00, 0x01, 0x80, 0x00, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6 | 0x00, 0x00, 0x00
7 | },{ // [1] 'bed-solid_17, 17x17px
8 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xcc,
9 | 0xfe, 0x00, 0xde, 0xff, 0x00, 0xde, 0xff, 0x00, 0xdc, 0xff, 0x80, 0xc0, 0xff, 0x80, 0xff, 0xff,
10 | 0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11 | 0x00, 0x00, 0x00
12 | },{// [2] 'bell_17, 17x17px
13 | 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x03, 0xe0, 0x00, 0x07, 0xf0, 0x00, 0x0c, 0x18, 0x00, 0x08,
14 | 0x08, 0x00, 0x08, 0x08, 0x00, 0x18, 0x0c, 0x00, 0x18, 0x0c, 0x00, 0x18, 0x0c, 0x00, 0x10, 0x04,
15 | 0x00, 0x30, 0x06, 0x00, 0x3f, 0xfe, 0x00, 0x1f, 0xfc, 0x00, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x00,
16 | 0x00, 0x80, 0x00
17 | },{// [3] 'bell-slash_17, 17x17px
18 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x33, 0xe0, 0x00, 0x0f,
19 | 0xf0, 0x00, 0x07, 0xf0, 0x00, 0x03, 0xf0, 0x00, 0x04, 0xf0, 0x00, 0x0e, 0x78, 0x00, 0x0f, 0x38,
20 | 0x00, 0x1f, 0xdc, 0x00, 0x00, 0x04, 0x00, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21 | 0x00, 0x00, 0x00
22 | },{// [4] 'angles_down_50_44', 50x44px
23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
25 | 0x03, 0x80, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x1f, 0xc0,
26 | 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x7f, 0x80, 0x00, 0x00,
27 | 0x3f, 0xc0, 0x00, 0xff, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0xf0,
28 | 0x03, 0xfc, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x0f, 0xf0,
29 | 0x00, 0x00, 0x00, 0x01, 0xfe, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0xc0, 0x00, 0x00,
30 | 0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
31 | 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8,
32 | 0x00, 0x00, 0x00, 0x00, 0x78, 0x03, 0xf0, 0x07, 0x80, 0x00, 0x00, 0xfc, 0x01, 0xe0, 0x0f, 0xc0,
33 | 0x00, 0x00, 0xfe, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00,
34 | 0x7f, 0x80, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0xff, 0x00, 0x00, 0x00, 0x1f, 0xe0,
35 | 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x07, 0xf8,
36 | 0x00, 0x00, 0x00, 0x03, 0xfc, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x1f, 0xe0, 0x00, 0x00,
37 | 0x00, 0x00, 0xff, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
38 | 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc,
39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00,
40 | 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 | 0x00, 0x00, 0x00, 0x00
43 | },{// [5] 'angles_up_50_44', 50x44px
44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0,
46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00,
47 | 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00,
48 | 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0xff,
49 | 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x0f, 0xf0,
50 | 0x00, 0x00, 0x00, 0x07, 0xf8, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0x00,
51 | 0x00, 0x1f, 0xe0, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0xff, 0x00, 0x00, 0x00, 0x7f,
52 | 0x80, 0x00, 0x7f, 0x80, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0xfe, 0x00, 0x00,
53 | 0x1f, 0xc0, 0x00, 0x00, 0xfc, 0x01, 0xe0, 0x0f, 0xc0, 0x00, 0x00, 0x78, 0x03, 0xf0, 0x07, 0x80,
54 | 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00,
55 | 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
56 | 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x1f, 0xe0,
57 | 0x00, 0x00, 0x00, 0x03, 0xfc, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x07, 0xf8, 0x00, 0x00,
58 | 0x00, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x3f,
59 | 0xc0, 0x00, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x7f, 0x80, 0x00, 0x00, 0xff, 0x00, 0x00,
60 | 0x3f, 0xc0, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x0f, 0xc0,
61 | 0x00, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 | 0x00, 0x00, 0x00, 0x00
64 | }
65 | };
--------------------------------------------------------------------------------
/radiowecker/tft_color_setting.h:
--------------------------------------------------------------------------------
1 | // Colors for the Main Screen
2 | #define COLOR_WIFI_RSSI ILI9341_ORANGE
3 | #define COLOR_IP ILI9341_ORANGE
4 | #define COLOR_SLEEP_SYMBOL ILI9341_ORANGE
5 | #define COLOR_ALARM_SYMBOL ILI9341_ORANGE
6 |
7 | #define COLOR_SLIDER ILI9341_ORANGE
8 | #define COLOR_SLIDER_BG ILI9341_BLACK
9 | #define COLOR_SLIDER_BORDER ILI9341_RED
10 |
11 | #define COLOR_BG ILI9341_BLACK
12 | #define COLOR_DATE ILI9341_ORANGE
13 | #define COLOR_TIME ILI9341_ORANGE
14 |
15 | #define COLOR_NEXT_ALARM ILI9341_ORANGE
16 |
17 | #define COLOR_STATION_BOX_BG ILI9341_BLACK
18 | #define COLOR_STATION_BOX_BORDER ILI9341_WHITE
19 |
20 | #define COLOR_STATION_NAME ILI9341_YELLOW
21 | #define COLOR_STATION_TITLE ILI9341_WHITE
22 | // Colors for the Settings Page
23 | #define COLOR_SETTING_BG ILI9341_LIGHTGREY
24 | #define COLOR_SETTING_BORDER ILI9341_BLUE
25 | #define COLOR_SETTING_UP_DOWN ILI9341_BLUE
26 |
27 | #define COLOR_KNOEPFE ILI9341_BLUE
28 | #define COLOR_KNOEPFE_BG ILI9341_LIGHTGREY
29 |
30 | #define COLOR_FAV_BUTTONS ILI9341_BLUE
31 | #define COLOR_FAV_BUTTONS_BG ILI9341_LIGHTGREY
32 | #define COLOR_FAV_BUTTONS_AKTIV ILI9341_ORANGE
33 | // to be done
34 | // maybe later all the color settings from the Webpage adjustable
35 |
--------------------------------------------------------------------------------
/radiowecker/weather.h:
--------------------------------------------------------------------------------
1 | #include "ArduinoJson.h"
2 |
3 | // Funktion zur Abfrage der Wetterdaten
4 | String getWeatherData(float latitude, float longitude, String timezone) {
5 | WiFiClient client;
6 | const char* host = "api.open-meteo.com";
7 | const int httpPort = 80;
8 |
9 | String url = "/v1/forecast?latitude=" + String(latitude, 6) +
10 | "&longitude=" + String(longitude, 6) +
11 | "¤t=temperature_2m,apparent_temperature,weather_code" +
12 | "&daily=temperature_2m_min,temperature_2m_max,weathercode&timezone=" + timezone;
13 |
14 | String fullUrl = "http://" + String(host) + url;
15 | Serial.println("Überprüfe die folgende URL im Browser:");
16 | Serial.println(fullUrl);
17 |
18 | if (!client.connect(host, httpPort)) {
19 | Serial.println("Verbindung zum Server fehlgeschlagen");
20 | return "";
21 | }
22 |
23 | Serial.println("Verbindung zum Server hergestellt.");
24 |
25 | client.print(String("GET ") + url + " HTTP/1.1\r\n" +
26 | "Host: " + host + "\r\n" +
27 | "Connection: close\r\n\r\n");
28 |
29 | Serial.println("HTTP-Request gesendet.");
30 |
31 | String jsonResponse;
32 | bool isBody = false; // Flag, um anzuzeigen, ob wir im Response-Body sind
33 |
34 | // Warte auf die Antwort vom Server
35 | unsigned long timeout = millis() + 5000; // 5 Sekunden Timeout
36 | while (!client.available()) {
37 | if (millis() > timeout) {
38 | Serial.println("Timeout beim Warten auf die Antwort vom Server.");
39 | return "";
40 | }
41 | delay(50);
42 | }
43 |
44 | Serial.println("Antwort vom Server verfügbar.");
45 |
46 | // Header und Body verarbeiten
47 | while (client.available()) {
48 | char c = client.read();
49 |
50 | // Erkenne den Beginn des Response-Bodys (Überspringe die Header)
51 | if (c == '{' || c == '[') {
52 | isBody = true; // Wir befinden uns jetzt im Body
53 | }
54 |
55 | // Füge das Zeichen zur JSON-Antwort hinzu, wenn wir im Body sind
56 | if (isBody) {
57 | jsonResponse += c;
58 | }
59 | }
60 |
61 | if (jsonResponse.length() > 0) {
62 | Serial.println("Wetterdaten empfangen.");
63 | Serial.println(jsonResponse); // Gibt die empfangene JSON-Antwort aus
64 | } else {
65 | Serial.println("Keine Wetterdaten empfangen.");
66 | }
67 |
68 | return jsonResponse; // JSON-Daten als String zurückgeben
69 | }
70 |
71 | // Funktion zur Rückgabe des passenden Icon-Indexes basierend auf dem Wettercode
72 | int getWeatherIcon(int weather_code) {
73 | // Überprüfe die Wettercodes und gebe den entsprechenden Icon-Index zurück
74 | if (weather_code == 0) return 0;
75 | else if (weather_code == 45 || weather_code == 48) return 1;
76 | else if (weather_code == 1) return 2;
77 | else if (weather_code == 2) return 3;
78 | else if (weather_code == 3) return 4;
79 | else if (weather_code == 51 || weather_code == 53 || weather_code == 55 || weather_code == 80) return 5;
80 | else if (weather_code == 56 || weather_code == 57) return 6;
81 | else if (weather_code == 66 || weather_code == 67) return 7;
82 | else if (weather_code == 81 || weather_code == 82 || weather_code == 61 || weather_code == 63 || weather_code == 65) return 8;
83 | else if (weather_code == 95) return 9;
84 | else if (weather_code == 77 || weather_code == 85 || weather_code == 86 || weather_code == 71 || weather_code == 73 || weather_code == 75) return 10;
85 | else if (weather_code == 96 || weather_code == 99) return 11;
86 | else return -1; // Falls der Wettercode ungültig ist, -1 zurückgeben
87 | }
--------------------------------------------------------------------------------
/radiowecker/weather_icons.h:
--------------------------------------------------------------------------------
1 | const unsigned char weather_icons PROGMEM [12][1536] = {
2 | {//[0] '0_clear', 30x25px
3 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
4 | 0x00, 0x03, 0x00, 0x00, 0x00, 0x83, 0x04, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x27, 0x90, 0x00,
5 | 0x00, 0x08, 0x40, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x30, 0x30, 0x00, 0x03, 0xf0, 0x3f, 0x00,
6 | 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x0f, 0xc0, 0x00,
7 | 0x00, 0x63, 0x18, 0x00, 0x00, 0xc3, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
8 | 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9 | 0x00, 0x00, 0x00, 0x00
10 | },{ //[1] '45_48_fog', 30x25px
11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
12 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x00,
13 | 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
14 | 0x07, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80,
15 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17 | 0x00, 0x00, 0x00, 0x00
18 | },{//[2] '1_mostly-clear', 30x25px
19 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
20 | 0x00, 0x40, 0x08, 0x00, 0x00, 0x27, 0x90, 0x00, 0x00, 0x0d, 0xc0, 0x00, 0x00, 0x10, 0x20, 0x00,
21 | 0x00, 0x30, 0x30, 0x00, 0x03, 0xb0, 0x17, 0x00, 0x03, 0xa0, 0x37, 0x00, 0x00, 0x30, 0x78, 0x00,
22 | 0x00, 0x10, 0x86, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x26, 0x00, 0x80, 0x00, 0x48, 0x00, 0x40,
23 | 0x00, 0x88, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x03, 0xff, 0x80,
24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25 | 0x00, 0x00, 0x00, 0x00
26 | },{//[3] '2_partly-cloudy', 30x25px
27 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x11, 0x10, 0x00, 0x00,
28 | 0x0f, 0xe7, 0xc0, 0x00, 0x0c, 0x6c, 0x30, 0x00, 0x08, 0x30, 0x1e, 0x00, 0xf8, 0x30, 0x0f, 0x00,
29 | 0x08, 0xe0, 0x01, 0x80, 0x0f, 0xc0, 0x00, 0xc0, 0x0e, 0x00, 0x00, 0x20, 0x1c, 0x00, 0x00, 0x10,
30 | 0x28, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x30,
31 | 0x04, 0x00, 0x00, 0x20, 0x03, 0x80, 0x01, 0xc0, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 | 0x00, 0x00, 0x00, 0x00
34 | },{//[4] '3_overcast-cloudy', 30x25px
35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xc3, 0x00,
36 | 0x00, 0x0f, 0x80, 0x80, 0x00, 0x38, 0x40, 0x40, 0x00, 0x60, 0x38, 0x20, 0x00, 0x40, 0x1c, 0x20,
37 | 0x03, 0xc0, 0x02, 0x20, 0x07, 0x80, 0x01, 0xc0, 0x08, 0x00, 0x00, 0xc0, 0x10, 0x00, 0x00, 0x60,
38 | 0x10, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x40,
39 | 0x08, 0x00, 0x00, 0xc0, 0x0e, 0x00, 0x03, 0x80, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 | 0x00, 0x00, 0x00, 0x00
42 | },{//[5] '51_53_55_80_drizzle', 30x25px
43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00,
44 | 0x00, 0x30, 0x60, 0x00, 0x00, 0x60, 0x3c, 0x00, 0x00, 0x40, 0x06, 0x00, 0x07, 0xc0, 0x03, 0x00,
45 | 0x0c, 0x00, 0x01, 0x80, 0x18, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x60,
46 | 0x30, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x60, 0x10, 0x22, 0x00, 0x40, 0x08, 0x04, 0x00, 0xc0,
47 | 0x07, 0x80, 0x07, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
48 | 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 | 0x00, 0x00, 0x00, 0x00
50 | },{//[6] '56_57_freezingdrizzle', 30x25px
51 | 0x00, 0x07, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x30, 0x70, 0x00, 0x00, 0x20, 0x38, 0x00,
52 | 0x01, 0xe0, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x80, 0x0c, 0x00, 0x01, 0x80,
53 | 0x0c, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x80, 0x04, 0x02, 0x01, 0x80, 0x02, 0x04, 0x03, 0x00,
54 | 0x03, 0xc8, 0x0e, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00,
55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x7a, 0x40, 0x00, 0x00, 0x7a, 0x20, 0x00,
56 | 0x00, 0x7b, 0x18, 0x00, 0x00, 0x37, 0x0c, 0x00, 0x00, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
57 | 0x00, 0x00, 0x00, 0x00
58 | },{//[7] '66_67_sleet', 30x25px
59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00,
60 | 0x00, 0x30, 0x60, 0x00, 0x00, 0x60, 0x3c, 0x00, 0x00, 0x40, 0x06, 0x00, 0x07, 0xc0, 0x03, 0x00,
61 | 0x0c, 0x00, 0x01, 0x80, 0x18, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x60,
62 | 0x30, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x60, 0x10, 0x01, 0x00, 0x40, 0x08, 0x00, 0x40, 0xc0,
63 | 0x07, 0x80, 0x87, 0x00, 0x01, 0x18, 0x04, 0x00, 0x00, 0x3c, 0x90, 0x00, 0x00, 0x7c, 0x20, 0x00,
64 | 0x00, 0x3c, 0x44, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 | 0x00, 0x00, 0x00, 0x00
66 | },{//[8] '81_82_61_63_65_rain', 30x25px
67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00,
68 | 0x00, 0x30, 0x60, 0x00, 0x00, 0x60, 0x3c, 0x00, 0x00, 0x40, 0x06, 0x00, 0x07, 0xc0, 0x03, 0x00,
69 | 0x0c, 0x00, 0x01, 0x80, 0x18, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x60,
70 | 0x30, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x60, 0x10, 0xcc, 0x80, 0x40, 0x08, 0x66, 0xc0, 0xc0,
71 | 0x07, 0xb6, 0x67, 0x00, 0x01, 0x13, 0x34, 0x00, 0x00, 0x19, 0xb0, 0x00, 0x00, 0x0c, 0x98, 0x00,
72 | 0x00, 0x06, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 | 0x00, 0x00, 0x00, 0x00
74 | },{//[9] '95_lightning', 30x25px
75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00,
76 | 0x00, 0x30, 0x60, 0x00, 0x00, 0x60, 0x3c, 0x00, 0x00, 0x40, 0x06, 0x00, 0x07, 0xc0, 0x03, 0x00,
77 | 0x0c, 0x00, 0x01, 0x80, 0x18, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x60,
78 | 0x30, 0x00, 0x00, 0x60, 0x10, 0x02, 0x00, 0x60, 0x10, 0x07, 0x00, 0x40, 0x08, 0x06, 0x00, 0xc0,
79 | 0x07, 0xee, 0x1f, 0x00, 0x01, 0xcf, 0x9c, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00,
80 | 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 | 0x00, 0x00, 0x00, 0x00
82 | },{//[10] '77_85_86_71_73_75_snow', 30x25px
83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00,
84 | 0x00, 0x30, 0x60, 0x00, 0x00, 0x60, 0x3c, 0x00, 0x00, 0x40, 0x06, 0x00, 0x07, 0xc0, 0x03, 0x00,
85 | 0x0c, 0x00, 0x01, 0x80, 0x18, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x60, 0x30, 0x00, 0x40, 0x60,
86 | 0x30, 0x00, 0xf0, 0x60, 0x10, 0x19, 0xf0, 0x60, 0x10, 0x3d, 0xf0, 0x40, 0x08, 0x7c, 0xf0, 0xc0,
87 | 0x07, 0xbc, 0x67, 0x00, 0x01, 0x3d, 0xc4, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00,
88 | 0x00, 0x03, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 | 0x00, 0x00, 0x00, 0x00
90 | },{//[11] '96_99_thunderstorm', 30x25px
91 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00,
92 | 0x00, 0x36, 0x60, 0x00, 0x00, 0x6e, 0x3c, 0x00, 0x00, 0x4e, 0x06, 0x00, 0x07, 0xcc, 0x03, 0x00,
93 | 0x0c, 0x0f, 0x81, 0x80, 0x18, 0x1f, 0x00, 0x40, 0x10, 0x03, 0x00, 0x60, 0x30, 0x02, 0x00, 0x60,
94 | 0x30, 0x06, 0x00, 0x60, 0x10, 0x00, 0x00, 0x60, 0x10, 0xcc, 0x80, 0x40, 0x08, 0x66, 0xc0, 0xc0,
95 | 0x07, 0xb6, 0x67, 0x00, 0x01, 0x13, 0x34, 0x00, 0x00, 0x19, 0xb0, 0x00, 0x00, 0x0c, 0x98, 0x00,
96 | 0x00, 0x06, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 | 0x00, 0x00, 0x00, 0x00
98 | }
99 | };
--------------------------------------------------------------------------------
/radiowecker/webserver.ino:
--------------------------------------------------------------------------------
1 | //home page and templatefor options
2 | #include "index.h"
3 | #include "ArduinoJson.h"
4 |
5 | WebServer server(80);
6 |
7 | // Konfiguriert den Webserver und richtet die Routen für verschiedene HTTP-Anfragen ein
8 | void setup_webserver() {
9 | // Optional: Aktiviert CORS (Cross-Origin Resource Sharing) für den Server
10 | // server.enableCORS();
11 |
12 | // Definiert die Route für die Root-URL, die auf die Funktion `handleRoot` verweist
13 | server.on("/", handleRoot);
14 |
15 | // Definiert die Routen für verschiedene AJAX-Befehle und verknüpft sie mit den entsprechenden Funktionen
16 | server.on("/cmd/stations", sendStations); // Ruft die Liste der verfügbaren Stationen ab
17 | server.on("/cmd/restorestations", restoreStations); // Stellt die gespeicherten Stationen wieder her
18 | server.on("/cmd/restart", restart); // Startet das System neu
19 | server.on("/cmd/setaccess", setAccessData); // Setzt die Zugangsdaten
20 | server.on("/cmd/getaccess", getAccessData); // Ruft die Zugangsdaten ab
21 | server.on("/cmd/getalarms", getAlarms); // Ruft die Alarmkonfiguration ab
22 | server.on("/cmd/setalarms", setAlarms); // Setzt die Alarmkonfiguration
23 | server.on("/cmd/getstation", getStationData); // Ruft die Daten der aktuellen Station ab
24 | server.on("/cmd/setstation", setStationData); // Setzt die Daten der aktuellen Station
25 | server.on("/cmd/teststation", testStation); // Testet die Verbindung zur aktuellen Station
26 | server.on("/cmd/endtest", endTest); // Beendet den Testmodus
27 |
28 | // Player-Tab: Definiert Routen für Steuerbefehle des Players
29 | server.on("/cmd/startPlay", startPlay); // Startet die Wiedergabe
30 | server.on("/cmd/stopPlay", stopPlay); // Stoppt die Wiedergabe
31 | server.on("/cmd/GainSlider", GainSlider); // Setzt den Wert des Lautstärkereglers
32 | server.on("/cmd/btnAlarm", btnAlarm); // Schaltet den Alarm ein oder aus
33 | server.on("/cmd/startSleep", startSleep); // Startet den Schlafmodus
34 | server.on("/cmd/beforeStation", beforeStation); // Wechselt zur vorherigen Station
35 | server.on("/cmd/nextStation", nextStation); // Wechselt zur nächsten Station
36 | server.on("/cmd/getCurrentStatus", getCurrentStatus); // Ruft den aktuellen Status ab
37 |
38 | // Info-Tab: Definiert die Route für das Abrufen von Systeminformationen
39 | server.on("/cmd/getInfo", getInfo); // Ruft allgemeine Systeminformationen ab
40 |
41 | // Startet den Webserver
42 | server.begin();
43 | }
44 |
45 | // Wird aus der Hauptschleife aufgerufen, um eingehende HTTP-Anfragen zu verarbeiten
46 | void webserver_loop() {
47 | server.handleClient(); // Bearbeitet alle an den Webserver gesendeten Anfragen
48 | }
49 |
50 | // Bearbeitet Anfragen an die Wurzel-URL ("/") des Webservers
51 | void handleRoot() {
52 | if (connected) {
53 | // Wenn verbunden, sende die Hauptseite
54 | server.send(200, "text/html", MAIN_page);
55 | } else {
56 | // Wenn nicht verbunden, sende die Konfigurationsseite
57 | // Parameter werden als Argumente im HTML-Request übergeben
58 | Serial.println("Got config:");
59 | uint8_t a = server.args(); // Anzahl der Argumente im Request
60 | Serial.print(a);
61 | Serial.println(" Arguments");
62 | for (uint8_t i = 0; i < a; i++) Serial.println(server.arg(i)); // Ausgabe aller Argumente
63 |
64 | // Speichern der SSID in den Einstellungen, falls vorhanden
65 | if (server.hasArg("conf_ssid")) {
66 | pref.putString("ssid", server.arg("conf_ssid"));
67 | Serial.println(server.arg("conf_ssid"));
68 | }
69 |
70 | // Speichern des PKEY in den Einstellungen, falls vorhanden
71 | if (server.hasArg("conf_pkey")) {
72 | pref.putString("pkey", server.arg("conf_pkey"));
73 | Serial.println(server.arg("conf_pkey"));
74 | }
75 |
76 | // Falls das Reset-Argument vorhanden ist, starte das System neu
77 | if (server.hasArg("reset")) {
78 | Serial.println("Restart!");
79 | ESP.restart();
80 | }
81 |
82 | // Sende die Konfigurationsseite an den Client
83 | server.send(200, "text/html", CONFIG_page);
84 | }
85 | }
86 |
87 | // Bearbeitet AJAX-Befehle für "/cmd/stations"
88 | // Sendet eine Liste der verfügbaren Stationen als HTML-Optionen
89 | void sendStations() {
90 | char* s; // Variable für das Symbol vor dem Stationsnamen
91 | char* sel; // Variable für das 'selected'-Attribut der aktuellen Station
92 | char buf[100]; // Buffer für die HTML-Ausgabe
93 |
94 | // Bereite die HTML-Antwort vor
95 | server.setContentLength(CONTENT_LENGTH_UNKNOWN);
96 | server.send(200, "text/html", "");
97 |
98 | // Sende alle Stationen als Optionsliste
99 | for (uint8_t i = 0; i < STATIONS; i++) {
100 | // Füge das 'selected'-Attribut hinzu, wenn die Station aktuell ist
101 | sel = "";
102 | if (i == actStation) sel = "selected";
103 |
104 | // Setze ein schwarzes Punkt-Symbol vor dem Stationsnamen, wenn aktiviert
105 | s = " ";
106 | if (stationlist[i].enabled) s = "●";
107 |
108 | // Erstelle den Eintrag für die Option mit der Vorlage
109 | sprintf(buf, OPTION_entry, i, sel, s, stationlist[i].name);
110 | server.sendContent(buf); // Sende den Inhalt der Option
111 | }
112 | }
113 |
114 | // Bearbeitet AJAX-Befehle für "/cmd/setaccess"
115 | // Speichert Zugangsdaten in den Einstellungen
116 | void setAccessData() {
117 | // Der Befehl erwartet drei Argumente
118 | // Die Zugangsdaten werden in den Einstellungen gespeichert
119 |
120 | // Speichere die SSID, wenn vorhanden
121 | if (server.hasArg("ssid")) {
122 | ssid = server.arg("ssid");
123 | pref.putString("ssid", ssid);
124 | }
125 |
126 | // Speichere den Pre-Shared Key (PKEY), wenn vorhanden
127 | if (server.hasArg("pkey")) {
128 | pkey = server.arg("pkey");
129 | pref.putString("pkey", pkey);
130 | }
131 |
132 | // Speichere die NTP-Server-Adresse, wenn vorhanden
133 | if (server.hasArg("ntp")) {
134 | ntp = server.arg("ntp");
135 | pref.putString("ntp", ntp);
136 | }
137 |
138 | // Speichere die Timezone, wenn vorhanden
139 | if (server.hasArg("TIME_ZONE_IANA")) {
140 | TIME_ZONE_IANA = server.arg("TIME_ZONE_IANA");
141 | pref.putString("TIME_ZONE_IANA", TIME_ZONE_IANA);
142 | }
143 |
144 | // Speichere die Latitude, wenn sie vorhanden ist
145 | if (server.hasArg("LATITUDE")) {
146 | LATITUDE = server.arg("LATITUDE").toFloat();
147 | pref.putFloat("LATITUDE", LATITUDE);
148 | }
149 |
150 | // Speichere die Longitude, wenn sie vorhanden ist
151 | if (server.hasArg("LONGITUDE")) {
152 | LONGITUDE = server.arg("LONGITUDE").toFloat();
153 | pref.putFloat("LONGITUDE", LONGITUDE);
154 | }
155 |
156 | // Antworte mit "OK"
157 | server.send(200, "text/plain", "OK");
158 | }
159 |
160 | // Bearbeitet AJAX-Befehle für "/cmd/getaccess"
161 | // Sendet Zugangsdaten als Textnachricht
162 | void getAccessData() {
163 | // Erstelle eine Nachricht mit den Zugangsdaten, getrennt durch Zeilenumbrüche
164 | String msg = String(ssid) + "\n" + String(pkey) + "\n" + String(ntp) + "\n" + String(TIME_ZONE_IANA) + "\n" + String(LATITUDE, 6) + "\n" + String(LONGITUDE, 6);
165 |
166 | // Antworte mit den Zugangsdaten
167 | server.send(200, "text/plain", msg);
168 | }
169 |
170 |
171 | // Bearbeitet AJAX-Befehle für "/cmd/getalarms"
172 | // Sendet die Alarmzeiten und die Wochentage für zwei Alarme als Textnachricht
173 | void getAlarms() {
174 | char buf[45];
175 | uint8_t h, m, mask, i;
176 |
177 | // Konvertiere die Alarmzeiten in Stunden und Minuten und formatiere sie
178 | h = alarm1 / 60;
179 | m = alarm1 % 60;
180 | sprintf(buf, "%02i:%02i\n", h, m);
181 |
182 | h = alarm2 / 60;
183 | m = alarm2 % 60;
184 | sprintf(&buf[20], "%02i:%02i\n", h, m);
185 |
186 | // Füge die Wochentage für beide Alarme hinzu
187 | for (i = 0; i < 7; i++) {
188 | mask = 1 << i;
189 | buf[6 + i * 2] = ((alarmday1 & mask) != 0) ? '1' : '0';
190 | buf[26 + i * 2] = ((alarmday2 & mask) != 0) ? '1' : '0';
191 | buf[7 + i * 2] = '\n';
192 | buf[27 + i * 2] = '\n';
193 | }
194 |
195 | buf[40] = 0; // Null-Terminierung des Strings
196 |
197 | // Antwort mit den Alarmdaten als Textnachricht
198 | server.send(200, "text/plain", String(buf));
199 | }
200 |
201 | // Berechnet die Gesamtanzahl der Minuten aus einer Stunden- und Minutenangabe im Format "HH:MM"
202 | // Gibt die Minuten als uint16_t zurück
203 | uint16_t stringToMinutes(String val) {
204 | uint8_t h, m;
205 | // Extrahiere die Stunden aus den ersten zwei Zeichen des Strings und konvertiere sie in eine Ganzzahl
206 | h = val.substring(0, 2).toInt();
207 | // Extrahiere die Minuten aus den Zeichen nach dem Doppelpunkt und konvertiere sie in eine Ganzzahl
208 | m = val.substring(3).toInt();
209 | // Berechne die Gesamtanzahl der Minuten und gebe sie zurück
210 | return h * 60 + m;
211 | }
212 |
213 | // Verarbeitet den AJAX-Befehl /cmd/setalarms zum Setzen der Alarmzeiten
214 | void setAlarms() {
215 | char txt[10];
216 | uint8_t b;
217 |
218 | // Debug-Ausgabe: Beginn des Setzens der Alarme
219 | Serial.println("Set alarms start");
220 |
221 | // Überprüfe, ob der Parameter "al0" vorhanden ist und setze alarm1
222 | if (server.hasArg("al0")) {
223 | alarm1 = stringToMinutes(server.arg("al0")); // Konvertiere die Zeit in Minuten
224 | Serial.print(server.arg("al0")); // Debug-Ausgabe der übergebenen Zeit
225 | Serial.printf(" = %i\n", alarm1); // Debug-Ausgabe des berechneten Alarmwerts
226 | pref.putUInt("alarm1", alarm1); // Speichere den Alarmwert in den Einstellungen
227 | }
228 |
229 | // Überprüfe, ob der Parameter "al8" vorhanden ist und setze alarm2
230 | if (server.hasArg("al8")) {
231 | alarm2 = stringToMinutes(server.arg("al8")); // Konvertiere die Zeit in Minuten
232 | Serial.print(server.arg("al8")); // Debug-Ausgabe der übergebenen Zeit
233 | Serial.printf(" = %i\n", alarm2); // Debug-Ausgabe des berechneten Alarmwerts
234 | pref.putUInt("alarm2", alarm2); // Speichere den Alarmwert in den Einstellungen
235 | }
236 |
237 | // Initialisiere die Wochentags-Flags für beide Alarme
238 | alarmday1 = 0;
239 | alarmday2 = 0;
240 |
241 | // Überprüfe die Wochentags-Parameter für alarmday1 und alarmday2
242 | for (uint8_t i = 0; i < 7; i++) {
243 | // Erstelle den Parameter-Namen für alarmday1
244 | sprintf(txt, "al%i", i + 1);
245 | if (server.hasArg(txt)) {
246 | if (server.arg(txt) == "1") alarmday1 = alarmday1 | (1 << i); // Setze das entsprechende Bit für alarmday1
247 | }
248 |
249 | // Erstelle den Parameter-Namen für alarmday2
250 | sprintf(txt, "al%i", i + 9);
251 | if (server.hasArg(txt)) {
252 | if (server.arg(txt) == "1") alarmday2 = alarmday2 | (1 << i); // Setze das entsprechende Bit für alarmday2
253 | }
254 | }
255 |
256 | // Speichere die Wochentags-Flags in den Einstellungen
257 | pref.putUShort("alarmday1", alarmday1);
258 | pref.putUShort("alarmday2", alarmday2);
259 |
260 | // Debug-Ausgabe der Wochentags-Flags
261 | Serial.printf("days1 %x days2 %x\n", alarmday1, alarmday2);
262 |
263 | // Finde den nächsten Alarm und zeige ihn an, falls der Clock-Modus aktiv ist
264 | findNextAlarm();
265 | if (clockmode) showNextAlarm();
266 |
267 | // Sende eine Bestätigung als Antwort
268 | server.send(200, "text/plain", "OK");
269 | }
270 |
271 | // Verarbeitet den AJAX-Befehl /cmd/getstation, um Daten einer spezifischen Station abzurufen
272 | void getStationData() {
273 | // Überprüft, ob der Parameter "stationid" vorhanden ist
274 | if (server.hasArg("stationid")) {
275 | uint8_t i = server.arg("stationid").toInt(); // Liest die Station-ID aus der Anfrage
276 |
277 | // Wenn die Station-ID außerhalb des gültigen Bereichs liegt, setze sie auf die letzte Station
278 | if (i >= STATIONS) i = STATIONS - 1;
279 |
280 | // Erstelle eine Nachricht mit dem Namen, der URL und dem Aktivierungsstatus der Station, getrennt durch neue Zeilen
281 | String msg = String(stationlist[i].name) + "\n" + String(stationlist[i].url) + "\n" + String(stationlist[i].enabled) + "\n" + String(i + 1);
282 |
283 | // Sende die Nachricht als Antwort
284 | server.send(200, "text/plain", msg);
285 | } else {
286 | // Wenn der Parameter fehlt oder ungültig ist, sende eine Fehlermeldung
287 | server.send(200, "text/plain", "Invalid command");
288 | }
289 | }
290 |
291 | // Verarbeitet den AJAX-Befehl /cmd/setstation, um Daten einer bestimmten Station zu setzen
292 | void setStationData() {
293 | // Erwartet eine gültige Station-ID als Argument
294 | // Daten werden ebenfalls als Argumente übermittelt:
295 | // name = Name der Station
296 | // url = URL der Station
297 | // enabled = Aktivierungsstatus
298 | // position = neue Position in der Liste
299 | char key[5];
300 |
301 | // Überprüft, ob die Station-ID vorhanden ist und innerhalb des gültigen Bereichs liegt
302 | if ((server.hasArg("stationid")) && (server.arg("stationid").toInt() < STATIONS)) {
303 | uint8_t i = server.arg("stationid").toInt();
304 |
305 | // Speichert die Werte aus den Argumenten in der Stationenliste
306 | if (server.hasArg("name")) {
307 | sprintf(key, "n%i", i);
308 | sender.putString(key, server.arg("name"));
309 | strlcpy(stationlist[i].name, server.arg("name").c_str(), 32);
310 | }
311 | if (server.hasArg("url")) {
312 | sprintf(key, "u%i", i);
313 | sender.putString(key, server.arg("url"));
314 | strlcpy(stationlist[i].url, server.arg("url").c_str(), 150);
315 | }
316 | if (server.hasArg("enabled")) {
317 | sprintf(key, "f%i", i);
318 | sender.putUChar(key, server.arg("enabled").toInt());
319 | stationlist[i].enabled = server.arg("enabled").toInt();
320 | }
321 | if (server.hasArg("position")) {
322 | int16_t newpos = server.arg("position").toInt();
323 | newpos--;
324 | Serial.printf("Move %i to position %i\n", i + 1, newpos + 1);
325 | if ((i != newpos) && (newpos >= 0) && (newpos < STATIONS)) {
326 | reorder(i, newpos); // Ändert die Position der Station in der Liste
327 | saveList(); // Speichert die aktualisierte Liste
328 | }
329 | }
330 |
331 | // Sendet eine Bestätigung der erfolgreichen Verarbeitung zurück
332 | server.send(200, "text/plain", "OK");
333 | } else {
334 | // Sendet eine Fehlermeldung zurück, wenn die Station-ID ungültig ist
335 | server.send(200, "text/plain", "Invalid station ID");
336 | }
337 | }
338 |
339 | // Verarbeitet den AJAX-Befehl /cmd/teststation, um eine URL zu testen
340 | void testStation() {
341 | // Erwartet ein Argument mit der zu testenden URL
342 | bool ret = true;
343 |
344 | // Überprüft, ob das URL-Argument vorhanden ist
345 | if (server.hasArg("url")) {
346 | // Versucht, die URL zu starten und speichert das Ergebnis
347 | ret = startUrl(server.arg("url"));
348 | }
349 |
350 | // Sendet eine Bestätigung bei Erfolg oder eine Fehlermeldung bei Misserfolg
351 | if (ret) {
352 | // Bei Erfolg: Antwort "OK" senden
353 | server.send(200, "text/plain", "OK");
354 | } else {
355 | // Bei Misserfolg: Wechselt zurück zur aktuellen Station und sendet "ERROR"
356 | startUrl(String(stationlist[actStation].url));
357 | server.send(300, "text/plain", "ERROR");
358 | }
359 | }
360 |
361 | // Verarbeitet den AJAX-Befehl /cmd/endtest, um den Test zu beenden
362 | void endTest() {
363 | // Wechselt zurück zur aktuellen Station, um den Test zu beenden
364 | startUrl(String(stationlist[actStation].url));
365 |
366 | // Sendet eine Bestätigung, dass der Test beendet wurde
367 | server.send(200, "text/plain", "OK");
368 | }
369 |
370 | // Verarbeitet den AJAX-Befehl /cmd/restorestations, um die Stationen wiederherzustellen
371 | void restoreStations() {
372 | restore(); // Stellt die Stationen aus dem Speicher wieder her
373 |
374 | // Sendet eine Bestätigung, dass die Wiederherstellung erfolgreich war
375 | server.send(200, "text/plain", "OK");
376 | }
377 |
378 | // Verarbeitet den AJAX-Befehl /cmd/restart, um das Gerät neu zu starten
379 | void restart() {
380 | ESP.restart(); // Startet das Gerät neu
381 | }
382 |
383 | // Player Tab ######################
384 | // Verarbeitet den AJAX-Befehl /cmd/startPlay, um das Radio zu starten
385 | void startPlay() {
386 | toggleRadio(false); // Schaltet das Radio ein
387 | server.send(200, "text/plain", "OK"); // Antwortet mit "OK"
388 | }
389 |
390 | // Verarbeitet den AJAX-Befehl /cmd/stopPlay, um das Radio zu stoppen
391 | void stopPlay() {
392 | toggleRadio(true); // Schaltet das Radio aus
393 | server.send(200, "text/plain", "OK"); // Antwortet mit "OK"
394 | }
395 |
396 | // Verarbeitet den AJAX-Befehl /cmd/GainSlider, um den Lautstärkewert zu setzen
397 | void GainSlider() {
398 | // Überprüft, ob der Parameter "GainValue" in der Anfrage vorhanden ist
399 | if (server.hasArg("GainValue")) {
400 | // Konvertiert den Wert des Parameters in einen float
401 | float floatWert = atof(server.arg("GainValue").c_str());
402 | // Setzt den Lautstärkewert
403 | setGainValue(floatWert, "WEBSITE");
404 | // Antwortet mit "OK"
405 | server.send(200, "text/plain", "OK");
406 |
407 | // Gibt den Wert für Debugging-Zwecke aus
408 | Serial.print("GainValue: ");
409 | Serial.println(floatWert);
410 | } else {
411 | // Antwortet mit einem Fehlercode, wenn der Parameter fehlt
412 | server.send(400, "text/plain", "ERROR");
413 | }
414 | }
415 |
416 | // Verarbeitet den AJAX-Befehl /cmd/btnAlarm, um den Alarm ein- oder auszuschalten
417 | void btnAlarm() {
418 | // Schaltet den Alarm um
419 | toggleAlarm();
420 | // Antwortet mit "OK"
421 | server.send(200, "text/plain", "OK");
422 | }
423 |
424 | // Verarbeitet den AJAX-Befehl /cmd/startSleep, um die Schlummerfunktion zu starten
425 | void startSleep() {
426 | // Startet die Schlummerfunktion
427 | startSnooze();
428 | // Antwortet mit "OK"
429 | server.send(200, "text/plain", "OK");
430 | }
431 |
432 | // Verarbeitet den AJAX-Befehl /cmd/beforeStation, um zur vorherigen "aktiven" Station zu wechseln
433 | void beforeStation() {
434 | // Zähle die Anzahl der Versuche, um Endlosschleifen zu vermeiden
435 | int attempts = 0;
436 | // Schleife, um die vorherige aktive Station zu finden
437 | do {
438 | // Verringert die aktuelle Station um eins
439 | curStation -= 1;
440 | // Wenn die aktuelle Station kleiner als 0 wird, setze sie auf die letzte Station
441 | if (curStation < 0) {
442 | curStation = STATIONS - 1;
443 | }
444 | // Erhöhe den Versuchszähler
445 | attempts++;
446 | // Wenn alle Stationen durchlaufen wurden und keine aktive gefunden wurde
447 | if (attempts >= STATIONS) {
448 | // Optional: Setze auf die letzte Station zurück (auch wenn sie deaktiviert ist)
449 | curStation = STATIONS - 1;
450 | // Debug-Ausgabe, dass keine aktive Station gefunden wurde
451 | Serial.println("Keine aktive Station gefunden.");
452 | // Antwortet mit einer Fehlermeldung
453 | server.send(200, "text/plain", "Keine aktive Station verfügbar.");
454 | return; // Beende die Funktion
455 | }
456 | } while (!stationlist[curStation].enabled);
457 | // Ändert die Station und zeigt die neue Station an
458 | changeStation();
459 | // Debug-Ausgabe der aktuellen Station
460 | Serial.println(curStation);
461 | // Antwortet mit "OK"
462 | server.send(200, "text/plain", "OK");
463 | }
464 |
465 | // Verarbeitet den AJAX-Befehl /cmd/nextStation, um zur nächsten "aktiven" Station zu wechseln
466 | void nextStation() {
467 | // Zähle die Anzahl der Versuche, um Endlosschleifen zu vermeiden
468 | int attempts = 0;
469 | // Schleife, um die nächste aktive Station zu finden
470 | do {
471 | // Erhöht die aktuelle Station um eins
472 | curStation += 1;
473 | // Wenn die aktuelle Station den Maximalwert überschreitet, setze sie auf die erste Station
474 | if (curStation >= STATIONS) {
475 | curStation = 0;
476 | }
477 | // Erhöhe den Versuchszähler
478 | attempts++;
479 | // Wenn alle Stationen durchlaufen wurden und keine aktive gefunden wurde
480 | if (attempts >= STATIONS) {
481 | // Optional: Setze auf die erste Station zurück (auch wenn sie deaktiviert ist)
482 | curStation = 0;
483 | // Debug-Ausgabe, dass keine aktive Station gefunden wurde
484 | Serial.println("Keine aktive Station gefunden.");
485 | // Antwortet mit einer Fehlermeldung
486 | server.send(200, "text/plain", "Keine aktive Station verfügbar.");
487 | return; // Beende die Funktion
488 | }
489 | } while (!stationlist[curStation].enabled);
490 | // Ändert die Station und zeigt die neue Station an
491 | changeStation();
492 | // Debug-Ausgabe der aktuellen Station
493 | Serial.println(curStation);
494 | // Antwortet mit "OK"
495 | server.send(200, "text/plain", "OK");
496 | }
497 |
498 | // AJAX-Befehl /cmd/getCurrentStatus
499 | // Diese Funktion wird aufgerufen, um den aktuellen Status des Systems zu ermitteln und als JSON-Daten zurückzugeben.
500 | // Die JSON-Antwort enthält Informationen über:
501 | // - Die Lautstärke des Radios
502 | // - Den Alarmstatus und die Alarmzeit
503 | // - Den aktuellen Radiosender und Titel (wenn das Radio aktiv ist)
504 | // - Datum und Uhrzeit
505 | // - Die WLAN-Signalstärke
506 | // - Den Status des Sleeptimers (ob aktiv oder nicht)
507 | void getCurrentStatus() {
508 | // Variablen zur Zeitberechnung
509 | uint8_t h, m;
510 | char txt[50] = "";
511 |
512 | // Erstellen eines JSON-Dokuments für die Antwort
513 | StaticJsonDocument<200> jsonDoc;
514 |
515 | // Lautstärke des Radios
516 | jsonDoc["gain"] = curGain;
517 |
518 | // Status des Alarms
519 | if (alarmday < 8) { // Alarm ist aktiv
520 | h = alarmtime / 60;
521 | m = alarmtime % 60;
522 | sprintf(txt, "%s %02i:%02i", days_short[alarmday], h, m);
523 | jsonDoc["alarm"] = "1";
524 | } else { // Alarm ist ausgeschaltet
525 | sprintf(txt, "AUS");
526 | jsonDoc["alarm"] = "0";
527 | }
528 | jsonDoc["alarmtime"] = txt;
529 |
530 | // Radio-Status
531 | if (radio) {
532 | jsonDoc["radioStation"] = stationlist[actStation].name;
533 | jsonDoc["radioTitle"] = title;
534 | } else {
535 | jsonDoc["radioStation"] = "";
536 | jsonDoc["radioTitle"] = "";
537 | }
538 |
539 | // Aktuelles Datum und Uhrzeit
540 | char tim[40];
541 | if (getLocalTime(&ti)) {
542 | sprintf(tim, "%s %i. %s %i", days[ti.tm_wday], ti.tm_mday, months[ti.tm_mon], ti.tm_year + 1900);
543 | jsonDoc["Date"] = tim;
544 | strftime(tim, sizeof(tim), "%H:%M", &ti);
545 | jsonDoc["Time"] = tim;
546 | }
547 |
548 | // WLAN-Signalstärke
549 | jsonDoc["Rssi"] = WiFi.RSSI();
550 |
551 | // Status des Sleeptimers
552 | jsonDoc["Sleep"] = snoozeTimeEnd != 0 ? 1 : 0;
553 |
554 | // Konvertieren des JSON-Dokuments in einen String
555 | String response;
556 | serializeJson(jsonDoc, response);
557 |
558 | // Senden der JSON-Antwort an den Client
559 | server.send(200, "application/json", response);
560 | }
561 |
562 | //################ Info Tab
563 | // AJAX-Befehl /cmd/getInfo
564 | // Diese Funktion wird aufgerufen, um detaillierte Systeminformationen als JSON-Daten zurückzugeben.
565 | // Die JSON-Antwort enthält:
566 | // - Die installierte Version des Radios
567 | // - Informationen zum aktuellen ESP8266/ESP32-Chip, einschließlich:
568 | // - Heap-Größe und freier Heap-Speicher
569 | // - Sketch-Größe und freier Sketch-Speicher
570 | // - Chip-Modell
571 | void getInfo() {
572 | // Erstellen eines JSON-Dokuments für die Antwort
573 | StaticJsonDocument<300> jsonDoc;
574 |
575 | // Installierte Radio-Version
576 | jsonDoc["radioversion"] = RADIOVERSION;
577 |
578 | // Erstellen eines Unterobjekts für ESP-Board-Informationen
579 | JsonObject ESP_INFO = jsonDoc.createNestedObject("ESP_INFO");
580 |
581 | // HEAP-Informationen
582 | JsonObject HEAP = ESP_INFO.createNestedObject("HEAP");
583 | HEAP["getHeapSize"] = ESP.getHeapSize(); // Gesamte Heap-Größe
584 | HEAP["getFreeHeap"] = ESP.getFreeHeap(); // Freier Heap-Speicher
585 |
586 | // SKETCH-Informationen
587 | JsonObject SKETCH = ESP_INFO.createNestedObject("SKETCH");
588 | SKETCH["getSketchSize"] = ESP.getSketchSize(); // Gesamte Sketch-Größe
589 | SKETCH["getFreeSketchSpace"] = ESP.getFreeSketchSpace(); // Freier Sketch-Speicher
590 |
591 | // CHIP-Informationen
592 | JsonObject CHIP = ESP_INFO.createNestedObject("CHIP");
593 | CHIP["getChipModel"] = ESP.getChipModel(); // Modell des verwendeten Chips
594 |
595 | // Konvertieren des JSON-Dokuments in einen String
596 | String response;
597 | serializeJson(jsonDoc, response);
598 |
599 | // Senden der JSON-Antwort an den Client
600 | server.send(200, "application/json", response);
601 | }
--------------------------------------------------------------------------------
/radiowecker/wlan.ino:
--------------------------------------------------------------------------------
1 | // Initialisiert das WiFi-Modul mit den angegebenen SSID und Passkey
2 | boolean initWiFi(String ssid, String pkey) {
3 | boolean connected = false; // Variable zur Verfolgung des Verbindungsstatus
4 |
5 | // Zuerst trennen alle bestehenden Verbindungen
6 | Serial.print(TXT_DISCONNECT); // Debug-Ausgabe, dass die Verbindung getrennt wird
7 | WiFi.disconnect(); // Trennt die aktuelle WiFi-Verbindung
8 | Serial.print(TXT_SOFT_AP_DISCONNECT); // Debug-Ausgabe, dass der Soft-AP-Modus getrennt wird
9 | WiFi.softAPdisconnect(true); // Trennt den Soft-AP-Modus, falls aktiv
10 |
11 | // Setzt den WiFi-Modus auf Station (Client) und konfiguriert den Hostnamen
12 | Serial.print(TXT_SET_WLAN_MODE); // Debug-Ausgabe, dass der WLAN-Modus gesetzt wird
13 | WiFi.setHostname(NETWORK_NAME); // Setzt den Hostnamen für das Gerät
14 | WiFi.mode(WIFI_STA); // Setzt den WiFi-Modus auf Station (Client)
15 |
16 | Serial.print(TXT_CONNECTING_TO); // Debug-Ausgabe, dass eine Verbindung zu einer SSID aufgebaut wird
17 | Serial.print(ssid); // Gibt die SSID auf der Konsole aus
18 | Serial.println(TXT_CONNECTING_ESTABLISH); // Debug-Ausgabe, dass die Verbindung aufgebaut wird
19 | Serial.println(pkey); // Gibt den Passkey auf der Konsole aus (Hinweis: Passkey nicht sicher in der Konsole ausgeben)
20 |
21 | // Wenn eine SSID angegeben wurde, versuche eine Verbindung herzustellen
22 | if (ssid != "") {
23 | WiFi.begin(ssid.c_str(), pkey.c_str()); // Beginnt den Verbindungsversuch zur angegebenen SSID mit dem Passkey
24 | uint8_t cnt = 0; // Zähler für die Anzahl der Versuche
25 | // Versuche bis zu 20 Mal, sich zu verbinden
26 | while ((WiFi.status() != WL_CONNECTED) && (cnt < 20)) {
27 | delay(500); // Warte 500 Millisekunden
28 | Serial.print("."); // Zeigt Fortschritt auf der Konsole an
29 | cnt++; // Erhöhe den Zähler
30 | }
31 | Serial.println(); // Neue Zeile für saubere Konsolenausgabe
32 | // Wenn die Verbindung erfolgreich hergestellt wurde
33 | if (WiFi.status() == WL_CONNECTED) {
34 | Serial.print(TXT_IP_ADDRESS); // Debug-Ausgabe der IP-Adresse
35 | Serial.println(WiFi.localIP()); // Gibt die lokale IP-Adresse auf der Konsole aus
36 | connected = true; // Setzt den Verbindungsstatus auf true
37 | }
38 | }
39 |
40 | // Wenn keine Verbindung hergestellt werden konnte
41 | if (!connected) {
42 | Serial.println(TXT_NO_CONNECTION); // Debug-Ausgabe, dass keine Verbindung hergestellt werden konnte
43 | WiFi.mode(WIFI_AP); // Setzt den WiFi-Modus auf Access Point (AP)
44 | WiFi.softAP(AP_NAME, "", 1); // Startet den Access Point mit dem angegebenen Namen und ohne Passwort
45 | }
46 |
47 | return connected; // Gibt den Verbindungsstatus zurück (true, wenn verbunden, sonst false)
48 | }
--------------------------------------------------------------------------------
/screenshot/alarm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/alarm.jpg
--------------------------------------------------------------------------------
/screenshot/info_tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/info_tab.png
--------------------------------------------------------------------------------
/screenshot/radio.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/radio.jpg
--------------------------------------------------------------------------------
/screenshot/result.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/result.jpg
--------------------------------------------------------------------------------
/screenshot/settings.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/settings.jpg
--------------------------------------------------------------------------------
/screenshot/settings_color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/settings_color.png
--------------------------------------------------------------------------------
/screenshot/website.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/website.png
--------------------------------------------------------------------------------
/screenshot/website_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/website_2.png
--------------------------------------------------------------------------------
/screenshot/website_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/website_3.png
--------------------------------------------------------------------------------
/screenshot/website_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/website_4.png
--------------------------------------------------------------------------------
/screenshot/wetter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beabel/radiowecker/f4736b45edb06e1a302fbad1fbc28fd7676b7e6a/screenshot/wetter.jpg
--------------------------------------------------------------------------------