nRF8001-Swift was written by Michael Teeuw [twitter].
- What is it?
- How to use
- Delegates AND Closures?!
- TL;DR - Give me the most simple example!
- Yeah, cool! But how do I connect my Bluefruit Breakout Board?
- Disclaimer
- Contributing
While working on one of my Arduino projects, I was in the need for a simple wrapper for communication with the Adafruit Bluefruit LE nRF8001 Breakout.
Since I was unable to find one (especially one that was Swift-ready) I wrote a Swift-wrapper myself. It is based on a Bluefruit LE Connect.
It has all the basic needs for basic two way communication and is easy to implement.
Add the NRFManager.swift file to your project and use the following implementation:
##Initialization
Use the shared instance:
let nrfManager = NRFManager.sharedInstance
Or simply create an instance yourself:
let nrfManager = NRFManager()
The Initializer takes 5 arguments. All of these arguments are optional and can be nil:
let nrfManager = NRFManager(delegate:NRFManagerDelegate? = nil, onConnect connectionCallback:(()->())? = nil, onDisconnect disconnectionCallback:(()->())? = nil, onData dataCallback:((data:NSData?, string:String?)->())? = nil, autoConnect:Bool = true)
-
The delegate argument sets the delegate for the NRFManager instance. The delegate must conform to the
NRFManagerDelegate
. Default isnil
. -
The onConnect argument can take a closure to execute when the NRFManager connects to the nRF8001 module. Default is
nil
. -
The onDisconnect argument can take a closure to execute when the NRFManager disconnects from the nRF8001 module. Default is
nil
. -
The onData argument can take a closure to execute when the NRFManager receives data from the nRF8001 module. This closure will receive a
data:NSData?
andstring:String?
object. Default isnil
. -
The autoConnect argument will tell the manager if it has to start searching and connect right away, and if it has to reconnect when the connection is lost. Default is
true
.
###Initialization examples:
// basic object which won't connect
let nrfBasicExample = NRFManager(autoConnect:false)
// using delegates
let nrfDelegateExample = NRFManager(delegate:self)
// using closures
let nrfClosureExample = NRFManager(
onConnect: {
println("Connected")
},
onDisconnect: {
println("Disconnected")
},
onData: {
(data:NSData?, string:String?)->() in
println("Recieved data - String: \(string) - Data: \(data)")
}
)
###Properties After initialization, it's possible to (re)set the following properties:
-
nrfManager.delegate
to set the delegate. -
nrfManager.connectionCallback
to set the onConnect callback. -
nrfManager.disconnectionCallback
to set the onDisconnect callback. -
nrfManager.dataCallback
to set the onData callback. -
nrfManager.autoConnect
to set the auto (re)connection behaviour. -
nrfManager.verbose
to enable or disable logging. This might be helpfull during debugging.
Additionally, the following properties are read-only:
-
nrfManager.connectionMode
returns an enum: ConnectionStatus (.Disconnected, .Scanning, .Connected). -
nrfManager.connectionStatus
returns an enum: ConnectionMode (.None, .PinIO, .UART).
A NRFManager can receive the following method calls:
nrfManager.connect()
Start looking for a connection. Only necessary when autoConnect
is set to false
.
nrfManager.disconnect()
Disconnect from the nRF8001 device. Note that when autoConnect
is set to true
, the NRFManager will be an annoying prick and start looking for an new connection instantly ...
nrfManager.writeString(string:String) -> Bool
Send a String to the nRF8001 device. It will return a Bool to tell you if it was possible to send it. (If there is no current connection, this will return false
in all other cases this will return true
.)
nrfManager.writeData(data:NSData) -> Bool
Send raw data (NSData) to the nRF8001 device. It will return a Bool to tell you if it was possible to send it. (If there is no current connection, this will return false
in all other cases this will return true
.)
The following methods are part of the NRFManagerDelegate protocol:
nrfDidConnect(nrfManager:NRFManager)
Called when the NRFManager connects to the nRF8001 module. The nrfManager
variable will contain a reference to the NRFManager instance which connected.
nrfDidDisconnect(nrfManager:NRFManager)
Called when the NRFManager disconnect from the nRF8001 module. The nrfManager
variable will contain a reference to the NRFManager instance which disconnected.
nrfReceivedData(nrfManager:NRFManager, data:NSData?, string:String?)
Called when the NRFManager receives data from the nRF8001 module. The nrfManager
variable will contain a reference to the NRFManager instance which received data. data
will contain the raw data, string
will contain the string representation of the received data.
The reason I implemented both is because I was unable to decide what the best approach is. Personally I tend to prefer the delegate route.
Although it is possible to both use the closures and the delegates, it wouldn't be the best idea to do so. That being said: Feel free to go wild! ... Both the delegate method and closure will be called when appropriate.
All closures and delegate methods are optional.
Okay okay, you lazy ass ... Here you go!
Using closures:
class ViewController: UIViewController {
var nrfManager:NRFManager!
override func viewDidLoad()
{
super.viewDidLoad()
nrfManager = NRFManager(
onConnect: {
println("Connected")
self.sendData()
},
onDisconnect: {
println("Disconnected")
},
onData: {
(data:NSData?, string:String?)->() in
println("Received data - String: \(string) - Data: \(data)")
}
)
}
func sendData()
{
let result = self.nrfManager.writeString("Hello, world!")
}
}
Using delegates:
class ViewController: UIViewController, NRFManagerDelegate {
var nrfManager:NRFManager!
override func viewDidLoad()
{
super.viewDidLoad()
nrfManager = NRFManager(delegate:self)
}
func sendData()
{
let result = self.nrfManager.writeString("Hello, world!")
}
// NRFManagerDelegate methods
func nrfDidConnect(nrfManager:NRFManager)
{
println("Connected")
self.sendData()
}
func nrfDidDisconnect(nrfManager:NRFManager)
{
println("Disconnected")
}
func nrfReceivedData(nrfManager:NRFManager, data: NSData?, string: String?) {
println("Received data - String: \(string) - Data: \(data)")
}
}
You can check out the example project to see how it works. It includes both the delegate and closure usage.
Check Adafruit's awesome tutorial on how to use the Bluefruit Breakout Board. You can use the echo example sketch to test out nRF8001-Swift.
This is my fist bluetooth experiment. So be gentle. ;)
Forks, pull requests and other feedback are welcome.
Photos Courtesy of Adafruit.