meshtastic-firmware/src/airtime.cpp

227 wiersze
6.8 KiB
C++
Czysty Zwykły widok Historia

#include "airtime.h"
#include "NodeDB.h"
#include "configuration.h"
2022-01-24 07:00:14 +00:00
AirTime *airTime = NULL;
// Don't read out of this directly. Use the helper functions.
2021-12-29 08:45:36 +00:00
void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
{
2021-12-29 08:45:36 +00:00
if (reportType == TX_LOG) {
2022-12-30 02:41:37 +00:00
LOG_DEBUG("AirTime - Packet transmitted : %ums\n", airtime_ms);
2021-12-29 08:45:36 +00:00
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
myNodeInfo.air_period_tx[0] = myNodeInfo.air_period_tx[0] + airtime_ms;
2022-01-15 19:19:50 +00:00
this->utilizationTX[this->getPeriodUtilHour()] = this->utilizationTX[this->getPeriodUtilHour()] + airtime_ms;
} else if (reportType == RX_LOG) {
2022-12-30 02:41:37 +00:00
LOG_DEBUG("AirTime - Packet received : %ums\n", airtime_ms);
2021-12-29 08:45:36 +00:00
this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms;
myNodeInfo.air_period_rx[0] = myNodeInfo.air_period_rx[0] + airtime_ms;
} else if (reportType == RX_ALL_LOG) {
2022-12-30 02:41:37 +00:00
LOG_DEBUG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
2021-12-29 08:45:36 +00:00
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
}
// Log all airtime type for channel utilization
2022-01-15 19:19:50 +00:00
this->channelUtilization[this->getPeriodUtilMinute()] = channelUtilization[this->getPeriodUtilMinute()] + airtime_ms;
}
uint8_t AirTime::currentPeriodIndex()
{
2022-03-03 04:38:14 +00:00
return ((getSecondsSinceBoot() / SECONDS_PER_PERIOD) % PERIODS_TO_LOG);
}
2023-01-21 13:34:29 +00:00
uint8_t AirTime::getPeriodUtilMinute()
{
2022-01-15 19:19:50 +00:00
return (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS;
}
2023-01-21 13:34:29 +00:00
uint8_t AirTime::getPeriodUtilHour()
{
2022-01-15 19:19:50 +00:00
return (getSecondsSinceBoot() / 60) % MINUTES_IN_HOUR;
}
void AirTime::airtimeRotatePeriod()
{
2022-01-15 23:27:25 +00:00
if (this->airtimes.lastPeriodIndex != this->currentPeriodIndex()) {
2022-12-30 02:41:37 +00:00
LOG_DEBUG("Rotating airtimes to a new period = %u\n", this->currentPeriodIndex());
2022-03-03 04:38:14 +00:00
for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) {
2021-12-29 08:45:36 +00:00
this->airtimes.periodTX[i + 1] = this->airtimes.periodTX[i];
this->airtimes.periodRX[i + 1] = this->airtimes.periodRX[i];
this->airtimes.periodRX_ALL[i + 1] = this->airtimes.periodRX_ALL[i];
myNodeInfo.air_period_tx[i + 1] = this->airtimes.periodTX[i];
myNodeInfo.air_period_rx[i + 1] = this->airtimes.periodRX[i];
2020-12-27 06:39:43 +00:00
}
2022-01-15 19:19:50 +00:00
2021-12-29 08:45:36 +00:00
this->airtimes.periodTX[0] = 0;
this->airtimes.periodRX[0] = 0;
this->airtimes.periodRX_ALL[0] = 0;
myNodeInfo.air_period_tx[0] = 0;
myNodeInfo.air_period_rx[0] = 0;
2022-01-15 23:27:25 +00:00
this->airtimes.lastPeriodIndex = this->currentPeriodIndex();
}
}
2021-12-29 08:45:36 +00:00
uint32_t *AirTime::airtimeReport(reportTypes reportType)
{
2020-12-27 06:39:43 +00:00
if (reportType == TX_LOG) {
2021-12-29 08:45:36 +00:00
return this->airtimes.periodTX;
2020-12-27 06:39:43 +00:00
} else if (reportType == RX_LOG) {
2021-12-29 08:45:36 +00:00
return this->airtimes.periodRX;
2020-12-27 06:39:43 +00:00
} else if (reportType == RX_ALL_LOG) {
2021-12-29 08:45:36 +00:00
return this->airtimes.periodRX_ALL;
}
2020-12-27 06:39:43 +00:00
return 0;
}
uint8_t AirTime::getPeriodsToLog()
{
2022-03-03 04:38:14 +00:00
return PERIODS_TO_LOG;
}
uint32_t AirTime::getSecondsPerPeriod()
2020-12-27 06:39:43 +00:00
{
return SECONDS_PER_PERIOD;
}
uint32_t AirTime::getSecondsSinceBoot()
{
return this->secSinceBoot;
}
float AirTime::channelUtilizationPercent()
{
uint32_t sum = 0;
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
sum += this->channelUtilization[i];
2022-12-30 02:41:37 +00:00
// LOG_DEBUG("ChanUtilArray %u %u\n", i, this->channelUtilization[i]);
}
return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100;
}
float AirTime::utilizationTXPercent()
{
uint32_t sum = 0;
for (uint32_t i = 0; i < MINUTES_IN_HOUR; i++) {
sum += this->utilizationTX[i];
}
return (float(sum) / float(MS_IN_HOUR)) * 100;
}
bool AirTime::isTxAllowedChannelUtil(bool polite)
{
2023-01-21 13:34:29 +00:00
uint8_t percentage = (polite ? polite_channel_util_percent : max_channel_util_percent);
if (channelUtilizationPercent() < percentage) {
2023-01-21 13:34:29 +00:00
return true;
} else {
LOG_WARN("Channel utilization is >%d percent. Skipping this opportunity to send.\n", percentage);
return false;
}
}
2023-01-21 13:34:29 +00:00
bool AirTime::isTxAllowedAirUtil()
{
if (!config.lora.override_duty_cycle && myRegion->dutyCycle < 100) {
2023-01-12 13:03:06 +00:00
if (utilizationTXPercent() < myRegion->dutyCycle * polite_duty_cycle_percent / 100) {
2023-01-21 13:34:29 +00:00
return true;
} else {
2023-01-21 13:34:29 +00:00
LOG_WARN("Tx air utilization is >%f percent. Skipping this opportunity to send.\n",
myRegion->dutyCycle * polite_duty_cycle_percent / 100);
return false;
}
}
return true;
}
// Get the amount of minutes we have to be silent before we can send again
2023-01-21 13:34:29 +00:00
uint8_t AirTime::getSilentMinutes(float txPercent, float dutyCycle)
{
float newTxPercent = txPercent;
for (int8_t i = MINUTES_IN_HOUR - 1; i >= 0; --i) {
newTxPercent -= ((float)this->utilizationTX[i] / (MS_IN_MINUTE * MINUTES_IN_HOUR / 100));
if (newTxPercent < dutyCycle)
return MINUTES_IN_HOUR - 1 - i;
}
2023-01-21 13:34:29 +00:00
return MINUTES_IN_HOUR;
2022-01-24 07:00:14 +00:00
}
2023-01-21 13:34:29 +00:00
AirTime::AirTime() : concurrency::OSThread("AirTime"), airtimes({}) {}
int32_t AirTime::runOnce()
{
secSinceBoot++;
2022-01-15 19:19:50 +00:00
uint8_t utilPeriod = this->getPeriodUtilMinute();
uint8_t utilPeriodTX = this->getPeriodUtilHour();
if (firstTime) {
// Init utilizationTX window to all 0
for (uint32_t i = 0; i < MINUTES_IN_HOUR; i++) {
this->utilizationTX[i] = 0;
}
// Init channelUtilization window to all 0
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
this->channelUtilization[i] = 0;
}
// Init airtime windows to all 0
2022-03-03 02:55:11 +00:00
for (int i = 0; i < myNodeInfo.air_period_rx_count; i++) {
this->airtimes.periodTX[i] = 0;
this->airtimes.periodRX[i] = 0;
this->airtimes.periodRX_ALL[i] = 0;
2022-01-15 19:19:50 +00:00
// myNodeInfo.air_period_tx[i] = 0;
// myNodeInfo.air_period_rx[i] = 0;
}
firstTime = false;
lastUtilPeriod = utilPeriod;
} else {
2022-01-15 23:27:25 +00:00
this->airtimeRotatePeriod();
// Reset the channelUtilization window when we roll over
if (lastUtilPeriod != utilPeriod) {
lastUtilPeriod = utilPeriod;
this->channelUtilization[utilPeriod] = 0;
}
if (lastUtilPeriodTX != utilPeriodTX) {
lastUtilPeriodTX = utilPeriodTX;
this->utilizationTX[utilPeriodTX] = 0;
}
2021-12-29 07:37:23 +00:00
// Update channel_utilization every second.
myNodeInfo.channel_utilization = airTime->channelUtilizationPercent();
// Update channel_utilization every second.
myNodeInfo.air_util_tx = airTime->utilizationTXPercent();
}
2023-01-21 13:34:29 +00:00
/*
LOG_DEBUG("utilPeriodTX %d TX Airtime %3.2f%\n", utilPeriodTX, airTime->utilizationTXPercent());
for (uint32_t i = 0; i < MINUTES_IN_HOUR; i++) {
LOG_DEBUG(
"%d,", this->utilizationTX[i]
);
}
LOG_DEBUG("\n");
*/
return (1000 * 1);
2022-01-24 07:00:14 +00:00
}