update km/h

This commit is contained in:
2026-01-14 14:29:47 +01:00
parent b8db847343
commit 5332ab9dc1
2 changed files with 58 additions and 50 deletions

View File

@@ -95,8 +95,8 @@
<div class="header-right">
<div class="weather-info">
<span title="Wind">🌬️ {weatherData.wind_speed.toFixed(1)}m/s</span>
<span title="Gust">💨 {weatherData.wind_gust.toFixed(1)}m/s</span>
<span title="Wind">🌬️ {weatherData.wind_speed.toFixed(1)} km/h</span>
<span title="Gust">💨 {weatherData.wind_gust.toFixed(1)} km/h</span>
<span title="Temperature">🌡️ {weatherData.temp.toFixed(1)} °C</span>
<span title="Feels like">{weatherData.feels_like.toFixed(1)} °C</span>
</div>

View File

@@ -13,7 +13,6 @@
// Update heading with detailed logging to debug
$: if (status?.heading !== undefined && status?.heading !== null) {
const newHeading = status.heading;
const oldHeading = heading;
if (heading === null) {
// First time: accept any value
@@ -25,7 +24,6 @@
} else {
// Normal update
heading = newHeading;
console.log(` ✓ Updated to ${heading}°`);
}
}
@@ -34,31 +32,38 @@
$: connected = status?.connected || false;
let targetHeading = 0;
let hasTarget = false;
// ✅ Target heading from rotator status (when controlled by PST Rotator or other software)
$: statusTargetHeading = status?.target_heading ?? null;
// Clear target when we reach it (within 5 degrees)
$: if (hasTarget && heading !== null) {
const diff = Math.abs(heading - targetHeading);
// Local target (when clicking on map in ShackMaster)
let localTargetHeading = null;
// ✅ Determine if antenna is moving to a target from status
// (target differs from current heading by more than 2 degrees)
$: isMovingFromStatus = statusTargetHeading !== null &&
heading !== null &&
(() => {
const diff = Math.abs(statusTargetHeading - heading);
const wrappedDiff = Math.min(diff, 360 - diff);
if (wrappedDiff < 5) {
hasTarget = false;
}
}
return wrappedDiff > 2;
})();
async function goToHeading() {
if (targetHeading < 0 || targetHeading > 359) {
// Removed alert popup - check console for errors
return;
}
try {
hasTarget = true; // Mark that we have a target
const adjustedHeading = (targetHeading + 360) % 360;
await api.rotator.setHeading(adjustedHeading);
} catch (err) {
console.error('Failed to set heading:', err);
hasTarget = false;
// Removed alert popup - check console for errors
// ✅ Active target: prefer status target when moving, otherwise use local target
$: activeTargetHeading = localTargetHeading ?? (isMovingFromStatus ? statusTargetHeading : null);
// ✅ Has target if there's an active target that differs from current heading
$: hasTarget = activeTargetHeading !== null && heading !== null && (() => {
const diff = Math.abs(activeTargetHeading - heading);
const wrappedDiff = Math.min(diff, 360 - diff);
return wrappedDiff > 2;
})();
// Clear local target when we reach it (within 3 degrees)
$: if (localTargetHeading !== null && heading !== null) {
const diff = Math.abs(heading - localTargetHeading);
const wrappedDiff = Math.min(diff, 360 - diff);
if (wrappedDiff < 3) {
localTargetHeading = null;
}
}
@@ -80,6 +85,7 @@
async function stop() {
try {
localTargetHeading = null; // Clear local target on stop
await api.rotator.stop();
} catch (err) {
console.error('Failed to stop:', err);
@@ -87,7 +93,7 @@
}
// Handle click on compass to set heading
function handleCompassClick(event) {
async function handleCompassClick(event) {
const svg = event.currentTarget;
const rect = svg.getBoundingClientRect();
const centerX = rect.width / 2;
@@ -103,10 +109,16 @@
// Round to nearest 5 degrees
const roundedHeading = Math.round(angle / 5) * 5;
const adjustedHeading = (roundedHeading + 360) % 360;
// Set target and go
targetHeading = roundedHeading;
goToHeading();
// ✅ CORRIGÉ : Send command first, then set localTargetHeading only on success
try {
await api.rotator.setHeading(adjustedHeading);
// Only set local target AFTER successful API call
localTargetHeading = adjustedHeading;
} catch (err) {
console.error('Failed to set heading:', err);
}
}
</script>
@@ -123,8 +135,8 @@
<div class="heading-label">CURRENT HEADING</div>
<div class="heading-value">
{displayHeading}°
{#if hasTarget}
<span class="target-indicator">{targetHeading}°</span>
{#if hasTarget && activeTargetHeading !== null}
<span class="target-indicator">{activeTargetHeading}°</span>
{/if}
</div>
</div>
@@ -281,19 +293,21 @@
</g>
<!-- Target arrow (if we have a target) -->
{#if hasTarget}
<g transform="rotate({targetHeading})">
<line x1="0" y1="0" x2="0" y2="-120"
<!-- Target arrow (yellow) - shown when antenna is moving to target -->
{#if hasTarget && activeTargetHeading !== null}
<g transform="rotate({activeTargetHeading})">
<!-- Target direction line (dashed yellow) -->
<line x1="0" y1="0" x2="0" y2="-135"
stroke="#ffc107"
stroke-width="3"
stroke-dasharray="8,4"
opacity="0.9"/>
<g transform="translate(0, -120)">
<polygon points="0,-15 -10,10 0,5 10,10"
<!-- Target arrow head with pulse animation -->
<g transform="translate(0, -135)">
<polygon points="0,-12 -8,6 0,2 8,6"
fill="#ffc107"
stroke="#ff9800"
stroke-width="2"
stroke-width="1.5"
style="filter: drop-shadow(0 0 10px rgba(255, 193, 7, 0.8))">
<animate attributeName="opacity" values="0.8;1;0.8" dur="1s" repeatCount="indefinite"/>
</polygon>
@@ -301,7 +315,7 @@
</g>
{/if}
<!-- Center dot (your QTH - JN36dg) -->
<!-- Center dot (your QTH) -->
<circle cx="0" cy="0" r="5" fill="#f44336" stroke="#fff" stroke-width="2">
<animate attributeName="r" values="5;7;5" dur="2s" repeatCount="indefinite"/>
</circle>
@@ -343,8 +357,6 @@
</div>
</div>
{/if}
<!-- Go To Heading -->
</div>
</div>
@@ -395,8 +407,6 @@
gap: 10px;
}
/* Heading Display */
.heading-controls-row {
display: flex;
align-items: center;
@@ -485,7 +495,6 @@
50% { opacity: 1; }
}
/* Map */
.map-container {
display: flex;
justify-content: center;
@@ -521,7 +530,7 @@
.clickable-compass {
cursor: crosshair;
user-select: none;
outline: none; /* Remove focus outline */
outline: none;
}
.clickable-compass:hover {
@@ -540,5 +549,4 @@
font-size: 12px;
font-weight: 600;
}
</style>