diff --git a/matrix.py b/matrix.py index 2400bd2..5bee526 100644 --- a/matrix.py +++ b/matrix.py @@ -225,9 +225,16 @@ class Matrix64Display(SampleBase): time_font, data_font, small_font = fonts time_color, humidity_color, hdd_color, label_color, line_color = colors - for y in range(24, 44): + # Black background + for y in range(22, 46): graphics.DrawLine(canvas, 0, y, 63, y, graphics.Color(0, 0, 0)) + # Border lines + border_color = graphics.Color(60, 60, 60) + graphics.DrawLine(canvas, 0, 22, 63, 22, border_color) + graphics.DrawLine(canvas, 0, 45, 63, 45, border_color) + + # Message msg_color = graphics.Color(0, 255, 100) msg_len = len(self.feedback_message) * 7 x = (64 - msg_len) // 2 @@ -241,8 +248,9 @@ class Matrix64Display(SampleBase): now = datetime.datetime.now() time_str = f"{now.hour:02d}:{now.minute:02d}:{now.second:02d}" - anim_offset = int(math.sin(self.animation_frame * 0.3) * 2) - draw_weather_icon(canvas, anim_offset, 0, self.weather_desc) + # Weather Icon (cloud moves, sun/icon stays fixed) + cloud_offset = int(math.sin(self.animation_frame * 0.3) * 2) + draw_weather_icon(canvas, 0, 0, self.weather_desc, cloud_offset) graphics.DrawLine(canvas, 28, 0, 28, 25, line_color) @@ -279,25 +287,29 @@ class Matrix64Display(SampleBase): time_font, data_font, small_font = fonts time_color, humidity_color, hdd_color, label_color, line_color = colors - graphics.DrawText(canvas, data_font, 4, 8, time_color, "Discos") + # Centered title + title = "Discos" + title_len = len(title) * 5 + title_x = (64 - title_len) // 2 + graphics.DrawText(canvas, data_font, title_x, 8, time_color, title) graphics.DrawLine(canvas, 0, 10, 63, 10, line_color) if self.hdd_temps and len(self.hdd_temps) > 1: temps = [(i+1, int(t[0])) for i, t in enumerate(self.hdd_temps[1:7]) if t] - y = 20 + y = 22 for idx, (num, temp_val) in enumerate(temps[:3]): temp_color = get_hdd_color(temp_val) - graphics.DrawText(canvas, data_font, 0, y, label_color, f"{num}:") - graphics.DrawText(canvas, data_font, 14, y, temp_color, f"{temp_val}C") - y += 10 + graphics.DrawText(canvas, data_font, 2, y, label_color, f"{num}:") + graphics.DrawText(canvas, data_font, 16, y, temp_color, f"{temp_val}C") + y += 11 - y = 20 + y = 22 for idx, (num, temp_val) in enumerate(temps[3:6]): temp_color = get_hdd_color(temp_val) graphics.DrawText(canvas, data_font, 34, y, label_color, f"{num}:") graphics.DrawText(canvas, data_font, 48, y, temp_color, f"{temp_val}C") - y += 10 + y += 11 if self.auto_cycle: graphics.DrawText(canvas, small_font, 58, 62, label_color, "A") @@ -323,8 +335,9 @@ class Matrix64Display(SampleBase): graphics.DrawLine(canvas, 0, 30, 63, 30, line_color) - anim_offset = int(math.sin(self.animation_frame * 0.3) * 2) - draw_weather_icon(canvas, 4 + anim_offset, 34, self.weather_desc) + # Weather icon (cloud animates, position fixed) + cloud_offset = int(math.sin(self.animation_frame * 0.3) * 2) + draw_weather_icon(canvas, 4, 34, self.weather_desc, cloud_offset) if self.temperature is not None: temp_color = get_temperature_color(self.temperature) @@ -338,25 +351,28 @@ class Matrix64Display(SampleBase): time_font, data_font, small_font = fonts time_color, humidity_color, hdd_color, label_color, line_color = colors - # Title - graphics.DrawText(canvas, data_font, 14, 8, time_color, "Tesla") + # Centered title + title = "Tesla" + title_len = len(title) * 5 + title_x = (64 - title_len) // 2 + graphics.DrawText(canvas, data_font, title_x, 8, time_color, title) graphics.DrawLine(canvas, 0, 10, 63, 10, line_color) if self.tesla: - # Battery + # Battery (with margin) battery = self.tesla.get("battery") if battery is not None: battery_color = graphics.Color(0, 255, 80) if battery > 20 else graphics.Color(255, 50, 50) - graphics.DrawText(canvas, data_font, 0, 22, label_color, "Bat:") - graphics.DrawText(canvas, time_font, 24, 24, battery_color, f"{battery}%") + graphics.DrawText(canvas, data_font, 4, 24, label_color, "Bat") + graphics.DrawText(canvas, time_font, 26, 26, battery_color, f"{battery}%") - # Range + # Range (with margin) range_km = self.tesla.get("range") if range_km is not None: - graphics.DrawText(canvas, data_font, 0, 36, label_color, "Km:") - graphics.DrawText(canvas, time_font, 20, 38, time_color, f"{range_km}") + graphics.DrawText(canvas, data_font, 4, 38, label_color, "Km") + graphics.DrawText(canvas, time_font, 22, 40, time_color, f"{range_km}") - # Status + # Status (centered) charging = self.tesla.get("charging", False) plugged = self.tesla.get("plugged", False) @@ -370,7 +386,9 @@ class Matrix64Display(SampleBase): status = "Listo" status_color = graphics.Color(100, 100, 100) - graphics.DrawText(canvas, data_font, 4, 54, status_color, status) + status_len = len(status) * 5 + status_x = (64 - status_len) // 2 + graphics.DrawText(canvas, data_font, status_x, 56, status_color, status) else: graphics.DrawText(canvas, data_font, 4, 32, label_color, "Sin datos") diff --git a/weather_icons.py b/weather_icons.py index 917caf9..0ead94c 100644 --- a/weather_icons.py +++ b/weather_icons.py @@ -54,31 +54,31 @@ def _draw_cloud_shape(canvas, x, y, color): graphics.DrawCircle(canvas, x + 12, y + 7, r, color) -def draw_partly_cloudy(canvas, x, y): - """Draw sun partially covered by cloud.""" +def draw_partly_cloudy(canvas, x, y, cloud_offset=0): + """Draw sun partially covered by cloud. Cloud can be animated.""" sun_color = graphics.Color(255, 200, 0) ray_color = graphics.Color(255, 140, 0) cloud_color = graphics.Color(220, 220, 220) - # Draw partial sun + # Draw partial sun (stays in place) graphics.DrawLine(canvas, x + 8, y + 2, x + 8, y + 4, ray_color) graphics.DrawLine(canvas, x + 2, y + 8, x + 4, y + 8, ray_color) graphics.DrawLine(canvas, x + 3, y + 3, x + 5, y + 5, ray_color) for r in range(4, 0, -1): graphics.DrawCircle(canvas, x + 8, y + 8, r, sun_color) - # Draw cloud - _draw_cloud_shape(canvas, x + 6, y + 10, cloud_color) + # Draw cloud (with animation offset) + _draw_cloud_shape(canvas, x + 6 + cloud_offset, y + 10, cloud_color) -def draw_partly_cloudy_night(canvas, x, y): +def draw_partly_cloudy_night(canvas, x, y, cloud_offset=0): """Draw moon partially covered by cloud.""" moon_color = graphics.Color(255, 255, 200) cloud_color = graphics.Color(180, 180, 200) for r in range(4, 0, -1): graphics.DrawCircle(canvas, x + 8, y + 8, r, moon_color) - _draw_cloud_shape(canvas, x + 6, y + 10, cloud_color) + _draw_cloud_shape(canvas, x + 6 + cloud_offset, y + 10, cloud_color) def draw_cloudy(canvas, x, y): @@ -218,16 +218,40 @@ WEATHER_ICONS = { } -def draw_weather_icon(canvas, x, y, weather_state): - """Draw weather icon based on state string.""" +def draw_weather_icon(canvas, x, y, weather_state, cloud_offset=0): + """Draw weather icon based on state string. + + Args: + canvas: The LED matrix canvas + x, y: Position to draw at + weather_state: Weather condition string + cloud_offset: Animation offset for cloud movement (optional) + """ weather_lower = weather_state.lower() if weather_state else '' - # Try exact match + # Icons with cloud animation support + ANIMATED_ICONS = { + 'partlycloudy': draw_partly_cloudy, + 'partly-cloudy-day': draw_partly_cloudy, + 'partly-cloudy-night': draw_partly_cloudy_night, + } + + # Try animated icons first + if weather_lower in ANIMATED_ICONS: + ANIMATED_ICONS[weather_lower](canvas, x, y, cloud_offset) + return + + # Try exact match for static icons if weather_lower in WEATHER_ICONS: WEATHER_ICONS[weather_lower](canvas, x, y) return # Try partial match + for key, draw_func in ANIMATED_ICONS.items(): + if key in weather_lower or weather_lower in key: + draw_func(canvas, x, y, cloud_offset) + return + for key, draw_func in WEATHER_ICONS.items(): if key in weather_lower or weather_lower in key: draw_func(canvas, x, y)