fix(amp): couple a chosen GROUP, not every amplifier
The first version was a single switch meaning "command them all", and that is wrong the moment a station has three: two SPE on a combiner and a PowerGenius on another antenna would all go into OPERATE together, keying an amplifier that has nothing to do with the pair. It is now a set. Each amplifier is ticked into the group or not, the group is stored as a list of ids, and an amplifier outside it keeps its own buttons — which is the entire point of it being a set. A group of fewer than two members is stored as none: one amplifier coupled to itself would make every command fan out to a single member for ever. A remembered member that is no longer running is skipped rather than failing the command — deleting one amplifier must not break the button on the other. An amplifier saved without an id cannot join, and the panel says so instead of quietly omitting it from the list.
This commit is contained in:
+51
-24
@@ -1,36 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
import "testing"
|
||||
|
||||
// A combiner sums two amplifiers and commands nothing, so "combined" operation
|
||||
// is really two amplifiers that must be kept in the same state. Leaving one in
|
||||
// OPERATE while the other sits in STANDBY is exactly what must not happen —
|
||||
// the combiner would then see power on one input only.
|
||||
func TestAmpTargets(t *testing.T) {
|
||||
// The coupling is a SET, not a global switch.
|
||||
//
|
||||
// A station can run a combiner pair AND a third amplifier that has nothing to
|
||||
// do with it — two SPE on the combiner, a PowerGenius on another antenna. A
|
||||
// global flag would send that third one into OPERATE alongside them.
|
||||
func TestAmpTargetsFollowTheGroup(t *testing.T) {
|
||||
a := &App{}
|
||||
a.ampInsts = map[string]*ampInst{"left": {}, "right": {}, "third": {}}
|
||||
a.ampInsts = map[string]*ampInst{"spe1": {}, "spe2": {}, "pgxl": {}}
|
||||
group := []string{"spe1", "spe2"}
|
||||
|
||||
// Unlinked: only the amplifier that was clicked.
|
||||
if got := a.ampTargets("left", false); len(got) != 1 || got[0] != "left" {
|
||||
t.Errorf("unlinked = %v, want just [left]", got)
|
||||
// A member commands the whole group, itself first.
|
||||
got := a.ampTargets("spe2", group)
|
||||
if len(got) != 2 || got[0] != "spe2" || got[1] != "spe1" {
|
||||
t.Errorf("member = %v, want [spe2 spe1] — the clicked one first", got)
|
||||
}
|
||||
|
||||
// Linked: every running amplifier, and the one clicked FIRST — a partial
|
||||
// failure should still have done what the operator asked before it stopped.
|
||||
// The amplifier OUTSIDE the group keeps its buttons to itself.
|
||||
if got := a.ampTargets("pgxl", group); len(got) != 1 || got[0] != "pgxl" {
|
||||
t.Errorf("outsider = %v, want just [pgxl]", got)
|
||||
}
|
||||
|
||||
got := a.ampTargets("right", true)
|
||||
if len(got) != 3 {
|
||||
t.Fatalf("linked = %v, want all three", got)
|
||||
// No group at all: everyone is on their own.
|
||||
if got := a.ampTargets("spe1", nil); len(got) != 1 || got[0] != "spe1" {
|
||||
t.Errorf("no group = %v, want just [spe1]", got)
|
||||
}
|
||||
if got[0] != "right" {
|
||||
t.Errorf("clicked amplifier is %q, want it first", got[0])
|
||||
|
||||
// A group remembering an amplifier that is gone must not carry it: it would
|
||||
// fail the command for a member that no longer exists.
|
||||
if got := a.ampTargets("spe1", []string{"spe1", "deleted"}); len(got) != 1 || got[0] != "spe1" {
|
||||
t.Errorf("stale member = %v, want it dropped", got)
|
||||
}
|
||||
rest := append([]string{}, got[1:]...)
|
||||
sort.Strings(rest)
|
||||
if rest[0] != "left" || rest[1] != "third" {
|
||||
t.Errorf("rest = %v, want the other two", rest)
|
||||
}
|
||||
|
||||
// One amplifier coupled to itself is not a group — storing it would make every
|
||||
// command fan out to a single member for ever, which is just noise.
|
||||
func TestLinkedAmpsNeedsTwo(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
in []string
|
||||
want int
|
||||
}{
|
||||
{[]string{"a", "b"}, 2},
|
||||
{[]string{"a"}, 0},
|
||||
{[]string{" ", "a"}, 0}, // blanks are not members
|
||||
{nil, 0},
|
||||
} {
|
||||
clean := make([]string, 0, len(tc.in))
|
||||
for _, id := range tc.in {
|
||||
if id != "" && id != " " {
|
||||
clean = append(clean, id)
|
||||
}
|
||||
}
|
||||
if len(clean) < 2 {
|
||||
clean = nil
|
||||
}
|
||||
if len(clean) != tc.want {
|
||||
t.Errorf("SetLinkedAmps(%v) would keep %d, want %d", tc.in, len(clean), tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16230,7 +16230,7 @@ func (a *App) AmpOperate(id string, on bool) error {
|
||||
// call this, and a coupling implemented in one of them would be missing from
|
||||
// the other — which on a combiner means one amplifier keyed and one not.
|
||||
var firstErr error
|
||||
for _, tid := range a.ampTargets(id, a.GetAmpsLinked()) {
|
||||
for _, tid := range a.ampTargets(id, a.GetLinkedAmps()) {
|
||||
if err := a.ampOperateOne(tid, on); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
@@ -16263,10 +16263,11 @@ func (a *App) AmpPower(id string, on bool) (err error) {
|
||||
applog.Printf("amp %s: power %v failed: %v", id, on, err)
|
||||
}
|
||||
}()
|
||||
linked := a.GetAmpsLinked()
|
||||
linked := a.GetLinkedAmps()
|
||||
targets := a.ampTargets(id, linked)
|
||||
var firstErr error
|
||||
for _, tid := range a.ampTargets(id, linked) {
|
||||
if e := a.ampPowerOne(tid, on, linked); e != nil && firstErr == nil {
|
||||
for _, tid := range targets {
|
||||
if e := a.ampPowerOne(tid, on, len(targets) > 1); e != nil && firstErr == nil {
|
||||
firstErr = e
|
||||
}
|
||||
}
|
||||
@@ -17850,12 +17851,36 @@ func (a *App) SetCompactHeight(h int) {
|
||||
// what must not happen — the combiner would see power on one input only.
|
||||
const keyAmpsLinked = "amps.linked"
|
||||
|
||||
// GetAmpsLinked reports whether the amplifiers are commanded together.
|
||||
func (a *App) GetAmpsLinked() bool { return a.settingOr(keyAmpsLinked, "") == "1" }
|
||||
// GetLinkedAmps returns the ids of the amplifiers commanded together.
|
||||
//
|
||||
// A SET, not a global flag. A station can have a combiner pair AND a third
|
||||
// amplifier that has nothing to do with it — two SPE on the combiner and a
|
||||
// PowerGenius on another antenna — and a global switch would send that third
|
||||
// one into OPERATE alongside them.
|
||||
func (a *App) GetLinkedAmps() []string {
|
||||
out := []string{}
|
||||
for _, id := range strings.Split(a.settingOr(keyAmpsLinked, ""), ",") {
|
||||
if id = strings.TrimSpace(id); id != "" {
|
||||
out = append(out, id)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// SetAmpsLinked turns coupling on or off.
|
||||
func (a *App) SetAmpsLinked(on bool) error {
|
||||
a.setSetting(keyAmpsLinked, boolStr(on))
|
||||
// SetLinkedAmps records which amplifiers are coupled.
|
||||
func (a *App) SetLinkedAmps(ids []string) error {
|
||||
clean := make([]string, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
if id = strings.TrimSpace(id); id != "" {
|
||||
clean = append(clean, id)
|
||||
}
|
||||
}
|
||||
// One amplifier coupled to itself is not a group; store nothing rather than
|
||||
// a set that would make ampTargets fan out to a single member for ever.
|
||||
if len(clean) < 2 {
|
||||
clean = nil
|
||||
}
|
||||
a.setSetting(keyAmpsLinked, strings.Join(clean, ","))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17865,21 +17890,33 @@ func (a *App) SetAmpsLinked(on bool) error {
|
||||
// The METERS are deliberately untouched by this — each amplifier keeps its own
|
||||
// bars. Two amps combined are still two amps, and an operator watching for one
|
||||
// of them to run away needs to see them apart.
|
||||
func (a *App) ampTargets(id string, linked bool) []string {
|
||||
if !linked {
|
||||
func (a *App) ampTargets(id string, linked []string) []string {
|
||||
inGroup := false
|
||||
for _, l := range linked {
|
||||
if l == id {
|
||||
inGroup = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// An amplifier outside the group keeps its own buttons to itself — that is
|
||||
// the whole point of the group being a set.
|
||||
if !inGroup {
|
||||
return []string{id}
|
||||
}
|
||||
a.ampsMu.Lock()
|
||||
defer a.ampsMu.Unlock()
|
||||
out := make([]string, 0, len(a.ampInsts))
|
||||
out := make([]string, 0, len(linked))
|
||||
// The one that was asked for goes FIRST, so a partial failure still did what
|
||||
// the operator clicked before it stopped.
|
||||
if _, ok := a.ampInsts[id]; ok {
|
||||
out = append(out, id)
|
||||
}
|
||||
for k := range a.ampInsts {
|
||||
if k != id {
|
||||
out = append(out, k)
|
||||
out = append(out, id)
|
||||
for _, l := range linked {
|
||||
if l == id {
|
||||
continue
|
||||
}
|
||||
// Only amplifiers actually running: a group remembering one that has been
|
||||
// deleted or switched off must not fail the whole command for it.
|
||||
if _, ok := a.ampInsts[l]; ok {
|
||||
out = append(out, l)
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
||||
+2
-2
@@ -3,10 +3,10 @@
|
||||
"version": "0.25.1",
|
||||
"date": "",
|
||||
"en": [
|
||||
"Amplifiers: an option commands them together — ON, OFF and OPERATE act on all at once, for a combiner. Each keeps its own meters."
|
||||
"Amplifiers: tick the ones sharing a combiner and ON, OFF and OPERATE act on all of them at once. Each keeps its own meters."
|
||||
],
|
||||
"fr": [
|
||||
"Amplificateurs : une option les commande ensemble — ON, OFF et OPERATE agissent sur tous à la fois, pour un combiner. Chacun garde ses mesures."
|
||||
"Amplificateurs : coche ceux qui partagent un combiner et ON, OFF et OPERATE agissent sur tous à la fois. Chacun garde ses mesures."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@ import {
|
||||
GetADIFMonitor, SaveADIFMonitor, PickADIFMonitorFile,
|
||||
GetRelayAuto, SaveRelayAuto, GetStationDevices,
|
||||
GetAwardDefs, GetTrackedAwards, SaveTrackedAwards,
|
||||
GetBandOpenSettings, SaveBandOpenSettings, GetPSKReporterStatus, GetChaseNewGrids, SetChaseNewGrids, GetGridCacheStatus, GetAmpsLinked, SetAmpsLinked, GetSpotTTLMinutes, SetSpotTTLMinutes,
|
||||
GetBandOpenSettings, SaveBandOpenSettings, GetPSKReporterStatus, GetChaseNewGrids, SetChaseNewGrids, GetGridCacheStatus, GetLinkedAmps, SetLinkedAmps, GetSpotTTLMinutes, SetSpotTTLMinutes,
|
||||
} from '../../wailsjs/go/main/App';
|
||||
import type { profile as profileModels } from '../../wailsjs/go/models';
|
||||
import type { LookupSettingsForm, StationSettingsForm, ListsSettingsForm, ModePresetForm } from '@/types';
|
||||
@@ -1274,7 +1274,7 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
// Amplifier list — operators can run SEVERAL amps (even two SPEs combined),
|
||||
// each with its own connection. Saved as a whole via SaveAmplifiers.
|
||||
const [amps, setAmps] = useState<AmpUI[]>([]);
|
||||
const [ampsLinked, setAmpsLinked] = useState(false);
|
||||
const [linkedAmps, setLinkedAmps] = useState<string[]>([]);
|
||||
|
||||
// WinKeyer CW keyer settings + macro editor.
|
||||
type WKMac = { label: string; text: string };
|
||||
@@ -1572,7 +1572,7 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
(async () => {
|
||||
try { setBandOpen(await GetBandOpenSettings()); } catch { /* defaults stand */ }
|
||||
try { setChaseGrids(await GetChaseNewGrids()); } catch { /* defaults stand */ }
|
||||
try { setAmpsLinked(await GetAmpsLinked()); } catch { /* defaults stand */ }
|
||||
try { setLinkedAmps((await GetLinkedAmps()) ?? []); } catch { /* defaults stand */ }
|
||||
try { const n = await GetSpotTTLMinutes(); setSpotTTL(n); setSpotTTLText(String(n)); } catch { /* defaults stand */ }
|
||||
})();
|
||||
// Poll the feed while the panel is open: a live count is the only thing that
|
||||
@@ -3604,20 +3604,36 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
<Plus className="size-3.5 mr-1" /> {t('amp.add')}
|
||||
</Button>
|
||||
|
||||
{/* Coupling belongs to the SET of amplifiers, not to any one of them,
|
||||
so it sits with the other set-level control rather than above the
|
||||
first card — where three tall cards push it out of view and it has
|
||||
to be hunted for. Shown from two amplifiers up: coupling one to
|
||||
itself is a switch that cannot do anything. */}
|
||||
{/* WHICH amplifiers are coupled, not whether coupling is on.
|
||||
A station can run a combiner pair AND a third amplifier that has
|
||||
nothing to do with it — two SPE on the combiner, a PowerGenius on
|
||||
another antenna — so a single switch would send that third one into
|
||||
OPERATE alongside them. Shown from two amplifiers up. */}
|
||||
{amps.length > 1 && (
|
||||
<label className="flex items-start gap-2 text-sm cursor-pointer border-t border-border/60 pt-3">
|
||||
<Checkbox checked={ampsLinked} className="mt-0.5"
|
||||
onCheckedChange={(c) => { setAmpsLinked(!!c); SetAmpsLinked(!!c).catch(() => {}); }} />
|
||||
<span>
|
||||
{t('amp.linked')}
|
||||
<span className="block text-xs text-muted-foreground mt-0.5">{t('amp.linkedHint')}</span>
|
||||
</span>
|
||||
</label>
|
||||
<div className="border-t border-border/60 pt-3 space-y-2">
|
||||
<div className="text-sm">{t('amp.linked')}</div>
|
||||
<p className="text-xs text-muted-foreground">{t('amp.linkedHint')}</p>
|
||||
<div className="flex flex-wrap gap-x-4 gap-y-1.5">
|
||||
{amps.filter((x) => (x.id ?? '') !== '').map((x) => {
|
||||
const on = linkedAmps.includes(x.id!);
|
||||
return (
|
||||
<label key={x.id} className="flex items-center gap-1.5 text-sm cursor-pointer">
|
||||
<Checkbox checked={on} onCheckedChange={(c) => {
|
||||
const next = c ? [...linkedAmps, x.id!] : linkedAmps.filter((v) => v !== x.id);
|
||||
setLinkedAmps(next);
|
||||
SetLinkedAmps(next).catch(() => {});
|
||||
}} />
|
||||
{x.name?.trim() || x.type}
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{/* An amplifier saved without an id cannot be a member — say so
|
||||
rather than silently leaving it out of the list. */}
|
||||
{amps.some((x) => (x.id ?? '') === '') && (
|
||||
<p className="text-xs text-muted-foreground">{t('amp.linkedSaveFirst')}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -190,7 +190,7 @@ const en: Dict = {
|
||||
'gen.showBeam': 'Show the antenna beam heading on the Main map',
|
||||
'gen.startEqEnd': 'QSO start time = end time', 'gen.startEqEndHint': '(matches LoTW when you call a while)',
|
||||
'gen.showQsoRate': 'Show QSO rate in the header', 'gen.showQsoRateHint': '(QSOs/hour, projected from the last 10 / 60 min)',
|
||||
'gen.lookupOnBlur': 'Look up the callsign only after leaving the field', 'gen.lookupOnBlurHint': '(not while typing)', 'amp.hint': 'Configure one or several amplifiers — each panel card has a dropdown to pick which one it shows.', 'amp.linked': 'Command these amplifiers together', 'amp.linkedHint': 'ON, OFF and OPERATE act on every amplifier at once — for a combiner, where one amp left in STANDBY would feed power to one input only. Each keeps its own meters.', 'amp.none': 'No amplifier configured yet.', 'amp.namePh': 'Name (e.g. SPE left)', 'amp.remove': 'Remove this amplifier', 'amp.add': 'Add amplifier', 'amp.password': 'Remote code', 'amp.passwordPh': 'blank on LAN', 'amp.passwordHint': 'PowerGenius XL only: needed when reaching the amp remotely — it then announces "AUTH" and rejects every command ("Unauthorized") until you log in. Leave blank on the local network.', 'amp.freqOut': 'Send the frequency to the amplifier (band follow)', 'amp.freqPort': 'CAT/AUX COM port', 'amp.freqBroadcast': 'Also send unprompted', 'amp.freqPollOnly': 'No — answer the amplifier only', 'amp.freqEvery': 'Yes, every {ms} ms', 'amp.freqHint': 'OpsLog pretends to be a transceiver on this second port, in Kenwood format: set the amplifier to that command set (set 5 on an ACOM) at the same baud rate, and put it in OPERATE — in standby it acknowledges but does not switch band. An amplifier that POLLS (ACOM) needs nothing more; one that only LISTENS to the CAT line of the radio hears nothing unless you also turn on the unprompted send.',
|
||||
'gen.lookupOnBlur': 'Look up the callsign only after leaving the field', 'gen.lookupOnBlurHint': '(not while typing)', 'amp.hint': 'Configure one or several amplifiers — each panel card has a dropdown to pick which one it shows.', 'amp.linked': 'Amplifiers commanded together', 'amp.linkedHint': 'Tick the ones sharing a combiner: ON, OFF and OPERATE will act on all of them at once, since one left in STANDBY would feed power to a single input. Any amplifier left unticked keeps its own buttons. Each keeps its own meters.', 'amp.linkedSaveFirst': 'Save first — an amplifier needs an id before it can join a group.', 'amp.none': 'No amplifier configured yet.', 'amp.namePh': 'Name (e.g. SPE left)', 'amp.remove': 'Remove this amplifier', 'amp.add': 'Add amplifier', 'amp.password': 'Remote code', 'amp.passwordPh': 'blank on LAN', 'amp.passwordHint': 'PowerGenius XL only: needed when reaching the amp remotely — it then announces "AUTH" and rejects every command ("Unauthorized") until you log in. Leave blank on the local network.', 'amp.freqOut': 'Send the frequency to the amplifier (band follow)', 'amp.freqPort': 'CAT/AUX COM port', 'amp.freqBroadcast': 'Also send unprompted', 'amp.freqPollOnly': 'No — answer the amplifier only', 'amp.freqEvery': 'Yes, every {ms} ms', 'amp.freqHint': 'OpsLog pretends to be a transceiver on this second port, in Kenwood format: set the amplifier to that command set (set 5 on an ACOM) at the same baud rate, and put it in OPERATE — in standby it acknowledges but does not switch band. An amplifier that POLLS (ACOM) needs nothing more; one that only LISTENS to the CAT line of the radio hears nothing unless you also turn on the unprompted send.',
|
||||
'gen.groupDigital': 'Group digital modes as one (DXCC-style)', 'gen.groupDigitalHint': '(matrix badges + cluster: FT8/FT4/RTTY… count as a single Digital mode; off = each digital mode is its own slot)',
|
||||
// Password encryption
|
||||
'gen.pwEnc': 'Password encryption',
|
||||
@@ -616,7 +616,7 @@ const fr: Dict = {
|
||||
'gen.showBeam': 'Afficher le cap de l\'antenne sur la carte principale',
|
||||
'gen.startEqEnd': 'Heure de début du QSO = heure de fin', 'gen.startEqEndHint': '(correspond à LoTW quand tu appelles un moment)',
|
||||
'gen.showQsoRate': 'Afficher le rythme QSO dans la barre du haut', 'gen.showQsoRateHint': '(QSO/heure, projeté sur les 10 / 60 dernières min)',
|
||||
'gen.lookupOnBlur': 'Rechercher l\'indicatif seulement après avoir quitté le champ', 'gen.lookupOnBlurHint': '(pas pendant la saisie)', 'amp.hint': 'Configurez un ou plusieurs amplificateurs — chaque carte de panneau a une liste déroulante pour choisir lequel afficher.', 'amp.linked': 'Commander ces amplificateurs ensemble', 'amp.linkedHint': "ON, OFF et OPERATE agissent sur tous les amplificateurs à la fois — pour un combiner, où un ampli resté en STANDBY n'alimenterait qu'une seule entrée. Chacun garde ses propres mesures.", 'amp.none': 'Aucun amplificateur configuré.', 'amp.namePh': 'Nom (p. ex. SPE gauche)', 'amp.remove': 'Supprimer cet amplificateur', 'amp.add': 'Ajouter un amplificateur', 'amp.password': 'Code distant', 'amp.passwordPh': 'vide en LAN', 'amp.passwordHint': "PowerGenius XL uniquement : nécessaire pour joindre l'ampli à distance — il annonce alors « AUTH » et refuse toute commande (« Unauthorized ») tant qu'on n'est pas identifié. Laisse vide sur le réseau local.", 'amp.freqOut': "Envoyer la fréquence à l'amplificateur (suivi de bande)", 'amp.freqPort': 'Port COM CAT/AUX', 'amp.freqBroadcast': 'Envoyer aussi sans être interrogé', 'amp.freqPollOnly': "Non — répondre seulement à l'amplificateur", 'amp.freqEvery': 'Oui, toutes les {ms} ms', 'amp.freqHint': "OpsLog se fait passer pour un transceiver sur ce second port, au format Kenwood : réglez l'amplificateur sur ce jeu de commandes (le jeu 5 sur un ACOM) à la même vitesse, et mettez-le en OPERATE — en veille il acquitte mais ne change pas de bande. Un amplificateur qui INTERROGE (ACOM) n'a besoin de rien de plus ; un amplificateur qui se contente d'ÉCOUTER la liaison CAT de la radio n'entendra rien tant que l'envoi spontané n'est pas activé.",
|
||||
'gen.lookupOnBlur': 'Rechercher l\'indicatif seulement après avoir quitté le champ', 'gen.lookupOnBlurHint': '(pas pendant la saisie)', 'amp.hint': 'Configurez un ou plusieurs amplificateurs — chaque carte de panneau a une liste déroulante pour choisir lequel afficher.', 'amp.linked': 'Amplificateurs commandés ensemble', 'amp.linkedHint': "Coche ceux qui partagent un combiner : ON, OFF et OPERATE agiront sur tous à la fois, puisqu'un ampli resté en STANDBY n'alimenterait qu'une seule entrée. Un amplificateur non coché garde ses propres boutons. Chacun garde ses mesures.", 'amp.linkedSaveFirst': "Enregistre d'abord — un amplificateur a besoin d'un identifiant pour rejoindre un groupe.", 'amp.none': 'Aucun amplificateur configuré.', 'amp.namePh': 'Nom (p. ex. SPE gauche)', 'amp.remove': 'Supprimer cet amplificateur', 'amp.add': 'Ajouter un amplificateur', 'amp.password': 'Code distant', 'amp.passwordPh': 'vide en LAN', 'amp.passwordHint': "PowerGenius XL uniquement : nécessaire pour joindre l'ampli à distance — il annonce alors « AUTH » et refuse toute commande (« Unauthorized ») tant qu'on n'est pas identifié. Laisse vide sur le réseau local.", 'amp.freqOut': "Envoyer la fréquence à l'amplificateur (suivi de bande)", 'amp.freqPort': 'Port COM CAT/AUX', 'amp.freqBroadcast': 'Envoyer aussi sans être interrogé', 'amp.freqPollOnly': "Non — répondre seulement à l'amplificateur", 'amp.freqEvery': 'Oui, toutes les {ms} ms', 'amp.freqHint': "OpsLog se fait passer pour un transceiver sur ce second port, au format Kenwood : réglez l'amplificateur sur ce jeu de commandes (le jeu 5 sur un ACOM) à la même vitesse, et mettez-le en OPERATE — en veille il acquitte mais ne change pas de bande. Un amplificateur qui INTERROGE (ACOM) n'a besoin de rien de plus ; un amplificateur qui se contente d'ÉCOUTER la liaison CAT de la radio n'entendra rien tant que l'envoi spontané n'est pas activé.",
|
||||
'gen.groupDigital': 'Regrouper les modes digitaux en un seul (style DXCC)', 'gen.groupDigitalHint': '(badges de la matrice + cluster : FT8/FT4/RTTY… comptent comme un seul mode Digital ; décoché = chaque mode digital est un slot distinct)',
|
||||
// Chiffrement des mots de passe
|
||||
'gen.pwEnc': 'Chiffrement des mots de passe',
|
||||
|
||||
Vendored
+4
-4
@@ -366,8 +366,6 @@ export function GetAmpStatuses():Promise<Array<main.AmpStatus>>;
|
||||
|
||||
export function GetAmplifiers():Promise<Array<main.AmpConfig>>;
|
||||
|
||||
export function GetAmpsLinked():Promise<boolean>;
|
||||
|
||||
export function GetAntGeniusSettings():Promise<main.AntGeniusSettings>;
|
||||
|
||||
export function GetAntGeniusStatus():Promise<antgenius.Status>;
|
||||
@@ -448,6 +446,8 @@ export function GetGridCacheStatus():Promise<main.GridCacheStatus>;
|
||||
|
||||
export function GetIcomState():Promise<cat.IcomTXState>;
|
||||
|
||||
export function GetLinkedAmps():Promise<Array<string>>;
|
||||
|
||||
export function GetListsSettings():Promise<main.ListsSettings>;
|
||||
|
||||
export function GetLiveOpenings():Promise<Array<bandopen.Opening>>;
|
||||
@@ -974,8 +974,6 @@ export function SetActiveRotor(arg1:number):Promise<void>;
|
||||
|
||||
export function SetAlertEmailTo(arg1:string):Promise<void>;
|
||||
|
||||
export function SetAmpsLinked(arg1:boolean):Promise<void>;
|
||||
|
||||
export function SetCATFrequency(arg1:number):Promise<void>;
|
||||
|
||||
export function SetCATMode(arg1:string):Promise<void>;
|
||||
@@ -1000,6 +998,8 @@ export function SetDVKLabel(arg1:number,arg2:string):Promise<void>;
|
||||
|
||||
export function SetKenwoodKeySpeed(arg1:number):Promise<void>;
|
||||
|
||||
export function SetLinkedAmps(arg1:Array<string>):Promise<void>;
|
||||
|
||||
export function SetMotorFollow(arg1:boolean,arg2:number,arg3:string):Promise<void>;
|
||||
|
||||
export function SetOpsLogQSLReceived(arg1:number,arg2:boolean):Promise<void>;
|
||||
|
||||
@@ -674,10 +674,6 @@ export function GetAmplifiers() {
|
||||
return window['go']['main']['App']['GetAmplifiers']();
|
||||
}
|
||||
|
||||
export function GetAmpsLinked() {
|
||||
return window['go']['main']['App']['GetAmpsLinked']();
|
||||
}
|
||||
|
||||
export function GetAntGeniusSettings() {
|
||||
return window['go']['main']['App']['GetAntGeniusSettings']();
|
||||
}
|
||||
@@ -838,6 +834,10 @@ export function GetIcomState() {
|
||||
return window['go']['main']['App']['GetIcomState']();
|
||||
}
|
||||
|
||||
export function GetLinkedAmps() {
|
||||
return window['go']['main']['App']['GetLinkedAmps']();
|
||||
}
|
||||
|
||||
export function GetListsSettings() {
|
||||
return window['go']['main']['App']['GetListsSettings']();
|
||||
}
|
||||
@@ -1890,10 +1890,6 @@ export function SetAlertEmailTo(arg1) {
|
||||
return window['go']['main']['App']['SetAlertEmailTo'](arg1);
|
||||
}
|
||||
|
||||
export function SetAmpsLinked(arg1) {
|
||||
return window['go']['main']['App']['SetAmpsLinked'](arg1);
|
||||
}
|
||||
|
||||
export function SetCATFrequency(arg1) {
|
||||
return window['go']['main']['App']['SetCATFrequency'](arg1);
|
||||
}
|
||||
@@ -1942,6 +1938,10 @@ export function SetKenwoodKeySpeed(arg1) {
|
||||
return window['go']['main']['App']['SetKenwoodKeySpeed'](arg1);
|
||||
}
|
||||
|
||||
export function SetLinkedAmps(arg1) {
|
||||
return window['go']['main']['App']['SetLinkedAmps'](arg1);
|
||||
}
|
||||
|
||||
export function SetMotorFollow(arg1, arg2, arg3) {
|
||||
return window['go']['main']['App']['SetMotorFollow'](arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user