라즈베리파이 c 코드(서버)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
#include <sys/wait.h>
#include <pthread.h>
#include <signal.h>
void *ThreadMain(void *argument);
bdaddr_t bdaddr_any = {0, 0, 0, 0, 0, 0};
bdaddr_t bdaddr_local = {0, 0, 0, 0xff, 0xff, 0xff};
int _str2uuid( const char *uuid_str, uuid_t *uuid ) {
/* This is from the pybluez stack */
uint32_t uuid_int[4];
char *endptr;
if( strlen( uuid_str ) == 36 ) {
char buf[9] = { 0 };
if( uuid_str[8] != '-' && uuid_str[13] != '-' &&
uuid_str[18] != '-' && uuid_str[23] != '-' ) {
return 0;
}
// first 8-bytes
strncpy(buf, uuid_str, 8);
uuid_int[0] = htonl( strtoul( buf, &endptr, 16 ) );
if( endptr != buf + 8 ) return 0;
// second 8-bytes
strncpy(buf, uuid_str+9, 4);
strncpy(buf+4, uuid_str+14, 4);
uuid_int[1] = htonl( strtoul( buf, &endptr, 16 ) );
if( endptr != buf + 8 ) return 0;
// third 8-bytes
strncpy(buf, uuid_str+19, 4);
strncpy(buf+4, uuid_str+24, 4);
uuid_int[2] = htonl( strtoul( buf, &endptr, 16 ) );
if( endptr != buf + 8 ) return 0;
// fourth 8-bytes
strncpy(buf, uuid_str+28, 8);
uuid_int[3] = htonl( strtoul( buf, &endptr, 16 ) );
if( endptr != buf + 8 ) return 0;
if( uuid != NULL ) sdp_uuid128_create( uuid, uuid_int );
} else if ( strlen( uuid_str ) == 8 ) {
// 32-bit reserved UUID
uint32_t i = strtoul( uuid_str, &endptr, 16 );
if( endptr != uuid_str + 8 ) return 0;
if( uuid != NULL ) sdp_uuid32_create( uuid, i );
} else if( strlen( uuid_str ) == 4 ) {
// 16-bit reserved UUID
int i = strtol( uuid_str, &endptr, 16 );
if( endptr != uuid_str + 4 ) return 0;
if( uuid != NULL ) sdp_uuid16_create( uuid, i );
} else {
return 0;
}
return 1;
}
sdp_session_t *register_service(uint8_t rfcomm_channel) {
/* A 128-bit number used to identify this service. The words are ordered from most to least
* significant, but within each word, the octets are ordered from least to most significant.
* For example, the UUID represneted by this array is 00001101-0000-1000-8000-00805F9B34FB. (The
* hyphenation is a convention specified by the Service Discovery Protocol of the Bluetooth Core
* Specification, but is not particularly important for this program.)
*
* This UUID is the Bluetooth Base UUID and is commonly used for simple Bluetooth applications.
* Regardless of the UUID used, it must match the one that the Armatus Android app is searching
* for.
*/
const char *service_name = "Armatus Bluetooth server";
const char *svc_dsc = "A HERMIT server that interfaces with the Armatus Android app";
const char *service_prov = "Armatus";
uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid,
svc_class_uuid;
sdp_list_t *l2cap_list = 0,
*rfcomm_list = 0,
*root_list = 0,
*proto_list = 0,
*access_proto_list = 0,
*svc_class_list = 0,
*profile_list = 0;
sdp_data_t *channel = 0;
sdp_profile_desc_t profile;
sdp_record_t record = { 0 };
sdp_session_t *session = 0;
// set the general service ID
//sdp_uuid128_create(&svc_uuid, &svc_uuid_int);
_str2uuid("00001101-0000-1000-8000-00805F9B34FB",&svc_uuid);
sdp_set_service_id(&record, svc_uuid);
char str[256] = "";
sdp_uuid2strn(&svc_uuid, str, 256);
printf("Registering UUID %s\n", str);
// set the service class
sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID);
svc_class_list = sdp_list_append(0, &svc_class_uuid);
sdp_set_service_classes(&record, svc_class_list);
// set the Bluetooth profile information
sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
profile.version = 0x0100;
profile_list = sdp_list_append(0, &profile);
sdp_set_profile_descs(&record, profile_list);
// make the service record publicly browsable
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root_list = sdp_list_append(0, &root_uuid);
sdp_set_browse_groups(&record, root_list);
// set l2cap information
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
l2cap_list = sdp_list_append(0, &l2cap_uuid);
proto_list = sdp_list_append(0, l2cap_list);
// register the RFCOMM channel for RFCOMM sockets
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
sdp_list_append(rfcomm_list, channel);
sdp_list_append(proto_list, rfcomm_list);
access_proto_list = sdp_list_append(0, proto_list);
sdp_set_access_protos(&record, access_proto_list);
// set the name, provider, and description
sdp_set_info_attr(&record, service_name, service_prov, svc_dsc);
// connect to the local SDP server, register the service record,
// and disconnect
session = sdp_connect(&bdaddr_any, &bdaddr_local, SDP_RETRY_IF_BUSY);
sdp_record_register(session, &record, 0);
// cleanup
sdp_data_free(channel);
sdp_list_free(l2cap_list, 0);
sdp_list_free(rfcomm_list, 0);
sdp_list_free(root_list, 0);
sdp_list_free(access_proto_list, 0);
sdp_list_free(svc_class_list, 0);
sdp_list_free(profile_list, 0);
return session;
}
char input[1024] = { 0 };
char *read_server(int client) {
// read data from the client
int bytes_read;
bytes_read = read(client, input, sizeof(input));
if (bytes_read > 0) {
printf("received [%s]\n", input);
return input;
} else {
return NULL;
}
}
void write_server(int client, char *message) {
// send data to the client
char messageArr[1024] = { 0 };
int bytes_sent;
strcpy(messageArr, message);
bytes_sent = write(client, messageArr, strlen(messageArr));
if (bytes_sent > 0) {
printf("sent [%s] %d\n", messageArr, bytes_sent);
}
}
int main()
{
pthread_t thread_id;
signal( SIGPIPE, SIG_IGN );
int port = 3, result, sock, client, bytes_read, bytes_sent;
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buffer[1024] = { 0 };
socklen_t opt = sizeof(rem_addr);
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = bdaddr_any;
loc_addr.rc_channel = (uint8_t) port;
// register service
sdp_session_t *session = register_service(port);
// allocate socket
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
printf("socket() returned %d\n", sock);
// bind socket to port 3 of the first available
result = bind(sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
printf("bind() on channel %d returned %d\n", port, result);
// put socket into listening mode
result = listen(sock, 1);
printf("listen() returned %d\n", result);
//sdpRegisterL2cap(port);
while(1)
{
// accept one connection
printf("calling accept()\n");
client = accept(sock, (struct sockaddr *)&rem_addr, &opt);
printf("accept() returned %d\n", client);
ba2str(&rem_addr.rc_bdaddr, buffer);
fprintf(stderr, "accepted connection from %s\n", buffer);
memset(buffer, 0, sizeof(buffer));
pthread_create( &thread_id, NULL, ThreadMain, (void*)client);
}
}
void *ThreadMain(void *argument)
{
char buf[1024];
pthread_detach(pthread_self());
int client = (int)argument;
while(1)
{
//char *recv_message = read_server(client);
//if ( recv_message == NULL ){
// printf("client disconnected\n");
// break;
//}
char buf[1024] = ;
scanf("%s", buf);
int size = strlen(buf);
buf[size] = '\n';
printf("%s\n", buf);
write_server(client, buf);
}
printf("disconnected\n" );
close(client);
return 0;
}
컴파일 하는 법
apt-get install libbluetooth-dev
gcc bluetooth_server.c -o bluetooth_server -lbluetooth -lpthread
sdp server 활성화
/etc/sytemd/system/dbus-org.bluez.service 파일을 열고
ExecStart=/usr/libexec/bluetooth/bluetoothd을
ExecStart=/usr/libexec/bluetooth/bluetoothd --compat으로 수정
안드로이드 코드 (클라이언트)
원본코드에서 약간 수정함
*
* webnautes@naver.com
*
* 참고
* https://github.com/googlesamples/android-BluetoothChat
* http://www.kotemaru.org/2013/10/30/android-bluetooth-sample.html
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity
{
private final int REQUEST_BLUETOOTH_ENABLE = 100;
private TextView mConnectionStatus;
private EditText mInputEditText;
ConnectedTask mConnectedTask = null;
static BluetoothAdapter mBluetoothAdapter;
private String mConnectedDeviceName = null;
private ArrayAdapter<String> mConversationArrayAdapter;
static boolean isConnectionError = false;
private static final String TAG = "BluetoothClient";
@SuppressLint("MissingPermission")
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button sendButton = (Button)findViewById(R.id.send_button);
sendButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
String sendMessage = mInputEditText.getText().toString();
if ( sendMessage.length() > 0 ) {
sendMessage(sendMessage);
}
}
});
mConnectionStatus = (TextView)findViewById(R.id.connection_status_textview);
mInputEditText = (EditText)findViewById(R.id.input_string_edittext);
ListView mMessageListview = (ListView) findViewById(R.id.message_listview);
mConversationArrayAdapter = new ArrayAdapter<>( this,
android.R.layout.simple_list_item_1 );
mMessageListview.setAdapter(mConversationArrayAdapter);
Log.d( TAG, "Initalizing Bluetooth adapter...");
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
showErrorDialog("This device is not implement Bluetooth.");
return;
}
if (!mBluetoothAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_BLUETOOTH_ENABLE);
}
else {
Log.d(TAG, "Initialisation successful.");
showPairedDevicesListDialog();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if ( mConnectedTask != null ) {
mConnectedTask.cancel(true);
}
}
private class ConnectTask extends AsyncTask<Void, Void, Boolean> {
private BluetoothSocket mBluetoothSocket = null;
private BluetoothDevice mBluetoothDevice = null;
@SuppressLint("MissingPermission")
ConnectTask(BluetoothDevice bluetoothDevice) {
mBluetoothDevice = bluetoothDevice;
mConnectedDeviceName = bluetoothDevice.getName();
//SPP
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
try {
mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);
Log.d( TAG, "create socket for "+mConnectedDeviceName);
} catch (IOException e) {
Log.e( TAG, "socket create failed " + e.getMessage());
}
mConnectionStatus.setText("connecting...");
}
@SuppressLint("MissingPermission")
@Override
protected Boolean doInBackground(Void... params) {
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mBluetoothSocket.connect();
} catch (IOException e) {
// Close the socket
try {
mBluetoothSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " +
" socket during connection failure", e2);
}
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean isSucess) {
if ( isSucess ) {
connected(mBluetoothSocket);
}
else{
isConnectionError = true;
Log.d( TAG, "Unable to connect device");
showErrorDialog("Unable to connect device");
}
}
}
public void connected( BluetoothSocket socket ) {
mConnectedTask = new ConnectedTask(socket);
mConnectedTask.execute();
}
private class ConnectedTask extends AsyncTask<Void, String, Boolean> {
private InputStream mInputStream = null;
private OutputStream mOutputStream = null;
private BluetoothSocket mBluetoothSocket = null;
ConnectedTask(BluetoothSocket socket){
mBluetoothSocket = socket;
try {
mInputStream = mBluetoothSocket.getInputStream();
mOutputStream = mBluetoothSocket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "socket not created", e );
}
Log.d( TAG, "connected to "+mConnectedDeviceName);
mConnectionStatus.setText( "connected to "+mConnectedDeviceName);
}
@Override
protected Boolean doInBackground(Void... params) {
byte [] readBuffer = new byte[1024];
int readBufferPosition = 0;
while (true) {
if ( isCancelled() ) return false;
try {
int bytesAvailable = mInputStream.available();
if(bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
mInputStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++) {
byte b = packetBytes[i];
if(b == '\n')
{
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0, encodedBytes, 0,
encodedBytes.length);
String recvMessage = new String(encodedBytes, "UTF-8");
readBufferPosition = 0;
Log.d(TAG, "recv message: " + recvMessage);
publishProgress(recvMessage);
}
else
{
readBuffer[readBufferPosition++] = b;
}
}
}
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
return false;
}
}
}
@Override
protected void onProgressUpdate(String... recvMessage) {
mConversationArrayAdapter.insert(mConnectedDeviceName + ": " + recvMessage[0], 0);
}
@Override
protected void onPostExecute(Boolean isSucess) {
super.onPostExecute(isSucess);
if ( !isSucess ) {
closeSocket();
Log.d(TAG, "Device connection was lost");
isConnectionError = true;
showErrorDialog("Device connection was lost");
}
}
@Override
protected void onCancelled(Boolean aBoolean) {
super.onCancelled(aBoolean);
closeSocket();
}
void closeSocket(){
try {
mBluetoothSocket.close();
Log.d(TAG, "close socket()");
} catch (IOException e2) {
Log.e(TAG, "unable to close() " +
" socket during connection failure", e2);
}
}
void write(String msg){
msg += "\n";
try {
mOutputStream.write(msg.getBytes());
mOutputStream.flush();
} catch (IOException e) {
Log.e(TAG, "Exception during send", e );
}
mInputEditText.setText(" ");
}
}
@SuppressLint("MissingPermission")
public void showPairedDevicesListDialog()
{
@SuppressLint("MissingPermission") Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
final BluetoothDevice[] pairedDevices = devices.toArray(new BluetoothDevice[0]);
if ( pairedDevices.length == 0 ){
showQuitDialog( "No devices have been paired.\n"
+"You must pair it with another device.");
return;
}
String[] items;
items = new String[pairedDevices.length];
for (int i=0;i<pairedDevices.length;i++) {
items[i] = pairedDevices[i].getName();
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select device");
builder.setCancelable(false);
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
ConnectTask task = new ConnectTask(pairedDevices[which]);
task.execute();
}
});
builder.create().show();
}
public void showErrorDialog(String message)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Quit");
builder.setCancelable(false);
builder.setMessage(message);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if ( isConnectionError ) {
isConnectionError = false;
finish();
}
}
});
builder.create().show();
}
public void showQuitDialog(String message)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Quit");
builder.setCancelable(false);
builder.setMessage(message);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
});
builder.create().show();
}
void sendMessage(String msg){
if ( mConnectedTask != null ) {
mConnectedTask.write(msg);
Log.d(TAG, "send message: " + msg);
mConversationArrayAdapter.insert("Me: " + msg, 0);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_BLUETOOTH_ENABLE) {
if (resultCode == RESULT_OK) {
//BlueTooth is now Enabled
showPairedDevicesListDialog();
}
if (resultCode == RESULT_CANCELED) {
showQuitDialog("You need to enable bluetooth");
}
}
}
}
출처
Android와 PC JAVA 프로그램 간 블루투스 통신 예제 - 멈춤보단 천천히라도 (webnautes.blog)
Android와 PC JAVA 프로그램 간 블루투스 통신 예제 - 멈춤보단 천천히라도
안드로이드의 앱과 PC의 JAVA 서버 프로그램 간에 Serial Port Profile(SPP)를 이용한 블루투스 통신을 다룹니다. SPP는 블루투스를 이용하여 시리얼 통신을 무선으로 대체할 수 있도록 합니다. 1. 자바 코
webnautes.blog
Raspberry Pi 3 블루투스 페어링 방법(bluetoothctl) 및 C언어 블루투스 서버 예제 - 멈춤보단 천천히라도 (tistory.com)
Raspberry Pi 3 블루투스 페어링 방법(bluetoothctl) 및 C언어 블루투스 서버 예제
Bluetooth 모듈이 내장되어 있는 Raspberry Pi 3와 윈도우가 설치된 PC 간에 페어링 및 메시지를 주고 받는 방법을 설명합니다. 블루투스 통신 테스트는 C언어로 작성된 Bluetooth 서버 예제를 Raspberry PI 3
webnautes.tistory.com
'네트워크 & 통신' 카테고리의 다른 글
| c 소켓 프로그래밍 예제 (0) | 2023.07.23 |
|---|---|
| 스위치 vs 브릿지 (0) | 2023.03.25 |
| Modbus 실습 (0) | 2023.02.14 |
| Modbus 공부 (2) | 2023.02.14 |