sforkowany z mirror/meshtastic-firmware
Merge pull request #1037 from mc-hamster/ChannelUtilization
Report on channel utilization on the screen and myNodeInfo1.2-legacy
commit
94aff87706
120
src/airtime.cpp
120
src/airtime.cpp
|
@ -1,117 +1,135 @@
|
|||
#include "configuration.h"
|
||||
#include "airtime.h"
|
||||
#include "NodeDB.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#define periodsToLog 24
|
||||
|
||||
AirTime *airTime;
|
||||
|
||||
uint32_t secondsPerPeriod = 3600;
|
||||
uint32_t lastMillis = 0;
|
||||
uint32_t secSinceBoot = 0;
|
||||
|
||||
// AirTime at;
|
||||
|
||||
// Don't read out of this directly. Use the helper functions.
|
||||
struct airtimeStruct {
|
||||
uint32_t periodTX[periodsToLog]; // AirTime transmitted
|
||||
uint32_t periodRX[periodsToLog]; // AirTime received and repeated (Only valid mesh packets)
|
||||
uint32_t periodRX_ALL[periodsToLog]; // AirTime received regardless of valid mesh packet. Could include noise.
|
||||
uint8_t lastPeriodIndex;
|
||||
} airtimes;
|
||||
|
||||
|
||||
void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
|
||||
{
|
||||
|
||||
// TODO: Is the airtimes array still necessary? It's now in myNodeInfo anyway
|
||||
|
||||
if (reportType == TX_LOG) {
|
||||
DEBUG_MSG("AirTime - Packet transmitted : %ums\n", airtime_ms);
|
||||
airtimes.periodTX[0] = airtimes.periodTX[0] + airtime_ms;
|
||||
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
|
||||
myNodeInfo.air_period_tx[0] = myNodeInfo.air_period_tx[0] + airtime_ms;
|
||||
} else if (reportType == RX_LOG) {
|
||||
DEBUG_MSG("AirTime - Packet received : %ums\n", airtime_ms);
|
||||
airtimes.periodRX[0] = airtimes.periodRX[0] + airtime_ms;
|
||||
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) {
|
||||
DEBUG_MSG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
|
||||
airtimes.periodRX_ALL[0] = airtimes.periodRX_ALL[0] + airtime_ms;
|
||||
} else {
|
||||
DEBUG_MSG("AirTime - Unknown report time. This should never happen!!\n");
|
||||
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
|
||||
}
|
||||
|
||||
uint8_t channelUtilPeriod = (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS;
|
||||
this->channelUtilization[channelUtilPeriod] = channelUtilization[channelUtilPeriod] + airtime_ms;
|
||||
}
|
||||
|
||||
uint8_t currentPeriodIndex()
|
||||
uint8_t AirTime::currentPeriodIndex()
|
||||
{
|
||||
return ((getSecondsSinceBoot() / secondsPerPeriod) % periodsToLog);
|
||||
return ((getSecondsSinceBoot() / SECONDS_PER_PERIOD) % PERIODS_TO_LOG);
|
||||
}
|
||||
|
||||
void airtimeRotatePeriod()
|
||||
void AirTime::airtimeRotatePeriod()
|
||||
{
|
||||
|
||||
if (airtimes.lastPeriodIndex != currentPeriodIndex()) {
|
||||
if (this->airtimes.lastPeriodIndex != currentPeriodIndex()) {
|
||||
DEBUG_MSG("Rotating airtimes to a new period = %u\n", currentPeriodIndex());
|
||||
|
||||
for (int i = periodsToLog - 2; i >= 0; --i) {
|
||||
airtimes.periodTX[i + 1] = airtimes.periodTX[i];
|
||||
airtimes.periodRX[i + 1] = airtimes.periodRX[i];
|
||||
airtimes.periodRX_ALL[i + 1] = airtimes.periodRX_ALL[i];
|
||||
for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) {
|
||||
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] = myNodeInfo.air_period_tx[i];
|
||||
myNodeInfo.air_period_rx[i + 1] = myNodeInfo.air_period_rx[i];
|
||||
}
|
||||
airtimes.periodTX[0] = 0;
|
||||
airtimes.periodRX[0] = 0;
|
||||
airtimes.periodRX_ALL[0] = 0;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
airtimes.lastPeriodIndex = currentPeriodIndex();
|
||||
this->airtimes.lastPeriodIndex = currentPeriodIndex();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *airtimeReport(reportTypes reportType)
|
||||
uint32_t *AirTime::airtimeReport(reportTypes reportType)
|
||||
{
|
||||
|
||||
if (reportType == TX_LOG) {
|
||||
return airtimes.periodTX;
|
||||
return this->airtimes.periodTX;
|
||||
} else if (reportType == RX_LOG) {
|
||||
return airtimes.periodRX;
|
||||
return this->airtimes.periodRX;
|
||||
} else if (reportType == RX_ALL_LOG) {
|
||||
return airtimes.periodRX_ALL;
|
||||
return this->airtimes.periodRX_ALL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t getPeriodsToLog()
|
||||
uint8_t AirTime::getPeriodsToLog()
|
||||
{
|
||||
return periodsToLog;
|
||||
return PERIODS_TO_LOG;
|
||||
}
|
||||
|
||||
uint32_t getSecondsPerPeriod()
|
||||
uint32_t AirTime::getSecondsPerPeriod()
|
||||
{
|
||||
return secondsPerPeriod;
|
||||
return SECONDS_PER_PERIOD;
|
||||
}
|
||||
|
||||
uint32_t getSecondsSinceBoot()
|
||||
uint32_t AirTime::getSecondsSinceBoot()
|
||||
{
|
||||
return secSinceBoot;
|
||||
return this->secSinceBoot;
|
||||
}
|
||||
|
||||
float AirTime::channelUtilizationPercent()
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
|
||||
sum += this->channelUtilization[i];
|
||||
// DEBUG_MSG("ChanUtilArray %u %u\n", i, this->channelUtilization[i]);
|
||||
}
|
||||
|
||||
return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100;
|
||||
}
|
||||
|
||||
AirTime::AirTime() : concurrency::OSThread("AirTime") {}
|
||||
|
||||
int32_t AirTime::runOnce()
|
||||
{
|
||||
//DEBUG_MSG("AirTime::runOnce()\n");
|
||||
|
||||
airtimeRotatePeriod();
|
||||
secSinceBoot++;
|
||||
|
||||
/*
|
||||
This actually doesn't need to be run once per second but we currently use it for the
|
||||
secSinceBoot counter.
|
||||
uint8_t utilPeriod = (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS;
|
||||
|
||||
if (firstTime) {
|
||||
airtimeRotatePeriod();
|
||||
|
||||
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
|
||||
this->channelUtilization[i] = 0;
|
||||
}
|
||||
|
||||
firstTime = false;
|
||||
lastUtilPeriod = utilPeriod;
|
||||
|
||||
} else {
|
||||
|
||||
// Reset the channelUtilization window when we roll over
|
||||
if (lastUtilPeriod != utilPeriod) {
|
||||
lastUtilPeriod = utilPeriod;
|
||||
|
||||
this->channelUtilization[utilPeriod] = 0;
|
||||
}
|
||||
|
||||
// Update channel_utilization every second.
|
||||
myNodeInfo.channel_utilization = airTime->channelUtilizationPercent();
|
||||
}
|
||||
|
||||
If we have a better counter of how long the device has been online (and not millis())
|
||||
then we can change this to something less frequent. Maybe once ever 5 seconds?
|
||||
*/
|
||||
return (1000 * 1);
|
||||
}
|
|
@ -23,21 +23,18 @@
|
|||
|
||||
RX_ALL_LOG - RX_LOG = Other lora radios on our frequency channel.
|
||||
*/
|
||||
|
||||
#define CHANNEL_UTILIZATION_PERIODS 6
|
||||
#define SECONDS_PER_PERIOD 3600
|
||||
#define PERIODS_TO_LOG 24
|
||||
|
||||
|
||||
enum reportTypes { TX_LOG, RX_LOG, RX_ALL_LOG };
|
||||
|
||||
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
|
||||
|
||||
void airtimeRotatePeriod();
|
||||
|
||||
uint8_t currentPeriodIndex();
|
||||
uint8_t getPeriodsToLog();
|
||||
|
||||
uint32_t getSecondsSinceBoot();
|
||||
|
||||
uint32_t *airtimeReport(reportTypes reportType);
|
||||
|
||||
uint32_t getSecondsPerPeriod();
|
||||
|
||||
class AirTime : private concurrency::OSThread
|
||||
{
|
||||
|
||||
|
@ -45,6 +42,27 @@ class AirTime : private concurrency::OSThread
|
|||
AirTime();
|
||||
|
||||
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
|
||||
float channelUtilizationPercent();
|
||||
uint32_t channelUtilization[CHANNEL_UTILIZATION_PERIODS];
|
||||
|
||||
uint8_t currentPeriodIndex();
|
||||
void airtimeRotatePeriod();
|
||||
uint8_t getPeriodsToLog();
|
||||
uint32_t getSecondsPerPeriod();
|
||||
uint32_t getSecondsSinceBoot();
|
||||
uint32_t *airtimeReport(reportTypes reportType);
|
||||
|
||||
private:
|
||||
bool firstTime = true;
|
||||
uint8_t lastUtilPeriod = 0;
|
||||
uint32_t secSinceBoot = 0;
|
||||
|
||||
struct airtimeStruct {
|
||||
uint32_t periodTX[PERIODS_TO_LOG]; // AirTime transmitted
|
||||
uint32_t periodRX[PERIODS_TO_LOG]; // AirTime received and repeated (Only valid mesh packets)
|
||||
uint32_t periodRX_ALL[PERIODS_TO_LOG]; // AirTime received regardless of valid mesh packet. Could include noise.
|
||||
uint8_t lastPeriodIndex;
|
||||
} airtimes;
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce() override;
|
||||
|
|
|
@ -1398,11 +1398,11 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, uptime);
|
||||
|
||||
#ifndef NO_ESP32
|
||||
// Show CPU Frequency.
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("CPU " + String(getCpuFrequencyMhz()) + "MHz"),
|
||||
y + FONT_HEIGHT_SMALL * 1, "CPU " + String(getCpuFrequencyMhz()) + "MHz");
|
||||
#endif
|
||||
// Display Channel Utilization
|
||||
char chUtil[13];
|
||||
sprintf(chUtil, "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil),
|
||||
y + FONT_HEIGHT_SMALL * 1, chUtil);
|
||||
|
||||
// Line 3
|
||||
if (radioConfig.preferences.gps_format != GpsCoordinateFormat_GpsFormatDMS) // if DMS then don't draw altitude
|
||||
|
|
|
@ -86,7 +86,7 @@ extern const pb_msgdesc_t AdminMessage_msg;
|
|||
#define AdminMessage_fields &AdminMessage_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define AdminMessage_size 461
|
||||
#define AdminMessage_size 529
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -125,7 +125,7 @@ extern const pb_msgdesc_t ChannelFile_msg;
|
|||
/* Maximum encoded size of messages (where known) */
|
||||
#define LegacyRadioConfig_size 4
|
||||
#define LegacyRadioConfig_LegacyPreferences_size 2
|
||||
#define DeviceState_size 9943
|
||||
#define DeviceState_size 9949
|
||||
#define ChannelFile_size 832
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -164,6 +164,7 @@ typedef struct _MyNodeInfo {
|
|||
pb_size_t air_period_rx_count;
|
||||
uint32_t air_period_rx[24];
|
||||
bool has_wifi;
|
||||
float channel_utilization;
|
||||
} MyNodeInfo;
|
||||
|
||||
typedef struct _Position {
|
||||
|
@ -332,7 +333,7 @@ extern "C" {
|
|||
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0}
|
||||
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
||||
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0}
|
||||
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}
|
||||
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0}
|
||||
#define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN}
|
||||
#define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}}
|
||||
#define ToRadio_init_default {0, {MeshPacket_init_default}}
|
||||
|
@ -344,7 +345,7 @@ extern "C" {
|
|||
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0}
|
||||
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
||||
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0}
|
||||
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}
|
||||
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0}
|
||||
#define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN}
|
||||
#define FromRadio_init_zero {0, 0, {MyNodeInfo_init_zero}}
|
||||
#define ToRadio_init_zero {0, {MeshPacket_init_zero}}
|
||||
|
@ -378,6 +379,7 @@ extern "C" {
|
|||
#define MyNodeInfo_air_period_tx_tag 16
|
||||
#define MyNodeInfo_air_period_rx_tag 17
|
||||
#define MyNodeInfo_has_wifi_tag 18
|
||||
#define MyNodeInfo_channel_utilization_tag 19
|
||||
#define Position_latitude_i_tag 1
|
||||
#define Position_longitude_i_tag 2
|
||||
#define Position_altitude_tag 3
|
||||
|
@ -559,7 +561,8 @@ X(a, STATIC, SINGULAR, UINT32, min_app_version, 14) \
|
|||
X(a, STATIC, SINGULAR, UINT32, max_channels, 15) \
|
||||
X(a, STATIC, REPEATED, UINT32, air_period_tx, 16) \
|
||||
X(a, STATIC, REPEATED, UINT32, air_period_rx, 17) \
|
||||
X(a, STATIC, SINGULAR, BOOL, has_wifi, 18)
|
||||
X(a, STATIC, SINGULAR, BOOL, has_wifi, 18) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, channel_utilization, 19)
|
||||
#define MyNodeInfo_CALLBACK NULL
|
||||
#define MyNodeInfo_DEFAULT NULL
|
||||
|
||||
|
@ -637,9 +640,9 @@ extern const pb_msgdesc_t ToRadio_PeerInfo_msg;
|
|||
#define Data_size 260
|
||||
#define MeshPacket_size 311
|
||||
#define NodeInfo_size 270
|
||||
#define MyNodeInfo_size 445
|
||||
#define MyNodeInfo_size 451
|
||||
#define LogRecord_size 81
|
||||
#define FromRadio_size 454
|
||||
#define FromRadio_size 460
|
||||
#define ToRadio_size 314
|
||||
#define ToRadio_PeerInfo_size 8
|
||||
|
||||
|
|
|
@ -502,12 +502,12 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
|||
|
||||
res->print("\"tx_log\": [");
|
||||
|
||||
logArray = airtimeReport(TX_LOG);
|
||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||
logArray = airTime->airtimeReport(TX_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != getPeriodsToLog() - 1) {
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
}
|
||||
|
@ -515,12 +515,12 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
|||
res->println("],");
|
||||
res->print("\"rx_log\": [");
|
||||
|
||||
logArray = airtimeReport(RX_LOG);
|
||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||
logArray = airTime->airtimeReport(RX_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != getPeriodsToLog() - 1) {
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
}
|
||||
|
@ -528,20 +528,20 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
|||
res->println("],");
|
||||
res->print("\"rx_all_log\": [");
|
||||
|
||||
logArray = airtimeReport(RX_ALL_LOG);
|
||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||
logArray = airTime->airtimeReport(RX_ALL_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != getPeriodsToLog() - 1) {
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
}
|
||||
|
||||
res->println("],");
|
||||
res->printf("\"seconds_since_boot\": %u,\n", getSecondsSinceBoot());
|
||||
res->printf("\"seconds_per_period\": %u,\n", getSecondsPerPeriod());
|
||||
res->printf("\"periods_to_log\": %u\n", getPeriodsToLog());
|
||||
res->printf("\"seconds_since_boot\": %u,\n", airTime->getSecondsSinceBoot());
|
||||
res->printf("\"seconds_per_period\": %u,\n", airTime->getSecondsPerPeriod());
|
||||
res->printf("\"periods_to_log\": %u\n", airTime->getPeriodsToLog());
|
||||
|
||||
res->println("},");
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue