Probleem
De uitgeleverde default is airtime_factor = 1.0, wat neerkomt op 50% duty cycle. get dutycycle rapporteert dat ook zo. De default frequentie is -D LORA_FREQ=869.618 (platformio.ini:29), die in de 869.4 tot 869.65 MHz sub-band valt. ETSI EN 300 220-2 begrenst die sub-band op 10%.
De default staat dus vijf keer hoger dan wat op de eigen default frequentie is toegestaan. Elke EU-operator moet dit met de hand per node aanpassen, en de waarde is niet vindbaar tenzij je al weet dat af over duty cycle gaat.
Upstream ligt hiervoor meshcore-dev#3351 open, met een enkele build-constante MAX_DUTY_CYCLE (default 10). Dat getal klopt voor 869.618, maar niet voor de rest van de band: 868.5 mag 1%, 869.0 mag 0.1%, en een US of ANZ build kent de limiet helemaal niet. Een enkele constante kan die spreiding niet uitdrukken.
Voorstel
De limiet afleiden uit de ingestelde frequentie in plaats van uit een build-constante.
Nieuw src/helpers/DutyCycleLimits.h / .cpp met twee vrije functies:
float getMaxDutyCyclePercent(float freq_mhz); // 100.0 = geen limiet
float dutyCycleToAirtimeFactor(float percent); // (100/dc) - 1
De tabel geldt alleen voor 863.0 tot 870.0 MHz, daarbuiten is het resultaat 100 en verandert er niets:
| sub-band (MHz) |
max duty cycle |
| 863.0 tot 865.0 |
0.1% |
| 865.0 tot 868.0 |
1% |
| 868.0 tot 868.6 |
1% |
| 868.7 tot 869.2 |
0.1% |
| 869.4 tot 869.65 |
10% |
| 869.7 tot 870.0 |
1% |
| de gaten ertussen |
0.1% |
Dit dekt ook de land-presets binnen de EU. Een preset die alleen in SF verschilt, zoals NL op SF7, zit op dezelfde sub-band als de algemene EU-preset en krijgt dus dezelfde limiet. SF, BW en CR raken de regelgeving niet, alleen de frequentie.
Nieuwe pref uint8_t dutycycle_auto, default 1, in src/helpers/CommonCLI.h en examples/companion_radio/NodePrefs.h, serializer-key dc_auto:
set dutycycle <n> en set af <n> zetten hem op 0, de handmatige waarde blijft dan leidend
set dutycycle auto zet hem terug op 1
get dutycycle rapporteert de effectieve waarde en of die auto of handmatig is
De vijf getAirtimeBudgetFactor() overrides (companion_radio, simple_repeater, simple_room_server, simple_secure_chat, simple_sensor) geven bij dutycycle_auto de uit _prefs.freq afgeleide factor terug, anders _prefs.airtime_factor. Dispatcher::updateTxBudget() evalueert die functie bij elke aanroep opnieuw (src/Dispatcher.cpp:42), dus de limiet volgt de frequentie meteen na set freq of set radio, zonder herstart en zonder wijziging in Dispatcher.
Gedragsverandering
dutycycle_auto staat ook aan na migratie van een bestaande prefs-file. Een node die vandaag op 869.618 met de default 50% draait, zakt na de update naar 10%. Dat is het doel van de wijziging, maar het is een stille verandering voor bestaande nodes. Wie bewust hoger wil zitten zet dat met set dutycycle <n> terug, en die keuze blijft dan staan.
Buiten scope
applyTempRadioParams (src/helpers/CommonCLI.cpp:251) zet een tijdelijke frequentie zonder _prefs.freq aan te raken. Tijdens tempradio blijft de limiet dus die van de opgeslagen frequentie. Ik laat dat hier liggen, het is een aparte wijziging.
Testen
getMaxDutyCyclePercent is een pure functie zonder radio-afhankelijkheid en krijgt een unit test in test/: grenswaarden per sub-band, de gaten, en frequenties buiten 863 tot 870. De rest is compile-coverage via de build matrix, want [env:native] compileert Dispatcher.cpp niet.
Probleem
De uitgeleverde default is
airtime_factor = 1.0, wat neerkomt op 50% duty cycle.get dutycyclerapporteert dat ook zo. De default frequentie is-D LORA_FREQ=869.618(platformio.ini:29), die in de 869.4 tot 869.65 MHz sub-band valt. ETSI EN 300 220-2 begrenst die sub-band op 10%.De default staat dus vijf keer hoger dan wat op de eigen default frequentie is toegestaan. Elke EU-operator moet dit met de hand per node aanpassen, en de waarde is niet vindbaar tenzij je al weet dat
afover duty cycle gaat.Upstream ligt hiervoor meshcore-dev#3351 open, met een enkele build-constante
MAX_DUTY_CYCLE(default 10). Dat getal klopt voor 869.618, maar niet voor de rest van de band: 868.5 mag 1%, 869.0 mag 0.1%, en een US of ANZ build kent de limiet helemaal niet. Een enkele constante kan die spreiding niet uitdrukken.Voorstel
De limiet afleiden uit de ingestelde frequentie in plaats van uit een build-constante.
Nieuw
src/helpers/DutyCycleLimits.h/.cppmet twee vrije functies:De tabel geldt alleen voor 863.0 tot 870.0 MHz, daarbuiten is het resultaat 100 en verandert er niets:
Dit dekt ook de land-presets binnen de EU. Een preset die alleen in SF verschilt, zoals NL op SF7, zit op dezelfde sub-band als de algemene EU-preset en krijgt dus dezelfde limiet. SF, BW en CR raken de regelgeving niet, alleen de frequentie.
Nieuwe pref
uint8_t dutycycle_auto, default 1, insrc/helpers/CommonCLI.henexamples/companion_radio/NodePrefs.h, serializer-keydc_auto:set dutycycle <n>enset af <n>zetten hem op 0, de handmatige waarde blijft dan leidendset dutycycle autozet hem terug op 1get dutycyclerapporteert de effectieve waarde en of die auto of handmatig isDe vijf
getAirtimeBudgetFactor()overrides (companion_radio, simple_repeater, simple_room_server, simple_secure_chat, simple_sensor) geven bijdutycycle_autode uit_prefs.freqafgeleide factor terug, anders_prefs.airtime_factor.Dispatcher::updateTxBudget()evalueert die functie bij elke aanroep opnieuw (src/Dispatcher.cpp:42), dus de limiet volgt de frequentie meteen naset freqofset radio, zonder herstart en zonder wijziging inDispatcher.Gedragsverandering
dutycycle_autostaat ook aan na migratie van een bestaande prefs-file. Een node die vandaag op 869.618 met de default 50% draait, zakt na de update naar 10%. Dat is het doel van de wijziging, maar het is een stille verandering voor bestaande nodes. Wie bewust hoger wil zitten zet dat metset dutycycle <n>terug, en die keuze blijft dan staan.Buiten scope
applyTempRadioParams(src/helpers/CommonCLI.cpp:251) zet een tijdelijke frequentie zonder_prefs.freqaan te raken. Tijdenstempradioblijft de limiet dus die van de opgeslagen frequentie. Ik laat dat hier liggen, het is een aparte wijziging.Testen
getMaxDutyCyclePercentis een pure functie zonder radio-afhankelijkheid en krijgt een unit test intest/: grenswaarden per sub-band, de gaten, en frequenties buiten 863 tot 870. De rest is compile-coverage via de build matrix, want[env:native]compileertDispatcher.cppniet.