wifimon

As I wrote about recently, I have been hacking on Raspberry Pi recently, using Swift. I got a bunch of parts from Adafruit today, and decided to attack a new project.

The Problem

I have several ideas for the summer…monitoring my record collection in the basement for humidity & temperature, monitoring the garden outside for light, temperature, etc, doggie cam… However, one thing many of these projects have in common is that I need two things: power and wifi. I’ll discuss long term portable power in the future, but for now, I just got a cheap “solar” battery, made for phones. Works good, and lets me charge and use the battery, so I can unplug the Pi and move it without rebooting.

That leads me to wifi. Unfortunately my wifi is not strong everywhere. I am trying different tweaking of the setup & also using different wifi adapters for the Pi, all to mostly test range. But how do you easily test this? How “good” is your wifi?

Thats the issue: how to measure my wifi.

Unix

I did some Googling and found that one simple file seemed to show the information I wanted, so seeing the output was as simple as:

pi@raspberrypi:~ $ 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  100.   77.    0.       0      0      0      0      0        0

This file is updated realtime, so all I have to do is get this link/level data into a program, and out onto a portable screen!

The Build

The main part I used was the HD44780 16x2 blue LCD from Adafruit. I cheated and got the assembled one, so i didn’t have to solder the header on.

I mostly followed this tutorial for how to wire the LCD to the Pi. Basically you just need the LCD, a pot (comes with LCD), a cobbler, breadboard and wires.

I am not that experienced with this stuff (learning!), so I initial had some trouble with my breadboard, but it didn’t take long to get it up and working.

The Software

Once I had things wired, it was time for coding. I knew I wanted to do everything in Swift. Seriously, RaspberryPi people, enough with the Python. 😀

I have a basic Swift setup on my Pi that I described in my previous post. Plus, the author of SwiftyGPIO also has a project for the HD44780!

My Code

I had to change some of the pins, but was able to get testing output going to the LCD easily enough:

1
2
3
4
5
let gpios = SwiftyGPIO.getGPIOsForBoard(.RaspberryPiRev2)
let lcd = HD44780LCD(rs:gpios[.P25]!,e:gpios[.P24]!,d7:gpios[.P22]!,d6:gpios[.P27]!,d5:gpios[.P17]!,d4:gpios[.P23]!,width:20,height:4)
lcd.clearScreen()
lcd.cursorHome()
lcd.printString(0,y:0,what:"Hello",usCharSet:true)

Now the tricky bit. At first, I tried to read the /proc/net/wireless file directly from Swift. I tried everything, all with no success. I think maybe it is just a weird system file that can’t be read directly? Or maybe the support just isn’t there in the Linux Foundation classes for Swift? Not sure.

Then I tried using my PiRunner code from last post to pull out the data I needed using the commandline. This worked good, but I couldn’t figure out how to get stdout from the run command to save to a variable inside my code. Normally, this would be done by assigned a NSPipe to the NSTask, but it doesn’t look like this functionality is available yet in NSTask.

SO…. I settled on kind of a hack solution. I re-route the file to a local file, then read the local file into my code, and parse out the data there:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import Glibc
import Foundation

func initLCD() -> HD44780LCD {
	let gpios = SwiftyGPIO.getGPIOsForBoard(.RaspberryPiRev2)
	let lcd = HD44780LCD(rs:gpios[.P25]!,e:gpios[.P24]!,d7:gpios[.P22]!,d6:gpios[.P27]!,d5:gpios[.P17]!,d4:gpios[.P23]!,width:20,height:4)
	return lcd	
}


while (true) {
	print("updating...")
	// weird i can't read this file directly
	PiRunner().shell("cat /proc/net/wireless | tail -n1 > outfile")

	do {
		let text = try NSString(contentsOfFile: "outfile", encoding: NSUTF8StringEncoding)

		let link = text.substringWithRange(NSRange(location: 14, length: 5))
		let level = text.substringWithRange(NSRange(location: 21, length: 5))

		let lcd = initLCD()
		lcd.cursorHome()
		lcd.clearScreen()

		lcd.printString(0,y:0,what:"Link: \(link)",usCharSet:true)	
		lcd.printString(0,y:1,what:"Level: \(level)",usCharSet:true)	
	} catch (_) {
		print("caught errrer")	
	}

	sleep(1)

}

And that works!

wifimon

While slightly clunky, I can walk around with this and test the wifi throughout my property, with different Wifi setups!

All my code for this project is available here.