Swift On Raspberry Pi From iPad Pro
Recently I dug out my old Raspberry Pi Model B (rev2) to try out open source Swift. It had been a long time, I started from scratch.
Basics
I re-imaged a fresh version of Raspbian Jesse Lite from here, following the OSX instructions here. It was a bit off, but if you are careful with the disk names, it works fine.
I don’t have a wifi adapter (yet, on order), so I used ethernet & booted up the pi. From my Mac, I used this command to find the Pi’s ip address (from here):
arp -na | grep -i b8:27:eb
With the proper address, I fired up Prompt and SSH’d using the default username and password (pi/raspberry).
Swift
I dug around and found @uraimo had done the work to get Swift up and running on ARMv6 (RaspberryPi1/Zero). My first attempt was Swift 2.2 from here, however that led to a compiler error…so then I tried his updated Swift 3.0 snapshot here. This worked perfect, and even includes Foundation.
Editor
Now I was setup with a compiler. I love a good terminal vi/nano/emacs as much as the next neckbeard, but using it for Swift development was not cutting it. I looked around and Panic’s other product Coda supports Swift syntax highlighting, working remotely via SSH, and terminals in tabs! Perfect! I got that setup on my iPad Pro and now I have a nice environment to write Swift for the Raspberry Pi.
Coding
I have a Raspberry Pi camera on order, so I know I am going to want to control that from Swift. I couldn’t find a Swift native library, like they have for Python. However, with the SwiftyGPIO project, it should be possible, right? For now, I will stick to using the command line tools like raspistill.
This means I’ll need to be able to run shell commands from Swift. Googling this leads to code that uses Foundation, and is some variation of this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func runCommand(path : String, args : [String]) -> (output: NSString, error: NSString, exitCode: Int32) {
let task = NSTask()
task.launchPath = path
task.arguments = args
let outpipe = NSPipe()
task.standardOutput = outpipe
let errpipe = NSPipe()
task.standardError = errpipe
task.launch()
let outdata = outpipe.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: outdata, encoding: NSUTF8StringEncoding)
let errdata = errpipe.fileHandleForReading.readDataToEndOfFile()
let error_output = NSString(data: errdata, encoding: NSUTF8StringEncoding)
task.waitUntilExit()
let status = task.terminationStatus
return (output!, error_output!, status)
}
So, we got NSTask
, NSPipe
, NSString
…oh boy.
Looking at the Foundation status page, it says NSTask
isn’t implemented yet, NSPipe
isn’t listed, and NSString
is partially implemented.
I figured, what the heck, try it. It compiles and runs! And (sorta) works! The issue is that it doesn’t seem to ever quit. I dug around in the source code a bit, and eventually just simplified my code to this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Foundation
func shell(command: String) {
// Create a Task instance
let task = NSTask()
// Set the task parameters
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
// Launch the task
task.launch()
task.waitUntilExit()
}
shell("raspistill")
This runs the command, and exits properly. I’m sure I’ll run into other issues once I get the camera & wifi going, but for now my iPad Pro Raspberry Pi Swift dev kit is going good!