44 #define LOG_MODULE "TSCH Stats" 45 #define LOG_LEVEL LOG_LEVEL_MAC 51 struct tsch_global_stats tsch_stats;
52 struct tsch_neighbor_stats tsch_neighbor_stats;
55 static struct ctimer periodic_timer;
57 static void periodic(
void *);
63 #if TSCH_STATS_SAMPLE_NOISE_RSSI 66 for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
67 tsch_stats.noise_rssi[i] = TSCH_STATS_DEFAULT_RSSI;
68 tsch_stats.channel_free_ewma[i] = TSCH_STATS_DEFAULT_CHANNEL_FREE;
72 tsch_stats_reset_neighbor_stats();
75 ctimer_set(&periodic_timer, TSCH_STATS_DECAY_INTERVAL / 10, periodic, NULL);
79 tsch_stats_reset_neighbor_stats(
void)
82 struct tsch_channel_stats *ch_stats;
84 ch_stats = tsch_neighbor_stats.channel_stats;
85 for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
86 ch_stats[i].rssi = TSCH_STATS_DEFAULT_RSSI;
87 ch_stats[i].lqi = TSCH_STATS_DEFAULT_LQI;
88 ch_stats[i].p_tx_success = TSCH_STATS_DEFAULT_P_TX;
92 struct tsch_neighbor_stats *
96 if(n != NULL && n->is_time_source) {
97 return &tsch_neighbor_stats;
103 tsch_stats_tx_packet(
struct tsch_neighbor *n, uint8_t mac_status, uint8_t channel)
105 struct tsch_neighbor_stats *stats;
107 stats = tsch_stats_get_from_neighbor(n);
109 uint8_t index = tsch_stats_channel_to_index(channel);
110 uint16_t new_tx_value = (mac_status ==
MAC_TX_OK ? 1 : 0);
111 new_tx_value *= TSCH_STATS_BINARY_SCALING_FACTOR;
112 TSCH_STATS_EWMA_UPDATE(stats->channel_stats[index].p_tx_success, new_tx_value);
117 tsch_stats_rx_packet(
struct tsch_neighbor *n, int8_t rssi, uint8_t lqi, uint8_t channel)
119 struct tsch_neighbor_stats *stats;
121 stats = tsch_stats_get_from_neighbor(n);
123 uint8_t index = tsch_stats_channel_to_index(channel);
125 TSCH_STATS_EWMA_UPDATE(stats->channel_stats[index].rssi,
126 TSCH_STATS_TRANSFORM(rssi, TSCH_STATS_RSSI_SCALING_FACTOR));
127 TSCH_STATS_EWMA_UPDATE(stats->channel_stats[index].lqi,
128 TSCH_STATS_TRANSFORM(lqi, TSCH_STATS_LQI_SCALING_FACTOR));
133 tsch_stats_on_time_synchronization(int32_t sync_error)
136 tsch_stats.max_sync_error = MAX(tsch_stats.max_sync_error, ABS(sync_error));
140 tsch_stats_sample_rssi(
void)
142 #if TSCH_STATS_SAMPLE_NOISE_RSSI 147 static uint8_t measurement_channel = TSCH_STATS_FIRST_CHANNEL;
149 index = tsch_stats_channel_to_index(measurement_channel);
152 NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, measurement_channel);
158 rv = NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &value);
159 if(rv == RADIO_RESULT_OK) {
160 tsch_stat_t prev_busyness_metric;
163 is_free = (((int)value <= TSCH_STATS_BUSY_CHANNEL_RSSI) ? 1 : 0) * TSCH_STATS_BINARY_SCALING_FACTOR;
167 TSCH_STATS_EWMA_UPDATE(tsch_stats.noise_rssi[index],
168 TSCH_STATS_TRANSFORM((
int)value, TSCH_STATS_RSSI_SCALING_FACTOR));
170 prev_busyness_metric = tsch_stats.channel_free_ewma[index];
171 (void)prev_busyness_metric;
172 TSCH_STATS_EWMA_UPDATE(tsch_stats.channel_free_ewma[index], is_free);
175 #ifdef TSCH_CALLBACK_CHANNEL_STATS_UPDATED 176 TSCH_CALLBACK_CHANNEL_STATS_UPDATED(measurement_channel, prev_busyness_metric);
179 LOG_ERR(
"! sampling RSSI failed: %d\n", (
int)rv);
183 measurement_channel++;
184 if(measurement_channel >= TSCH_STATS_FIRST_CHANNEL + TSCH_STATS_NUM_CHANNELS) {
185 measurement_channel = TSCH_STATS_FIRST_CHANNEL;
196 struct tsch_channel_stats *stats = tsch_neighbor_stats.channel_stats;
198 #if TSCH_STATS_SAMPLE_NOISE_RSSI 199 LOG_DBG(
"Noise RSSI:\n");
200 for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
201 LOG_DBG(
" channel %u: %d rssi, %u/%u free\n",
202 TSCH_STATS_FIRST_CHANNEL + i,
203 tsch_stats.noise_rssi[i] / TSCH_STATS_RSSI_SCALING_FACTOR,
204 tsch_stats.channel_free_ewma[i],
205 TSCH_STATS_BINARY_SCALING_FACTOR);
210 if(timesource != NULL) {
211 LOG_DBG(
"Time source neighbor:\n");
213 for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
214 LOG_DBG(
" channel %u: %d rssi, %u lqi, %u/%u P(tx)\n",
215 TSCH_STATS_FIRST_CHANNEL + i,
216 stats[i].rssi / TSCH_STATS_RSSI_SCALING_FACTOR,
217 stats[i].lqi / TSCH_STATS_LQI_SCALING_FACTOR,
218 stats[i].p_tx_success,
219 TSCH_STATS_BINARY_SCALING_FACTOR);
224 for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
226 TSCH_STATS_EWMA_UPDATE(stats[i].rssi, TSCH_STATS_DEFAULT_RSSI);
227 TSCH_STATS_EWMA_UPDATE(stats[i].lqi, TSCH_STATS_DEFAULT_LQI);
229 TSCH_STATS_EWMA_UPDATE(stats[i].p_tx_success, TSCH_STATS_DEFAULT_P_TX);
232 ctimer_set(&periodic_timer, TSCH_STATS_DECAY_INTERVAL, periodic, NULL);
Header file for the radio API
TSCH neighbor information.
struct tsch_neighbor * tsch_queue_get_time_source(void)
Get the TSCH time source (we currently assume there is only one)
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
The MAC layer transmission was OK.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Main API declarations for TSCH.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the logging system