How to properly connect the bluetooth server in C for Android? - android

I'm trying to connect an application between the computer and an android app. The app will be the client and the computer will be the server.
Using BlueZ (C library for bluetooth on linux) for server:
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
}
// close connection
close(client);
close(s);
return 0;
}
The source of this example is : http://people.csail.mit.edu/albert/bluez-intro/x502.html
And the class of the app that i'm using to connect is:
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Message;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.UUID;
public class ConnectionThread extends Thread {
BluetoothSocket btSocket = null;
BluetoothServerSocket btServerSocket = null;
InputStream input = null;
OutputStream output = null;
String btDevAddress = null;
String myUUID = "00000101-0000-1000-8000-00805F9C34BF";
boolean server;
boolean running = false;
public ConnectionThread() {
this.server = true;
}
public ConnectionThread(String btDevAddress) {
this.server = false;
this.btDevAddress = btDevAddress;
}
public void run() {
this.running = true;
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
if(this.server) {
try {
btServerSocket = btAdapter.listenUsingRfcommWithServiceRecord("Super Bluetooth", UUID.fromString(myUUID));
btSocket = btServerSocket.accept();
if(btSocket != null) {
btServerSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
toMainActivity("---N".getBytes());
}
} else {
try {
BluetoothDevice btDevice = btAdapter.getRemoteDevice(btDevAddress);
btSocket = btDevice.createRfcommSocketToServiceRecord(UUID.fromString(myUUID));
btAdapter.cancelDiscovery();
if (btSocket != null)
btSocket.connect();
} catch (IOException e) {
e.printStackTrace();
toMainActivity("---N".getBytes());
}
}
if(btSocket != null) {
toMainActivity("---S".getBytes());
try {
input = btSocket.getInputStream();
output = btSocket.getOutputStream();
byte[] buffer = new byte[1024];
int bytes;
while(running) {
bytes = input.read(buffer);
toMainActivity(Arrays.copyOfRange(buffer, 0, bytes));
}
} catch (IOException e) {
e.printStackTrace();
toMainActivity("---N".getBytes());
}
}
}
private void toMainActivity(byte[] data) {
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putByteArray("data", data);
message.setData(bundle);
MainActivity.handler.sendMessage(message);
}
public void write(byte[] data) {
if(output != null) {
try {
output.write(data);
} catch (IOException e) {
e.printStackTrace();
}
} else {
toMainActivity("---N".getBytes());
}
}
public void cancel() {
try {
running = false;
btServerSocket.close();
btSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
running = false;
}
}
To send a data to the server I do:
ConnectionThread connect = new ConnectionThread(data.getStringExtra("Address_server"));
connect.start();
byte[] data = "20".getBytes();
connect.write(data);
The problem is not that the connection is occurring. I believe it's because the server is out of UUID.
How can I insert the UUID into the server so that it can receive the data sent?

This question may be slightly old, but seeing as I faced the same problem recently, I want to share one possible solution I came up with. The solution is essentially two projects (skeletal examples): a CMake project (Linux side) and an Android Studio project (APK). To avoid sharing winded explanations, I'll embed the Github repository here. Im open to questions should the need arise, and good luck to the next person who tackles this problem!

I don't know how to do this in libbluetooth/raw socket based. But you can use profile manager interface provided by Bluez to create your own custom profile and register this with bluetoothd.
Below is the sample slide directly copied from this presentation.
To explain in detail, you need to define the methods described in Profile1 interface and register it with Bluetoothd using "RegisterProfile" method.
I don't have any custom profile implementation example, but you can always refer bluez-alsa repository for AG/HFP/HS based profile implementations, which is implemented as external profiles using this interface.
Most interesting part for you in this repository is, "register_profile" API, which take UUID and other required parameters. You can copy the same implementation and register your own UUID and implement,
NewConnection: Action which needs to be performed when new device is connected with server. You can find how to connect using DBUS in Linux here with explanation here.
RequestDisconnection: Which will be called by Bluetoothd when device is disconnected. You can perform cleanup for device based allocation/resources.
Release: Which will be called when Bluetoothd exits. You can perform the profile complete cleanup and UnregisterProfile for graceful exit.

Related

Why is my program having troubles connecting to Arduino's bluetooth module using .connect()?

I’m currently struggling with implementing a bluetooth communictation between an Arduino (HC-06 bluetooth module) and an Android mobile phone. I’ve created a number of textView.setText(…) commands in order to follow how the program reacts when running.
My ambition for now is to get some primitive data from the Arduino (some characters only), and at the moment of the aquisition some reaction should happen on the screen (like a textView changes). That’s what I was trying to implement in my code below.
At the current state I’m having the following problems:
Sometimes mmSocket.connect(); is run properly and the otherwise constantly blinking red LED on the Arduino Bluetooth module starts shining, indicating that connection is established between the two devices. This is quite random though, usually this is not the case. Instead, I get a "Socket closed due to connect exception." answer, i.e. the try{} block isn’t run for some reason.
When, accidentally, connection is established, the red LED is shining, I don’t see anything on the screen of my phone. Normally it is supposed to output 4 textViews, each of them providing information about different parts of the code. How can I get it react real-time? It seems the .connect() makes the program halt around that point, although I don’t understand why.
I would appreciate any kind of help, I’m pretty new to this.
import android.bluetooth.BluetoothSocket;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mDevice;
private ConnectThread mConnectThread;
private Thread workerThread;
private String MAC = "30:14:10:17:06:93";
private boolean stopWorker;
private int readBufferPosition;
private byte readBuffer[];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView supportsBTorNot = (TextView) findViewById(R.id.supportsBTorNot);
TextView listPairedDevices = (TextView) findViewById(R.id.listPairedDevices);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
supportsBTorNot.setText("The device does not support bluetooth.");
}
else{
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
else{
supportsBTorNot.setText("The device supports bluetooth.");
}
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
listPairedDevices.setText(pairedDevices.toString());
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
if(device.getAddress().equals(MAC)) {
mDevice = device;
break;
}
}
}
if (mDevice == null) {
//Device is not paired yet
//Need to initiate a connection request
}
mConnectThread = new ConnectThread(mDevice);
mConnectThread.start();
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private ConnectedThread mConnectedThread;
private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
TextView socketConnected = (TextView) findViewById(R.id.socketConnected);
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
socketConnected.setText("Socket's create() method failed");
}
mmSocket = tmp;
run(); }
public void run() {
mBluetoothAdapter.cancelDiscovery();
try {
mmSocket.connect(); } catch (IOException connectException) { socketConnected.setText("Socket closed due to connect exception.");
try { mmSocket.close();
} catch (IOException closeException) {
socketConnected.setText("Could not close the client socket.");
}
return;
}
if (mmSocket.toString() != null) {
socketConnected.setText("The socket is established successfully.");
}
else {
socketConnected.setText("The socket could not be stablished.");
}
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
socketConnected.setText("Could not close the client socket.");
}
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final OutputStream mmOutStream;
TextView socketReadyForDataAquisition = (TextView) findViewById(R.id.socketReadyForDataAquisition);
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
try {
socketReadyForDataAquisition.setText("Querying the input stream has started.");
tmpIn = socket.getInputStream();
} catch (IOException e) {
socketReadyForDataAquisition.setText("Querying of input suspended due to IOException!");
}
beginListenForData(tmpIn);
}
public void beginListenForData(InputStream iStream)
{
final Handler handler = new Handler();
final InputStream mmInputStream = iStream;
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
try
{
int bytesAvailable = mmInputStream.available();
if(bytesAvailable > 0)
{
final byte[] packetBytes = new byte[bytesAvailable];
mmInputStream.read(packetBytes);
if(packetBytes != null) {
socketReadyForDataAquisition.setText("DATA ARRIVED");
}
}
}
catch (IOException ex)
{
stopWorker = true;
}
}
}
});
workerThread.start();
}
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
public void cancel() {
try{
mmSocket.close();
} catch (IOException e) { }
}
}
}
Generally looking over your code nothing plainly pops out, but reading though your issue it seems that perhaps the Arduino does not close its socket even though you think you have disconnected the phone from it. I am no expert in Arduino so that is more of a general suggestion to look into as I had a similar problem working with a Raspberry Pi and connecting it to an android phone.
Specifically for your Android code, I would recommend to look into this guide:
https://developer.android.com/guide/topics/connectivity/bluetooth.html
If you plan on sending something back from the Arduino to the Phone you should consider setting up the phone as both a server and a client so it can send as well as receive data.
The developer guide is very useful and may help you see an issue. Additionally you may consider updating UI in its own thread as I have seen that also cause issues.
I am fairly new to Android Development, however, I have had to work with BT and that guide was a life saver.

how to reconnect after get data from my esp 8266 in android

hello im having stuck after i sending data from esp8266
i connected esp8266 with my arduino
this is my arduino code
#include <SoftwareSerial.h>
//#include <OneWire.h>
//#include <DallasTemperature.h>
//#include <stdlib.h>
//#include "Wire.h"
//#define DS3231_I2C_ADDRESS 0x68
//#define ONE_WIRE_BUS 5
//WIFI
#include <SPI.h>
#include <WiFi.h>
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
//OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
//DallasTemperature sensors(&oneWire);
int wifiTx = 4;
int wifiRx = 3;
#define DEBUG true
char com;
String data;
SoftwareSerial wifi(wifiTx, wifiRx);
//wifi
char ssid[] = "waifu"; // your network SSID (name)
char pass[] = "chronoangel"; // your network password
//int status = WL_IDLE_STATUS; // the Wifi radio's status
void setup() {
// put your setup code here, to run once:
Wire.begin();
Serial.begin(9600);
wifi.begin(115200);
sensors.begin();
//sekon, menit,jam, day of week, hari, bulan taun
//setDS3231time(0,15,2,1,13,7,16);
//\start_wifi();
esp();
}
void loop() {
test_wifi();
//loop_esp();
}
void esp()
{
sendCommand("AT\r\n",2000,DEBUG);
sendCommand("AT+RST\r\n",2000,DEBUG); // reset module
sendCommand("AT+CWMODE=1\r\n",1000,DEBUG); // configure as access point
sendCommand("AT+CWJAP=\"waifu\",\"chronoangel\"\r\n",3000,DEBUG);
delay(10000);
//Serial.println("\nCek IP");
//sendCommand("AT+CIFSR\r\n",1000,DEBUG); // get ip address
sendCommand("AT+CIPMUX=1\r\n",1000,DEBUG); // configure for multiple connections
Serial.println("\nGet PORT");
sendCommand("AT+CIPSERVER=1,80\r\n",1000,DEBUG); // turn on server on port 80
Serial.println("\nSet IP");
sendCommand("AT+CIPSTA=\"192.168.1.7\"\r\n",1000,DEBUG); // set ip address
sendCommand("AT+CIFSR\r\n",1000,DEBUG); // get ip address
Serial.println("\nServer Ready");
}
void test_wifi()
{
if(wifi.available())
{
char toSend = (char)wifi.read();
Serial.print(toSend);
}
//Read from usb serial to wifi
if(Serial.available())
{
char toSend = (char)Serial.read();
wifi.print(toSend);
}
}
and this is my android studio code
package com.example.chronoangel.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.AsyncTask;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textResponse;
EditText editTextAddress, editTextPort;
Button buttonConnect, buttonClear;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = (EditText) findViewById(R.id.IP);
editTextPort = (EditText) findViewById(R.id.Port);
buttonConnect = (Button) findViewById(R.id.connect);
//buttonClear = (Button)findViewById(R.id.clear);
textResponse = (TextView) findViewById(R.id.textData);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
}
OnClickListener buttonConnectOnClickListener = new OnClickListener(){
#Override
public void onClick(View arg0) {
MyClientTask myClientTask = new MyClientTask(editTextAddress.getText().toString(), Integer.parseInt(editTextPort.getText().toString()));
myClientTask.execute();
}};
//class to get data from esp8266
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "";
MyClientTask(String addr, int port) {
dstAddress = addr;
dstPort = port;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
/*
* notice:
* inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}
}
this is my view of my program :
my problem is similiar to this page :
http://stackoverflow.com/questions/34274774/esp8266-wifi-server-to-android-client
but i think in there didnt have clue either how to reconnected after send a data
the program run after i click connect on android app
in my serial arduino after i send AT+ COMMAND
AT+CIPSEND = 0,2
then i send data "ab" to my android
the data was not send, but if ii send AT+COMMAND
AT+CIPCLOSE=0
the data was send,but i must click connect again to get the data from esp
my question is can we get continous data after click connect ?
how suppose i do with the android to connect again after arduino send a message ?
This is more an advice than an answer, because I think there is no other way than to close the connection everytime.
But i highly recommend to use your own Software for your ESP8266 rather than to use the AT-Commands. They are nice for the start, to connect to a network and so on. But they are limited. Since you're using arduino allready, i would suggest to use the IDE to write some code for your ESP.
You can find a lot of code and help here.
https://create.arduino.cc/projecthub/Metavix/programming-the-esp8266-with-the-arduino-ide-in-3-simple-601c16
And the ESP8266WiFi.h offers a lot of functions that are ready to use.

Android + Arduino Bluetooth Data Transfer

I can get my Android app to connect via Bluetooth to my Arduino. However no data can be transmitted between them. Below is my setup and code:
HTC Android v2.2, Bluetooth mate gold modem, Arduino Mega (ATmega1280)
Android Java code:
package com.example.BluetoothExample;
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.view.View;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
public class BluetoothExampleActivity extends Activity {
TextView myLabel;
EditText myTextbox;
BluetoothAdapter mBluetoothAdapter;
BluetoothSocket mmSocket;
BluetoothDevice mmDevice;
OutputStream mmOutputStream;
InputStream mmInputStream;
Thread workerThread;
byte[] readBuffer;
int readBufferPosition;
int counter;
volatile boolean stopWorker;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button openButton = (Button)findViewById(R.id.open);
Button sendButton = (Button)findViewById(R.id.send);
Button closeButton = (Button)findViewById(R.id.close);
myLabel = (TextView)findViewById(R.id.label);
myTextbox = (EditText)findViewById(R.id.entry);
//Open Button
openButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
findBT();
openBT();
}
catch (IOException ex) { }
}
});
//Send Button
sendButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
sendData();
}
catch (IOException ex) {
showMessage("SEND FAILED");
}
}
});
//Close button
closeButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
closeBT();
}
catch (IOException ex) { }
}
});
}
void findBT() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter == null) {
myLabel.setText("No bluetooth adapter available");
}
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("FireFly-108B")) {
mmDevice = device;
break;
}
}
}
myLabel.setText("Bluetooth Device Found");
}
void openBT() throws IOException {
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard //SerialPortService ID
mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
mmSocket.connect();
mmOutputStream = mmSocket.getOutputStream();
mmInputStream = mmSocket.getInputStream();
beginListenForData();
myLabel.setText("Bluetooth Opened");
}
void beginListenForData() {
final Handler handler = new Handler();
final byte delimiter = 10; //This is the ASCII code for a newline character
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable() {
public void run() {
while(!Thread.currentThread().isInterrupted() && !stopWorker) {
try {
int bytesAvailable = mmInputStream.available();
if(bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
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;
handler.post(new Runnable() {
public void run() {
myLabel.setText(data);
}
});
}
else {
readBuffer[readBufferPosition++] = b;
}
}
}
}
catch (IOException ex) {
stopWorker = true;
}
}
}
});
workerThread.start();
}
void sendData() throws IOException {
String msg = myTextbox.getText().toString();
msg += "\n";
//mmOutputStream.write(msg.getBytes());
mmOutputStream.write('A');
myLabel.setText("Data Sent");
}
void closeBT() throws IOException {
stopWorker = true;
mmOutputStream.close();
mmInputStream.close();
mmSocket.close();
myLabel.setText("Bluetooth Closed");
}
private void showMessage(String theMsg) {
Toast msg = Toast.makeText(getBaseContext(),
theMsg, (Toast.LENGTH_LONG)/160);
msg.show();
}
}
Arduino Code:
#include <SoftwareSerial.h>
int bluetoothTx = 45;
int bluetoothRx = 47;
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
void setup() {
//pinMode(45, OUTPUT);
//pinMode(47, INPUT);
pinMode(53, OUTPUT);
//Setup usb serial connection to computer
Serial.begin(9600);
//Setup Bluetooth serial connection to android
bluetooth.begin(115200);
bluetooth.print("$$$");
delay(100);
bluetooth.println("U,9600,N");
bluetooth.begin(9600);
}
void loop() {
//Read from bluetooth and write to usb serial
if(bluetooth.available()) {
char toSend = (char)bluetooth.read();
Serial.print(toSend);
flashLED();
}
//Read from usb serial to bluetooth
if(Serial.available()) {
char toSend = (char)Serial.read();
bluetooth.print(toSend);
flashLED();
}
}
void flashLED() {
digitalWrite(53, HIGH);
delay(500);
digitalWrite(53, LOW);
}
I've tried using 115200 and 9600 for the baud rates, and I've tried setting the bluetooth rx and tx pins as input/output and output/input. The Arduino is receiving serial data from the PC but can't send it to the Android (I can see this because of the flashLED() method).
The Android can't send any data at all to the Arduino. However they are both connected because the green light on the modem turns on and goes off and the red led flashes when I close the connection. The sendData() method doesn't throw an exception because otherwise showMessage("SEND FAILED"); would appear.
I also have this in my manifest .xml
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" />
Any help would be greatly appreciated!
Code taken from:
http://bellcode.wordpress.com/2012/01/02/android-and-arduino-bluetooth-communication/
Just solved the problem for anyone else who came across this page.
Seems that my Arduino doesn't like me using digital pins for serial communication, I use TX and RX instead with this code taken from http://jondontdoit.blogspot.com.au/2011/11/bluetooth-mate-tutorial.html, also seems that 9600 is a good baud instead of 115200.
/***********************
Bluetooth test program
***********************/
//TODO
//TEST THIS PROGRAM WITH ANDROID,
//CHANGE PINS TO RX AND TX THO ON THE ARDUINO!
//int counter = 0;
int incomingByte;
void setup() {
pinMode(53, OUTPUT);
Serial.begin(9600);
}
void loop() {
// see if there's incoming serial data:
if (Serial.available() > 0) {
// read the oldest byte in the serial buffer:
incomingByte = Serial.read();
// if it's a capital R, reset the counter
if (incomingByte == 'g') {
digitalWrite(53, HIGH);
delay(500);
digitalWrite(53, LOW);
delay(500);
//Serial.println("RESET");
//counter=0;
}
}
//Serial.println(counter);
//counter++;
//delay(250);
}
I was getting the same thing. I went into 'Settings'->'Wireless and Networks'->'Bluetooth Settings' and paired the device. When I went back and re-ran my code, it connected, no exception. I put controls in my UI for displaying the paired devices, I'm going to see if I can code to manage pairing devices from my UI.
I was able to get this to run only after replacing this section:
Set<BluetoothDevice> pairedDevices = BluetoothAdapter.getBondedDevices();
if(pairedDevices.size() > 0)
{
for(BluetoothDevice device : pairedDevices)
{
if(device.getName().startsWith("FireFly-"))
{
mmDevice = device;
Log.d("ArduinoBT", "findBT found device named " + mmDevice.getName());
Log.d("ArduinoBT", "device address is " + mmDevice.getAddress());
break;
}
}
}
with this:
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
mmDevice = mBluetoothAdapter.getRemoteDevice("00:06:66:46:5A:91");
if (pairedDevices.contains(mmDevice))
{
statusText.setText("Bluetooth Device Found, address: " + mmDevice.getAddress() );
Log.d("ArduinoBT", "BT is paired");
}
where I entered the address of my Bluetooth device.
The original code finds the device and returns the correct address, but
mmSocket.connect();
generates an exception "java.io.IOException: Service discovery failed"
Suggestions?
For anyone who finds this page, but is stuck using a hardcoded mac address as above, set mac address to NULL, and insert this code into OnResume()
try{
File f = new File(Environment.getExternalStorageDirectory()+"/mac.txt");
FileInputStream fileIS = new FileInputStream(f);
buf = new BufferedReader(new InputStreamReader(fileIS));
String readString = new String();
while((readString = buf.readLine())!= null){
address = readString;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
ALSO, don't forget to allow eclipse to include necessary libraries, and place your mac address into mac.txt on the root of the SD Card, then you can simply give users a text file with their mac address while still allowing the app to be downloaded from the market without customizing every instance.
#Backwards_Dave just for a curious, try to connect to 45 and 46 pins and use this simple code. I use it and have no problem. You will be able to send data from Arduino Serial Monitor and read it there.
/*
Pinout:
45 --> BT module Tx
46 --> BT module Rx
*/
#include <SoftwareSerial.h>
SoftwareSerial mySerial(45, 46); // RX, TX
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
Serial.println("I am ready to send some stuff!");
// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
}
void loop() // run over and over
{
if (mySerial.available())
Serial.write(mySerial.read());
if (Serial.available())
mySerial.write(Serial.read());
}
Also, what BlueTooth shield are you using for Arduino? HC-06?
EDIT
Just tested it with Mega2560(don't have 1280) and it works with no problem.
I believe problem was with pinout.
Waiting for your feedback
If you're still looking for an answer, try changing the software serial pins. This is a well known limitation of the library you are using.
Not all pins on the Mega support change interrupts, so only the following can be used for RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69). Refs
Hope this helps.
I think it might be some fault in Bluetooth.. its better to re-install its drivers.. as the code given above looks correct.

initialize a bluetooth connection between Android (server) and bluecove on pc (client)

I know there are other topics about that but in my case I want the Android device to initialize the bluetooth connection as a server. I followed the Documentation and I wrote the server in this way:
private class AcceptThread implements Runnable {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
try {
tmp = mBluetooth.listenUsingRfcommWithServiceRecord(
"myService", mUuid);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
System.out.println("SERVER SOCKET LISTENING");
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
System.out.println("SIGNAL RECEIVED");
// Do work to manage the connection (in a separate thread)
Toast.makeText(getApplicationContext(), "SIGNAL RECEIVED", Toast.LENGTH_LONG).show();
try {
mmServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
On the other side I have bluecove API that discover remote devices and services.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Vector;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
/**
* A simple SPP client that connects with an SPP server
*/
public class SampleSPPClient implements DiscoveryListener{
//object used for waiting
private static Object lock=new Object();
//vector containing the devices discovered
private static Vector vecDevices=new Vector();
private static String connectionURL=null;
public static void main(String[] args) throws IOException {
SampleSPPClient client=new SampleSPPClient();
//display local device address and name
LocalDevice localDevice = LocalDevice.getLocalDevice();
System.out.println("Address: "+localDevice.getBluetoothAddress());
System.out.println("Name: "+localDevice.getFriendlyName());
//find devices
DiscoveryAgent agent = localDevice.getDiscoveryAgent();
System.out.println("Starting device inquiry...");
agent.startInquiry(DiscoveryAgent.GIAC, client);
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Device Inquiry Completed. ");
//print all devices in vecDevices
int deviceCount=vecDevices.size();
if(deviceCount <= 0){
System.out.println("No Devices Found .");
System.exit(0);
}
else{
//print bluetooth device addresses and names in the format [ No. address (name) ]
System.out.println("Bluetooth Devices: ");
for (int i = 0; i <deviceCount; i++) {
RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(i);
System.out.println((i+1)+". "+remoteDevice.getBluetoothAddress()+" ("+remoteDevice.getFriendlyName(true)+")");
}
}
System.out.print("Choose Device index: ");
BufferedReader bReader=new BufferedReader(new InputStreamReader(System.in));
String chosenIndex=bReader.readLine();
int index=Integer.parseInt(chosenIndex.trim());
//check for spp service
RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(index-1);
UUID[] uuidSet = new UUID[1];
uuidSet[0]=new UUID("4e3aea40e2a511e095720800200c9a66", false);
System.out.println("\nSearching for service...");
agent.searchServices(null,uuidSet,remoteDevice,client);
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
if(connectionURL==null){
System.out.println("Device does not support Simple SPP Service.");
System.exit(0);
}
//connect to the server and send a line of text
StreamConnection streamConnection=(StreamConnection)Connector.open(connectionURL);
//send string
OutputStream outStream=streamConnection.openOutputStream();
PrintWriter pWriter=new PrintWriter(new OutputStreamWriter(outStream));
pWriter.write("Test String from SPP Client\r\n");
pWriter.flush();
//read response
InputStream inStream=streamConnection.openInputStream();
BufferedReader bReader2=new BufferedReader(new InputStreamReader(inStream));
String lineRead=bReader2.readLine();
System.out.println(lineRead);
}//main
//methods of DiscoveryListener
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
//add the device to the vector
if(!vecDevices.contains(btDevice)){
vecDevices.addElement(btDevice);
}
}
//implement this method since services are not being discovered
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
System.out.println(servRecord[0].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false));
if(servRecord!=null && servRecord.length>0){
connectionURL=servRecord[0].getConnectionURL(ServiceRecord.AUTHENTICATE_ENCRYPT,false);
}
synchronized(lock){
lock.notify();
}
}
//implement this method since services are not being discovered
public void serviceSearchCompleted(int transID, int respCode) {
synchronized(lock){
lock.notify();
}
}
public void inquiryCompleted(int discType) {
synchronized(lock){
lock.notify();
}
}//end method
}
The client found the device and the service but when retrieve the url from the ServiceRecord to establish the connection it fails. It retrieve an Url in which the channel is wrong and it throws an exception: javax.bluetooth.BluetoothConnectionException: Failed to connect;
How can I solve the problem?
I managed to find some phone ServiceRecords when using:
UUID[] uuidSet = new UUID[1];
uuidSet[0]=new UUID(0x0100);
int[] attrIds = { 0x0100 };
System.out.println("\nSearching for service...");
agent.searchServices(attrIds, uuidSet, remoteDevice, client);
And you will be calling lock.notify() twice after a serviceSearch, remove it in the servicesDiscovered function.
You should also go through the service records and look for the one you are interested in. The URL will state btgoep:// or btspp://
When searching through the for loop use this code to list the service name
for(int i = 0; i < servRecord.length; i++)
{
String url = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
DataElement serviceName = srs[i].getAttributeValue(0x0100);
if (serviceName != null) {
System.out.println("service " + serviceName.getValue() + " found " + url);
} else {
System.out.println("service found " + url);
}
I have the exact problem, it seems like the android api doesn't register the ServiceRecord with the SDP so the Bluecove api can find it.
No matter what UUID I use it will only find the ones my phone register as default, i e Audio gateways and Phonebook OBEX push and such.
EDIT ---
I had the same problem, but realized I had not actually called listenUsingInsecureRFCOMMSocket yet. And then it did not register the service record.
But after that it worked just fine.

Bluetooth-connection between Android and Lego Mindstorm NXT

Does anybody know, how to build a bluetooth connection between Android and LEGO-Mindstorm-NXT?
The connection between two NXTs works fine. But the other Connection-type likes not so easy.
I am working with the LeJOS Firmware 0.85 and the Android SDK Tools (2.2 Froyo).
So i've solved it and will show all how does it works, because i've seen that a lot of people have problems with that.
The class includes 4 functions:
Bluetooth enable if not enabled before -> enableBT()
Connect to 2 NXTs -> connectToNXTs()
Write Message to one of the NXTs -> writeMessage(byte msg, String nxt)
Read Message from one of the NXTs -> readMessage(String nxt)
Here is the code for the android device (BT_comm.java):
package de.joen.android.CubeScan;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
public class BT_Comm {
//Target NXTs for communication
final String nxt2 = "00:16:53:04:52:3A";
final String nxt1 = "00:16:53:07:AA:F6";
BluetoothAdapter localAdapter;
BluetoothSocket socket_nxt1, socket_nxt2;
boolean success = false;
// Enables Bluetooth if not enabled
public void enableBT(){
localAdapter = BluetoothAdapter.getDefaultAdapter();
// If Bluetooth not enable then do it
if (!localAdapter.isEnabled()) {
localAdapter.enable();
while(!(localAdapter.isEnabled()));
}
}
// Connect to both NXTs
public boolean connectToNXTs() {
// Get the BluetoothDevice of the NXT
BluetoothDevice nxt_2 = localAdapter.getRemoteDevice(nxt2);
BluetoothDevice nxt_1 = localAdapter.getRemoteDevice(nxt1);
// Try to connect to the nxt
try {
socket_nxt2 = nxt_2.createRfcommSocketToServiceRecord(UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB"));
socket_nxt1 = nxt_1.createRfcommSocketToServiceRecord(UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB"));
socket_nxt2.connect();
socket_nxt1.connect();
success = true;
} catch (IOException e) {
Log.d("Bluetooth","Err: Device not found or cannot connect");
success=false;
}
return success;
}
public void writeMessage(byte msg, String nxt) throws InterruptedException {
BluetoothSocket connSock;
// Swith nxt socket
if (nxt.equals("nxt2")) {
connSock=socket_nxt2;
} else if(nxt.equals("nxt1")) {
connSock = socket_nxt1;
} else {
connSock=null;
}
if (connSock!=null) {
try {
OutputStreamWriter out = new OutputStreamWriter(connSock.getOutputStream());
out.write(msg);
out.flush();
Thread.sleep(1000);
} catch (IOException e) {
// TODO: Auto-generated catch block
e.printStackTrace();
}
} else {
// Error
}
}
public int readMessage(String nxt) {
BluetoothSocket connSock;
int n;
// Swith nxt socket
if (nxt.equals("nxt2")) {
connSock=socket_nxt2;
} else if (nxt.equals("nxt1")) {
connSock=socket_nxt1;
} else {
connSock=null;
}
if (connSock!=null) {
try {
InputStreamReader in = new InputStreamReader(connSock.getInputStream());
n = in.read();
return n;
} catch (IOException e) {
// TODO: Auto-generated catch block
e.printStackTrace();
return -1;
}
} else {
// Error
return -1;
}
}
}
To get messages from the Android Smartphone you must have a read call on the NXT-side.
Here is the code from the NXT-side wich will accept the connection from the Smartphone and read messages from it:
Boolean isrunning = true;
// Main loop
while (true)
{
LCD.drawString(waiting,0,0);
LCD.refresh();
// Listen for incoming connection
NXTConnection btc = Bluetooth.waitForConnection();
btc.setIOMode(NXTConnection.RAW);
LCD.clear();
LCD.drawString(connected,0,0);
LCD.refresh();
// The InputStream for read data
DataInputStream dis = btc.openDataInputStream();
// Loop for read data
while (isrunning) {
Byte n = dis.readByte();
LCD.clear();
LCD.drawInt(n, 4, 4);
}
dis.close();
// Wait for data to drain
Thread.sleep(100);
LCD.clear();
LCD.drawString(closing,0,0);
LCD.refresh();
btc.close();
LCD.clear();
}
Hope this will help others...
There is a document I found very useful
http://wiki.tinyclr.com/images/d/df/LEGO_MINDSTORMS_NXT_Direct_commands.pdf
The MINDdroid package on github is a fine place to start.

Categories

Resources