I'm presenting a very early draft of my
bluetooth
library. As its name suggests,
bluetooth
is a Haskell frontend to low-level Bluetooth APIs, making it similar in spirit to Python's
PyBluez and Java's
BlueCove.
What it can do
Currently,
bluetooth
only supports Linux. It has the capability of running an RFCOMM server and client. Theoretically, it should also support L2CAP servers and clients, although this has not been tested yet.
What it will eventually do
I plan to have
bluetooth
support each of the GHC
Tier 1 platforms—that is, Windows, OS X, Linux, and FreeBSD. I want to have the capability to run the full gamut of L2CAP and RFCOMM-related functions on each OS, as well as any additional OS-specific functionality.
Motivation
Bluetooth programming on Haskell is currently in a very primitive state. As of now, there are only two packages on Hackage that make any mention of Bluetooth (as far as I can tell):
network
hints in its Network.Socket
module that there is an AF_BLUETOOTH
socket address family. However, trying to use it with network
will fail, since there is no corresponding Bluetooth SockAddr
.
simple-bluetooth
by Stephen Blackheath offers some of what my own bluetooth
package offers (namely, RFCOMM client capability on Windows and Linux).
However, there is currently no comprehensive, cross-platform Haskell Bluetooth library
à la PyBluez or BlueCove. I want
bluetooth
to fill that niche.
How bluetooth
works
bluetooth
can be thought of as a wrapper around
network
. After all, Bluetooth programming is socket-based, so
Network.Socket
already provides most of what one needs to implement a Bluetooth server or client. There are several gotchas with Bluetooth programming, however:
- Every major OS has a completely different Bluetooth software stack. For example, Linux uses BlueZ, and Windows has several different stacks, including Winsock and Widcomm. Therefore,
bluetooth
is not likely to work identically on every OS.
- Windows in particular is challenging to support since several Winsock functions do not work correctly on the version of MinGW-w64 that is currently shipped with GHC for Windows (only the 64-bit version, no less). For this reason, I probably won't develop a Windows version of
bluetooth
until this issue is resolved.
It is recommended that you have a basic understanding of Bluetooth programming before attempting to use
bluetooth
. I recommend
this introduction by Albert Huang.
Examples
The following are abridged examples of the RFCOMM
client and
server examples from the
bluetooth
repo.
RFCOMM server
module Main where
import Data.Set
import Network.Bluetooth
import Network.Socket
main :: IO ()
main = withSocketsDo $ do
let uuid = serviceClassToUUID SerialPort
proto = RFCOMM
settings = defaultSDPInfo {
sdpServiceName = Just "Roto-Rooter Data Router"
, sdpProviderName = Just "Roto-Rooter"
, sdpDescription = Just "An experimental plumbing router"
, sdpServiceClasses = singleton SerialPort
, sdpProfiles = singleton SerialPort
}
handshakeSock <- bluetoothSocket proto
btPort <- bluetoothBindAnyPort handshakeSock anyAddr
bluetoothListen handshakeSock 1
service <- registerSDPService uuid settings proto btPort
(connSock, connAddr) <- bluetoothAccept handshakeSock
putStrLn $ "Established connection with address " ++ show connAddr
message <- recv connSock 4096
putStrLn $ "Received message! [" ++ message ++ "]"
let response = reverse message
respBytes <- send connSock response
putStrLn $ "Sent response! " ++ show respBytes ++ " bytes."
close connSock
close handshakeSock
closeSDPService service
RFCOMM client
module Main where
import Network.Bluetooth
import Network.Socket
import System.IO
main :: IO ()
main = withSocketsDo $ do
let addr = read "12:34:56:78:90:00"
port = 1
sock <- bluetoothSocket RFCOMM
bluetoothConnect sock addr port
putStrLn "Established a connection!"
putStr "Please enter a message to send: "
hFlush stdout
message <- getLine
messBytes <- send sock message
response <- recv sock 4096
putStrLn $ "Received reponse! [" ++ reponse ++ "]"
close sock
No comments:
Post a Comment