Hallo zusammen,
anlässlich eines Studium Projektes befasse ich mich neuerdings mit Java.
Das geplante Projekt ist ein per Android App (Bluetooth) gesteuertes Modellauto mittels Raspberry Pi.
Das Layout/Design und einige kleine Funktionen der App funktionieren bereits.
Allerdings hänge ich seit Tagen an der Steuerung bzw. Verbindung des Raspberry Pis.
Gedacht sei es eine RFCOMM Verbindung herzustellen (Raspberry = Server , Smartphone = Client) um Python Skripte am Pi über das Smartphone zu starten (Lenkung, Gas, Bremse).
Nun nach etlicher Recherche im Internet bin ich auf ein Java Skript gestoßen welches eine Verbindung mit dem Pi herstellt und eine LED ein und ausschalten soll (mit jeweiligen Buttons)
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
BluetoothSocket mmSocket;
BluetoothDevice mmDevice = null;
final byte delimiter = 33;
int readBufferPosition = 0;
public void sendBtMsg(String msg2send)
{
//UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard SerialPortService ID
UUID uuid = UUID.fromString("94f39d29-7d6d-437d-973b-fba39e49d4ee"); //Standard SerialPortService ID
try
{
mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
if (!mmSocket.isConnected()){
mmSocket.connect();
}
String msg = msg2send;
//msg += "\n";
OutputStream mmOutputStream = mmSocket.getOutputStream();
mmOutputStream.write(msg.getBytes());
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler handler = new Handler();
final TextView myLabel = (TextView) findViewById(R.id.btResult);
final Button tempButton = (Button) findViewById(R.id.tempButton);
final Button lightOnButton = (Button) findViewById(R.id.lightOn);
final Button lightOffButton = (Button) findViewById(R.id.lightOff);
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
final class workerThread implements Runnable
{
private String btMsg;
public workerThread(String msg)
{
btMsg = msg;
}
public void run()
{
sendBtMsg(btMsg);
while(!Thread.currentThread().isInterrupted())
{
int bytesAvailable;
boolean workDone = false;
try
{
final InputStream mmInputStream;
mmInputStream = mmSocket.getInputStream();
bytesAvailable = mmInputStream.available();
if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
Log.e("Aquarium recv bt","bytes available");
byte[] readBuffer = new byte[1024];
mmInputStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
final String data = new String(encodedBytes, "US-ASCII");
readBufferPosition = 0;
//The variable data now contains our full command
handler.post(new Runnable()
{
public void run()
{
myLabel.setText(data);
}
});
workDone = true;
break;
}
else
{
readBuffer[readBufferPosition++] = b;
}
}
if (workDone == true)
{
mmSocket.close();
break;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
// start temp button handler
tempButton.setOnClickListener
(new View.OnClickListener()
{
public void onClick(View v)
{
// Perform action on temp button click
(new Thread(new workerThread("temp"))).start();
}
}
);
//end temp button handler
//start light on button handler
lightOnButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on temp button click
(new Thread(new workerThread("lightOn"))).start();
}
});
//end light on button handler
//start light off button handler
lightOffButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v) {
// Perform action on temp button click
(new Thread(new workerThread("lightOff"))).start();
}
});
// end light off button handler
if(!mBluetoothAdapter.isEnabled())
{
Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth, 0);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if(pairedDevices.size() > 0)
{
for(BluetoothDevice device : pairedDevices)
{
if(device.getName().equals("PiBluetooth")) {
Log.e("Aquarium",device.getName());
mmDevice = device;
break;
}
}
}
}
Alles anzeigen
Das dazugehörige Python Skript auf dem Pi sieht folgendermaßen aus:
import os
import glob
import time
import RPi.GPIO as GPIO
from bluetooth import *
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()[1]
uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
advertise_service( server_sock, "AquaPiServer",
service_id = uuid,
service_classes = [ uuid, SERIAL_PORT_CLASS ],
profiles = [ SERIAL_PORT_PROFILE ],
# protocols = [ OBEX_UUID ]
)
while True:
print "Waiting for connection on RFCOMM channel %d" % port
client_sock, client_info = server_sock.accept()
print "Accepted connection from ", client_info
try:
data = client_sock.recv(1024)
if len(data) == 0: break
print "received [%s]" % data
if data == 'temp':
data = str(read_temp())+'!'
elif data == 'lightOn':
GPIO.output(17,False)
data = 'light on!'
elif data == 'lightOff':
GPIO.output(17,True)
data = 'light off!'
else:
data = 'WTF!'
client_sock.send(data)
print "sending [%s]" % data
except IOError:
pass
except KeyboardInterrupt:
print "disconnected"
client_sock.close()
server_sock.close()
print "all done"
break
Alles anzeigen
Nun das ganze funktioniert soweit auch nur bedingt.
Die Verbindung wird bei jedem einzelnen "Knopfdruck" getrennt und anschließend wartet er auf eine neue Verbindung.
[Blockierte Grafik: https://1drv.ms/u/s!AtpcnnBEDRKmkxOBARjXY0rVEE2e]
Meine zunächst erst Frage ist nun:
Wie muss der Java Code geändert werden um nur eine einmalige RFCOMM Verbindung aufzubauen?
Ich bitte um Hilfe ich kämpfe hier schon den ganzen Tag ohne eine Lösung.
Mit freundlichen Grüßen