My goal is : send via bluetooth certain string comand from my Android app to a Raspberry Pi device so it can runs a script,and after it is done, send back the message to my Android app
My approach:
- Used this python code(from my Pi3) for tryn to connect as a client on my server class
import socket
serverMACAddress = 'F8:8F:07:3D:7A:7B'
port = 2
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.connect((serverMACAddress,port))
while 1:
text = input()
if text == "quit":
break
s.send(bytes(text, 'UTF-8'))
s.close()
The problem: Rpi3 connects just at the level of my phone os bluetooth, but the server client that i wrote in my android app doesnt accept it, also, can't send/receive data from one to another (ofc)
I tried a lot of things in this app for a lot of time,changed a lot of libraries for the client app in python, nothing worked, i spent at least 5 weeks on this part.
I will provide you my kotlin code(note: i dont use ClientClass but maybe it will help posting it, ofc that i want that android client class that i dont use, somehow be translated to python to work on my pi) and also pics with what i have achieved:
class TrackYourWorkoutFragment : Fragment() {
private lateinit var binding: FragmentTrackYourWorkoutDataBinding
var MAC_ADDRESS = "E4:5F:01:0A:7D:20"
var MAC_ADDRESS_SAMSUNG = "F8:8F:07:3D:7A:7B"
val DEVICE_NAME = "raspberrypi"
var bluetoothSocket: BluetoothSocket? = null
var isConnected: Boolean = false
private lateinit var bluetoothAdapter: BluetoothAdapter
private lateinit var sendReceive: SendReceive
companion object {
private const val APP_NAME: String = "RealStats"
var SHARED_UUID: UUID = UUID.fromString("f4b18e71-c048-43a0-99cc-06f99eb6b654")
private const val STATE_LISTENING = 1
private const val STATE_CONNECTING = 2
private const val STATE_CONNECTED = 3
private const val STATE_CONNECTION_FAILED = 4
private const val STATE_MESSAGE_RECEIVED = 5
}
private val viewModel: TrackYourWorkoutFragmentViewModel by lazy {
ViewModelProvider(this, viewModelFactory {
TrackYourWorkoutFragmentViewModel(
onConnectToPiClick = { startServerSoPiConnects() },
onStartWorkoutClick = { startWorkout() }
)
})[TrackYourWorkoutFragmentViewModel::class.java]
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_track_your_workout,
container,
false
)
binding.viewModel = viewModel
binding.lifecycleOwner = viewLifecycleOwner
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(requireActivity() as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.toolbar_track_your_workout)
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
enableBluetooth()
}
var handler = Handler { msg ->
when (msg.what) {
STATE_LISTENING -> binding.tvInfoConnection.text = "Listening"
STATE_CONNECTING -> binding.tvInfoConnection.text = "Connecting"
STATE_CONNECTED -> binding.tvInfoConnection.text = "Connected"
STATE_CONNECTION_FAILED -> binding.tvInfoConnection.text = "Connection Failed"
STATE_MESSAGE_RECEIVED -> {
val readBuff = msg.obj as ByteArray
val tempMsg = String(readBuff, 0, msg.arg1)
binding.tvInfo.text = tempMsg
}
}
true
}
@SuppressLint("MissingPermission")
private fun startServerSoPiConnects() {
//val piDevice: BluetoothDevice = bluetoothAdapter.getRemoteDevice(MAC_ADDRESS)
val serverClass = ServerClass()
serverClass.start()
}
private fun startWorkout() {
val startMessageForPi = "s"
sendReceive.write(startMessageForPi.toByteArray())
}
private fun enableBluetooth() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT
)
)
}
}
@SuppressLint("MissingPermission")
private val requestMultiplePermissions =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
if (!bluetoothAdapter.isEnabled) {
bluetoothAdapter.enable()
Toast.makeText(this.context, "Bluetooth enabled", Toast.LENGTH_SHORT).show()
}
}
private inner class ServerClass @SuppressLint("MissingPermission") constructor() : Thread() {
private lateinit var serverSocket: BluetoothServerSocket
init {
try {
serverSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(
APP_NAME,
SHARED_UUID
)
} catch (e: IOException) {
e.printStackTrace()
}
}
override fun run() {
var socket: BluetoothSocket? = null
while (socket == null) {
try {
val message: Message = Message.obtain()
message.what = STATE_CONNECTING
handler.sendMessage(message)
socket = serverSocket.accept()
} catch (e: IOException) {
e.printStackTrace()
val message: Message = Message.obtain()
message.what = STATE_CONNECTION_FAILED
handler.sendMessage(message)
}
if (socket != null) {
val message: Message = Message.obtain()
message.what = STATE_CONNECTED
handler.sendMessage(message)
sendReceive = SendReceive(socket)
sendReceive.start()
break
}
}
}
}
private inner class ClientClass @SuppressLint("MissingPermission") constructor(deviceR: BluetoothDevice) :
Thread() {
private var device: BluetoothDevice
private lateinit var socket: BluetoothSocket
init {
device = deviceR
try {
socket = device.createRfcommSocketToServiceRecord(SHARED_UUID)
} catch (e: IOException) {
e.printStackTrace()
}
}
@SuppressLint("MissingPermission")
override fun run() {
try {
socket.connect()
val message = Message.obtain()
message.what = STATE_CONNECTED
handler.sendMessage(message)
sendReceive = SendReceive(socket)
sendReceive.start()
} catch (e: IOException) {
e.printStackTrace()
val message = Message.obtain()
message.what = STATE_CONNECTION_FAILED
handler.sendMessage(message)
}
}
}
private inner class SendReceive(socket: BluetoothSocket) :
Thread() {
private var bluetoothSocket: BluetoothSocket
private lateinit var inputStream: InputStream
private lateinit var outputStream: OutputStream
init {
bluetoothSocket = socket
var tempIn: InputStream? = null
var tempOut: OutputStream? = null
try {
tempIn = bluetoothSocket.inputStream
tempOut = bluetoothSocket.outputStream
} catch (e: IOException) {
e.printStackTrace()
}
if (tempIn != null) {
inputStream = tempIn
}
if (tempOut != null) {
outputStream = tempOut
}
}
override fun run() {
val buffer = ByteArray(1024)
var bytes: Int
while (true) {
try {
bytes = inputStream.read(buffer)
handler.obtainMessage(STATE_MESSAGE_RECEIVED, bytes, -1, buffer).sendToTarget()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
fun write(bytes: ByteArray) {
try {
outputStream.write(bytes)
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
after starting the server, by clicking connect to pi
If someone manages to solve this somehow, or provide me some usefull notes at least, please, i want to send you a NICE(i hope) gift.
FINALLY FOUND IT, THIS IS THE ANSWER import bluetooth import threading import time import random import sys