Monitoring Your Wireless Interfaces

#1

Originally published at: https://www.influxdata.com/blog/monitoring-wireless-interfaces/

If you’ve followed my last few posts, you’ll see that I’ve been waist-deep in routers and wireless stuff. I’m building a larger, more complicated ‘reference architecture’ for IoT monitoring with InfluxDB, and to do that, I’m using all sorts of different boxes. I’m re-using my Pine-64 box (see here) and I wanted to be able to monitor the stats of the Wireless interface. Turns out, there was no Telegraf Plugin for that! WHAT??!?! So I wrote one.

If you’ve ever done a cat /proc/net/wireless you’ll know that, while the output is straightforward and helpful, someone decided that a 2-line header was a great idea. It wasn’t.

ubuntu@pine64:~$ cat /proc/net/wireless
Inter-| sta-| Quality | Discarded packets | Missed | WE
 face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
 wlan0: 0000 0. -256. -256. 0 0 0 0 0 0
 wlan1: 0000 42. -73. -256. 0 0 0 0 0 0
ubuntu@pine64:~$
I mean, it looks nice and all that, but it really wasn’t meant to be easily parsed into something meaningful. Anyway, since I was embarking on writing another Telegraf plugin, parsing it was exactly what I was going to need to do. This is the spaghetti I had to write to parse that header and put it together into something that would be meaningful to store in InfluxDB:x
func loadWirelessTable(table []byte, dumpZeros bool) (map[string]interface{}, map[string]string, error) {
	metrics := map[string]interface{}{}
	tags := map[string]string{}
	myLines := strings.Split(string(table), "\n")
	for x := 0; x < len(myLines)-1; x++ {
		f := strings.SplitN(myLines[x], ":", 2)
		f[0] = strings.Trim(f[0], " ")
		f[1] = strings.Trim(f[1], " ")
		if f[0] == "BSSID" {
			tags[strings.Replace(strings.Trim(f[0], " "), " ", "_", -1)] = strings.Replace(strings.Trim(string(f[1]), " "), " ", "_", -1)
			continue
		}
		n, err := strconv.ParseInt(strings.Trim(f[1], " "), 10, 64)
		if err != nil {
			tags[strings.Replace(strings.Trim(f[0], " "), " ", "_", -1)] = strings.Replace(strings.Trim(f[1], " "), " ", "_", -1)
			continue
		}
		if n == 0 {
			if dumpZeros {
				continue
			}
		}
		metrics[strings.Trim(f[0], " ")] = n
}
tags["interface"] = "airport"
return metrics, tags, nil

}


All of that so that we can see this:

in Chronograf! Nice! Notice how I turned the multi-line header into distinct values for ‘quality_level’ etc. and made them InfluxDB-friendly by replacing spaces with underscores, etc. We can now monitor all the various aspects of our Wireless interface(s)! So, since I’m running the latest version of Chronograf:

Google ChromeScreenSnapz001

I have a handy gauge with the RSSI of my active wireless interface! Of course, since this new plugin (coming at some point to a version of Telegraf!) relies on /proc/net/wireless, it will only work for Linux.

But wait, I didn’t forget about all of you Mac users out there. After a fair amount of google-fu, I found a roughly similar way to get wireless info from Mac OS. It’s buried and not easily accessible but I dug it out for you. It formats the output in a much more reasonable way, making it super easy to get into InfluxDB:

$ /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I
     agrCtlRSSI: -63
     agrExtRSSI: 0
    agrCtlNoise: -95
    agrExtNoise: 0
          state: running
        op mode: station
     lastTxRate: 65
        maxRate: 72
lastAssocStatus: 0
    802.11 auth: open
      link auth: wpa2-psk
          BSSID: 36:c3:d2:e3:ed:8e
           SSID: Influx-IoT2
            MCS: 7
        channel: 3
$
which cuts the code to make that useful down considerably:
func loadWirelessTable(table []byte, dumpZeros bool) (map[string]interface{}, map[string]string, error) {
	metrics := map[string]interface{}{}
	tags := map[string]string{}
	myLines := strings.Split(string(table), "\n")
	for x := 0; x < len(myLines)-1; x++ {
		f := strings.SplitN(myLines[x], ":", 2)
		f[0] = strings.Trim(f[0], " ")
		f[1] = strings.Trim(f[1], " ")
		if f[0] == "BSSID" {
			tags[strings.Replace(strings.Trim(f[0], " "), " ", "_", -1)] = strings.Replace(strings.Trim(string(f[1]), " "), " ", "_", -1)
			continue
		}
		n, err := strconv.ParseInt(strings.Trim(f[1], " "), 10, 64)
		if err != nil {
			tags[strings.Replace(strings.Trim(f[0], " "), " ", "_", -1)] = strings.Replace(strings.Trim(f[1], " "), " ", "_", -1)
			continue
		}
		if n == 0 {
			if dumpZeros {
				continue
			}
		}
		metrics[strings.Trim(f[0], " ")] = n
}
tags["interface"] = "airport"
return metrics, tags, nil

}


much more reasonable, don’t you think? It turns all those readings into nice tags and fields:

And gives me a similar gauge on my Mac:

Google ChromeScreenSnapz003

Pretty nifty!

Now, you’re probably wondering why I went to all this trouble just to be able to monitor the RSSI of a wireless interface. And that’s a great question! You see, in the world of IoT, you are going to have gateway devices out there that will be gathering data via wireless interfaces— you know, to connect with wireless sensors. So it’s important to be able to monitor the health and activity of those wireless interfaces. I added the Mac one just because it was easy and I wanted it.

So, stay tuned. I’ll be adding a number of blog posts on the sensors I’m connecting to this wireless gateway data collector. It’s actually part of a bigger project of building out a larger, more industrial-focused IoT demo platform.

#2

Hello, We are using Wireless Vibration sensors https://store.ncd.io/product/iot-long-range-wireless-vibration-and-temperature-sensor/ with one high tech machine and trying to Machine health monitoring system. This sensors is using the private network modules and with help of wireless nodes data is travelling and received by same PAN module which is connected to Raspberry Pi and I wanted to send this data to Influx Database and at same wanted to display the status on smartphones, but as new comer to this thing I still need to learn a lot, so any suggestion wll be much helpful to make IoT monitoring solution for this kind of sensors.

#3

Since they already have an integration using Node-Red, it should be trivial to use the Node-Red InfluxDB module to send the data to InfluxDB from the sensor devices.

This looks like a cool sensor!

dg

#4

Hello,
Thanks for the reply actually I am using particle electron which is using cellular services but I am quite confuse, to know the possibility about sending the data of sensor using Node Red InfluxDB module any advice to make this happen will be helpful.