FEAT-NETATMO-06: V1 Status-Update Redesign + shared helpers foundation
Netatmo-Plugin komplett auf V1 Status-Update Layout umgebaut:
- 4-Sektionen: Aussen / Wind+Regen / Indoor / Vorhersage
- Echte 12h-History fuer MIN/MAX (vorher estimated +-2/+-4)
- Dynamische Forecast-Daten (datetime.now() + timedelta)
- DE strings durchgaengig (AUSSEN, FEUCHTE, DRUCK, Bo, HEUTE, Boerse, ...)
- 7-Farben ACeP palette (kein Greyscale, kein Anti-Alias)
- Indoor-Sensoren: rote Tag-Box + 22pt+ Temp + CO2-Bar + Batt aligned
- Chart mit 2-Tick Y-Grid (min/max), 12h Linie in Gruen
- Wetter-Icons (WMO codes) in Vorhersage, Regen-Drop-Icon pro Tag
Foundation / shared helpers:
- palette.py: BATT_*, DE_WEEKDAYS/MONTHS, WMO_ICONS, format_*,
POWER_DEFAULTS, temp_color, co2_color, batt_color
- plugins/base.py: draw_battery, draw_compass, draw_trend,
draw_line_chart, draw_mini_bar, draw_weather_icon,
draw_deepsleep_indicator, draw_zzz_indicator,
_fit_size, _get_base_sans, de_* formatters
- designbase.py: THEMES dict (light/dark/retro/mag), Layout templates
(bereits importierbar)
Tools:
- tools/render_mockup.py: 3 design-Varianten Mockup-Generator
- tools/verify_netatmo.py: Self-verification mit dynamic mock data
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
"""Verifizierungs-Script: rendert Netatmo mit dynamischen Mock-Daten.
|
||||
|
||||
Findet und behebt:
|
||||
1. Statische Forecast-Daten (jetzt relativ zu heute)
|
||||
2. Synthetische Outdoor-History mit groesserer Range (damit Chart nicht flach)
|
||||
3. Bessere Indoor Batt-Darstellung
|
||||
"""
|
||||
import sys
|
||||
sys.path.insert(0, '.')
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from plugins.netatmo import Widget
|
||||
from datetime import datetime, timedelta
|
||||
import math
|
||||
import os
|
||||
|
||||
# FIX 1: Mock-Daten mit dynamischen Daten (heute + 2 Tage)
|
||||
now = datetime.now()
|
||||
forecast_days = [(now + timedelta(days=i)).date().isoformat() for i in range(3)]
|
||||
|
||||
# FIX 2: Synthetische Outdoor-History mit groesserem Temperatur-Range
|
||||
# 12h-Verlauf mit sin-voller Swing (12.5 - 22.5 Grad, also 10 Grad Range)
|
||||
outdoor_temps = []
|
||||
for h in range(12):
|
||||
t = 17.5 + 4.5 * math.sin(h / 2.2) + 1.0 * math.cos(h / 1.3)
|
||||
outdoor_temps.append(round(t, 1))
|
||||
temp_history = ';'.join(str(t) for t in outdoor_temps)
|
||||
print(f'History: min={min(outdoor_temps)}, max={max(outdoor_temps)}, n={len(outdoor_temps)}')
|
||||
|
||||
mock = {
|
||||
'station_name': 'Daheim', 'place': {},
|
||||
'main': {'name': 'Daheim', 'data': {'Temperature': 21.5, 'CO2': 620, 'Humidity': 48, 'Pressure': 1014, 'Pressure_trend': 'down'}},
|
||||
'modules': [
|
||||
# Aussentemperatur = letzter Wert der History
|
||||
{'type': 'NAModule1', 'name': 'Aussen', 'data': {'Temperature': outdoor_temps[-1], 'Humidity': 67, 'Temp_history': temp_history}, 'battery_pct': 78},
|
||||
{'type': 'NAModule2', 'name': 'Wind', 'data': {'WindStrength': 12, 'GustStrength': 24, 'WindAngle': 215}, 'battery_pct': 65},
|
||||
{'type': 'NAModule3', 'name': 'Regen', 'data': {'RainRate': 0.0, 'sum_rain_1': 0.4, 'sum_rain_24': 6.2}, 'battery_pct': 82},
|
||||
{'type': 'NAModule4', 'name': 'Kueche', 'data': {'Temperature': 23.5, 'CO2': 980}, 'battery_pct': 88},
|
||||
{'type': 'NAModule4', 'name': 'Schlafen', 'data': {'Temperature': 20.8, 'CO2': 1450}, 'battery_pct': 41},
|
||||
],
|
||||
'forecast': {
|
||||
'daily': {
|
||||
'time': forecast_days, # DYNAMISCH: heute + 2 Tage
|
||||
'temperature_2m_max': [19, 21, 17],
|
||||
'temperature_2m_min': [9, 11, 8],
|
||||
'precipitation_sum': [0.0, 2.4, 8.1],
|
||||
'weather_code': [0, 3, 61],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
w = Widget({})
|
||||
w.fetch = lambda: mock
|
||||
fonts = {}
|
||||
for sz in [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, 40, 48, 60, 72, 84, 96]:
|
||||
fonts[str(sz)] = ImageFont.truetype(os.path.join('C:/Windows/Fonts/arial.ttf'), sz)
|
||||
fonts['default'] = ImageFont.load_default()
|
||||
|
||||
img = Image.new('RGB', (800, 480), (255, 255, 255))
|
||||
draw = ImageDraw.Draw(img)
|
||||
w.set_fonts(fonts)
|
||||
w.render(draw, fonts, 0, 0, 800, 480)
|
||||
img.save('docs/test_netatmo_v10.png')
|
||||
print(f'OK saved v10 ({now.strftime("%H:%M")})')
|
||||
Reference in New Issue
Block a user