mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-03 12:46:49 +02:00
Merge branch '0.1.8b' into feature/accurate-usage-tracking
This commit is contained in:
@@ -91,6 +91,7 @@ async def get_settings(
|
||||
"ams_history_retention_days",
|
||||
"ftp_retry_count",
|
||||
"ftp_retry_delay",
|
||||
"ftp_timeout",
|
||||
"mqtt_port",
|
||||
]:
|
||||
settings_dict[setting.key] = int(setting.value)
|
||||
|
||||
@@ -86,6 +86,7 @@ class AppSettings(BaseModel):
|
||||
ftp_retry_enabled: bool = Field(default=True, description="Enable automatic retry for FTP operations")
|
||||
ftp_retry_count: int = Field(default=3, description="Number of retry attempts for FTP operations (1-10)")
|
||||
ftp_retry_delay: int = Field(default=2, description="Seconds to wait between FTP retry attempts (1-30)")
|
||||
ftp_timeout: int = Field(default=30, description="FTP connection timeout in seconds (10-120)")
|
||||
|
||||
# MQTT Relay settings for publishing events to external broker
|
||||
mqtt_enabled: bool = Field(default=False, description="Enable MQTT event publishing to external broker")
|
||||
@@ -168,6 +169,7 @@ class AppSettingsUpdate(BaseModel):
|
||||
ftp_retry_enabled: bool | None = None
|
||||
ftp_retry_count: int | None = None
|
||||
ftp_retry_delay: int | None = None
|
||||
ftp_timeout: int | None = None
|
||||
mqtt_enabled: bool | None = None
|
||||
mqtt_broker: str | None = None
|
||||
mqtt_port: int | None = None
|
||||
|
||||
@@ -76,18 +76,6 @@ class PrintScheduler:
|
||||
if item.scheduled_time and item.scheduled_time > datetime.utcnow():
|
||||
continue
|
||||
|
||||
# Safety: Skip stale items (older than 24 hours) to prevent phantom reprints
|
||||
# This protects against items that got stuck in "pending" status due to
|
||||
# crashes/restarts after the print already started
|
||||
stale_threshold = timedelta(hours=24)
|
||||
if item.created_at and datetime.utcnow() - item.created_at.replace(tzinfo=None) > stale_threshold:
|
||||
logger.warning(f"Queue item {item.id} is stale (created {item.created_at}), marking as expired")
|
||||
item.status = "expired"
|
||||
item.error_message = "Queue item expired - older than 24 hours"
|
||||
item.completed_at = datetime.utcnow()
|
||||
await db.commit()
|
||||
continue
|
||||
|
||||
# Skip items that require manual start
|
||||
if item.manual_start:
|
||||
continue
|
||||
|
||||
@@ -1890,63 +1890,59 @@ export function SettingsPage() {
|
||||
<label className="block text-sm text-bambu-gray mb-1">
|
||||
Retry attempts
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
<div className="relative w-44">
|
||||
<select
|
||||
value={localSettings.ftp_retry_count ?? 3}
|
||||
onChange={(e) => updateSetting('ftp_retry_count', Math.min(10, Math.max(1, parseInt(e.target.value) || 3)))}
|
||||
className="w-24 px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none"
|
||||
/>
|
||||
<span className="text-bambu-gray">times</span>
|
||||
onChange={(e) => updateSetting('ftp_retry_count', parseInt(e.target.value))}
|
||||
className="w-full px-3 py-2 pr-10 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none appearance-none cursor-pointer"
|
||||
>
|
||||
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(n => (
|
||||
<option key={n} value={n}>{n} {n === 1 ? 'time' : 'times'}</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray pointer-events-none" />
|
||||
</div>
|
||||
<p className="text-xs text-bambu-gray mt-1">
|
||||
Number of retry attempts before giving up (1-10)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm text-bambu-gray mb-1">
|
||||
Retry delay
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
max="30"
|
||||
<div className="relative w-44">
|
||||
<select
|
||||
value={localSettings.ftp_retry_delay ?? 2}
|
||||
onChange={(e) => updateSetting('ftp_retry_delay', Math.min(30, Math.max(1, parseInt(e.target.value) || 2)))}
|
||||
className="w-24 px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none"
|
||||
/>
|
||||
<span className="text-bambu-gray">seconds</span>
|
||||
onChange={(e) => updateSetting('ftp_retry_delay', parseInt(e.target.value))}
|
||||
className="w-full px-3 py-2 pr-10 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none appearance-none cursor-pointer"
|
||||
>
|
||||
{[1, 2, 3, 5, 10, 15, 20, 30].map(n => (
|
||||
<option key={n} value={n}>{n} {n === 1 ? 'second' : 'seconds'}</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray pointer-events-none" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm text-bambu-gray mb-1">
|
||||
Connection timeout
|
||||
</label>
|
||||
<div className="relative w-44">
|
||||
<select
|
||||
value={localSettings.ftp_timeout ?? 30}
|
||||
onChange={(e) => updateSetting('ftp_timeout', parseInt(e.target.value))}
|
||||
className="w-full px-3 py-2 pr-10 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none appearance-none cursor-pointer"
|
||||
>
|
||||
{[10, 15, 20, 30, 45, 60, 90, 120].map(n => (
|
||||
<option key={n} value={n}>{n} seconds</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray pointer-events-none" />
|
||||
</div>
|
||||
<p className="text-xs text-bambu-gray mt-1">
|
||||
Wait time between retries (1-30)
|
||||
Increase for printers with weak WiFi
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="pt-2 border-t border-bambu-dark-tertiary">
|
||||
<label className="block text-sm text-bambu-gray mb-1">
|
||||
Connection timeout
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
min="10"
|
||||
max="120"
|
||||
value={localSettings.ftp_timeout ?? 30}
|
||||
onChange={(e) => updateSetting('ftp_timeout', Math.min(120, Math.max(10, parseInt(e.target.value) || 30)))}
|
||||
className="w-24 px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none"
|
||||
/>
|
||||
<span className="text-bambu-gray">seconds</span>
|
||||
</div>
|
||||
<p className="text-xs text-bambu-gray mt-1">
|
||||
Socket timeout for slow connections. Increase for A1/A1 Mini printers with weak WiFi (10-120)
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-2
@@ -23,8 +23,8 @@
|
||||
|
||||
<!-- Splash screens for iOS -->
|
||||
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
|
||||
<script type="module" crossorigin src="/assets/index-CwIN-fI6.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CosC5iN4.css">
|
||||
<script type="module" crossorigin src="/assets/index-DJ147FSl.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-togsBDt6.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
Reference in New Issue
Block a user