### Here's a patch that adds a signal-to-noise bar and makes the ### signalbar only report on signal strength. Also fixes the signalbar ### for cards that report levels in dbm. The signalbar was not working ### at all in these cases. Some interesting work remains: the signal ### strength is a naive approximation but I framed it in RSSI terms, ### for anyone who wants to figure out how to get rssi and rssi_max ### values (maybe via ioctls in pcapsource.cc?). Tested on FreeBSD 6.1. ### Index: packetracker.cc =================================================================== --- packetracker.cc (revision 1943) +++ packetracker.cc (working copy) @@ -54,6 +54,8 @@ num_networks = num_packets = num_dropped = num_noise = num_crypt = num_interesting = num_cisco = 0; + best_signal = worst_signal = 0; + errstr[0] = '\0'; filter_export_bssid = filter_export_source = filter_export_dest = NULL; @@ -535,25 +537,51 @@ if (info->source_mac == net->bssid) net->last_sequence = info->sequence_number; - if (info->noise != 0 || info->signal != 0) { + if (info->signal != 0) net->signal = info->signal; - if (info->signal > net->best_signal || net->best_signal == 0) { - net->best_signal = info->signal; - if (info->gps_fix >= 2) { - net->best_lat = info->gps_lat; - net->best_lon = info->gps_lon; - net->best_alt = info->gps_alt; - } + // Record best signal level so far for this network + if (info->signal != 0 && + (info->signal > net->best_signal || net->best_signal == 0)) { + net->best_signal = info->signal; + if (info->gps_fix >= 2) { + net->best_lat = info->gps_lat; + net->best_lon = info->gps_lon; + net->best_alt = info->gps_alt; } + } - net->noise = info->noise; + // Record best and worst signal levels ever seen on any network + if (info->signal != 0) { + if (info->signal > best_signal || best_signal == 0) + best_signal = info->signal; + if (info->signal < worst_signal) + worst_signal = info->signal; + } - // Record the "best" (aka 'worst') noise level - if (info->noise > net->best_noise || net->best_noise == 0) - net->best_noise = info->noise; + // Fake RSSI against a floating ceiling. FIXME - get RSSI from driver. + if (info->signal < 0) { + // dbM signal level + double strength = + (double)(info->signal - worst_signal) / + (double)(best_signal - worst_signal); + net->rssi = (int)(strength * 100); + net->rssi_max = 100; } + else { + // absolute, driver-specific signal level + net->rssi = info->signal; + net->rssi_max = best_signal == 0 ? 100 : best_signal; + } + if (info->noise != 0) + net->noise = info->noise; + + // Record the "best" (aka 'worst') noise level + if (info->noise != 0 && + (info->noise < net->best_noise || net->best_noise == 0)) + net->best_noise = info->noise; + if (info->gps_fix >= 2) { // Don't aggregate slow-moving packets to prevent average "pulling".. if (info->gps_spd <= 0.3) { Index: packetracker.h =================================================================== --- packetracker.h (revision 1943) +++ packetracker.h (working copy) @@ -125,6 +125,8 @@ int num_networks, num_packets, num_dropped, num_noise, num_crypt, num_interesting, num_cisco; + int best_signal, worst_signal; + // all the networks vector network_list; Index: panelfront.h =================================================================== --- panelfront.h (revision 1943) +++ panelfront.h (working copy) @@ -338,7 +338,7 @@ mcol_wep, mcol_channel, mcol_data, mcol_llc, mcol_crypt, mcol_weak, mcol_bssid, mcol_flags, mcol_ip, /* mcol_mask, mcol_gateway, */ mcol_packets, mcol_info, mcol_maxrate, mcol_manuf, mcol_signal, mcol_quality, mcol_noise, mcol_clients, - mcol_datasize, mcol_signalbar, mcol_qualitybar, mcol_dupeiv + mcol_datasize, mcol_signalbar, mcol_qualitybar, mcol_dupeiv, mcol_snrbar }; enum client_columns { Index: server_protocols.cc =================================================================== --- server_protocols.cc (revision 1943) +++ server_protocols.cc (working copy) @@ -102,6 +102,7 @@ "octets", "cloaked", "beaconrate", "maxrate", "manufkey", "manufscore", "quality", "signal", "noise", + "rssi", "rssi_max", "bestquality", "bestsignal", "bestnoise", "bestlat", "bestlon", "bestalt", "agglat", "agglon", "aggalt", "aggpoints", @@ -458,6 +459,12 @@ snprintf(tmpstr, 128, "%d", net->noise); data->ndvec.push_back(tmpstr); + snprintf(tmpstr, 128, "%d", net->rssi); + data->ndvec.push_back(tmpstr); + + snprintf(tmpstr, 128, "%d", net->rssi_max); + data->ndvec.push_back(tmpstr); + snprintf(tmpstr, 128, "%d", net->best_quality); data->ndvec.push_back(tmpstr); Index: tracktypes.h =================================================================== --- tracktypes.h (revision 1943) +++ tracktypes.h (working copy) @@ -127,6 +127,7 @@ signal = quality = noise = 0; best_signal = best_quality = best_noise = 0; + rssi = 0; rssi_max = 100; best_lat = best_lon = best_alt = 0; memset(&ipdata, 0, sizeof(net_ip_data)); @@ -237,7 +238,7 @@ int metric; // Last seen quality for a packet from this client - int quality, signal, noise; + int quality, signal, noise, rssi, rssi_max; int best_quality, best_signal, best_noise; float best_lat, best_lon, best_alt; @@ -311,6 +312,7 @@ quality = signal = noise = 0; best_quality = best_signal = best_noise = 0; + rssi = 0; rssi_max = 100; best_lat = best_lon = best_alt = 0; client_disconnects = 0; @@ -486,7 +488,7 @@ int metric; // Connection information - int quality, signal, noise; + int quality, signal, noise, rssi, rssi_max; int best_quality, best_signal, best_noise; float best_lat, best_lon, best_alt; Index: panelfront.cc =================================================================== --- panelfront.cc (revision 1943) +++ panelfront.cc (working copy) @@ -933,6 +933,8 @@ return mcol_datasize; } else if (in_token == "signalbar") { return mcol_signalbar; + } else if (in_token == "snrbar") { + return mcol_snrbar; /* } else if (in_token == "qualitybar") { return mcol_qualitybar; Index: server_protocols.h =================================================================== --- server_protocols.h (revision 1943) +++ server_protocols.h (working copy) @@ -37,6 +37,7 @@ NETWORK_octets, NETWORK_cloaked, NETWORK_beaconrate, NETWORK_maxrate, NETWORK_manufkey, NETWORK_manufscore, NETWORK_quality, NETWORK_signal, NETWORK_noise, + NETWORK_rssi, NETWORK_rssi_max, NETWORK_bestquality, NETWORK_bestsignal, NETWORK_bestnoise, NETWORK_bestlat, NETWORK_bestlon, NETWORK_bestalt, NETWORK_agglat, NETWORK_agglon, NETWORK_aggalt, NETWORK_aggpoints, Index: tcpclient.cc =================================================================== --- tcpclient.cc (revision 1943) +++ tcpclient.cc (working copy) @@ -33,7 +33,7 @@ protocol_default_map["NETWORK"] = "bssid,type,ssid,beaconinfo,llcpackets,datapackets,cryptpackets," "weakpackets,channel,wep,firsttime,lasttime,atype,rangeip,gpsfixed,minlat,minlon,minalt,minspd," "maxlat,maxlon,maxalt,maxspd,octets,cloaked,beaconrate,maxrate," - "quality,signal,noise,bestquality,bestsignal,bestnoise,bestlat,bestlon,bestalt," + "quality,signal,noise,rssi,rssi_max,bestquality,bestsignal,bestnoise,bestlat,bestlon,bestalt," "agglat,agglon,aggalt,aggpoints,datasize,turbocellnid,turbocellmode,turbocellsat," "carrierset,maxseenrate,encodingset,decrypted,dupeivpackets,bsstimestamp"; protocol_default_map["CLIENT"] = "bssid,mac,type,firsttime,lasttime," @@ -360,8 +360,8 @@ int maxseenrate; // Connection information - int quality, signal, noise; - int best_quality, best_signal, best_noise; + int quality, signal, noise, rssi, rssi_max; + int best_quality, best_signal, best_noise; float best_lat, best_lon, best_alt; // Amount of data, in bytes @@ -404,7 +404,7 @@ scanned = sscanf(in_data+hdrlen+18, "%d \001%255[^\001]\001 " "\001%255[^\001]\001 " "%d %d %d %d %d %d %d %d %d %hd.%hd.%hd.%hd " - "%d %f %f %f %f %f %f %f %f %d %d %d %f %d %d %d %d %d %d " + "%d %f %f %f %f %f %f %f %f %d %d %d %f %d %d %d %d %d %d %d %d" "%f %f %f %lf %lf %lf %ld %ld" "%d %d %d %d %d %d %d %d %lld", &tmptype, ssid, beaconstr, @@ -416,8 +416,8 @@ &min_alt, &min_spd, &max_lat, &max_lon, &max_alt, &max_spd, &octets, &cloaked, &beacon, &maxrate, &quality, - &signal, &noise, &best_quality, - &best_signal, &best_noise, + &signal, &noise, &rssi, &rssi_max, + &best_quality, &best_signal, &best_noise, &best_lat, &best_lon, &best_alt, &aggregate_lat, &aggregate_lon, &aggregate_alt, &aggregate_points, &datasize, @@ -431,7 +431,7 @@ turbocell_mode = static_cast(tmpturbocell_mode); } - if (scanned < 51) { + if (scanned < 54) { // fprintf(stderr, "Flubbed network, discarding... %s '%s'\n", bssid_str, in_data); // Can't delete us out of the tracker offhand if we're not a new network, // remove us cleanly. @@ -487,6 +487,8 @@ net->quality = quality; net->signal = signal; net->noise = noise; + net->rssi = rssi; + net->rssi_max = rssi_max; net->best_quality = best_quality; net->best_signal = best_signal; net->best_noise = best_noise; Index: panelfront_display.cc =================================================================== --- panelfront_display.cc (revision 1943) +++ panelfront_display.cc (working copy) @@ -227,36 +227,63 @@ snprintf(element, 6, "%4ldM", net->datasize/1024/1024); len = 5; } else if (colindex == mcol_signalbar) { - if (net->best_signal > 0) { - int sx = 0; + int sx = 0; - // see if it looks like dBm... - if (net->signal < 0 && idle_time < (decay * 2)) { - // If we have a dB noise level, get the percentage of signal to noise - if (net->noise < 0) - sx = (int) (double) (net->noise / net->signal) * 15; - else - sx = (int) (double) (100 / abs(net->signal)) * 15; - } else if (idle_time < (decay * 2)) { - // Extract the signal percentage of the best signal seen - sx = (int)((double)(idle_time < (decay * 2) ? net->signal : 0) / - net->best_signal * 15); + if (idle_time < (decay * 2)) + sx = (int)(15 * (double)net->rssi / (double)net->rssi_max); + + // Boundscheck sx + if (sx < 0) + sx = 0; + else if (sx > 15) + sx = 15; + + char sg[16]; + + if (sx > 0) { + memset(sg, 'X', sx); + memset(sg + sx, '=', 15 - sx); + sg[15] = '\0'; + snprintf(element, 16, "%s", sg); + } else + snprintf(element, 1024, "==============="); + + len = 15; + + } else if (colindex == mcol_snrbar) { + int sx = 0; + + if (idle_time < (decay * 2)) { + double snr = 0.0; + + if (net->signal < 0 && net->noise < 0) { + // dBm levels + snr = exp(M_LN10 * ((double)net->signal - (double)net->noise) / 10); } + else if (net->signal > 0 && net->noise > 0) { + // absolute, driver-specific levels + snr = (double)net->signal / (double)net->noise; + } - char sg[16]; + sx = int(15 * snr / (snr + 1)); + } - // Boundscheck sx - if (sx < 0) - sx = 0; - else if (sx > 15) - sx = 15; + char sg[16]; + // Boundscheck sx + if (sx < 0) + sx = 0; + else if (sx > 15) + sx = 15; + + if (sx > 0) { memset(sg, 'X', sx); memset(sg + sx, '=', 15 - sx); sg[15] = '\0'; snprintf(element, 16, "%s", sg); } else snprintf(element, 1024, "==============="); + len = 15; } else if (colindex == mcol_dupeiv) { snprintf(element, 5, "%4d", net->dupeiv_packets); @@ -514,6 +541,9 @@ } else if (colind == mcol_signalbar) { snprintf(title, 1024, "SignalGraph"); len = 15; + } else if (colind == mcol_snrbar) { + snprintf(title, 1024, "SNRGraph"); + len = 15; } else if (colind == mcol_dupeiv) { snprintf(title, 1024, "DIV"); len = 4; Index: README =================================================================== --- README (revision 1943) +++ README (working copy) @@ -441,7 +441,8 @@ shortname Shortened name of the network or group for small displays shortssid Shortened SSID for small displays signal Last seen signal level - signalbar Graphical representation of signal level + signalbar Graphical representation of signal strength + snrbar Graphical representation of signal-to-noise ratio size Amount of data transfered on network ssid SSID/ESSID of the network or group type Network type (Probe, Adhoc, Infra, etc)