Explorar o código

Fix log handler performance and restore Still Sands timezone

- Remove expensive timezone conversion from log handler that created
  ZoneInfo objects on every log message (major Pi performance issue)
- Logs now use simple local system time
- Move timezone setting back to Still Sands where it's actually needed
- Remove unused timezone from Machine Settings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
tuanchris hai 3 semanas
pai
achega
1ad00dc3d9
Modificáronse 2 ficheiros con 46 adicións e 131 borrados
  1. 44 104
      frontend/src/pages/SettingsPage.tsx
  2. 2 27
      modules/core/log_handler.py

+ 44 - 104
frontend/src/pages/SettingsPage.tsx

@@ -37,7 +37,6 @@ interface Settings {
   gear_ratio?: number
   gear_ratio?: number
   x_steps_per_mm?: number
   x_steps_per_mm?: number
   y_steps_per_mm?: number
   y_steps_per_mm?: number
-  timezone?: string
   available_table_types?: { value: string; label: string }[]
   available_table_types?: { value: string; label: string }[]
   // Homing settings
   // Homing settings
   homing_mode?: number
   homing_mode?: number
@@ -61,6 +60,7 @@ interface StillSandsSettings {
   enabled: boolean
   enabled: boolean
   finish_pattern: boolean
   finish_pattern: boolean
   control_wled: boolean
   control_wled: boolean
+  timezone: string
   time_slots: TimeSlot[]
   time_slots: TimeSlot[]
 }
 }
 
 
@@ -136,6 +136,7 @@ export function SettingsPage() {
     enabled: false,
     enabled: false,
     finish_pattern: false,
     finish_pattern: false,
     control_wled: false,
     control_wled: false,
+    timezone: '',
     time_slots: [],
     time_slots: [],
   })
   })
 
 
@@ -312,7 +313,6 @@ export function SettingsPage() {
         gear_ratio: data.machine?.gear_ratio,
         gear_ratio: data.machine?.gear_ratio,
         x_steps_per_mm: data.machine?.x_steps_per_mm,
         x_steps_per_mm: data.machine?.x_steps_per_mm,
         y_steps_per_mm: data.machine?.y_steps_per_mm,
         y_steps_per_mm: data.machine?.y_steps_per_mm,
-        timezone: data.machine?.timezone || 'UTC',
         available_table_types: data.machine?.available_table_types,
         available_table_types: data.machine?.available_table_types,
         // Homing settings
         // Homing settings
         homing_mode: data.homing?.mode,
         homing_mode: data.homing?.mode,
@@ -341,6 +341,7 @@ export function SettingsPage() {
           enabled: data.scheduled_pause.enabled || false,
           enabled: data.scheduled_pause.enabled || false,
           finish_pattern: data.scheduled_pause.finish_pattern || false,
           finish_pattern: data.scheduled_pause.finish_pattern || false,
           control_wled: data.scheduled_pause.control_wled || false,
           control_wled: data.scheduled_pause.control_wled || false,
+          timezone: data.scheduled_pause.timezone || '',
           time_slots: data.scheduled_pause.time_slots || [],
           time_slots: data.scheduled_pause.time_slots || [],
         })
         })
       }
       }
@@ -641,7 +642,6 @@ export function SettingsPage() {
         body: JSON.stringify({
         body: JSON.stringify({
           machine: {
           machine: {
             table_type_override: settings.table_type_override || '',
             table_type_override: settings.table_type_override || '',
-            timezone: settings.timezone || 'UTC',
           },
           },
         }),
         }),
       })
       })
@@ -996,104 +996,6 @@ export function SettingsPage() {
               </AlertDescription>
               </AlertDescription>
             </Alert>
             </Alert>
 
 
-            <Separator />
-
-            {/* Timezone Setting */}
-            <div className="space-y-3">
-              <Label>Timezone</Label>
-              <p className="text-sm text-muted-foreground">
-                Set the timezone for logs and scheduled features like Still Sands.
-              </p>
-              <div className="flex gap-3">
-                <Select
-                  value={settings.timezone || 'UTC'}
-                  onValueChange={(value) =>
-                    setSettings({ ...settings, timezone: value })
-                  }
-                >
-                  <SelectTrigger className="flex-1">
-                    <SelectValue placeholder="UTC" />
-                  </SelectTrigger>
-                  <SelectContent>
-                    <SelectItem value="UTC">UTC</SelectItem>
-                    {/* UTC Offsets */}
-                    <SelectItem value="Etc/GMT+12">UTC-12</SelectItem>
-                    <SelectItem value="Etc/GMT+11">UTC-11</SelectItem>
-                    <SelectItem value="Etc/GMT+10">UTC-10</SelectItem>
-                    <SelectItem value="Etc/GMT+9">UTC-9</SelectItem>
-                    <SelectItem value="Etc/GMT+8">UTC-8</SelectItem>
-                    <SelectItem value="Etc/GMT+7">UTC-7</SelectItem>
-                    <SelectItem value="Etc/GMT+6">UTC-6</SelectItem>
-                    <SelectItem value="Etc/GMT+5">UTC-5</SelectItem>
-                    <SelectItem value="Etc/GMT+4">UTC-4</SelectItem>
-                    <SelectItem value="Etc/GMT+3">UTC-3</SelectItem>
-                    <SelectItem value="Etc/GMT+2">UTC-2</SelectItem>
-                    <SelectItem value="Etc/GMT+1">UTC-1</SelectItem>
-                    <SelectItem value="Etc/GMT-1">UTC+1</SelectItem>
-                    <SelectItem value="Etc/GMT-2">UTC+2</SelectItem>
-                    <SelectItem value="Etc/GMT-3">UTC+3</SelectItem>
-                    <SelectItem value="Etc/GMT-4">UTC+4</SelectItem>
-                    <SelectItem value="Etc/GMT-5">UTC+5</SelectItem>
-                    <SelectItem value="Etc/GMT-6">UTC+6</SelectItem>
-                    <SelectItem value="Etc/GMT-7">UTC+7</SelectItem>
-                    <SelectItem value="Etc/GMT-8">UTC+8</SelectItem>
-                    <SelectItem value="Etc/GMT-9">UTC+9</SelectItem>
-                    <SelectItem value="Etc/GMT-10">UTC+10</SelectItem>
-                    <SelectItem value="Etc/GMT-11">UTC+11</SelectItem>
-                    <SelectItem value="Etc/GMT-12">UTC+12</SelectItem>
-                    {/* Americas */}
-                    <SelectItem value="America/New_York">US Eastern</SelectItem>
-                    <SelectItem value="America/Chicago">US Central</SelectItem>
-                    <SelectItem value="America/Denver">US Mountain</SelectItem>
-                    <SelectItem value="America/Los_Angeles">US Pacific</SelectItem>
-                    <SelectItem value="America/Anchorage">US Alaska</SelectItem>
-                    <SelectItem value="Pacific/Honolulu">US Hawaii</SelectItem>
-                    <SelectItem value="America/Toronto">Toronto</SelectItem>
-                    <SelectItem value="America/Vancouver">Vancouver</SelectItem>
-                    <SelectItem value="America/Mexico_City">Mexico City</SelectItem>
-                    <SelectItem value="America/Sao_Paulo">São Paulo</SelectItem>
-                    <SelectItem value="America/Buenos_Aires">Buenos Aires</SelectItem>
-                    {/* Europe */}
-                    <SelectItem value="Europe/London">London</SelectItem>
-                    <SelectItem value="Europe/Paris">Paris</SelectItem>
-                    <SelectItem value="Europe/Berlin">Berlin</SelectItem>
-                    <SelectItem value="Europe/Amsterdam">Amsterdam</SelectItem>
-                    <SelectItem value="Europe/Rome">Rome</SelectItem>
-                    <SelectItem value="Europe/Madrid">Madrid</SelectItem>
-                    <SelectItem value="Europe/Stockholm">Stockholm</SelectItem>
-                    <SelectItem value="Europe/Warsaw">Warsaw</SelectItem>
-                    <SelectItem value="Europe/Moscow">Moscow</SelectItem>
-                    <SelectItem value="Europe/Istanbul">Istanbul</SelectItem>
-                    {/* Asia */}
-                    <SelectItem value="Asia/Dubai">Dubai</SelectItem>
-                    <SelectItem value="Asia/Kolkata">India (Kolkata)</SelectItem>
-                    <SelectItem value="Asia/Bangkok">Bangkok</SelectItem>
-                    <SelectItem value="Asia/Singapore">Singapore</SelectItem>
-                    <SelectItem value="Asia/Hong_Kong">Hong Kong</SelectItem>
-                    <SelectItem value="Asia/Shanghai">Shanghai</SelectItem>
-                    <SelectItem value="Asia/Tokyo">Tokyo</SelectItem>
-                    <SelectItem value="Asia/Seoul">Seoul</SelectItem>
-                    {/* Oceania */}
-                    <SelectItem value="Australia/Perth">Perth</SelectItem>
-                    <SelectItem value="Australia/Sydney">Sydney</SelectItem>
-                    <SelectItem value="Australia/Melbourne">Melbourne</SelectItem>
-                    <SelectItem value="Pacific/Auckland">Auckland</SelectItem>
-                  </SelectContent>
-                </Select>
-                <Button
-                  onClick={handleSaveMachineSettings}
-                  disabled={isLoading === 'machine'}
-                  className="gap-2"
-                >
-                  {isLoading === 'machine' ? (
-                    <span className="material-icons-outlined animate-spin">sync</span>
-                  ) : (
-                    <span className="material-icons-outlined">save</span>
-                  )}
-                  Save
-                </Button>
-              </div>
-            </div>
           </AccordionContent>
           </AccordionContent>
         </AccordionItem>
         </AccordionItem>
 
 
@@ -2003,6 +1905,44 @@ export function SettingsPage() {
                       }
                       }
                     />
                     />
                   </div>
                   </div>
+
+                  {/* Timezone */}
+                  <div className="flex items-center justify-between pt-3 border-t">
+                    <div className="flex items-center gap-3">
+                      <span className="material-icons-outlined text-muted-foreground">
+                        schedule
+                      </span>
+                      <div>
+                        <p className="text-sm font-medium">Timezone</p>
+                        <p className="text-xs text-muted-foreground">
+                          Select a timezone for still periods
+                        </p>
+                      </div>
+                    </div>
+                    <Select
+                      value={stillSandsSettings.timezone || '__system__'}
+                      onValueChange={(value) =>
+                        setStillSandsSettings({ ...stillSandsSettings, timezone: value === '__system__' ? '' : value })
+                      }
+                    >
+                      <SelectTrigger className="w-[200px]">
+                        <SelectValue placeholder="System Default" />
+                      </SelectTrigger>
+                      <SelectContent>
+                        <SelectItem value="__system__">System Default</SelectItem>
+                        <SelectItem value="America/New_York">Eastern Time</SelectItem>
+                        <SelectItem value="America/Chicago">Central Time</SelectItem>
+                        <SelectItem value="America/Denver">Mountain Time</SelectItem>
+                        <SelectItem value="America/Los_Angeles">Pacific Time</SelectItem>
+                        <SelectItem value="Europe/London">London</SelectItem>
+                        <SelectItem value="Europe/Paris">Paris</SelectItem>
+                        <SelectItem value="Europe/Berlin">Berlin</SelectItem>
+                        <SelectItem value="Asia/Tokyo">Tokyo</SelectItem>
+                        <SelectItem value="Asia/Shanghai">Shanghai</SelectItem>
+                        <SelectItem value="Australia/Sydney">Sydney</SelectItem>
+                      </SelectContent>
+                    </Select>
+                  </div>
                 </div>
                 </div>
 
 
                 {/* Time Slots */}
                 {/* Time Slots */}
@@ -2097,9 +2037,9 @@ export function SettingsPage() {
                 <Alert className="flex items-start">
                 <Alert className="flex items-start">
                   <span className="material-icons-outlined text-base mr-2 shrink-0">info</span>
                   <span className="material-icons-outlined text-base mr-2 shrink-0">info</span>
                   <AlertDescription>
                   <AlertDescription>
-                    Times are based on the timezone configured in Machine Settings. Still periods
-                    that span midnight (e.g., 22:00 to 06:00) are supported. Patterns resume
-                    automatically when still periods end.
+                    Times are based on the timezone selected above (or system default). Still
+                    periods that span midnight (e.g., 22:00 to 06:00) are supported. Patterns
+                    resume automatically when still periods end.
                   </AlertDescription>
                   </AlertDescription>
                 </Alert>
                 </Alert>
               </div>
               </div>

+ 2 - 27
modules/core/log_handler.py

@@ -8,31 +8,11 @@ via WebSocket.
 
 
 import logging
 import logging
 from collections import deque
 from collections import deque
-from datetime import datetime, timezone as dt_timezone
+from datetime import datetime
 from typing import List, Dict, Any
 from typing import List, Dict, Any
 import threading
 import threading
 import asyncio
 import asyncio
 
 
-try:
-    from zoneinfo import ZoneInfo
-except ImportError:
-    from backports.zoneinfo import ZoneInfo
-
-
-def _get_configured_timezone() -> ZoneInfo:
-    """
-    Get the configured timezone from state.
-
-    Returns UTC if state is not available or timezone is invalid.
-    """
-    try:
-        # Import here to avoid circular import at module load time
-        from modules.core.state import state
-        tz_name = getattr(state, 'timezone', 'UTC') or 'UTC'
-        return ZoneInfo(tz_name)
-    except Exception:
-        return ZoneInfo('UTC')
-
 
 
 class MemoryLogHandler(logging.Handler):
 class MemoryLogHandler(logging.Handler):
     """
     """
@@ -86,13 +66,8 @@ class MemoryLogHandler(logging.Handler):
         Returns:
         Returns:
             Dictionary containing formatted log data.
             Dictionary containing formatted log data.
         """
         """
-        # Convert timestamp to configured timezone
-        tz = _get_configured_timezone()
-        utc_dt = datetime.fromtimestamp(record.created, tz=dt_timezone.utc)
-        local_dt = utc_dt.astimezone(tz)
-
         return {
         return {
-            "timestamp": local_dt.isoformat(),
+            "timestamp": datetime.fromtimestamp(record.created).isoformat(),
             "level": record.levelname,
             "level": record.levelname,
             "logger": record.name,
             "logger": record.name,
             "line": record.lineno,
             "line": record.lineno,