fix(pgxl): draw the amplifier card's meters from the amp when there is no Flex
The PowerGenius XL card gated its whole meter row on flex.amp_available, so on any station without a FlexRadio it rendered OPERATE and the fan selector over an otherwise empty two-column card — reported from a TS-590 station. Nothing was missing from the backend. internal/powergenius already parses forward power, drain current, VSWR and temperature out of the GSCP status frame, and the docked AmpWidget already prefers the radio's meter stream and falls back to those. Only the full card never learnt the fallback. Same source preference as the widget, and the same two exclusions: peakfwd and peakid are latched maxima that are never reset and survive in the last-known status after the amp disconnects, so the plain readings are used and gated on the transmit state instead of freezing on the last over.
This commit is contained in:
+4
-2
@@ -5,12 +5,14 @@
|
|||||||
"en": [
|
"en": [
|
||||||
"QSOs logged from WSJT-X now carry the space weather and the distance, like hand-logged ones. The UDP path stamped the station profile, the DXCC and the QSL defaults but not SFI, A, K or distance — so an operator running digital had those fields empty across the whole log. Space weather is only stamped on a contact less than a day old: a logger re-broadcasting its backlog would otherwise be handed this morning readings for last month contacts.",
|
"QSOs logged from WSJT-X now carry the space weather and the distance, like hand-logged ones. The UDP path stamped the station profile, the DXCC and the QSL defaults but not SFI, A, K or distance — so an operator running digital had those fields empty across the whole log. Space weather is only stamped on a contact less than a day old: a logger re-broadcasting its backlog would otherwise be handed this morning readings for last month contacts.",
|
||||||
"Band openings: EME contacts are no longer mistaken for an opening. A 2 m opening was announced at 9650 km towards Japan on stations working moonbounce — real contacts, but the moon says nothing about the band, and an antenna pointed that way finds nothing. Each band now has the longest path the atmosphere can actually carry: 3500 km on 2 m, 4000 on 4 m, and no limit at all on 6 and 10 m where multi-hop really does go round the world.",
|
"Band openings: EME contacts are no longer mistaken for an opening. A 2 m opening was announced at 9650 km towards Japan on stations working moonbounce — real contacts, but the moon says nothing about the band, and an antenna pointed that way finds nothing. Each band now has the longest path the atmosphere can actually carry: 3500 km on 2 m, 4000 on 4 m, and no limit at all on 6 and 10 m where multi-hop really does go round the world.",
|
||||||
"Kenwood: WSJT-X \"Fake It\" no longer leaves the dial on the transmit frequency. A frequency set while transmitting was not recorded, so WSJT-X was told the radio was already back on the receive frequency and never restored it."
|
"Kenwood: WSJT-X \"Fake It\" no longer leaves the dial on the transmit frequency. A frequency set while transmitting was not recorded, so WSJT-X was told the radio was already back on the receive frequency and never restored it.",
|
||||||
|
"PowerGenius XL: the Station Control card now shows power, current, SWR and temperature without a FlexRadio. The meters were only ever drawn from the radio's stream, so a station on any other rig got an empty card while the amplifier was reporting all four over its own link."
|
||||||
],
|
],
|
||||||
"fr": [
|
"fr": [
|
||||||
"Les QSO enregistrés depuis WSJT-X portent désormais la météo spatiale et la distance, comme ceux saisis à la main. Le chemin UDP posait le profil station, le DXCC et les défauts QSL mais ni SFI, ni A, ni K, ni distance — un opérateur en numérique avait donc ces champs vides sur tout son log. La météo spatiale n est posée que sur un contact de moins d un jour : sinon un logiciel qui rediffuse son historique se verrait attribuer les relevés de ce matin sur des contacts du mois dernier.",
|
"Les QSO enregistrés depuis WSJT-X portent désormais la météo spatiale et la distance, comme ceux saisis à la main. Le chemin UDP posait le profil station, le DXCC et les défauts QSL mais ni SFI, ni A, ni K, ni distance — un opérateur en numérique avait donc ces champs vides sur tout son log. La météo spatiale n est posée que sur un contact de moins d un jour : sinon un logiciel qui rediffuse son historique se verrait attribuer les relevés de ce matin sur des contacts du mois dernier.",
|
||||||
"Ouvertures de bande : les contacts EME ne sont plus pris pour une ouverture. Une ouverture 2 m était annoncée à 9650 km vers le Japon sur des stations en rebond lunaire — de vrais contacts, mais la Lune ne dit rien de la bande, et une antenne pointée par là ne trouve rien. Chaque bande a désormais la distance maximale que l atmosphère peut réellement porter : 3500 km en 2 m, 4000 en 4 m, et aucune limite en 6 et 10 m où les sauts multiples font vraiment le tour du monde.",
|
"Ouvertures de bande : les contacts EME ne sont plus pris pour une ouverture. Une ouverture 2 m était annoncée à 9650 km vers le Japon sur des stations en rebond lunaire — de vrais contacts, mais la Lune ne dit rien de la bande, et une antenne pointée par là ne trouve rien. Chaque bande a désormais la distance maximale que l atmosphère peut réellement porter : 3500 km en 2 m, 4000 en 4 m, et aucune limite en 6 et 10 m où les sauts multiples font vraiment le tour du monde.",
|
||||||
"Kenwood : le « Fake It » de WSJT-X ne laisse plus le VFO sur la fréquence d émission. Un changement de fréquence pendant l émission n était pas enregistré, WSJT-X croyait donc la radio déjà revenue sur la fréquence de réception et ne la remettait jamais en place."
|
"Kenwood : le « Fake It » de WSJT-X ne laisse plus le VFO sur la fréquence d émission. Un changement de fréquence pendant l émission n était pas enregistré, WSJT-X croyait donc la radio déjà revenue sur la fréquence de réception et ne la remettait jamais en place.",
|
||||||
|
"PowerGenius XL : la carte du Contrôle station affiche désormais puissance, courant, ROS et température sans FlexRadio. Les mesures n étaient tirées que du flux de la radio, si bien qu une station sur une autre radio n avait qu une carte vide alors que l amplificateur remontait les quatre sur sa propre liaison."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -174,6 +174,41 @@ export function AmpCard({ amp, flex, t }: { amp: Amp; flex: any; t: (k: string,
|
|||||||
const operate = viaFlex ? !!flex?.amp_operate : !!pg.operate;
|
const operate = viaFlex ? !!flex?.amp_operate : !!pg.operate;
|
||||||
const connected = !!pg.connected || viaFlex;
|
const connected = !!pg.connected || viaFlex;
|
||||||
const fault = flex?.amp_fault;
|
const fault = flex?.amp_fault;
|
||||||
|
|
||||||
|
// Meters built from the amplifier's own GSCP status frame, for when the radio
|
||||||
|
// is not feeding a meter stream.
|
||||||
|
//
|
||||||
|
// Whether there is power is the amp's state field; how much is the plain
|
||||||
|
// forward figure. NOT "peakfwd" — that is a latched maximum which is never
|
||||||
|
// reset and survives in the last-known status after the amp disconnects, so it
|
||||||
|
// once claimed 1350 W from an old transmission while 10 W was going out. Same
|
||||||
|
// reason peak_id is left alone. Both readings are gated on transmit so they
|
||||||
|
// fall back to zero between overs instead of freezing on the last one.
|
||||||
|
const pgxlMeters = () => {
|
||||||
|
if (!pg.connected) return null;
|
||||||
|
const txing = typeof flex?.transmitting === 'boolean' ? flex.transmitting : /TRANSMIT/i.test(pg.state || '');
|
||||||
|
const fwdW = peakHold('pgfwd', txing ? Number(pg.fwd_w) || 0 : 0);
|
||||||
|
const idA = peakHold('pgid', txing ? Number(pg.id) || 0 : 0);
|
||||||
|
const swr = peakHold('pgswr', txing ? Number(pg.vswr) || 0 : 0);
|
||||||
|
const tempC = Number(pg.temperature) || 0;
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-2 sm:grid-cols-4 gap-2 mt-2 pt-2 border-t border-border/50">
|
||||||
|
<MeterBar label={t('flxp.outputPower')} value={fwdW} unit="W" lo={0} hi={2000}
|
||||||
|
display={`${Math.round(fwdW)} W`}
|
||||||
|
segColor={(f) => (f > 0.9 ? '#dc2626' : f > 0.75 ? '#f59e0b' : '#ea580c')} />
|
||||||
|
<MeterBar label={t('ampw.id')} value={idA} lo={0} hi={25} display={`${idA.toFixed(1)} A`} accent="#16a34a" />
|
||||||
|
{/* Below 1:1 the reading is meaningless, so an idle amp shows a flat bar
|
||||||
|
rather than a zero that looks like a perfect match. */}
|
||||||
|
<MeterBar label={t('ampw.swr')} value={swr >= 1 ? swr : 1} lo={1} hi={3}
|
||||||
|
display={swr >= 1 ? swr.toFixed(1) : '—'}
|
||||||
|
segColor={(f) => (f > 0.75 ? '#dc2626' : f > 0.4 ? '#f59e0b' : '#16a34a')} />
|
||||||
|
<MeterBar label={t('ampw.temp')} value={tempC} unit="°C" lo={0} hi={100}
|
||||||
|
display={tempC > 0 ? `${Math.round(tempC)} °C` : '—'}
|
||||||
|
segColor={(f) => (f > 0.8 ? '#dc2626' : f > 0.6 ? '#f59e0b' : '#ea580c')} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card icon={Flame} ckey="amplifier" title={`${t('flxp.amplifier')}${flex?.amp_model ? ' · ' + flex.amp_model : (pg.model ? ' · ' + pg.model : '')} · ${amp.name}`} accent="#ea580c">
|
<Card icon={Flame} ckey="amplifier" title={`${t('flxp.amplifier')}${flex?.amp_model ? ' · ' + flex.amp_model : (pg.model ? ' · ' + pg.model : '')} · ${amp.name}`} accent="#ea580c">
|
||||||
<div className="flex items-center gap-3 flex-wrap">
|
<div className="flex items-center gap-3 flex-wrap">
|
||||||
@@ -204,13 +239,20 @@ export function AmpCard({ amp, flex, t }: { amp: Amp; flex: any; t: (k: string,
|
|||||||
<span className="px-2 py-1 rounded bg-danger-muted text-danger-muted-foreground text-xs font-bold">{t('flxp.fault')}: {fault}</span>
|
<span className="px-2 py-1 rounded bg-danger-muted text-danger-muted-foreground text-xs font-bold">{t('flxp.fault')}: {fault}</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* Amplifier meters (FWD / ID / TEMP …) from the FlexRadio UDP stream. */}
|
{/* Amplifier meters (FWD / ID / TEMP …).
|
||||||
{viaFlex && (() => {
|
The FlexRadio UDP stream is the preferred source — it is fast and reads
|
||||||
|
the same as SmartSDR. When there is no Flex, or it is not streaming,
|
||||||
|
the amplifier's OWN link carries the same figures; falling back to them
|
||||||
|
is what the docked widget already does. Without that fallback this card
|
||||||
|
showed an operator on a Kenwood nothing but OPERATE and the fan mode,
|
||||||
|
while the amplifier was reporting power, current and temperature all
|
||||||
|
along. */}
|
||||||
|
{(() => {
|
||||||
const meters = (flex?.meters as any[]) || [];
|
const meters = (flex?.meters as any[]) || [];
|
||||||
const dbmToW = (d: number) => Math.pow(10, (d - 30) / 10);
|
const dbmToW = (d: number) => Math.pow(10, (d - 30) / 10);
|
||||||
const amps = meters.filter((m) => (m.src || '').toUpperCase().includes('AMP')
|
const amps = meters.filter((m) => (m.src || '').toUpperCase().includes('AMP')
|
||||||
&& !/^(RL|DRV)$/i.test((m.name || '').trim()));
|
&& !/^(RL|DRV)$/i.test((m.name || '').trim()));
|
||||||
if (amps.length === 0) return null;
|
if (!viaFlex || amps.length === 0) return pgxlMeters();
|
||||||
// Power comes from the radio's meter stream and nothing else. The
|
// Power comes from the radio's meter stream and nothing else. The
|
||||||
// amplifier also reports a "peakfwd", and using it was a mistake twice
|
// amplifier also reports a "peakfwd", and using it was a mistake twice
|
||||||
// over: it is a latched maximum that is never reset, and it survives in
|
// over: it is a latched maximum that is never reset, and it survives in
|
||||||
|
|||||||
Reference in New Issue
Block a user