From 90a5b9c052fbd6285cc32c1a6220b87b8c646610 Mon Sep 17 00:00:00 2001 From: Elektr0Vodka <211697683+Elektr0Vodka@users.noreply.github.com> Date: Mon, 19 Oct 2026 21:03:06 +0200 Subject: [PATCH] fix(region-gating): describe dc.gate as true TX duty, default 35 The firmware (dmc-dev PR #25, propagated to observer and packetlog on 2026-10-19) now measures dc.gate against the true TX duty cycle over 60 s instead of a share of the duty-cycle budget, with default threshold 35. - CLI Wiki (firmwareRegistry, nl/de descriptions), Region Gating help panel and i18n labels: true TX duty wording, default 35, re-open below 25%, 1% sub-band hint and the upgrade note. - regionCommands: default and clamp fallback 70 -> 35; tests follow. - RegionGatingForm: live status reads "duty", not "budget". - Changelog: firmware entry for the 10-19 merges (dc.gate threshold reset to 35 on upgrade, code-0 floods, filter limiters, SenseCAP GPS, observer MQTT prefs) and a toolbox entry, in EN/NL/DE. --- src/components/config/RegionGatingForm.tsx | 5 +- src/components/config/panelHelpContent.ts | 18 +++---- src/i18n.ts | 6 +-- src/lib/cli/descriptions.de.ts | 6 +-- src/lib/cli/descriptions.nl.ts | 6 +-- src/lib/cli/firmwareRegistry.ts | 8 +-- src/lib/config/regionCommands.ts | 4 +- src/pages/ChangelogPage.tsx | 57 ++++++++++++++++++++++ src/test/regionCommands.test.ts | 4 +- 9 files changed, 86 insertions(+), 28 deletions(-) diff --git a/src/components/config/RegionGatingForm.tsx b/src/components/config/RegionGatingForm.tsx index dd87deb..5d426a0 100644 --- a/src/components/config/RegionGatingForm.tsx +++ b/src/components/config/RegionGatingForm.tsx @@ -13,7 +13,8 @@ interface Props { // Duty-cycle region gating only. DMC firmware feature (current dmc-dev builds and // the MQTT observer), gated on device.dcGateSupported by the parent. Threshold and -// hysteresis are a share of the duty-cycle budget, not of wall-clock time. The region tree and neighbour discovery +// hysteresis are the true TX duty cycle (share of wall-clock time spent transmitting +// over 60 s), not a share of the duty-cycle budget. The region tree and neighbour discovery // are base repeater features and live in RegionSettingsForm. export default function RegionGatingForm({ value, onChange, onSendCommand }: Props) { const { t } = useLang() @@ -53,7 +54,7 @@ export default function RegionGatingForm({ value, onChange, onSendCommand }: Pro className="btn" type="button" onClick={async () => { const s = parseDcGateStatus(await onSendCommand('get dc.gate.status')) - setGateStatus(s ? `budget ${s.dutyPct}% / level ${s.level}/${s.maxLevel}` : '-') + setGateStatus(s ? `duty ${s.dutyPct}% / level ${s.level}/${s.maxLevel}` : '-') }} > {t('region_dcgate_status')} diff --git a/src/components/config/panelHelpContent.ts b/src/components/config/panelHelpContent.ts index 8d889d3..7719ce2 100644 --- a/src/components/config/panelHelpContent.ts +++ b/src/components/config/panelHelpContent.ts @@ -330,29 +330,29 @@ export const PANEL_HELP: Record> = { regionGating: { nl: { title: 'Regiogating', - intro: 'DMC-repeaterfirmware met duty-cycle-regiogating (huidige dev-builds en de MQTT-observer). Als de repeater het grootste deel van zijn duty-cycle-budget heeft verbruikt, laat hij flood-verkeer tussen regio\'s vallen, van de buitenste laag naar binnen. De binnenste regio en de thuisregio blijven altijd open, en het gaten wordt nooit opgeslagen.', + intro: 'DMC-repeaterfirmware met duty-cycle-regiogating (huidige dev-builds en de MQTT-observer). Als de repeater een groot deel van de tijd zendt, laat hij flood-verkeer tussen regio\'s vallen, van de buitenste laag naar binnen. De binnenste regio en de thuisregio blijven altijd open, en het gaten wordt nooit opgeslagen.', fields: [ { label: 'dc.gate inschakelen', body: 'Zet duty-cycle-regiogating aan (standaard uit). Een repeater zonder benoemde regio\'s gate nooit.' }, - { label: 'Drempel', body: 'Percentage van het duty-cycle-budget (set dutycycle) dat verbruikt mag zijn voordat gating start, niet een percentage van de tijd. Met dutycycle 10 mag de repeater 360 s per uur zenden; bij drempel 70 start gating na 252 s. 70 of 80 werkt bij elke limiet. Standaard 70.' }, - { label: 'Hysterese', body: 'Herstelmarge in procentpunten: regio\'s gaan weer open zodra het verbruik onder drempel min hysterese zakt (standaard 10, dus onder 60%). Voorkomt schommelen.' }, + { label: 'Drempel', body: 'Echte TX-duty-cycle: het deel van de kloktijd dat de repeater de afgelopen 60 s zond. Niet de duty-cycle-limiet (set dutycycle), die per uur geldt. Met dutycycle 10 blijft normaal verkeer ruim onder 35%; op een 1%-subband is 10-15 beter. Standaard 35. Eerdere DMC-builds maten een % van het budget (standaard 70); na de update begint de drempel op 35.' }, + { label: 'Hysterese', body: 'Herstelmarge in procentpunten: regio\'s gaan weer open zodra de duty-cycle onder drempel min hysterese zakt (standaard 10, dus onder 25%). Voorkomt schommelen.' }, ], }, en: { title: 'Region gating', - intro: 'DMC repeater firmware with duty-cycle region gating (current dev builds and the MQTT observer). When the repeater has used up most of its duty-cycle budget, it sheds inter-region flood traffic from the outermost layer inward. The innermost region and the home region always stay open, and the gate is never saved.', + intro: 'DMC repeater firmware with duty-cycle region gating (current dev builds and the MQTT observer). When the repeater is transmitting a large share of the time, it sheds inter-region flood traffic from the outermost layer inward. The innermost region and the home region always stay open, and the gate is never saved.', fields: [ { label: 'Enable dc.gate', body: 'Turns duty-cycle region gating on (off by default). A repeater with no named regions never gates.' }, - { label: 'Threshold', body: 'Share of the duty-cycle budget (set dutycycle) that may be used before gating starts, not a share of wall-clock time. With dutycycle 10 the repeater may transmit 360 s per hour; at threshold 70 gating starts after 252 s. 70 or 80 works with any limit. Default 70.' }, - { label: 'Hysteresis', body: 'Recovery margin in percentage points: regions re-open once usage drops below threshold minus hysteresis (default 10, so below 60%). Prevents flapping.' }, + { label: 'Threshold', body: 'True TX duty cycle: the share of wall-clock time the repeater spent transmitting over the last 60 s. Not the duty-cycle limit (set dutycycle), which applies per hour. With dutycycle 10 normal traffic stays well below 35%; on a 1% sub-band 10-15 is better. Default 35. Earlier DMC builds measured a % of the budget (default 70); after the update the threshold starts at 35.' }, + { label: 'Hysteresis', body: 'Recovery margin in percentage points: regions re-open once the duty cycle drops below threshold minus hysteresis (default 10, so below 25%). Prevents flapping.' }, ], }, de: { title: 'Regionen-Gating', - intro: 'DMC-Repeater-Firmware mit Duty-Cycle-Regionen-Gating (aktuelle Dev-Builds und der MQTT-Observer). Hat der Repeater den Großteil seines Duty-Cycle-Budgets verbraucht, verwirft er Flood-Verkehr zwischen Regionen, von der äußersten Ebene nach innen. Die innerste Region und die Heimatregion bleiben immer offen, und das Gating wird nie gespeichert.', + intro: 'DMC-Repeater-Firmware mit Duty-Cycle-Regionen-Gating (aktuelle Dev-Builds und der MQTT-Observer). Sendet der Repeater einen großen Teil der Zeit, verwirft er Flood-Verkehr zwischen Regionen, von der äußersten Ebene nach innen. Die innerste Region und die Heimatregion bleiben immer offen, und das Gating wird nie gespeichert.', fields: [ { label: 'dc.gate aktivieren', body: 'Schaltet das Duty-Cycle-Regionen-Gating ein (standardmäßig aus). Ein Repeater ohne benannte Regionen gated nie.' }, - { label: 'Schwelle', body: 'Anteil des Duty-Cycle-Budgets (set dutycycle), der verbraucht sein darf, bevor das Gating beginnt, nicht ein Anteil der Uhrzeit. Mit dutycycle 10 darf der Repeater 360 s pro Stunde senden; bei Schwelle 70 beginnt das Gating nach 252 s. 70 oder 80 passt zu jedem Limit. Standard 70.' }, - { label: 'Hysterese', body: 'Erholungsspanne in Prozentpunkten: Regionen öffnen wieder, sobald der Verbrauch unter Schwelle minus Hysterese fällt (Standard 10, also unter 60%). Verhindert Flattern.' }, + { label: 'Schwelle', body: 'Echter TX-Duty-Cycle: der Anteil der Uhrzeit, in dem der Repeater in den letzten 60 s gesendet hat. Nicht das Duty-Cycle-Limit (set dutycycle), das pro Stunde gilt. Mit dutycycle 10 bleibt normaler Verkehr deutlich unter 35 %; auf einem 1-%-Subband ist 10-15 besser. Standard 35. Frühere DMC-Builds maßen einen % des Budgets (Standard 70); nach dem Update beginnt die Schwelle bei 35.' }, + { label: 'Hysterese', body: 'Erholungsspanne in Prozentpunkten: Regionen öffnen wieder, sobald der Duty-Cycle unter Schwelle minus Hysterese fällt (Standard 10, also unter 25 %). Verhindert Flattern.' }, ], }, }, diff --git a/src/i18n.ts b/src/i18n.ts index 2e7746b..15f4a92 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -401,7 +401,7 @@ export const STRINGS = { region_add_child: 'Subregio toevoegen', region_dcgate: 'Duty-cycle-poort', region_dcgate_enable: 'Duty-cycle-poort inschakelen', - region_dcgate_thresh: 'Drempel (% van budget)', + region_dcgate_thresh: 'Drempel (% TX-duty)', region_dcgate_hyst: 'Hysterese %', region_dcgate_status: 'Live status lezen', region_neighbors: 'Buren', @@ -810,7 +810,7 @@ export const STRINGS = { region_add_child: 'Add child', region_dcgate: 'Duty-cycle gating', region_dcgate_enable: 'Enable duty-cycle gating', - region_dcgate_thresh: 'Threshold (% of budget)', + region_dcgate_thresh: 'Threshold (% TX duty)', region_dcgate_hyst: 'Hysteresis %', region_dcgate_status: 'Read live status', region_neighbors: 'Neighbours', @@ -1219,7 +1219,7 @@ export const STRINGS = { region_add_child: 'Unterregion hinzufügen', region_dcgate: 'Duty-Cycle-Sperre', region_dcgate_enable: 'Duty-Cycle-Sperre aktivieren', - region_dcgate_thresh: 'Schwellwert (% des Budgets)', + region_dcgate_thresh: 'Schwellwert (% TX-Duty)', region_dcgate_hyst: 'Hysterese %', region_dcgate_status: 'Live-Status lesen', region_neighbors: 'Nachbarn', diff --git a/src/lib/cli/descriptions.de.ts b/src/lib/cli/descriptions.de.ts index af67e57..7ae53eb 100644 --- a/src/lib/cli/descriptions.de.ts +++ b/src/lib/cli/descriptions.de.ts @@ -30,11 +30,11 @@ export const CLI_DESC_DE: Record = { "set af ": "Airtime-Faktor direkt einstellen (Duty-Cycle-Budget), 0-9.", "get dc.gate": "Status des Duty-Cycle-Regionen-Gatings anzeigen.", "set dc.gate ": "Duty-Cycle-Regionen-Gating ein- oder ausschalten: on|off (1/0 geht auch).", - "get dc.gate.thresh": "Den Anteil des Duty-Cycle-Budgets in % anzeigen, ab dem Gating aktiviert.", - "set dc.gate.thresh ": "Gating-Schwelle als % des verbrauchten Duty-Cycle-Budgets einstellen (1-100), nicht als % der Uhrzeit. Standard 70.", + "get dc.gate.thresh": "Den echten TX-Duty-Cycle in % anzeigen, ab dem Gating aktiviert.", + "set dc.gate.thresh ": "Gating-Schwelle als echten TX-Duty-Cycle einstellen: % der Uhrzeit, in dem der Repeater in den letzten 60 s gesendet hat (1-100). Standard 35.", "get dc.gate.hyst": "Hysteresespanne des Gatings anzeigen.", "set dc.gate.hyst ": "Gating-Hysterese in Prozentpunkten einstellen (0-50). Regionen öffnen wieder unter Schwelle minus Hysterese. Standard 10.", - "get dc.gate.status": "Live den verbrauchten Anteil des Duty-Cycle-Budgets in % und die aktuelle Gate-Stufe (Stufe/Max) anzeigen.", + "get dc.gate.status": "Live den echten TX-Duty-Cycle in % und die aktuelle Gate-Stufe (Stufe/Max) anzeigen.", "get int.thresh": "Interferenzschwelle anzeigen.", "set int.thresh ": "Interferenzschwelle einstellen.", "get agc.reset.interval": "AGC-Reset-Intervall anzeigen.", diff --git a/src/lib/cli/descriptions.nl.ts b/src/lib/cli/descriptions.nl.ts index 8cd9b20..dec570d 100644 --- a/src/lib/cli/descriptions.nl.ts +++ b/src/lib/cli/descriptions.nl.ts @@ -31,11 +31,11 @@ export const CLI_DESC_NL: Record = { "set af ": "Stel airtime-factor direct in (duty-cycle-budget), 0-9.", "get dc.gate": "Toon status van duty-cycle-regiogating.", "set dc.gate ": "Schakel duty-cycle-regiogating in of uit: on|off (1/0 werkt ook).", - "get dc.gate.thresh": "Toon het % van het duty-cycle-budget waarboven gating activeert.", - "set dc.gate.thresh ": "Stel gating-drempel in als % van het gebruikte duty-cycle-budget (1-100), niet als % van de kloktijd. Standaard 70.", + "get dc.gate.thresh": "Toon de echte TX-duty-cycle in % waarboven gating activeert.", + "set dc.gate.thresh ": "Stel gating-drempel in als echte TX-duty-cycle: % van de kloktijd dat de repeater de afgelopen 60 s zond (1-100). Standaard 35.", "get dc.gate.hyst": "Toon hysteresemarge van gating.", "set dc.gate.hyst ": "Stel gating-hysterese in, in procentpunten (0-50). Regio's heropenen onder drempel min hysterese. Standaard 10.", - "get dc.gate.status": "Toon live het gebruikte % van het duty-cycle-budget en het huidige gate-niveau (niveau/max).", + "get dc.gate.status": "Toon live de echte TX-duty-cycle in % en het huidige gate-niveau (niveau/max).", "get int.thresh": "Toon interferentiedrempel.", "set int.thresh ": "Stel interferentiedrempel in.", "get agc.reset.interval": "Toon AGC-reset-interval.", diff --git a/src/lib/cli/firmwareRegistry.ts b/src/lib/cli/firmwareRegistry.ts index 413e1ff..555fa13 100644 --- a/src/lib/cli/firmwareRegistry.ts +++ b/src/lib/cli/firmwareRegistry.ts @@ -122,14 +122,14 @@ export const MESHCORE_COMMANDS: CliCommand[] = [ { cmd: 'set dutycycle ', category: 'radio', deviceTypes: 'all', placeholder: 'set dutycycle ', desc: 'Set duty-cycle limit. Range: 1-100.' }, { cmd: 'get af', category: 'radio', deviceTypes: 'all', desc: 'Show airtime factor (duty-cycle budget).' }, { cmd: 'set af ', category: 'radio', deviceTypes: 'all', placeholder: 'set af ', desc: 'Set airtime factor directly (duty-cycle budget), 0-9.' }, - // v1.17 duty-cycle region gating (off by default; thresh 70 %, hyst 10 %) + // v1.17 duty-cycle region gating (off by default; thresh 35 % true TX duty, hyst 10 %) { cmd: 'get dc.gate', category: 'radio', deviceTypes: ['repeater','roomserver'], desc: 'Show duty-cycle region-gating state.', sinceVersion: 'v1.17' }, { cmd: 'set dc.gate ', category: 'radio', deviceTypes: ['repeater','roomserver'], placeholder: 'set dc.gate ', desc: 'Enable or disable duty-cycle region gating: on|off (1/0 also accepted).', sinceVersion: 'v1.17' }, - { cmd: 'get dc.gate.thresh', category: 'radio', deviceTypes: ['repeater','roomserver'], desc: 'Show the % of the duty-cycle budget used above which gating activates.', sinceVersion: 'v1.17' }, - { cmd: 'set dc.gate.thresh ', category: 'radio', deviceTypes: ['repeater','roomserver'], placeholder: 'set dc.gate.thresh ', desc: 'Set gating threshold as % of the duty-cycle budget used (1-100), not % of wall-clock time. Default 70.', sinceVersion: 'v1.17' }, + { cmd: 'get dc.gate.thresh', category: 'radio', deviceTypes: ['repeater','roomserver'], desc: 'Show the true TX duty cycle (%) above which gating activates.', sinceVersion: 'v1.17' }, + { cmd: 'set dc.gate.thresh ', category: 'radio', deviceTypes: ['repeater','roomserver'], placeholder: 'set dc.gate.thresh ', desc: 'Set gating threshold as true TX duty cycle: % of wall-clock time spent transmitting over the last 60 s (1-100). Default 35.', sinceVersion: 'v1.17' }, { cmd: 'get dc.gate.hyst', category: 'radio', deviceTypes: ['repeater','roomserver'], desc: 'Show gating hysteresis margin.', sinceVersion: 'v1.17' }, { cmd: 'set dc.gate.hyst ', category: 'radio', deviceTypes: ['repeater','roomserver'], placeholder: 'set dc.gate.hyst ', desc: 'Set gating hysteresis in percentage points (0-50). Regions reopen below thresh minus hyst. Default 10.', sinceVersion: 'v1.17' }, - { cmd: 'get dc.gate.status', category: 'radio', deviceTypes: ['repeater','roomserver'], desc: 'Show live % of the duty-cycle budget used and the current gate level (level/max).', sinceVersion: 'v1.17' }, + { cmd: 'get dc.gate.status', category: 'radio', deviceTypes: ['repeater','roomserver'], desc: 'Show the live true TX duty cycle (%) and the current gate level (level/max).', sinceVersion: 'v1.17' }, { cmd: 'get int.thresh', category: 'radio', deviceTypes: 'all', desc: 'Show interference threshold.' }, { cmd: 'set int.thresh ', category: 'radio', deviceTypes: 'all', placeholder: 'set int.thresh ', desc: 'Set interference threshold.' }, { cmd: 'get agc.reset.interval', category: 'radio', deviceTypes: 'all', desc: 'Show AGC reset interval.' }, diff --git a/src/lib/config/regionCommands.ts b/src/lib/config/regionCommands.ts index 899d1b9..7e13b42 100644 --- a/src/lib/config/regionCommands.ts +++ b/src/lib/config/regionCommands.ts @@ -26,7 +26,7 @@ export function defaultRegionSettings(): RegionSettings { tree: { name: '*', flood: false, children: [] }, home: null, default: null, - dcGate: { enabled: false, thresh: 70, hyst: 10 }, + dcGate: { enabled: false, thresh: 35, hyst: 10 }, } } @@ -379,7 +379,7 @@ export function parseSharedRegionSettings(text: string): RegionSettings | null { if (g && typeof g === 'object') { s.dcGate = { enabled: g.enabled === true, - thresh: clampInt(g.thresh, 1, 100, 70), + thresh: clampInt(g.thresh, 1, 100, 35), hyst: clampInt(g.hyst, 0, 50, 10), } } diff --git a/src/pages/ChangelogPage.tsx b/src/pages/ChangelogPage.tsx index 3a8d79d..96d2e84 100644 --- a/src/pages/ChangelogPage.tsx +++ b/src/pages/ChangelogPage.tsx @@ -31,6 +31,18 @@ type LangKey = 'en' | 'nl' | 'de' const content: Record = { en: { firmware: [ + { + version: 'v1.18.0 · dev', + date: '2026-10-19', + title: 'All DMC branches', + items: [ + <>dc.gate now measures the true TX duty cycle: the share of wall-clock time the repeater spent transmitting over the last 60 seconds, not a share of the duty-cycle budget. The default threshold drops from 70 to 35 (hysteresis stays 10, so regions re-open below 25%). After the update the threshold starts at 35: a value set on an earlier build was a budget percentage and is not carried over, so check get dc.gate.thresh if you had changed it. On a 1% sub-band, 10-15 is a better threshold., + <>Floods with transport code 0 now obey region denyf *, flood.max.unscoped and dc.gate, just like unscoped floods. Before, a modified client could use code 0 to get past them., + <>Packet filter: filter on now applies the default rate limits right away on a repeater that never saved filter settings, and filter reset now also resets the active limits., + <>SenseCAP Solar P1-Pro (repeater, room server, companion): the GPS is turned on once by default, also after an OTA update; a later gps off is kept. Not on the MQTT observer branch., + <>Observer: set mqtt.config, mqtt.filter.interval and mqttN.extras are now kept after a reboot., + ], + }, { version: 'v1.18.0 · dev', date: '2026-10-15', @@ -114,6 +126,13 @@ const content: Record = { }, ], toolbox: [ + { + version: 'USB Setup & CLI Wiki: dc.gate true TX duty', + date: '2026-10-19', + items: [ + <>Region Gating panel, CLI Wiki and command help now describe the dc.gate threshold as the true TX duty cycle (default 35) instead of a share of the duty-cycle budget (default 70). The live status reads duty, and the default the panel falls back to is 35., + ], + }, { version: 'CLI Wiki & filter: v1.18 companion and Meshcomod', date: '2026-10-16', @@ -194,6 +213,18 @@ const content: Record = { }, nl: { firmware: [ + { + version: 'v1.18.0 · dev', + date: '2026-10-19', + title: 'Alle DMC-branches', + items: [ + <>dc.gate meet nu de echte TX-duty-cycle: het deel van de kloktijd dat de repeater de afgelopen 60 seconden zond, niet een deel van het duty-cycle-budget. De standaarddrempel gaat van 70 naar 35 (hysterese blijft 10, dus regio's heropenen onder 25%). Na de update begint de drempel op 35: een waarde die op een eerdere build is ingesteld was een budgetpercentage en wordt niet overgenomen, dus controleer get dc.gate.thresh als je hem had aangepast. Op een 1%-subband is 10-15 een betere drempel., + <>Floods met transportcode 0 volgen nu region denyf *, flood.max.unscoped en dc.gate, net als floods zonder scope. Eerder kon een aangepaste client met code 0 daaromheen., + <>Packet filter: filter on past de standaard-rate-limits nu direct toe op een repeater die nooit filterinstellingen heeft opgeslagen, en filter reset zet nu ook de actieve limieten terug., + <>SenseCAP Solar P1-Pro (repeater, room server, companion): de GPS gaat eenmalig standaard aan, ook na een OTA-update; een latere gps off blijft staan. Niet op de MQTT-observer-branch., + <>Observer: set mqtt.config, mqtt.filter.interval en mqttN.extras blijven nu bewaard na een herstart., + ], + }, { version: 'v1.18.0 · dev', date: '2026-10-15', @@ -277,6 +308,13 @@ const content: Record = { }, ], toolbox: [ + { + version: 'USB Setup & CLI Wiki: dc.gate echte TX-duty', + date: '2026-10-19', + items: [ + <>Regiogating-paneel, CLI Wiki en de commandohulp beschrijven de dc.gate-drempel nu als de echte TX-duty-cycle (standaard 35) in plaats van een deel van het duty-cycle-budget (standaard 70). De live status toont duty, en het paneel valt terug op standaard 35., + ], + }, { version: 'CLI Wiki & filter: v1.18-companion en Meshcomod', date: '2026-10-16', @@ -357,6 +395,18 @@ const content: Record = { }, de: { firmware: [ + { + version: 'v1.18.0 · dev', + date: '2026-10-19', + title: 'Alle DMC-Branches', + items: [ + <>dc.gate misst jetzt den echten TX-Duty-Cycle: den Anteil der Uhrzeit, in dem der Repeater in den letzten 60 Sekunden gesendet hat, nicht einen Anteil des Duty-Cycle-Budgets. Die Standardschwelle sinkt von 70 auf 35 (Hysterese bleibt 10, Regionen öffnen also unter 25 % wieder). Nach dem Update beginnt die Schwelle bei 35: ein auf einem früheren Build gesetzter Wert war ein Budget-Prozentsatz und wird nicht übernommen, prüfe also get dc.gate.thresh, falls du ihn geändert hattest. Auf einem 1-%-Subband ist 10-15 eine bessere Schwelle., + <>Floods mit Transportcode 0 befolgen jetzt region denyf *, flood.max.unscoped und dc.gate, genau wie Floods ohne Scope. Vorher konnte ein modifizierter Client sie mit Code 0 umgehen., + <>Packet-Filter: filter on wendet die Standard-Ratenlimits jetzt sofort an, auch auf einem Repeater, der nie Filtereinstellungen gespeichert hat, und filter reset setzt jetzt auch die aktiven Limits zurück., + <>SenseCAP Solar P1-Pro (Repeater, Room Server, Companion): das GPS wird einmalig standardmäßig eingeschaltet, auch nach einem OTA-Update; ein späteres gps off bleibt bestehen. Nicht auf dem MQTT-Observer-Branch., + <>Observer: set mqtt.config, mqtt.filter.interval und mqttN.extras bleiben jetzt nach einem Neustart erhalten., + ], + }, { version: 'v1.18.0 · dev', date: '2026-10-15', @@ -440,6 +490,13 @@ const content: Record = { }, ], toolbox: [ + { + version: 'USB Setup & CLI Wiki: dc.gate echter TX-Duty', + date: '2026-10-19', + items: [ + <>Regionen-Gating-Panel, CLI Wiki und Befehlshilfe beschreiben die dc.gate-Schwelle jetzt als echten TX-Duty-Cycle (Standard 35) statt als Anteil des Duty-Cycle-Budgets (Standard 70). Der Live-Status zeigt duty, und das Panel fällt auf Standard 35 zurück., + ], + }, { version: 'CLI Wiki & Filter: v1.18-Companion und Meshcomod', date: '2026-10-16', diff --git a/src/test/regionCommands.test.ts b/src/test/regionCommands.test.ts index 80777f3..a8c97f7 100644 --- a/src/test/regionCommands.test.ts +++ b/src/test/regionCommands.test.ts @@ -115,7 +115,7 @@ describe('defaults and clone', () => { b.tree.children.push({ name: 'x', flood: true, children: [] }) b.dcGate.thresh = 42 expect(a.tree.children).toHaveLength(0) - expect(a.dcGate.thresh).toBe(70) + expect(a.dcGate.thresh).toBe(35) }) }) @@ -126,7 +126,7 @@ describe('parseDcGate', () => { expect(parseDcGate({ enabled: '> on', thresh: '> 70', hyst: '> 10' })) .toEqual({ enabled: true, thresh: 70, hyst: 10 }) expect(parseDcGate({ enabled: '> off', thresh: '', hyst: '' })) - .toEqual({ enabled: false, thresh: 70, hyst: 10 }) // falls back to defaults + .toEqual({ enabled: false, thresh: 35, hyst: 10 }) // falls back to defaults }) })