Platforms to show: All Mac Windows Linux Cross-Platform

/Bluetooth/Mac Bluetooth/Mac Bluetooth Connection


Required plugins for this example: MBS MacBase Plugin, MBS Bluetooth Plugin, MBS Main Plugin

You find this example project in your Plugins Download as a Xojo project file within the examples folder: /Bluetooth/Mac Bluetooth/Mac Bluetooth Connection

This example is the version from Wed, 26th Jun 2018.

Project "Mac Bluetooth Connection.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
EventHandler Sub Open() host = new MyIOBluetoothHostController End EventHandler
EventHandler Function UnhandledException(error As RuntimeException) As Boolean MsgBox Introspection.GetType(error).fullname+EndOfLine+error.Message Return true End EventHandler
Property host As MyIOBluetoothHostController
End Class
Class MainWindow Inherits Window
Control List Inherits Listbox
ControlInstance List Inherits Listbox
End Control
Control ListenButton Inherits PushButton
ControlInstance ListenButton Inherits PushButton
EventHandler Sub Action() ServiceBrowserController.beginSheetModalForWindow(self) End EventHandler
End Control
Control MessageField Inherits TextField
ControlInstance MessageField Inherits TextField
EventHandler Sub TextChange() SendButton.Enabled = me.text.len > 0 End EventHandler
End Control
Control SendButton Inherits PushButton
ControlInstance SendButton Inherits PushButton
EventHandler Sub Action() dim s as string = MessageField.Text.ConvertEncoding(encodings.UTF8) if lenb(s) > 0 then dim m as MemoryBlock = s Channel.writeAsync m log str(m.size)+" Bytes sent." end if End EventHandler
End Control
EventHandler Sub Close() if ServiceBrowserController <> nil then ServiceBrowserController.parent = nil end if End EventHandler
EventHandler Sub Open() ServiceBrowserController = new IOBluetoothServiceBrowserController(IOBluetoothServiceBrowserController.kOptionsNone) ServiceBrowserController.Title = "Service Browser" ServiceBrowserController.parent = self #if DebugBuild then device = IOBluetoothDeviceMBS.deviceWithAddressString("00-16-53-5c-02-b7") if device <> nil then const ChannelID = 1 log "Device: "+device.name+" "+device.addressString log "Open service on channel "+str(ChannelID) Channel = new MyChannel if Channel.openRFCOMMChannelAsync(Device, ChannelID) then else log "Open failed with error "+str(Channel.Lasterror) end if end if #endif End EventHandler
Function MindstormEV3PlaySound() As Boolean if Channel <> nil and channel.isOpen then EVPlaySound else MsgBox "Channel not open?" end if Return True End Function
Function MindstormEV3QueryDeviceInputList() As Boolean if Channel <> nil and channel.isOpen then EVQueryInputDeviceList else MsgBox "Channel not open?" end if Return True End Function
Function MindstormEV3Querydirectorylisting() As Boolean if Channel <> nil and channel.isOpen then EVListFiles else MsgBox "Channel not open?" end if Return True End Function
Sub EVListFiles() 'Bytes send to the brick: 'xxxxxxxx0199xxxxxxx 'bbbbmmmmttssllllnnn... 'bbbb = bytes in message mmmm = message counter tt = type of message 'ss = system command 'llll = max. bytes to read nnn.. = path name dim path as string = "/" // put linux path here // bbbbmmmmttssllllnnn dim m as MemoryBlock = new MemoryBlock(9 + lenb(path)) m.LittleEndian = true m.UInt16Value(0) = m.size m.UInt16Value(2) = 0 m.UInt8Value(4) = 1 m.UInt8Value(5) = &h99 m.UInt16Value(6) = 1012 m.StringValue(8,lenb(path)) = path Channel.EVListFiles = true Channel.writeAsync m log EncodeHex(m) log str(m.size)+" Bytes sent." End Sub
Sub EVPlaySound() 'Play a 1Kz tone at level 2 for 1 sec. 'opSOUND,LC0(TONE),LC1(2),LC2(1000),LC2(1000) 'opSOUND LC0(TONE) LC1(2) LC2(1000) LC2(1000) 'Bytes sent to the brick: 'Opcode sound related 'Command (TONE) encoded as single byte constant Sound-level 2 encoded as one constant 'byte to follow Frequency 1000 Hz. encoded as two constant bytes to follow Duration 1000 mS. 'encoded as two constant bytes to follow '0F00xxxx8000009401810282E80382E803 'Bbbbmmmmtthhhhcccccccccccccccccccc 'bbbb = bytes in message 15 excl. packet length bytes 'mmmm = message counter 'tt = type of command - Direct command no reply 'hhhh = header variable alloc*). 'cc/CC = byte codes. '*)hhhh = 10 least significant bits are number of globals, 6 most significal bits are locals dim s as string s = "0F0000000000009401810282E80382E803" // Bbbbmmmmtthhhhcccccccccccccccccccc dim m as MemoryBlock = DecodeHex(s) Channel.writeAsync m log EncodeHex(m) log str(m.size)+" Bytes sent." End Sub
Sub EVQueryInputDeviceList() 'opINPUT_DEVICE_LIST Example ' 'Get all device types connected to input ports: ' 'Byte codes: opINPUT_DEVICE_LIST,LC0(4),GV0(0),GV0(4), '\ / '\ ------- '\ / 'Hex values send: 0900xxxx00050098046064 ' ' 'Hex value received: 0800xxxx027E7E7E7D00 '^--------- '| 'Command global variable (response buffer offset) '0=port 1 type, 1=port 2 type, 2=port 3 type, 3=port4 type, 4=change flag. dim s as string s = "0900000000050098046064" // bbbbmmmmtthhhhcccccccc dim m as MemoryBlock = DecodeHex(s) Channel.writeAsync m log EncodeHex(m) log str(m.size)+" Bytes sent." Channel.EVQueryInputDeviceList = true // seems like answer doesn't come until next packet goes to device? End Sub
Sub Log(s as string) List.AddRow s End Sub
Sub OpenService(Service as IOBluetoothSDPServiceRecordMBS) device = Service.Device dim ChannelID as integer = Service.RFCOMMChannelID if ChannelID = 0 then // no channel? break else Channel = nil // clear old if any log "Device: "+device.name+" "+device.addressString log "Open service on channel "+str(ChannelID) Channel = new MyChannel if Channel.openRFCOMMChannelAsync(Service.Device, ChannelID) then // okay else log "Open failed with error "+str(Channel.Lasterror) end if end if End Sub
Property Channel As MyChannel
Property ServiceBrowserController As IOBluetoothServiceBrowserController
Property counter As Integer
Property device As IOBluetoothDeviceMBS
End Class
MenuBar MainMenuBar
MenuItem FileMenu = "&File"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem MindstormEV3Menu = "Mindstorm EV3"
MenuItem MindstormEV3PlaySound = "Play Sound"
MenuItem MindstormEV3QueryDeviceInputList = "Query Device Input List"
MenuItem MindstormEV3Querydirectorylisting = "Query directory listing"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem EditSeparator1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem EditSeparator2 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
Class MyChannel Inherits IOBluetoothRFCOMMChannelMBS
EventHandler Sub Closed() log "Closed" End EventHandler
EventHandler Sub ControlSignalsChanged() log "Control signals changed" End EventHandler
EventHandler Sub DataReceived(data as MemoryBlock, dataLength as Integer) dim s as string = data dim e as string = EncodeHex(s) // data MainWindow.log "Data received: "+e if EVQueryInputDeviceList and mid(e, 9, 4) = "0221" then // e.g. 0800000002217E101D06 dim Port0 as integer = data.UInt8Value(5) // e.g. 21 = EV3 IR sensor dim Port1 as integer = data.UInt8Value(6) // e.g. 7E = Port empty or not available dim Port2 as integer = data.UInt8Value(7) // e.g. 10 = EV3 touch sensor dim Port3 as integer = data.UInt8Value(8) // e.g. 1D = EV3 color sensor MainWindow.log "Port0: "+str(Port0)+" "+GetEVSensorType(port0) MainWindow.log "Port1: "+str(Port1)+" "+GetEVSensorType(port1) MainWindow.log "Port2: "+str(Port2)+" "+GetEVSensorType(port2) MainWindow.log "Port3: "+str(Port3)+" "+GetEVSensorType(port3) EVQueryInputDeviceList = false end if if EVListFiles and mid(e, 9, 4) = "0399" then // got file listing s = data.StringValue(12, data.size-12) s = DefineEncoding(s, encodings.UTF8) s = ReplaceLineEndings(s, EndOfLine) dim lines() as string = split(s, EndOfLine) for each line as string in lines MainWindow.log "> "+line next EVListFiles = false end if End EventHandler
EventHandler Sub FlowControlChanged() log "Flow control changed" End EventHandler
EventHandler Sub OpenCompleted(status as Integer) if status = 0 then log "Open completed." else log "Open completed with error "+str(status) MainWindow.MessageField.Enabled = true end if End EventHandler
EventHandler Sub QueueSpaceAvailable() log "Queue space available." End EventHandler
EventHandler Sub WriteCompleted(status as integer, tag as Variant) log "Write completed: "+str(status) End EventHandler
Function GetEVSensorType(n as integer) As string // Types defined in "typedata.rcf" const TYPE_NXT_TOUCH = 1 //!< Device is NXT touch sensor const TYPE_NXT_LIGHT = 2 //!< Device is NXT light sensor const TYPE_NXT_SOUND = 3 //!< Device is NXT sound sensor const TYPE_NXT_COLOR = 4 //!< Device is NXT color sensor const TYPE_NXT_ULTRASONIC = 5 //!< Device is NXT ultra sonic sensor const TYPE_NXT_TEMPERATURE = 6 //!< Device is NXT temperature sensor const TYPE_TACHO = 7 //!< Device is EV3/NXT tacho motor const TYPE_MINITACHO = 8 //!< Device is EV3 mini tacho motor const TYPE_NEWTACHO = 9 //!< Device is EV3 new tacho motor const TYPE_TOUCH = 16 //!< Device is EV3 touch sensor // Types defined in known EV3 digital devices const TYPE_COLOR = 29 //!< Device is EV3 color sensor const TYPE_ULTRASONIC = 30 //!< Device is EV3 ultra sonic sensor const TYPE_GYRO = 32 //!< Device is EV3 gyro sensor const TYPE_IR = 33 //!< Device is EV3 IR sensor // Type range reserved for third party devices const TYPE_THIRD_PARTY_START = 50 const TYPE_THIRD_PARTY_END = 98 // Special types const TYPE_ENERGYMETER = 99 //!< Device is energy meter const TYPE_IIC_UNKNOWN = 100 //!< Device type is not known yet const TYPE_NXT_TEST = 101 //!< Device is a NXT ADC test sensor const TYPE_NXT_IIC = 123 //!< Device is NXT IIC sensor const TYPE_TERMINAL = 124 //!< Port is connected to a terminal const TYPE_UNKNOWN = 125 //!< Port not empty but type has not been determined const TYPE_NONE = 126 //!< Port empty or not available const TYPE_ERROR = 127 //!< Port not empty and type is invalid if n >= TYPE_THIRD_PARTY_START and n <= TYPE_THIRD_PARTY_END then return "Third Party Sensor" end if Select case n // Types defined in "typedata.rcf" case TYPE_NXT_TOUCH return "Device is NXT touch sensor" case TYPE_NXT_LIGHT return "Device is NXT light sensor" case TYPE_NXT_SOUND return "Device is NXT sound sensor" case TYPE_NXT_COLOR return "Device is NXT color sensor" case TYPE_NXT_ULTRASONIC return "Device is NXT ultra sonic sensor" case TYPE_NXT_TEMPERATURE return "Device is NXT temperature sensor" case TYPE_TACHO return "Device is EV3/NXT tacho motor" case TYPE_MINITACHO return "Device is EV3 mini tacho motor" case TYPE_NEWTACHO return "Device is EV3 new tacho motor" case TYPE_TOUCH return "Device is EV3 touch sensor" // Types defined in known EV3 digital devices case TYPE_COLOR return "Device is EV3 color sensor" case TYPE_ULTRASONIC return "Device is EV3 ultra sonic sensor" case TYPE_GYRO return "Device is EV3 gyro sensor" case TYPE_IR return "Device is EV3 IR sensor" // Special types case TYPE_ENERGYMETER return "Device is energy meter" case TYPE_IIC_UNKNOWN return "Device type is not known yet" case TYPE_NXT_TEST return "Device is a NXT ADC test sensor" case TYPE_NXT_IIC return "Device is NXT IIC sensor" case TYPE_TERMINAL return "Port is connected to a terminal" case TYPE_UNKNOWN return "Port not empty but type has not been determined" case TYPE_NONE return "Port empty or not available" case TYPE_ERROR return "Port not empty and type is invalid" end Select End Function
Sub Log(s as string) Mainwindow.List.AddRow s End Sub
Property EVListFiles As Boolean
Property EVQueryInputDeviceList As Boolean
End Class
Class IOBluetoothServiceBrowserController Inherits IOBluetoothServiceBrowserControllerMBS
ComputedProperty parent As MainWindow
Sub Set() if value <> nil then weakParent = new weakRef(value) end if End Set
Sub Get() if weakParent <> nil then dim v as variant = weakParent.value return v end if End Get
End ComputedProperty
EventHandler Sub SheetDone(returnCode as Integer, tag as Variant) select case returnCode case me.kIOBluetoothUISuccess Log "Success" case me.kIOBluetoothUIUserCanceledErr Log "Cancelled" end Select dim serviceRecords() as IOBluetoothSDPServiceRecordMBS = me.Results if UBound(serviceRecords) >= 0 then parent.OpenService serviceRecords(0) end if End EventHandler
Sub Log(s as string) parent.List.AddRow s End Sub
Property Private weakParent As WeakRef
End Class
Class MyIOBluetoothHostController Inherits IOBluetoothHostControllerMBS
EventHandler Sub PoweredOff() MainWindow.List.AddRow "Power off" End EventHandler
EventHandler Sub PoweredOn() MainWindow.List.AddRow "Power on" End EventHandler
EventHandler Sub readLinkQualityForDeviceCompleted(device as IOBluetoothDeviceMBS, HCILinkQuality as Integer, error as Integer) MainWindow.List.AddRow device.name+": "+str(HCILinkQuality) End EventHandler
EventHandler Sub readRSSIForDeviceCompleted(device as IOBluetoothDeviceMBS, HCIRSSIValue as Integer, error as Integer) MainWindow.List.AddRow device.name+": "+str(HCIRSSIValue) End EventHandler
End Class
End Project

See also:

The items on this page are in the following plugins: MBS Bluetooth Plugin.


The biggest plugin in space...