zoukankan      html  css  js  c++  java
  • Examples

    最近需要在某个开发板上面通过蓝牙和手机蓝牙连接,并通过RFCOMM通信。还没有做过蓝牙RFCOMM相关工作,因此先在linux PC上面调试一下流程,并在此记录调试过程。

    一、说明

    RFCOMM协议基于L2CAP协议的串行(9针RS-232)仿真。

    本文中实现了RFCOMM server和client通信。

    二、设备

    linux主机(Ubuntu-14.04)、linux虚拟机(Ubuntu-14.04)、Android手机一台、不知名蓝牙dongle_1(controller)、CSR 蓝牙dongle_2(controller)。

    Linux主机+dongle_1作为server端; linux虚拟机+dongle_2作为client端;Android手机作为client端。

    三、环境搭建

    Server端:

     1. 安装bluez协议栈

     2. 查看bluetoothd进程是否启动:ps -ef|grep blue

    root      1891     1  0  5月19 ?      00:00:00 /usr/sbin/bluetoothd

     

    如果没有启动,执行:/usr/sbin/bluetoothd -C &

    注:开始测试,如果把bluetoothd进程kill了,也能进行连接成功。后来发现如果不启动bluetoothd,就连接不成功。理论上说server端程序使用socket通信,应该不需要bluetoothd。

    至今没有搞清楚原因。

     

     

     3. 查看bluetooth service是否存在:service --status-all | grep blue

    如果不存在,执行:service bluetooth start

     

     

     

    4. 将dongle_1插入linux主机端;并配置。

    1> 执行:hciconfig,观察dongle状态是否为UP RUNNING,如果不为UP RUNNING,则执行:hciconfig hci0 UP

    注:hci0是根据hciconfig打印的BD Address来确定的。如果有两个dongle,有可能是hci1。

     

    2> 使蓝牙设备可见(可被其他蓝牙设备扫描到,如手机)

    执行命令:hciconfig piscan

    然后执行hciconfig,观察状态是否为UP RUNNING PSCAN ISCAN

     

    3> 添加SPP服务

    sdptool add SP

    也可以执行添加所有服务:

    sdptool add --channel=1 DID SP DUN LAN FAX OPUSH FTP HS HF SAP NAP GN PANU HID CIP CTP A2SRC A2SNK SYNCML NOKID PCSUITE SR1

     

    4> 关闭pin码验证

    hciconfig hci0 noauth;

     

    5. 编写并编译测试程序

    gcc -o rfcomm_server rfcomm_server.c

     

    Client端(linux虚拟机):

    1. 安装bluez协议栈

    2. 查看bluetoothd进程是否启动:ps -ef|grep blue,如果没有启动,则启动该进程。

    3. 查看bluetooth service是否存在:service --status-all | grep blue  

    如果不存在,执行:service bluetooth start

    4. 添加SPP服务,关闭pin码验证。

    5. 创建RFCOMM设备节点:mknod /dev/rfcomm0 c 216 0

    chmod 666 /dev/rfcomm0

    6. 绑定server端蓝牙mac地址

    rfcomm bind 0 00:19:86:00:2B:BD 1 //0表示rfcomm0, 00:19:86:00:2B:BD为server端的蓝牙地址,1为通道

    7. 编写并编译rfcomm_client

    Client端(Android手机)

    1. 下载蓝牙串口SPP应用程序

    四、测试

    1. Server + client(linux虚拟机)

    1> 在server端执行rfcomm_server

    2> 在client端执行rfcomm_client

    可以在两端观察到写入和读出的数据

     

    2. Server + Android手机

    1> 在server端执行rfcomm_server

    2> Client端,打开蓝牙SPP应用,扫描到server端的蓝牙设备,连接。即可和server端进行通信

    rfcomm_server.c

    #include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <bluetooth/bluetooth.h> #include <bluetooth/rfcomm.h> int str2ba(const char *str, bdaddr_t *ba) { uint8_t b[6]; const char *ptr = str; int i; for (i = 0; i < 6; i++) { b[i] = (uint8_t) strtol(ptr, NULL, 16); if (i != 5 && !(ptr = strchr(ptr, ':'))) ptr = ":00:00:00:00:00"; ptr++; } } void baswap(bdaddr_t *dst, const bdaddr_t *src) { unsigned char *d = (unsigned char *) dst; const unsigned char *s = (const unsigned char *) src; int i; for (i = 0; i < 6; i++) d[i] = s[5-i]; } int ba2str(const bdaddr_t *ba, char *str) { uint8_t b[6]; baswap((bdaddr_t *) b, ba); return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", b[0], b[1], b[2], b[3], b[4], b[5]); } 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); char write_buf[1204]="hello world"; char flag = 1; char count=0; // 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 ", buf); while( flag ) { memset(buf, 0, sizeof(buf)); #if 0 // read data from the client bytes_read = read(client, buf, sizeof(buf)); if( bytes_read > 0 ) { printf("[rcv]:%s ", buf); if(!strcmp(buf,"exit")) { flag = 0; } // write( client,write_buf,16 ); } usleep(5000); #endif #if 1 //write data to client strcpy( buf, "abcdefgh" ); bytes_read = 9; write( client,buf,bytes_read ); usleep(50000); #endif } // close connection close(client); close(s); return 0; }
    rfcomm_client.c
    
    #include <stdio.h>
    #include <sys/types.h>
     #include <sys/stat.h>
     #include <fcntl.h>
     #include <unistd.h>
     #include <string.h>
    int main( int argc, char **argv ) 
    {
        int fd ;
        unsigned char buff[64] = "hello";
        char read_buff[128] = {0};
        int read_n;
        int write_n;
        fd = open( "/dev/rfcomm0",O_RDWR);
        
        if( fd<0 )
            printf( "open rfcomm0 error
    " );
            
        while(1)
        {
    #if 0
        //    printf( "write hello to rfcomm
    " );    
            write_n = write( fd, buff, 64 );
            if( write_n<0)
                printf( "write error
    " );
            else if(write_n==0)
                printf( "write nothing
    " );
            else
                printf( "write %d byte
    ",write_n );
        //    sleep(1);
    #endif
    #if 1
            memset( read_buff, 0, sizeof(read_buff) );
            read_n = read( fd, read_buff, sizeof(read_buff) );
            if( read_n > 0 )
                {
                    printf( "[receive]:%s
    ",read_buff );
                }
                
                usleep(50000);
                #endif
        }
        close(fd);
    }

    在网上查了一下资料,有rfcomm_client.c是创建socket,并bind、connect,但是我调试的时候执行该程序,会报错。原因没有找到。下面将代码贴出来,以后可以找一下原因。


    #include <stdio.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/rfcomm.h>
    
    
    int str2ba(const char *str, bdaddr_t *ba)
    {
        uint8_t b[6];
        const char *ptr = str;
        int i;
    
        for (i = 0; i < 6; i++) 
        {
              b[i] = (uint8_t) strtol(ptr, NULL, 16);
              if (i != 5 && !(ptr = strchr(ptr, ':')))
               ptr = ":00:00:00:00:00";
              ptr++;
          }
    }
    
    
    
    int main(int argc, char **argv)
    {
        struct sockaddr_rc addr = { 0 };
        int s, status;
        char dest[18] = "00:19:86:00:2B:BD";
    
        // allocate a socket
        s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
    
        // set the connection parameters (who to connect to)
        addr.rc_family = AF_BLUETOOTH;
        addr.rc_channel = (uint8_t) 1;
        str2ba( dest, &addr.rc_bdaddr );
        printf( "connect device
    " );
        // connect to server
        status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
    
        // send a message
        if( status == 0 ) {
            status = write(s, "hello!", 6);
        }
    
        if( status < 0 ) perror("uh oh");
    
        close(s);
        return 0;
    }



    网上资料,有文章介绍需要设置rfcomm.conf, 个人以为如果需要client上电自动连接,可以用此方法进行设置(还需要进行其他配置),和用命令设置效果一样。

     

    其中:不知名蓝牙dongle ,hciconfig -a信息如下:

    root@localhost:bin# hciconfig -a

    hci0:   Type: BR/EDR  Bus: USB

            BD Address: 00:19:86:00:2B:BD  ACL MTU: 1021:8  SCO MTU: 64:1

            UP RUNNING PSCAN

            RX bytes:66976 acl:1214 sco:0 events:1729 errors:0

            TX bytes:67686 acl:1976 sco:0 commands:203 errors:0

            Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87

            Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3

            Link policy: RSWITCH SNIFF

            Link mode: SLAVE ACCEPT

            Name: 'localhost-0'

            Class: 0x600100

            Service Classes: Audio, Telephony

            Device Class: Computer, Uncategorized

            HCI Version: 4.0 (0x6)  Revision: 0x1000

            LMP Version: 4.0 (0x6)  Subversion: 0x220e

  • 相关阅读:
    ubuntu12.04 死机 卡屏 画面冻结解决方案
    Install Firefox 20 in Ubuntu 13.04, Ubuntu 12.10, Ubuntu 12.04, Linux Mint 14 and Linux Mint 13 by PPA
    ListView1.SelectedItems.Clear()
    android studio 下载地址
    jquery.slider.js jquery幻灯片测试
    jquery.hovermenu.js
    jquery.tab.js选项卡效果
    适配 placeholder,jquery版
    jquery.autoscroll.js jquery自动滚动效果
    将 Google Earth 地图集成到自己的窗体上的 简单控件
  • 原文地址:https://www.cnblogs.com/hjj801006/p/12930290.html
Copyright © 2011-2022 走看看