B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Class
Version=10.7
@EndOfDesignText@
'BluetoothAsynchStream Class
'version: 1.00

#Event: Connected (Success As Boolean)
#Event: StateChanged (State As String)
Sub Class_Globals
	Private Admin As BluetoothAdmin
	Public Astreams As AsyncStreams
	Private Serial As Serial
	Private PH As Phone
	Private mParent As Object
	Private mEventName As String
	Private lblStatus As Label
	Private ProgressBar1 As ProgressBar

	Private GenericDeviceName, DeviceName As String
	
	Public BluetoothState, ConnectionState, DeviceFound As Boolean
	Private DeviceName, DeviceMacAdress As String
	
	Public CharSet = "UTF-8" As String
	Private sb As StringBuilder
	Public State As String
End Sub

'Initializes the object.
'Parent = Parent modu
'EventName = generic event name
'Code Example: <code>
'Private BT As BluetoothManagement
'BT.Initialize(Me, "BT")</code>
Public Sub Initialize(Parent As Object, EventName As String, StatusLabel As Label, Pgb As ProgressBar)
	mParent = Parent
	mEventName = EventName
	lblStatus = StatusLabel
	Admin.Initialize("Admin")
	Serial.Initialize("Serial")
	ProgressBar1 = Pgb
	sb.Initialize
	
	If Admin.IsEnabled = False Then
		If Admin.Enable = False Then
			ToastMessageShow("Error enabling Bluetooth adapter.", True)
		Else
			ToastMessageShow("Enabling Bluetooth adapter...", False)
		End If
	Else
		BluetoothState = True
	End If
End Sub

Public Sub Connect(Name As String)
	GenericDeviceName = Name
	Dim success As Boolean = Admin.StartDiscovery
	If success = False Then
		lblStatus.Text = "Error starting discovery process."
	Else
		lblStatus.Text = "Start discovery"
		ProgressBar1.Visible = True
	End If
End Sub

Public Sub Disconnect
	If Astreams.IsInitialized Then Astreams.Close
	If Serial.IsInitialized Then Serial.Disconnect
End Sub

'event raised when a device is found
Private Sub Admin_DeviceFound (Name As String, MacAddress As String)
	Log(Name & ":" & MacAddress)
	If Name.Contains(GenericDeviceName) Then
		Log(GenericDeviceName & " found")
		DeviceName = Name
		DeviceMacAdress = MacAddress
		'unfortunately we must wait for the end of discovery on newer devices
		'with the call below, my device, Android 11, throughs the error below.
		'java.io.IOException: read failed, socket might closed or timeout, read ret: -1
		If PH.SdkVersion <= 24 Then
			Admin.CancelDiscovery
			lblStatus.Text = GenericDeviceName & " found"
		Else
			lblStatus.Text = GenericDeviceName & " found, please wait."
		End If
	End If
End Sub

'event raised when discovery is finished
'Admin.StartDiscovery starts the discovery for about 12 seconds
'After this time, the DiscoveryFinished event is raised or if Admin.CancelDiscovery is called 
Private Sub Admin_DiscoveryFinished
	If DeviceName = "" Then
		lblStatus.Text = "Device " & GenericDeviceName & " Not found"
	Else
		lblStatus.Text = "Connecting to: " & GenericDeviceName
		Serial.Connect(DeviceMacAdress)
	End If
End Sub

Private Sub Admin_StateChanged (NewState As Int, OldState As Int)
	Log("State changed: " & NewState)
	lblStatus.Text = "State changed: " & NewState
	BluetoothState = NewState = Admin.STATE_ON
End Sub

'will be called when a client connects to this device
Sub Serial_Connected (Success As Boolean)
	Private msg As String
	If Success = True Then
		If Astreams.IsInitialized Then Astreams.Close
		Astreams.Initialize(Serial.InputStream, Serial.OutputStream, "Astreams")
		msg = "Connected"
		ProgressBar1.Visible = False
	Else
		Log(LastException.Message)
		msg = LastException.Message
	End If
	lblStatus.Text = msg
	CallSubDelayed2(mParent, mEventName & "_Connected", Success)
End Sub

'sends an Array of Bytes via AsynchStreams
Public Sub SendBytes(Buffer() As Byte)
	Astreams.Write(Buffer)
End Sub

'sends a text via AsynchStreams
'the default CharacterSet is "UTF-8"
'you can define other CharacterSets with the CharSet variable
Public Sub SendText(Text As String)
	Astreams.Write(Text.GetBytes(CharSet))
End Sub

Public Sub Ast_NewText(Text As String)
	CallSubDelayed2(mParent, mEventName & "_NewText", Text)
	Log(Text)
End Sub

'Sends the text. Note that this method does not add end of line characters.
Public Sub WriteText(Text As String)
	Astreams.Write(Text.GetBytes(CharSet))
End Sub

'Sends the text. Note that this method does not add end of line characters.
Public Sub WriteBytes(Buffer() As Byte)
	Astreams.Write(Buffer)
End Sub

Private Sub Astreams_NewData (Buffer() As Byte)
	Dim newDataStart As Int = sb.Length
	sb.Append(BytesToString(Buffer, 0, Buffer.Length, CharSet))
	Dim s As String = sb.ToString
	Dim start As Int = 0
	For i = newDataStart To s.Length - 1
		Dim c As Char = s.CharAt(i)
		If i = 0 And c = Chr(10) Then '\n...
			start = 1 'might be a broken end of line character
			Continue
		End If
		If c = Chr(10) Then '\n
			CallSubDelayed2(mParent, mEventName & "_NewText", s.SubString2(start, i))
			start = i + 1
		Else If c = Chr(13) Then '\r
			CallSubDelayed2(mParent, mEventName & "_NewText", s.SubString2(start, i))
			If i < s.Length - 1 And s.CharAt(i + 1) = Chr(10) Then '\r\n
				i = i + 1
			End If
			start = i + 1
		End If
	Next
	If start > 0 Then sb.Remove(0, start)
End Sub

Private Sub Astreams_Terminated
	CallSubDelayed(mParent, mEventName & "_Terminated")
End Sub

Private Sub Astreams_Error
	Log("error: " & LastException)
	Astreams.Close
	CallSubDelayed(mParent, mEventName & "_Terminated")
End Sub

Public Sub Close
	Astreams.Close
End Sub
