5 Replies Latest reply on Jan 5, 2016 6:20 AM by Intel_Peter

    is there any way to register a service through the terminal? (Bluetooth)

    Eng_akhamis

      Hi,

       

      I'm wondering if I can register a bluetooth service (with spicific port number and UUID) manually using the terminal?. I saw in the bluetooth manual of Intel Edison that I can perform this using a test written in Python. I tried to use sdp_record_register through my sketch code and it didn't work for me. My idea is to register the service manually and then use the same port number to listen for the incoming data. Any suggestions please?

       

      Best regards,

      Abdulrahman Khamis

       

      example for listening on an RFCOMM port:

       

      #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) 11;   // I will use the same number to register the service

        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);

      }

        • 1. Re: is there any way to register a service through the terminal? (Bluetooth)
          Intel_Peter

          Hello Eng_akhamis,

           

          What exactly do you want to achieve, I mean, you want to register a device manually and then you want to use an OBEX based profile to receive files, is that it? Or do you want to receive data as if it was a serial port as a continuous stream?

          I mean, you can in fact pair, connect, and set the board to do both things from terminal but I'm not sure what's your final goal and maybe I'd give a more complex answer than I should if I don't know enough of your problem. So in simple terms, what is the objective of your project?

           

          Peter.

          • 2. Re: is there any way to register a service through the terminal? (Bluetooth)
            Eng_akhamis

            Mr. Intel_Peter,

             

            Thanks for all your responses. Let explain my goal first :

             

            I have an android device and Intel Edison with Arduino breakboard. I built an android app to connect to a bluetooth device and send text messages ( String data type ). My goal is to make Edison accept the connection request and receive the data using a code similar to this:

             

            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) 12;
              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;
            }
            

             

            form RFCOMM sockets

             

            The problem is, Android doesn't make bluetooth connections using a port number. It searches for a specific UUID that specify the service. Since the above code doesn't specify and register the service with an UUID linked to port number 12 ( loc_addr.rc_channel = (uint8_t) 12; ), I have to add some code to advertise the service. So I added this:

             

            void register_service(){
                //Serial.println("hi ");
                uint32_t service_uuid_int[] = { 0, 0, 0, 0x77FE183EA9D911E5ACA9C2AE1D5D46B0};
                uint8_t rfcomm_channel = 11;
                const char *service_name = "Edison";
                const char *service_dsc = "An experiment about bluetooth";
                const char *service_prov = "Abdul";
            
                uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid;
                sdp_list_t *l2cap_list = 0,
                           *rfcomm_list = 0,
                           *root_list = 0,
                           *proto_list = 0,
                           *access_proto_list = 0;
                sdp_data_t *channel = 0, *psm = 0;
               
                sdp_record_t *record = sdp_record_alloc();
               
                // set the general service ID
                sdp_uuid128_create( &svc_uuid, &service_uuid_int );
                sdp_set_service_id( record, svc_uuid );
            
                // 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 );
            
                // set rfcomm information
                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 );
               
                // attach protocol information to service record
                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, service_dsc);
               
                int err = 0;
                sdp_session_t *session = 0;
            
                // connect to the local SDP server, register the service record, and
                // disconnect
                session = sdp_connect( ptrAny, ptrLoc, SDP_RETRY_IF_BUSY );
                err = sdp_record_register(session, record, 0);
            
                lcd.clear();
                lcd.print("Stop here");
            
                // 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 );
            }
            

             

            This function should do the work but unfortunately it doesn't. If you can notice I use an lcd to debug the sketch. When the sketch comes to err = sdp_record_register(session, record, 0); it doesn't proceed and untill now I don't know why. So I was looking for and trying many solutions and through my searching I found a reasonable solution but there are some parts of it that are unclear for me. I was reading the bluetooth guide http://download.intel.com/support/edison/sb/edisonbluetooth_331704004.pdf on page 30 this:

             

            "BlueZ provides a set a Python scripts (in the test folder) that interact with the bluetoothd daemon using the exposed D-Bus API, so it is possible to use these scripts, and get the same results as when using bluetoothctl."

            .

            and on page 48 CH 6.7 Serial Port Profile (SPP) : They used a Python script (SPP-loopback.py) to make a virtual serial port for communication. The script ( as I can understand after reading the script) can advertise the service with an UUID and specific port number.

             

            This makes me ask a few questions and I really appreciate your help:

             

            1 - Are the scripts written in Python just tests or I can use them as a major part of my projects?

            2 - Can I make a specific script runs directly when the Edison is turned on?

            3 - after the script runs using a channel with a specific number, Can I use the sketch that listen for connection and receive Strings using the same channel number? would that work?

            4 - How can I make the bluetooth runs directly when the Edison is turned on?

             

             

            best regards,

            Abdulrahman Khamis

            • 3. Re: is there any way to register a service through the terminal? (Bluetooth)
              Intel_Peter

              Sorry for the delay in my response.

               

              1. You could use the Python scripts as a main part of your project but they would require a big amount of modification in order to set them to work appropriately. So, that's an option, another option is to set it manually and implement it on your code. You can see in Re: Bluetooth communication using Java? how to manually set an SPP connection, why don't you give it a look, it might be of your interest.

               

              2. Yes, that's called system service. I did a brief explanation in how to create one in Re: C++ Creating Release Version, check it out, the example is in C but the main idea can be translated to any programming language.

               

              3. This one is a bit more difficult to answer. Please correct me if I'm wrong, what you mean is that you are establishing the connection to certain port, then you leave it running on the background and then you want to listen to the same port? If so, then yes, you are correct, you can make the code listen to the same port; I mean when you create an SPP connection, it is basically a "serial port" so you can send and receive data from it. In fact in Re: Bluetooth communication using Java? the last line is to read what you are currently receiving.

               

              4. Automatically connect to a device through Bluetooth .

               

              Peter.

               

              P.S.: I modified your post to make the code look a little bit more easy to read.

              • 4. Re: is there any way to register a service through the terminal? (Bluetooth)
                Eng_akhamis

                Thank you so much Mr. Peter I really appreciate your help. That was really helpful for me. Finally, the pure arduino sketch ( without Python ) worked after a little modification. The problem was not in the code. I just needed to modify bluetooth.service file ( I added -C after bluetoothd)  and boom it worked.

                 

                Best regrads,

                Abdulrahman Khamis

                • 5. Re: is there any way to register a service through the terminal? (Bluetooth)
                  Intel_Peter

                  I'm glad to hear that your project is now working, I hope I was of help. If you ever have any other issues or doubts, don't hesitate to come back to the community, we'll do our best to help you!

                   

                  Peter.