feat(kpa): the Elecraft amplifiers in the Settings, the card and the widget
Wired into the multi-amplifier support that already carries the SPE, the
ACOM and the PowerGenius: a fourth brand rather than a fourth mechanism.
The linking, the fan-out and the poll all work on it unchanged.
Three things the KPA does differently, and each is handled where it shows
rather than explained in a hint:
- A KPA500 has no network side at all. Choosing it puts the entry on
serial, and a configuration still asking for TCP is refused with a
line saying so instead of retrying an address that cannot answer.
- The amplifier answers ^ON while its main supplies are OFF — a sleeping
microcontroller stays awake for exactly that — so power-on stays
available over the network, unlike the SPE and ACOM which need their
serial control lines.
- Going to OPERATE clears the current fault, everything except
temperature. The widget says so under the fault, because the button
that fixes it is the one already on screen.
Defaults that leave a working configuration when the model is changed:
38400 baud, TCP port 1500, and a full-scale power mark of 500 or 1500 W
by model — a KPA500 read against a 1500 W scale looks idle at full
output.
This commit is contained in:
@@ -905,9 +905,10 @@ function AmpStatusCard({ id }: { id: string }) {
|
||||
const t = window.setInterval(tick, 1000);
|
||||
return () => { alive = false; window.clearInterval(t); };
|
||||
}, [id]);
|
||||
const st: any = amp?.spe ?? amp?.acom ?? amp?.pgxl ?? { connected: false };
|
||||
const st: any = amp?.spe ?? amp?.acom ?? amp?.kpa ?? amp?.pgxl ?? { connected: false };
|
||||
const isSPE = !!amp?.spe;
|
||||
const isACOM = !!amp?.acom;
|
||||
const isKPA = !!amp?.kpa;
|
||||
const operate = !!st.operate;
|
||||
return (
|
||||
<div className="rounded-md border border-border p-3 space-y-2 text-xs max-w-xl">
|
||||
@@ -948,7 +949,23 @@ function AmpStatusCard({ id }: { id: string }) {
|
||||
{st.err_text && <div className="col-span-4 text-warning">⚠ {st.err_text} ({st.err_code})</div>}
|
||||
</div>
|
||||
)}
|
||||
{st.connected && !isSPE && !isACOM && (
|
||||
{st.connected && isKPA && (
|
||||
<div className="grid grid-cols-4 gap-x-3 gap-y-1 font-mono text-[11px]">
|
||||
<div>{st.power_on ? 'ON' : 'OFF'}</div>
|
||||
<div>Band {st.band || '—'}</div>
|
||||
<div>{st.fwd_w} W</div>
|
||||
<div>SWR {Number(st.swr ?? 0).toFixed(1)}</div>
|
||||
<div>{st.volt_v} V</div>
|
||||
<div>{st.cur_a} A</div>
|
||||
<div>{st.temp_c}°C</div>
|
||||
<div>{st.tuning ? 'TUNING' : ''}</div>
|
||||
{/* A fault has already put the amplifier in standby by itself, so it
|
||||
is the one thing worth the width — and OPERATE is the way out of
|
||||
it, which the button above already is. */}
|
||||
{st.fault_text && <div className="col-span-4 text-warning">⚠ {st.fault_text}</div>}
|
||||
</div>
|
||||
)}
|
||||
{st.connected && !isSPE && !isACOM && !isKPA && (
|
||||
<div className="grid grid-cols-3 gap-x-3 gap-y-1 font-mono text-[11px]">
|
||||
<div>{st.state || ''}</div>
|
||||
<div>Fan {st.fan_mode || '—'}</div>
|
||||
@@ -4142,15 +4159,27 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
|
||||
{ value: 'acom1200', label: '1200S' },
|
||||
{ value: 'acom2020', label: '2020S' },
|
||||
],
|
||||
kpa: [
|
||||
{ value: 'kpa1500', label: 'KPA1500' },
|
||||
{ value: 'kpa500', label: 'KPA500' },
|
||||
],
|
||||
};
|
||||
const brandOf = (ty: string) => (!ty || ty === 'pgxl') ? 'pgxl' : ty.startsWith('acom') ? 'acom' : 'spe';
|
||||
const brandOf = (ty: string) => (!ty || ty === 'pgxl') ? 'pgxl'
|
||||
: ty.startsWith('acom') ? 'acom'
|
||||
: ty.startsWith('kpa') ? 'kpa' : 'spe';
|
||||
const patchAmp = (i: number, patch: Partial<AmpUI>) => setAmps((l) => l.map((a, j) => (j === i ? { ...a, ...patch } : a)));
|
||||
// Each family has a fixed serial speed: SPE talks 115200, the ACOM S-series is
|
||||
// 9600 8N1 — preset it so switching brand just works. PGXL is TCP-only.
|
||||
// Each family has its own fixed serial speed and its own default port, so
|
||||
// switching model leaves a working configuration rather than one the
|
||||
// operator has to repair. A KPA500 has no network side at all — it is put
|
||||
// on serial here rather than being allowed to sit on a TCP setting that
|
||||
// could never connect.
|
||||
const applyType = (i: number, v: string) => patchAmp(i, {
|
||||
type: v,
|
||||
transport: v === 'pgxl' ? 'tcp' : amps[i].transport,
|
||||
baud: v.startsWith('acom') ? 9600 : v.startsWith('spe') ? 115200 : amps[i].baud,
|
||||
transport: v === 'pgxl' ? 'tcp' : v === 'kpa500' ? 'serial' : amps[i].transport,
|
||||
baud: v.startsWith('acom') ? 9600 : v.startsWith('spe') ? 115200 : v.startsWith('kpa') ? 38400 : amps[i].baud,
|
||||
port: v === 'kpa1500' ? 1500 : amps[i].port,
|
||||
});
|
||||
const addAmp = () => setAmps((l) => [...l, {
|
||||
id: '', name: '', enabled: true, type: 'spe13', transport: 'tcp', host: '', port: 9008, com_port: '', baud: 115200,
|
||||
@@ -4195,6 +4224,7 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
|
||||
<SelectItem value="pgxl">4O3A</SelectItem>
|
||||
<SelectItem value="spe">SPE</SelectItem>
|
||||
<SelectItem value="acom">ACOM</SelectItem>
|
||||
<SelectItem value="kpa">Elecraft</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user