feat: SPE amp ON/OFF buttons and Low/Mid/High power-level control (keystroke codes best-guess from APG, pending hw verification)

This commit is contained in:
2026-07-21 01:25:55 +02:00
parent be1ae76eb3
commit 7d7d175ede
5 changed files with 92 additions and 2 deletions
+24 -1
View File
@@ -4,7 +4,7 @@ import {
GetFlexState, FlexSetPower, FlexSetTunePower, FlexTune, FlexSetVox, FlexSetVoxLevel, FlexSetVoxDelay,
FlexSetProcessor, FlexSetProcessorLevel, FlexSetMon, FlexSetMonLevel, FlexSetMic,
FlexMox, FlexAmpOperate,
GetPGXLStatus, PGXLSetFanMode, GetPGXLSettings, GetSPEStatus, SPESetOperate,
GetPGXLStatus, PGXLSetFanMode, GetPGXLSettings, GetSPEStatus, SPESetOperate, SPESetPower, SPESetPowerLevel,
FlexSetAGCMode, FlexSetAGCThreshold, FlexSetAudioLevel, FlexSetMute, FlexSetRXAntenna, FlexSetTXAntenna, FlexSetSplit, FlexSetActiveSlice, FlexSetTXSlice,
FlexSetRIT, FlexSetRITFreq, FlexSetXIT, FlexSetXITFreq,
FlexSetNB, FlexSetNBLevel, FlexSetNR, FlexSetNRLevel, FlexSetANF, FlexSetANFLevel,
@@ -814,6 +814,29 @@ export function FlexPanel({ onCWSpeed, onReportRST }: { onCWSpeed?: (wpm: number
spe.operate ? 'bg-warning text-warning-foreground border-warning shadow-[0_0_14px] shadow-warning/50' : 'bg-card text-warning border-warning hover:bg-warning-muted')}>
{spe.operate ? 'OPERATE' : 'STANDBY'}
</button>
{/* Power ON / OFF (best-guess keystrokes from the APG — verify on hw). */}
<div className="inline-flex rounded-lg overflow-hidden border-2 border-success/70">
<button type="button" disabled={!spe.connected}
onClick={() => SPESetPower(true).catch(() => {})}
className="px-3 py-2 text-sm font-bold bg-card text-success hover:bg-success/15 disabled:opacity-30">ON</button>
<button type="button" disabled={!spe.connected}
onClick={() => SPESetPower(false).catch(() => {})}
className="px-3 py-2 text-sm font-bold bg-card text-danger border-l-2 border-success/70 hover:bg-danger/15 disabled:opacity-30">OFF</button>
</div>
{/* Output power level: Low / Mid / High. */}
<div className="inline-flex rounded-lg overflow-hidden border border-border">
{(['L', 'M', 'H'] as const).map((lvl, i) => {
const active = (spe.power_level || '').trim().toUpperCase() === lvl;
return (
<button key={lvl} type="button" disabled={!spe.connected}
onClick={() => SPESetPowerLevel(lvl).catch(() => {})}
className={cn('px-3 py-2 text-sm font-bold disabled:opacity-30', i > 0 && 'border-l border-border',
active ? 'bg-primary text-primary-foreground' : 'bg-card text-muted-foreground hover:bg-muted')}>
{powerLevelLabel(lvl)}
</button>
);
})}
</div>
<span className={cn('inline-flex items-center gap-1.5 text-sm', spe.connected ? 'text-muted-foreground' : 'text-danger')}>
<span className={cn('size-2 rounded-full', spe.connected ? 'bg-success' : 'bg-danger')} />
{spe.connected ? (spe.tx ? 'TX' : 'RX') : t('flxp.pgOffline')}
+4
View File
@@ -721,6 +721,10 @@ export function RunBackupNow():Promise<string>;
export function SPESetOperate(arg1:boolean):Promise<void>;
export function SPESetPower(arg1:boolean):Promise<void>;
export function SPESetPowerLevel(arg1:string):Promise<void>;
export function SaveADIFFile():Promise<string>;
export function SaveADIFMonitor(arg1:main.ADIFMonitorConfig):Promise<void>;
+8
View File
@@ -1398,6 +1398,14 @@ export function SPESetOperate(arg1) {
return window['go']['main']['App']['SPESetOperate'](arg1);
}
export function SPESetPower(arg1) {
return window['go']['main']['App']['SPESetPower'](arg1);
}
export function SPESetPowerLevel(arg1) {
return window['go']['main']['App']['SPESetPowerLevel'](arg1);
}
export function SaveADIFFile() {
return window['go']['main']['App']['SaveADIFFile']();
}