This commit is contained in:
2026-01-10 04:39:21 +01:00
parent 8de9a0dd87
commit eee3f48569
6 changed files with 75 additions and 31 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -7,7 +7,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
<script type="module" crossorigin src="/assets/index-DY7RBkJT.js"></script>
<script type="module" crossorigin src="/assets/index-CQrlLShx.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-PFp0U9rZ.css">
</head>
<body>
+48 -27
View File
@@ -27,6 +27,7 @@ type Client struct {
// Auto fan management
autoFanEnabled bool
lastFanMode string // Remember last manual mode
autoFanActive bool // Track if auto-fan is currently active (in Broadcast mode)
}
type Status struct {
@@ -190,6 +191,47 @@ func (c *Client) pollLoop() {
// Override PowerForward with display power for frontend
status.PowerForward = status.displayPower
// Auto fan management based on temperature
// Do this BEFORE merging to use the fresh temperature value
if c.autoFanEnabled {
// Use the temperature from the current status message
// If it's 0, use the last known temperature
temp := status.Temperature
if temp == 0 && c.lastStatus != nil {
temp = c.lastStatus.Temperature
}
currentMode := strings.ToUpper(status.FanMode)
if currentMode == "" && c.lastStatus != nil {
currentMode = strings.ToUpper(c.lastStatus.FanMode)
}
// Only act on valid temperature readings
if temp > 5.0 { // Ignore invalid/startup readings below 5°C
// If temp >= 60°C, switch to Broadcast
if temp >= 60.0 && currentMode != "BROADCAST" {
if !c.autoFanActive {
log.Printf("PowerGenius: Temperature %.1f°C >= 60°C, switching fan to Broadcast mode", temp)
c.autoFanActive = true
}
if err := c.setFanModeInternal("BROADCAST"); err != nil {
log.Printf("PowerGenius: Failed to set fan mode: %v", err)
}
}
// If temp <= 55°C, switch back to Contest
if temp <= 55.0 && currentMode == "BROADCAST" {
if c.autoFanActive {
log.Printf("PowerGenius: Temperature %.1f°C <= 55°C, switching fan back to Contest mode", temp)
c.autoFanActive = false
}
if err := c.setFanModeInternal("CONTEST"); err != nil {
log.Printf("PowerGenius: Failed to set fan mode: %v", err)
}
}
}
}
// Merge with existing status (spontaneous messages may only update some fields)
c.statusMu.Lock()
if c.lastStatus != nil {
@@ -216,32 +258,6 @@ func (c *Client) pollLoop() {
c.lastStatus = status
c.statusMu.Unlock()
// Auto fan management based on temperature
if c.autoFanEnabled {
temp := status.Temperature
currentMode := status.FanMode
// If temp >= 60°C, switch to Broadcast
if temp >= 60.0 && currentMode != "Broadcast" {
log.Printf("PowerGenius: Temperature %.1f°C >= 60°C, switching fan to Broadcast mode", temp)
if err := c.SetFanMode("Broadcast"); err != nil {
log.Printf("PowerGenius: Failed to set fan mode: %v", err)
}
}
// If temp <= 55°C, switch back to Contest (or last manual mode)
if temp <= 55.0 && currentMode == "Broadcast" {
targetMode := c.lastFanMode
if targetMode == "" || targetMode == "Broadcast" {
targetMode = "Contest"
}
log.Printf("PowerGenius: Temperature %.1f°C <= 55°C, switching fan back to %s mode", temp, targetMode)
if err := c.SetFanMode(targetMode); err != nil {
log.Printf("PowerGenius: Failed to set fan mode: %v", err)
}
}
}
case <-c.stopChan:
return
}
@@ -462,7 +478,12 @@ func (c *Client) SetFanMode(mode string) error {
// We store it in title case: "Standard", "Contest", "Broadcast"
c.lastFanMode = strings.Title(strings.ToLower(mode))
cmd := fmt.Sprintf("setup fanmode=%s", modeUpper)
return c.setFanModeInternal(modeUpper)
}
// setFanModeInternal sets fan mode without updating lastFanMode (for auto-fan)
func (c *Client) setFanModeInternal(mode string) error {
cmd := fmt.Sprintf("setup fanmode=%s", mode)
_, err := c.sendCommand(cmd)
return err
}
+2 -2
View File
@@ -102,14 +102,14 @@
<!-- Temperature Gauges -->
<div class="temp-group">
<div class="temp-item">
<div class="temp-value" style="color: {tempColor}">{temperature.toFixed(0)}°</div>
<div class="temp-value" style="color: {tempColor}">{temperature.toFixed(1)}°</div>
<div class="temp-label">PA Temp</div>
<div class="temp-mini-bar">
<div class="temp-mini-fill" style="width: {(temperature / 80) * 100}%; background: {tempColor}"></div>
</div>
</div>
<div class="temp-item">
<div class="temp-value" style="color: {tempColor}">{harmonicLoadTemp.toFixed(0)}°</div>
<div class="temp-value" style="color: {tempColor}">{harmonicLoadTemp.toFixed(1)}°</div>
<div class="temp-label">HL Temp</div>
<div class="temp-mini-bar">
<div class="temp-mini-fill" style="width: {(harmonicLoadTemp / 80) * 100}%; background: {tempColor}"></div>
+8 -1
View File
@@ -3,7 +3,14 @@
export let status;
$: heading = status?.heading || 0;
let heading = 0;
let connected = false;
// Update heading only if we have a valid value from status
$: if (status?.heading !== undefined && status?.heading !== null) {
heading = status.heading;
}
$: connected = status?.connected || false;
let targetHeading = 0;