mirror of
https://github.com/espressif/openthread.git
synced 2026-09-27 19:37:37 +00:00
[channel-monitor] use "channel occupancy" instead of "quality"
This commit changes the API names (and spinel properties and documentation) related to "channel monitor" feature to use "channel occupancy" instead of the term "channel quality" to represent the rate/percentage of RSSI samples which are higher than a threshold.
This commit is contained in:
@@ -49,7 +49,7 @@ Total number of RSSI samples (per channel) taken by the channel
|
||||
monitoring module since its start (since Thread network interface
|
||||
was enabled).
|
||||
|
||||
### PROP 4618: SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_QUALITY (#prop-channel-monitor-channel-quality)
|
||||
### PROP 4618: SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY (#prop-channel-monitor-channel-occupancy)
|
||||
|
||||
* Type: Read-Only
|
||||
* Packing-Encoding: `A(t(cU))`
|
||||
@@ -57,9 +57,9 @@ was enabled).
|
||||
Data per item is:
|
||||
|
||||
* `C`: Channel
|
||||
* `U`: Channel quality indicator
|
||||
* `U`: Channel occupancy indicator
|
||||
|
||||
The channel quality value represents the average rate/percentage of
|
||||
The channel occupancy value represents the average rate/percentage of
|
||||
RSSI samples that were above RSSI threshold ("bad" RSSI samples) within
|
||||
(approximately) latest sample window RSSI samples.
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ extern "C" {
|
||||
* When channel monitoring is active, a zero-duration Energy Scan is performed, collecting a single RSSI sample on
|
||||
* every channel per sample interval. The RSSI samples are compared with a pre-specified RSSI threshold. As an
|
||||
* indicator of channel quality, the channel monitoring module maintains and provides the average rate/percentage of
|
||||
* RSSI samples that are above the threshold within (approximately) a specified sample window.
|
||||
* RSSI samples that are above the threshold within (approximately) a specified sample window (referred to as channel
|
||||
* occupancy).
|
||||
*
|
||||
* @{
|
||||
*
|
||||
@@ -134,25 +135,25 @@ uint32_t otChannelMonitorGetSampleWindow(otInstance *aInstance);
|
||||
uint32_t otChannelMonitorGetSampleCount(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Gets the current channel quality value for a given channel.
|
||||
* Gets the current channel occupancy for a given channel.
|
||||
*
|
||||
* The channel quality value represents the average rate/percentage of RSSI samples that were above RSSI threshold
|
||||
* The channel occupancy value represents the average rate/percentage of RSSI samples that were above RSSI threshold
|
||||
* ("bad" RSSI samples).
|
||||
*
|
||||
* For the first "sample window" samples, the average is maintained as the actual percentage (i.e., ratio of number
|
||||
* of "bad" samples by total number of samples). After "window" samples, the averager uses an exponentially
|
||||
* weighted moving average. Practically, this means the quality is representative of up to `3 * window` last samples
|
||||
* with highest weight given to latest `kSampleWindow` samples.
|
||||
* weighted moving average. Practically, this means the average is representative of up to `3 * window` last samples
|
||||
* with highest weight given to the latest `kSampleWindow` samples.
|
||||
*
|
||||
* Max value of `0xffff` indicates all RSSI samples were above RSSI threshold (i.e. 100% of samples were "bad").
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aChannel The channel for which to get the link quality.
|
||||
* @param[in] aChannel The channel for which to get the link occupancy.
|
||||
*
|
||||
* @returns The current channel quality value for the given channel.
|
||||
* @returns The current channel occupancy for the given channel.
|
||||
*
|
||||
*/
|
||||
uint16_t otChannelMonitorGetChannelQuality(otInstance *aInstance, uint8_t aChannel);
|
||||
uint16_t otChannelMonitorGetChannelOccupancy(otInstance *aInstance, uint8_t aChannel);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -82,11 +82,11 @@ uint32_t otChannelMonitorGetSampleCount(otInstance *aInstance)
|
||||
return instance.GetChannelMonitor().GetSampleCount();
|
||||
}
|
||||
|
||||
uint16_t otChannelMonitorGetChannelQuality(otInstance *aInstance, uint8_t aChannel)
|
||||
uint16_t otChannelMonitorGetChannelOccupancy(otInstance *aInstance, uint8_t aChannel)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.GetChannelMonitor().GetChannelQuality(aChannel);
|
||||
return instance.GetChannelMonitor().GetChannelOccupancy(aChannel);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_ENABLE_CHANNEL_MONITOR
|
||||
|
||||
@@ -56,7 +56,7 @@ ChannelMonitor::ChannelMonitor(Instance &aInstance)
|
||||
, mSampleCount(0)
|
||||
, mTimer(aInstance, &ChannelMonitor::HandleTimer, this)
|
||||
{
|
||||
memset(mChannelQuality, 0, sizeof(mChannelQuality));
|
||||
memset(mChannelOccupancy, 0, sizeof(mChannelOccupancy));
|
||||
}
|
||||
|
||||
otError ChannelMonitor::Start(void)
|
||||
@@ -88,20 +88,20 @@ void ChannelMonitor::Clear(void)
|
||||
{
|
||||
mChannelMaskIndex = 0;
|
||||
mSampleCount = 0;
|
||||
memset(mChannelQuality, 0, sizeof(mChannelQuality));
|
||||
memset(mChannelOccupancy, 0, sizeof(mChannelOccupancy));
|
||||
|
||||
otLogDebgUtil(GetInstance(), "ChannelMonitor: Clearing data");
|
||||
}
|
||||
|
||||
uint16_t ChannelMonitor::GetChannelQuality(uint8_t aChannel) const
|
||||
uint16_t ChannelMonitor::GetChannelOccupancy(uint8_t aChannel) const
|
||||
{
|
||||
uint16_t quality = 0;
|
||||
uint16_t occupancy = 0;
|
||||
|
||||
VerifyOrExit((OT_RADIO_CHANNEL_MIN <= aChannel) && (aChannel <= OT_RADIO_CHANNEL_MAX));
|
||||
quality = mChannelQuality[aChannel - OT_RADIO_CHANNEL_MIN];
|
||||
occupancy = mChannelOccupancy[aChannel - OT_RADIO_CHANNEL_MIN];
|
||||
|
||||
exit:
|
||||
return quality;
|
||||
return occupancy;
|
||||
}
|
||||
|
||||
void ChannelMonitor::RestartTimer(void)
|
||||
@@ -162,7 +162,7 @@ void ChannelMonitor::HandleEnergyScanResult(otEnergyScanResult *aResult)
|
||||
else
|
||||
{
|
||||
uint8_t channelIndex = (aResult->mChannel - OT_RADIO_CHANNEL_MIN);
|
||||
uint32_t newAverage = mChannelQuality[channelIndex];
|
||||
uint32_t newAverage = mChannelOccupancy[channelIndex];
|
||||
uint32_t newValue = 0;
|
||||
uint32_t weight;
|
||||
|
||||
@@ -172,19 +172,19 @@ void ChannelMonitor::HandleEnergyScanResult(otEnergyScanResult *aResult)
|
||||
|
||||
if (aResult->mMaxRssi != OT_RADIO_RSSI_INVALID)
|
||||
{
|
||||
newValue = (aResult->mMaxRssi >= kRssiThreshold) ? kMaxQualityIndicator : 0;
|
||||
newValue = (aResult->mMaxRssi >= kRssiThreshold) ? kMaxOccupancy : 0;
|
||||
}
|
||||
|
||||
// `mChannelQuality` stores the average rate/percentage of RSS samples
|
||||
// that are higher than a given RSS threshold ("bad" RSS samples). For
|
||||
// the first `kSampleWindow` samples, the average is maintained as the
|
||||
// actual percentage (i.e., ratio of number of "bad" samples by total
|
||||
// number of samples). After `kSampleWindow` samples, the averager
|
||||
// uses an exponentially weighted moving average logic with weight
|
||||
// coefficient `1/kSampleWindow` for new values. Practically, this
|
||||
// means the quality is representative of up to `3 * kSampleWindow`
|
||||
// last samples with highest weight given to latest `kSampleWindow`
|
||||
// samples.
|
||||
// `mChannelOccupancy` stores the average rate/percentage of RSS
|
||||
// samples that are higher than a given RSS threshold ("bad" RSS
|
||||
// samples). For the first `kSampleWindow` samples, the average is
|
||||
// maintained as the actual percentage (i.e., ratio of number of
|
||||
// "bad" samples by total number of samples). After `kSampleWindow`
|
||||
// samples, the averager uses an exponentially weighted moving
|
||||
// average logic with weight coefficient `1/kSampleWindow` for new
|
||||
// values. Practically, this means the average is representative
|
||||
// of up to `3 * kSampleWindow` samples with highest weight given
|
||||
// to the latest `kSampleWindow` samples.
|
||||
|
||||
if (mSampleCount >= kSampleWindow)
|
||||
{
|
||||
@@ -197,7 +197,7 @@ void ChannelMonitor::HandleEnergyScanResult(otEnergyScanResult *aResult)
|
||||
|
||||
newAverage = (newAverage * weight + newValue) / (weight + 1);
|
||||
|
||||
mChannelQuality[channelIndex] = static_cast<uint16_t>(newAverage);
|
||||
mChannelOccupancy[channelIndex] = static_cast<uint16_t>(newAverage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,11 +206,11 @@ void ChannelMonitor::LogResults(void)
|
||||
otLogInfoUtil(
|
||||
GetInstance(),
|
||||
"ChannelMonitor: %u [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
|
||||
mSampleCount, mChannelQuality[0] >> 8, mChannelQuality[1] >> 8, mChannelQuality[2] >> 8,
|
||||
mChannelQuality[3] >> 8, mChannelQuality[4] >> 8, mChannelQuality[5] >> 8, mChannelQuality[6] >> 8,
|
||||
mChannelQuality[7] >> 8, mChannelQuality[8] >> 8, mChannelQuality[9] >> 8, mChannelQuality[10] >> 8,
|
||||
mChannelQuality[11] >> 8, mChannelQuality[12] >> 8, mChannelQuality[13] >> 8, mChannelQuality[14] >> 8,
|
||||
mChannelQuality[15] >> 8);
|
||||
mSampleCount, mChannelOccupancy[0] >> 8, mChannelOccupancy[1] >> 8, mChannelOccupancy[2] >> 8,
|
||||
mChannelOccupancy[3] >> 8, mChannelOccupancy[4] >> 8, mChannelOccupancy[5] >> 8, mChannelOccupancy[6] >> 8,
|
||||
mChannelOccupancy[7] >> 8, mChannelOccupancy[8] >> 8, mChannelOccupancy[9] >> 8, mChannelOccupancy[10] >> 8,
|
||||
mChannelOccupancy[11] >> 8, mChannelOccupancy[12] >> 8, mChannelOccupancy[13] >> 8, mChannelOccupancy[14] >> 8,
|
||||
mChannelOccupancy[15] >> 8);
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Utils {
|
||||
* channel collecting a single RSSI sample per channel. The RSSI samples are compared with a pre-specified RSSI
|
||||
* threshold `kRssiThreshold`. As an indicator of channel quality, the `ChannelMonitor` maintains and provides the
|
||||
* average rate/percentage of RSSI samples that are above the threshold within (approximately) a specified sample
|
||||
* window.
|
||||
* window (referred to as "channel occupancy").
|
||||
*
|
||||
*/
|
||||
class ChannelMonitor : public InstanceLocator
|
||||
@@ -148,34 +148,34 @@ public:
|
||||
uint32_t GetSampleCount(void) const { return mSampleCount; }
|
||||
|
||||
/**
|
||||
* This method returns the current channel quality value for a given channel.
|
||||
* This method returns the current channel occupancy for a given channel.
|
||||
*
|
||||
* The channel quality value represents the average rate/percentage of RSSI samples that were above RSSI threshold
|
||||
* The channel occupancy represents the average rate/percentage of RSSI samples that were above RSSI threshold
|
||||
* `kRssiThreshold` ("bad" RSSI samples).
|
||||
*
|
||||
* For the first `kSampleWindow` samples, the average is maintained as the actual percentage (i.e., ratio of number
|
||||
* of "bad" samples by total number of samples). After `kSampleWindow` samples, the averager uses an exponentially
|
||||
* weighted moving average logic with weight coefficient `1/kSampleWindow` for new values. Practically, this means
|
||||
* the quality is representative of up to `3 * kSampleWindow` last samples with highest weight given to latest
|
||||
* `kSampleWindow` samples.
|
||||
* the occupancy is representative of up to `3 * kSampleWindow` last samples with highest weight given to the
|
||||
* latest `kSampleWindow` samples.
|
||||
*
|
||||
* Max value of `0xffff` indicates all RSSI samples were above RSSI threshold (i.e. 100% of samples were "bad").
|
||||
*
|
||||
* @param[in] aChannel The channel for which to get the link quality.
|
||||
* @param[in] aChannel The channel for which to get the link occupancy.
|
||||
*
|
||||
* @returns the current channel quality value for the given channel.
|
||||
* @returns the current channel occupancy for the given channel.
|
||||
*
|
||||
*/
|
||||
uint16_t GetChannelQuality(uint8_t aChannel) const;
|
||||
uint16_t GetChannelOccupancy(uint8_t aChannel) const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kNumChannels = (OT_RADIO_CHANNEL_MAX - OT_RADIO_CHANNEL_MIN + 1),
|
||||
kNumChannelMasks = 4,
|
||||
kTimerInterval = (kSampleInterval / kNumChannelMasks),
|
||||
kMaxJitterInterval = 4096,
|
||||
kMaxQualityIndicator = 0xffff,
|
||||
kNumChannels = (OT_RADIO_CHANNEL_MAX - OT_RADIO_CHANNEL_MIN + 1),
|
||||
kNumChannelMasks = 4,
|
||||
kTimerInterval = (kSampleInterval / kNumChannelMasks),
|
||||
kMaxJitterInterval = 4096,
|
||||
kMaxOccupancy = 0xffff,
|
||||
};
|
||||
|
||||
void RestartTimer(void);
|
||||
@@ -189,7 +189,7 @@ private:
|
||||
|
||||
uint8_t mChannelMaskIndex : 2;
|
||||
uint32_t mSampleCount : 30;
|
||||
uint16_t mChannelQuality[kNumChannels];
|
||||
uint16_t mChannelOccupancy[kNumChannels];
|
||||
TimerMilli mTimer;
|
||||
};
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ const NcpBase::PropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] =
|
||||
NCP_GET_PROP_HANDLER_ENTRY(CHANNEL_MONITOR_RSSI_THRESHOLD),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(CHANNEL_MONITOR_SAMPLE_WINDOW),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(CHANNEL_MONITOR_SAMPLE_COUNT),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(CHANNEL_MONITOR_CHANNEL_QUALITY),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(CHANNEL_MONITOR_CHANNEL_OCCUPANCY),
|
||||
#endif
|
||||
#if OPENTHREAD_ENABLE_LEGACY
|
||||
NCP_GET_PROP_HANDLER_ENTRY(NEST_LEGACY_ULA_PREFIX),
|
||||
|
||||
@@ -605,7 +605,7 @@ protected:
|
||||
NCP_GET_PROP_HANDLER(CHANNEL_MONITOR_RSSI_THRESHOLD);
|
||||
NCP_GET_PROP_HANDLER(CHANNEL_MONITOR_SAMPLE_WINDOW);
|
||||
NCP_GET_PROP_HANDLER(CHANNEL_MONITOR_SAMPLE_COUNT);
|
||||
NCP_GET_PROP_HANDLER(CHANNEL_MONITOR_CHANNEL_QUALITY);
|
||||
NCP_GET_PROP_HANDLER(CHANNEL_MONITOR_CHANNEL_OCCUPANCY);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_ENABLE_LEGACY
|
||||
|
||||
@@ -1565,7 +1565,7 @@ otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_SAMPLE_COUNT(void)
|
||||
return mEncoder.WriteUint32(otChannelMonitorGetSampleCount(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_CHANNEL_QUALITY(void)
|
||||
otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_CHANNEL_OCCUPANCY(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
@@ -1574,7 +1574,7 @@ otError NcpBase::GetPropertyHandler_CHANNEL_MONITOR_CHANNEL_QUALITY(void)
|
||||
SuccessOrExit(error = mEncoder.OpenStruct());
|
||||
|
||||
SuccessOrExit(error = mEncoder.WriteUint8(channel));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(otChannelMonitorGetChannelQuality(mInstance, channel)));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(otChannelMonitorGetChannelOccupancy(mInstance, channel)));
|
||||
|
||||
SuccessOrExit(error = mEncoder.CloseStruct());
|
||||
}
|
||||
|
||||
+2
-2
@@ -1209,8 +1209,8 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
|
||||
ret = "PROP_CHANNEL_MONITOR_SAMPLE_COUNT";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_QUALITY:
|
||||
ret = "PROP_CHANNEL_MONITOR_CHANNEL_QUALITY";
|
||||
case SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY:
|
||||
ret = "PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_MAC_SCAN_STATE:
|
||||
|
||||
+4
-4
@@ -768,7 +768,7 @@ typedef enum
|
||||
SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_COUNT
|
||||
= SPINEL_PROP_PHY_EXT__BEGIN + 9,
|
||||
|
||||
/// Channel monitoring channel quality
|
||||
/// Channel monitoring channel occupancy
|
||||
/** Format: `A(t(CU))` (read-only)
|
||||
*
|
||||
* Required capability: SPINEL_CAP_CHANNEL_MONITOR
|
||||
@@ -776,9 +776,9 @@ typedef enum
|
||||
* Data per item is:
|
||||
*
|
||||
* `C`: Channel
|
||||
* `U`: Channel quality indicator
|
||||
* `U`: Channel occupancy indicator
|
||||
*
|
||||
* The channel quality value represents the average rate/percentage of
|
||||
* The channel occupancy value represents the average rate/percentage of
|
||||
* RSSI samples that were above RSSI threshold ("bad" RSSI samples) within
|
||||
* (approximately) sample window latest RSSI samples.
|
||||
*
|
||||
@@ -786,7 +786,7 @@ typedef enum
|
||||
* threshold (i.e. 100% of samples were "bad").
|
||||
*
|
||||
*/
|
||||
SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_QUALITY
|
||||
SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY
|
||||
= SPINEL_PROP_PHY_EXT__BEGIN + 10,
|
||||
|
||||
SPINEL_PROP_PHY_EXT__END = 0x1300,
|
||||
|
||||
Reference in New Issue
Block a user