Seeed hat mir für diesen Beitrag ein reTerminal E1004 zur Verfügung gestellt – vielen Dank an Mason und das Team. Meine Einschätzung bleibt davon unberührt: Ich zeige euch ehrlich, was gut funktioniert, welche Herstellerangaben kritisch zu betrachten sind und in welche Falle ich selbst tagelang getappt bin, bevor ich die Lösung fand.
Was ist das reTerminal E1004 ĂĽberhaupt?
Das reTerminal E1004 ist das größte Modell der reTerminal-E-Serie von Seeed. Diese Produktfamilie umfasst ESP32-S3-basierte E-Paper-Terminals, die von 7,3 Zoll (monochrom) bis zu diesem 13,3-Zoll-Vollfarb-Panel reichen. Im Gegensatz zu den meisten smarten Bilderrahmen kommt das E1004 ganz ohne WLAN-Kamera, App-Zwang oder Cloud-Abo aus. Stattdessen nutzt es wahlweise die No-Code-Dashboard-Plattform „SenseCraft Seeedash“ oder – und darum geht es in diesem Beitrag – bietet volle ESPHome-Unterstützung.
Technische Daten (laut Hersteller)
Bevor ich auf meine eigenen Erfahrungen eingehe, hier die offiziellen Spezifikationen:
- Display: 13,3″ Vollfarb-E-Paper, E Ink® Spectra™ 6 Technologie, 1600 Ă— 1200 Pixel Auflösung (6 native Farben)
- Prozessor: ESP32-S3 mit 8 MB PSRAM
- Speicher: 32 MB Flash (laut Produktseite), inkl. microSD-Kartenslot (16 GB Karte vorinstalliert, FAT32 bis 32 GB unterstĂĽtzt)
- Akku: 5.000 mAh, bis zu 6 Monate Laufzeit im Standard-Energiesparmodus (ein Refresh pro Tag)
- Konnektivität: WLAN 2,4 GHz, Bluetooth 5.0
- Bedienung: Touch-Buttons fĂĽr manuellen Bildwechsel oder Refresh
- Software ab Werk: SenseCraft Seeedash (No-Code-Dashboard und Bild-Upload)
- ESPHome-Kompatibilität: Ab Version 2026.7.0 (der E1004-Displaytreiber wurde erst kürzlich integriert)
- Preis: 242,99 € (UVP laut Produktseite)
Wichtige Anmerkung zum Speicher: Auf der Produktseite werden 32 MB Flash angegeben. Bei jedem Boot-Vorgang meines Testgeräts gab der Bootloader jedoch unmissverständlich
SPI Flash Size: 4MBaus. Dieser Wert wird direkt vom Chip ausgelesen und ist keine Schätzung. Ob dies an meiner speziellen Produktionscharge liegt oder ob sich die Angabe auf eine andere Variante bezieht, kann ich nicht sicher sagen. Für den Betrieb mit eigener Firmware macht dies jedoch einen spürbaren Unterschied. Daher rechne ich im Folgenden mit den tatsächlich gemessenen 4 MB.
Der eigentliche Clou: 100 % lokal mit ESPHome
Das Besondere am reTerminal E1004 ist die Möglichkeit, die Werksfirmware komplett durch ein eigenes ESPHome-Setup zu ersetzen. Damit entfällt jegliche Cloud-Abhängigkeit: Kein Bild-Upload über fremde Server, keine Registrierung und kein Abo. Das Gerät lädt seine Inhalte entweder direkt über eine URL eurer Wahl (in meinem Fall mein eigener Webspace) oder die Bilder werden fest in die Firmware eingebettet. Beides läuft vollständig innerhalb eures eigenen lokalen Netzwerks.

Für mich als Verfechter des „lokal, sonst nix“-Prinzips – insbesondere bei Kameras – ist das genau der Ansatz, den ich mir für einen smarten Bilderrahmen wünsche. Der Kompromiss im Vergleich zu SenseCraft Seeedash: Ihr müsst selbst Hand anlegen und eine YAML-Konfiguration anstelle einer No-Code-Oberfläche nutzen. Dafür erhaltet ihr jedoch die volle Kontrolle, inklusive Home-Assistant-Anbindung, eigener Sensorik und allen weiteren Funktionen, die ESPHome bietet.
Meine Lösung: Bild-Rotation, Wetter-Dashboard und Deep Sleep
Mein finales Setup umfasst folgende Funktionen:
- Bild-Rotation: Das Display wechselt alle 45 Minuten automatisch zwischen zwei Motiven (in meinem Test ein KI-generiertes Bild und eine Stadtkarte). Die Bilder werden abwechselnd via
online_imagedirekt von meinem Webserver geladen. - Deep Sleep: Zwischen den Aktualisierungen schläft das Gerät komplett. Es wacht nur kurz auf, lädt das nächste Bild, zeigt es an und geht sofort wieder in den Ruhemodus.
- On-Demand-Dashboard: Ein Tastendruck weckt das Gerät und zeigt für 60 Sekunden eine Kachel-Übersicht an. Diese beinhaltet Temperatur und Luftfeuchtigkeit (über den internen Sensor), den Akkustand sowie eine 3-Tage-Wetter- und Solarertrags-Prognose aus Home Assistant. Danach kehrt der Rahmen automatisch zur Bildrotation zurück.
Das gesamte Setup läuft über eine einzige ESPHome-YAML-Datei – ganz ohne SenseCraft oder Cloud-Anbindung.

Der Stolperstein: Wenn online_image einfach hängen bleibt
Hier muss ich ehrlich zugeben: Ich hätte fast aufgegeben.
Der naheliegendste Weg, ein Bild von einer URL anzuzeigen, ist die online_image-Komponente von ESPHome. Sie lädt das Bild zur Laufzeit per HTTP und zeichnet es direkt auf das Display. Das klingt simpel, war es aber in der Praxis nicht.
Sobald ich ein Farbfoto oder ein Bild in voller Panel-Auflösung anzeigen wollte, trat eines von zwei Problemen auf: Entweder stürzte das Gerät mit einem Speicherfehler an wechselnden, scheinbar unzusammenhängenden Stellen im Code ab (ein klassisches Indiz für Speicherkorruption). Oder es fror komplett und ohne Fehlermeldung ein – teilweise für über 20 Minuten, ohne dass etwas passierte. Kleine, in Graustufen gehaltene Bilder funktionierten hingegen zuverlässig.
Zunächst vermutete ich die Bildgröße als Ursache, dann das Farbformat und schließlich die Akkuspannung. Auf Anraten von Seeed testete ich systematisch den Betrieb via USB und reinem Akku, doch das Fehlerbild blieb identisch.
Nach einem ausführlichen GitHub-Issue und mit der Unterstützung eines ESPHome-Maintainers fand sich die Ursache: Der direkte Zeichenaufruf (lambda: it.image(...)), den ich ursprünglich genutzt hatte, rendert das komplette Bild in einem einzigen, blockierenden Vorgang. Bei fast zwei Millionen Pixeln in Farbe reicht das aus, um interne Sicherheitsmechanismen (wie den Task-Watchdog) auszulösen oder den Treiber in einen unerwarteten Zustand zu versetzen.
Die Lösung: Das Bild darf nicht mehr direkt per Lambda gezeichnet werden. Stattdessen muss es über LVGL (eine in ESPHome integrierte Grafikbibliothek) gerendert werden. LVGL zeichnet gepuffert in kleinen Segmenten anstatt in einem Rutsch und wartet zusätzlich, bis das Display wirklich bereit ist (update_when_display_idle: true). Genau diese Synchronisation hatte zuvor gefehlt. Seit dieser Umstellung läuft mein Setup selbst mit vollformatigen Farbfotos absolut zuverlässig.
Mein Tipp für euch: Falls ihr selbst mit online_image und einem E-Paper-Display arbeitet: Greift bei größeren oder farbigen Bildern von Anfang an auf LVGL zurück und verzichtet auf direkte Lambda-Zeichnungen. Das hätte mir locker zwei bis drei Abende Fehlersuche erspart.

Hier noch mein genutzter Code:
# =============================================================================
# reTerminal E1004 - Picture frame with on-demand sensor dashboard
#
# Default state: rotates between two images (Einstein / Cologne map) every
# 45 minutes via deep_sleep, using the LVGL-based online_image approach
# confirmed working in https://github.com/esphome/esphome/issues/18797.
#
# KEY1 (GPIO4): wakes the device (if asleep) and shows a sensor dashboard
# (local temperature/humidity, battery, HA weather) for 60 seconds, then
# automatically returns to the current rotation image and goes back to
# sleep.
#
# TODO before flashing: create the three HA template sensors from
# ha-forecast-templates.yaml first (sensor.frame_forecast_day0/1/2), or the
# forecast tiles below will just show "--".
# =============================================================================
substitutions:
device_name: reterminal-e1004
friendly_name: "reTerminal_E1004"
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
on_boot:
priority: -100
then:
- output.turn_on: bsp_battery_enable
- delay: 200ms
- component.update: sht4x_sensor
- component.update: battery_voltage
- component.update: battery_level
esp32:
board: seeed_xiao_esp32s3
# ESPHome's default 5s task watchdog can be too short for a full-panel
# LVGL image quantization pass. 60s gives generous headroom.
watchdog_timeout: 60s
framework:
type: esp-idf
psram:
mode: octal
logger:
hardware_uart: UART0
level: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
on_connect:
# Alternates between the two images on each wake: downloads only the
# one due to be shown this cycle, then flips the flag for next time.
# show_cologne_next persists across deep_sleep via RTC memory
# (restore_value: true), so the alternation survives sleep cycles.
- lambda: |-
if (id(show_cologne_next)) {
id(image_cologne).update();
} else {
id(image_einstein).update();
}
id(show_cologne_next) = !id(show_cologne_next);
# Persists across deep_sleep (RTC memory) - tracks which image to show next.
globals:
- id: show_cologne_next
type: bool
restore_value: true
initial_value: "true"
# Home Assistant native API
api:
encryption:
key: !secret api_key
# Time synced from Home Assistant, used to show the date (DD.MM.) next to
# Heute/Morgen/Ăśbermorgen on the dashboard.
time:
- platform: homeassistant
id: ha_time
timezone: "Europe/Berlin"
# OTA (Over-The-Air) firmware update over WiFi
ota:
- platform: esphome
password: !secret ota_password
http_request:
# =============================================================================
# Images: platform: online_image, rendered via the LVGL image widget on
# image_page (see lvgl: section below).
# =============================================================================
image:
- platform: online_image
url: "URL-ZU-DEINEM-BILD"
id: image_einstein
format: JPEG
type: RGB565
resize: 1200x1600
on_download_finished:
- lvgl.image.update:
src: image_einstein
id: lv_image
- platform: online_image
url: "URL-ZU-DEINEM-BILD"
id: image_cologne
format: JPEG
type: RGB565
resize: 1200x1600
on_download_finished:
- lvgl.image.update:
src: image_cologne
id: lv_image
spi:
clk_pin: GPIO7
mosi_pin: GPIO9
miso_pin: GPIO8
i2c:
sda: GPIO19
scl: GPIO20
output:
# Battery measurement enable
- platform: gpio
pin: GPIO21
id: bsp_battery_enable
font:
- file:
type: gfonts
family: Montserrat
weight: 700
id: font_dashboard_large
size: 48
bpp: 2
glyphsets: [GF_Latin_Kernel, GF_Latin_Core]
- file:
type: gfonts
family: Montserrat
weight: 700
id: font_dashboard_medium
size: 32
bpp: 2
glyphsets: [GF_Latin_Kernel, GF_Latin_Core]
- file:
type: gfonts
family: Montserrat
weight: 600
id: font_dashboard_small
size: 24
bpp: 2
glyphsets: [GF_Latin_Kernel, GF_Latin_Core]
sensor:
- platform: sht4x
id: sht4x_sensor
temperature:
name: "Temperature"
id: temp_sensor
humidity:
name: "Relative Humidity"
id: hum_sensor
update_interval: 60s
- platform: adc
pin: GPIO1
name: "Battery Voltage"
id: battery_voltage
update_interval: 60s
attenuation: 12db
filters:
- multiply: 2.0
- platform: template
name: "Battery Level"
id: battery_level
unit_of_measurement: "%"
icon: "mdi:battery"
device_class: battery
state_class: measurement
lambda: 'return id(battery_voltage).state;'
update_interval: 60s
filters:
- calibrate_linear:
- 4.15 -> 100.0
- 3.96 -> 90.0
- 3.91 -> 80.0
- 3.85 -> 70.0
- 3.80 -> 60.0
- 3.75 -> 50.0
- 3.68 -> 40.0
- 3.58 -> 30.0
- 3.49 -> 20.0
- 3.41 -> 10.0
- 3.30 -> 5.0
- 3.27 -> 0.0
- clamp:
min_value: 0
max_value: 100
# Raw forecast values from the HA template sensors (see
# ha-forecast-templates.yaml) - formatting/line breaks happen in the
# show_dashboard script below.
- platform: homeassistant
id: fc0_templow
entity_id: sensor.frame_forecast_day_0_templow
internal: true
- platform: homeassistant
id: fc0_temphigh
entity_id: sensor.frame_forecast_day_0_temphigh
internal: true
- platform: homeassistant
id: fc0_precip
entity_id: sensor.frame_forecast_day_0_precip
internal: true
- platform: homeassistant
id: fc0_uv
entity_id: sensor.frame_forecast_day_0_uv
internal: true
- platform: homeassistant
id: fc1_templow
entity_id: sensor.frame_forecast_day_1_templow
internal: true
- platform: homeassistant
id: fc1_temphigh
entity_id: sensor.frame_forecast_day_1_temphigh
internal: true
- platform: homeassistant
id: fc1_precip
entity_id: sensor.frame_forecast_day_1_precip
internal: true
- platform: homeassistant
id: fc1_uv
entity_id: sensor.frame_forecast_day_1_uv
internal: true
- platform: homeassistant
id: fc2_templow
entity_id: sensor.frame_forecast_day_2_templow
internal: true
- platform: homeassistant
id: fc2_temphigh
entity_id: sensor.frame_forecast_day_2_temphigh
internal: true
- platform: homeassistant
id: fc2_precip
entity_id: sensor.frame_forecast_day_2_precip
internal: true
- platform: homeassistant
id: fc2_uv
entity_id: sensor.frame_forecast_day_2_uv
internal: true
# Solcast PV forecast - different entity per day (existing entities,
# no template sensor needed).
- platform: homeassistant
id: solar_day0
entity_id: sensor.solcast_pv_forecast_prognose_verbleibende_leistung_heute
internal: true
- platform: homeassistant
id: solar_day1
entity_id: sensor.solcast_pv_forecast_prognose_morgen
internal: true
- platform: homeassistant
id: solar_day2
entity_id: sensor.solcast_pv_forecast_prognose_tag_3
internal: true
binary_sensor:
# KEY1 (GPIO4) - wakes the device (if asleep) and shows the sensor
# dashboard for 60s, then returns to the current rotation image.
- platform: gpio
pin:
number: GPIO4
allow_other_uses: true
mode: INPUT
inverted: true
id: button_2
name: "KEY1 Dashboard Button"
filters:
- delayed_on: 20ms
- delayed_off: 20ms
on_press:
then:
- logger.log: "KEY1 (GPIO4) pressed - Dashboard"
- script.execute: show_dashboard
script:
- id: show_dashboard
mode: restart
then:
# Keep the device awake for the full 60s dashboard display, even if
# the normal deep_sleep run_duration would otherwise expire first.
- deep_sleep.prevent: deep_sleep_1
- lvgl.label.update:
id: dashboard_temp_label
text:
format: "%.1f °C"
args: ["id(temp_sensor).state"]
- lvgl.label.update:
id: dashboard_hum_label
text:
format: "%.0f %% rF"
args: ["id(hum_sensor).state"]
- lvgl.label.update:
id: dashboard_battery_label
text:
format: "%.0f %%"
args: ["id(battery_level).state"]
- lvgl.label.update:
id: dashboard_forecast0_label
text: !lambda |-
char buf[128];
snprintf(buf, sizeof(buf), "Temp.: %.0f°/%.0f°\nNiederschlag: %.1f mm\nUV-Index: %.1f\nPV: %.1f kWh",
id(fc0_templow).state, id(fc0_temphigh).state,
id(fc0_precip).state, id(fc0_uv).state,
id(solar_day0).state);
return std::string(buf);
- lvgl.label.update:
id: dashboard_forecast1_label
text: !lambda |-
char buf[128];
snprintf(buf, sizeof(buf), "Temp.: %.0f°/%.0f°\nNiederschlag: %.1f mm\nUV-Index: %.1f\nPV: %.1f kWh",
id(fc1_templow).state, id(fc1_temphigh).state,
id(fc1_precip).state, id(fc1_uv).state,
id(solar_day1).state);
return std::string(buf);
- lvgl.label.update:
id: dashboard_forecast2_label
text: !lambda |-
char buf[128];
snprintf(buf, sizeof(buf), "Temp.: %.0f°/%.0f°\nNiederschlag: %.1f mm\nUV-Index: %.1f\nPV: %.1f kWh",
id(fc2_templow).state, id(fc2_temphigh).state,
id(fc2_precip).state, id(fc2_uv).state,
id(solar_day2).state);
return std::string(buf);
# Day titles with date (DD.MM.), computed from HA-synced time.
- lvgl.label.update:
id: dashboard_day0_title
text: !lambda |-
char buf[32];
time_t t = id(ha_time).now().timestamp;
struct tm tm_info;
localtime_r(&t, &tm_info);
char datebuf[8];
strftime(datebuf, sizeof(datebuf), "%d.%m.", &tm_info);
snprintf(buf, sizeof(buf), "Heute, %s", datebuf);
return std::string(buf);
- lvgl.label.update:
id: dashboard_day1_title
text: !lambda |-
char buf[32];
time_t t = id(ha_time).now().timestamp + 86400;
struct tm tm_info;
localtime_r(&t, &tm_info);
char datebuf[8];
strftime(datebuf, sizeof(datebuf), "%d.%m.", &tm_info);
snprintf(buf, sizeof(buf), "Morgen, %s", datebuf);
return std::string(buf);
- lvgl.label.update:
id: dashboard_day2_title
text: !lambda |-
char buf[32];
time_t t = id(ha_time).now().timestamp + 2 * 86400;
struct tm tm_info;
localtime_r(&t, &tm_info);
char datebuf[8];
strftime(datebuf, sizeof(datebuf), "%d.%m.", &tm_info);
snprintf(buf, sizeof(buf), "Ăśbermorgen, %s", datebuf);
return std::string(buf);
- lvgl.page.show: dashboard_page
- delay: 60s
- lvgl.page.show: image_page
# Give LVGL/epaper_spi time to actually finish redrawing the image
# before sleeping - otherwise deep_sleep.enter can cut the refresh
# off mid-way and the display stays stuck showing the dashboard.
- delay: 45s
- deep_sleep.allow: deep_sleep_1
- deep_sleep.enter: deep_sleep_1
display:
- platform: epaper_spi
model: seeed-reterminal-e1004
lvgl:
update_when_display_idle: true
buffer_size: 25%
pages:
- id: image_page
bg_color: 0xFFFFFF
bg_opa: COVER
pad_all: 0
widgets:
- image:
id: lv_image
src: image_cologne
- id: dashboard_page
bg_color: 0xFFFFFF
bg_opa: COVER
pad_all: 40
widgets:
- label:
text: "STATUS"
text_font: font_dashboard_large
text_color: 0x000000
x: 0
y: 0
- obj:
x: 0
y: 100
width: 1120
height: 260
bg_color: 0xFFFFFF
bg_opa: COVER
border_color: 0x000000
border_width: 3
radius: 10
pad_all: 24
widgets:
- label:
text: "Temperatur / Feuchte"
text_font: font_dashboard_medium
text_color: 0x000000
- label:
id: dashboard_temp_label
y: 60
text: "-- °C"
text_font: font_dashboard_large
text_color: 0x000000
- label:
id: dashboard_hum_label
y: 140
text: "-- % rF"
text_font: font_dashboard_large
text_color: 0x000000
- obj:
x: 0
y: 400
width: 1120
height: 200
bg_color: 0xFFFFFF
bg_opa: COVER
border_color: 0x000000
border_width: 3
radius: 10
pad_all: 24
widgets:
- label:
text: "Akku"
text_font: font_dashboard_medium
text_color: 0x000000
- label:
id: dashboard_battery_label
y: 60
text: "-- %"
text_font: font_dashboard_large
text_color: 0x000000
- obj:
x: 0
y: 640
width: 1120
height: 420
bg_color: 0xFFFFFF
bg_opa: COVER
border_color: 0x000000
border_width: 3
radius: 10
pad_all: 24
widgets:
- label:
text: "Wetter & Solar-Prognose"
text_font: font_dashboard_medium
text_color: 0x000000
- obj:
x: 0
y: 60
width: 340
height: 320
bg_color: 0xFFFFFF
bg_opa: COVER
border_color: 0x000000
border_width: 2
radius: 8
pad_all: 14
widgets:
- label:
id: dashboard_day0_title
width: 310
text: "Heute"
text_font: font_dashboard_medium
text_color: 0x000000
long_mode: WRAP
- label:
id: dashboard_forecast0_label
y: 70
width: 310
height: 240
text: "--"
text_font: font_dashboard_small
text_color: 0x000000
long_mode: WRAP
- obj:
x: 370
y: 60
width: 340
height: 320
bg_color: 0xFFFFFF
bg_opa: COVER
border_color: 0x000000
border_width: 2
radius: 8
pad_all: 14
widgets:
- label:
id: dashboard_day1_title
width: 310
text: "Morgen"
text_font: font_dashboard_medium
text_color: 0x000000
long_mode: WRAP
- label:
id: dashboard_forecast1_label
y: 70
width: 310
height: 240
text: "--"
text_font: font_dashboard_small
text_color: 0x000000
long_mode: WRAP
- obj:
x: 740
y: 60
width: 340
height: 320
bg_color: 0xFFFFFF
bg_opa: COVER
border_color: 0x000000
border_width: 2
radius: 8
pad_all: 14
widgets:
- label:
id: dashboard_day2_title
width: 310
text: "Ăśbermorgen"
text_font: font_dashboard_medium
text_color: 0x000000
long_mode: WRAP
- label:
id: dashboard_forecast2_label
y: 70
width: 310
height: 240
text: "--"
text_font: font_dashboard_small
text_color: 0x000000
long_mode: WRAP
# =============================================================================
# [9] Deep sleep - refreshes the image automatically every 45 minutes, and
# can also be woken early at any time by pressing KEY1 (GPIO4) to show the
# dashboard on demand. run_duration is generous enough to cover WiFi
# connect, download, and the LVGL/epaper_spi redraw.
# =============================================================================
deep_sleep:
id: deep_sleep_1
run_duration: 120s
sleep_duration: 45min
esp32_ext1_wakeup:
pins:
- number: GPIO4
allow_other_uses: true
mode: INPUT_PULLUP
mode: ANY_LOW
# secrets.yaml (create this file alongside your config):
# wifi_ssid: "Your WiFi SSID"
# wifi_password: "Your WiFi Password"
# api_key: "generate with: openssl rand -base64 32"
# ota_password: "choose-a-strong-password"
Fazit
Das reTerminal E1004 bietet genau das, was ich von einem smarten Bilderrahmen erwarte: ein echtes, rein lokales Setup ohne Cloud-Zwang, gepaart mit einem Panel, das bei Tageslicht deutlich besser aussieht als herkömmliche LCD-Rahmen.
Die ESPHome-Integration steckt allerdings noch in den Kinderschuhen (der Displaytreiber existiert erst seit wenigen Wochen). Das habe ich beim online_image-Problem deutlich gespürt – es handelt sich noch nicht um eine jahrelang gehärtete Software, sondern um eine aktive Baustelle. Wer jedoch bereit ist, sich in ESPHome einzuarbeiten und im Zweifelsfall auch mal ein GitHub-Issue zu eröffnen, wird mit einem Gerät belohnt, über das er die volle Kontrolle behält.
Was mir für ein abschließendes Urteil noch fehlt, sind Langzeit-Erfahrungswerte zur tatsächlichen Akkulaufzeit bei meinem spezifischen Nutzungsmuster. Eine 45-Minuten-Rotation ist deutlich ressourcenintensiver als der vom Hersteller beworbene „ein Refresh pro Tag“. Ein entsprechendes Update dazu werde ich bei Gelegenheit nachreichen.

Das genannte Produkt wurde mir vom Hersteller kostenlos zur Verfügung gestellt. Ich weise hierauf ausdrücklich hin, da ich Wert auf größtmögliche Transparenz lege.
Das kostenlose Bereitstellen eines Produktmusters hat keine Auswirkung auf meine Berichte hierzu, was du an möglicher geäußerter Kritik auch immer erkennen kannst.
Produktempfehlungen


