update km/h
This commit is contained in:
@@ -95,10 +95,10 @@
|
||||
|
||||
<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="Temperature">🌡️ {weatherData.temp.toFixed(1)}°C</span>
|
||||
<span title="Feels like">→ {weatherData.feels_like.toFixed(1)}°C</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>
|
||||
<div class="clock">
|
||||
<span class="time">{formatTime(currentTime)}</span>
|
||||
|
||||
@@ -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);
|
||||
return wrappedDiff > 2;
|
||||
})();
|
||||
|
||||
// ✅ 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);
|
||||
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
|
||||
// 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>
|
||||
Reference in New Issue
Block a user