Bluetooth Serial Port Protocol (SPP)

With webOS 2.0, your app can use the Bluetooth SPP to access certain Bluetooth devices. At this time, only the SPP is exposed. Note that you can see what Bluetooth profiles your device supports in the Device Info application.

Bluetooth Code Sample - GPS Device

The SDK code samples contain a Bluetooth project which opens a port to a Bluetooth GPS device and reads its position data.

In this section:


Methods


Basic Process for Server/Client Data Exchange

Before beginning, both client and server webOS devices should have "paired" using their Bluetooth installed programs. Bluetooth pairing happens when two Bluetooth enabled devices agree to communicate with one another. Both devices have to have Bluetooth turned on so they can "discover" one another. When they agree to communicate, the two devices join what is called a "trusted pair."

Server

  1. Call subscribenotifications to receive SPP notifications.
  2. Call enableserver to make device an SPP server with specified service name.
  3. Wait for connect notification from client device. Extract instance ID.
  4. Using instance ID from client, open an SPP port for client communications.
  5. Write data to client. Repeat calling write until done.
  6. Wait until disconnect notification arrives from client before calling close to remove the port connection.
  7. Call disableserver to remove device as SPP server.

Client

  1. Call subscribenotifications to receive SPP notifications.
  2. Call gettrusteddevices to get a list of paired devices from the Bluetooth service.
  3. Call connect to connect to server device.
  4. Wait for service names notification to arrive. Extract service's instance ID and service name.
  5. Call selectservice using service name and instance ID from service names notification.
  6. Use instance ID to open port to Server.
  7. Read data from server. Repeat calling read until done.
  8. Close port to server.
  9. Disconnect from server.

Notifications

When an app calls subscribenotifications, they can begin receiving one of the following SPP notifications.

Syntax

{
    "notification" : string,
    "instanceId"   : int,
    "address"      : string,
    "name"         : string,
    "services"     : string array,
    "error"        : int    
}   

Parameters

Parameter Required Type Description
notification Yes string One of the following:
  • notifnserverenabled -- Device is enabled as an SPP server.
  • notifnserverdisenabled -- Device is disabled as an SPP server.
  • notifndatasent -- Indicates that data has been sent.
  • notifnconnected -- Connected. Sent when a client connects to an SPP server. This notification contains an instance ID the server can use to open a communications port to the client.
  • notifndisconnected -- Disconnected from SPP server.
  • notifnservicenames -- After a client connects to an SPP server, it gets a list of the SPP server's services and an instance ID it can use to select a service.
instanceId No int Subscribed service identifier. Sent for notifnservicenames, notifnconnected, and notifndisconnected.
address No string Bluetooth device address containing hex digits for an IEEE standard MAC address, i.e., "00:0d:b5:38:c0:3f". Sent for notifnconnected and notifndisconnected.
name No string User given device name, i.e., "Joe's HP TouchPad". Sent for notifnconnected and notifndisconnected.
services No string array Array of SPP server names. Sent for notifnservicenames.
error No int Error code. 0 = No error.


Examples

{
   "notification":"notifnserverenabled",
   "error":0
}

{
   "notification":"notifnservicenames",
   "instanceId":23,
   "services":[
      "HPQA"
   ]
}

{
   "notification":"notifnconnected",
   "address":"00:1d:fe:77:c3:a7",
   "name":"Joe's HP TouchPad",
   "instanceId":27,
   "error":0
}

{
   "notification":"notifndisconnected",
   "address":"08:1d:fe:77:c2:d3",
   "name":"My Palm3",
   "instanceId":23,
   "error":0
}

Mojo -- Sample Notification Implementation Code

Note that this is not a completely self-contained example, but should give you some idea of flow. Note also that this is server side code, the code for a client would be somewhat different.

MainAssistant.prototype.setup = function()
{

    this.count      = 0;
    this.maxcount   = 10;
    this.urlgap     = 'palm://com.palm.bluetooth/gap';
    this.urlspp     = 'palm://com.palm.bluetooth/spp';
    this.urlservice = 'palm://com.palm.service.bluetooth.spp';

}

MainAssistant.prototype.subscribe = function(sub)
{
    var msg =
    {
        method: "subscribenotifications",
        parameters: {"subscribe": true},
        onSuccess: this.sppNotify.bind(this),
    };
    this.sppNotificationService = this.serviceRequest(this.urlspp, msg);
}    

MainAssistant.prototype.sppNotify = function(objData)
{
    var that = this; // for scoping

    if (! objData.notification)
    {
        this.log("sppNotify", Object.toJSON(objData));
        if (objData.returnValue  &&  objData.subscribed)
        {
            this.enableserver(true);
        }
        return;
    }

    switch(objData.notification)
    {
        case "notifnserverenabled":
            this.log(objData.notification, "error = " + objData.error);
        break;

        case "notifnserverdisabled":
            this.log(objData.notification, "error = " + objData.error);
            if (this.count >= this.maxcount)
            {
                this.log("", "SUCCESSFUL!");
            }
        break;

        case "notifnconnected":
            this.log(objData.notification, objData.instanceId);
            if (objData.error === 0)
            {
                this.open(objData.instanceId);
            }
        break;

        case "notifndisconnected":
            this.log(objData.notification, "Connection terminated/Out of range");
            this.enableserver(false);
        break;

        default:
            this.log(objData.notification, Object.toJSON(objData));
        break;
    }
}


GAP Method

GAP (Generic Access Profile) defines how two Bluetooth units discover and establish a connection with each other.

The URI for the one GAP method is:

com.palm.bluetooth/gap/gettrusteddevices

gettrusteddevices

Return information about Bluetooth devices that are paired with a webOS device.

Syntax

{}

Parameters

None.

Returns

{
    "returnValue" : boolean,
    "trusteddevices" :
    [{
        "address"          : string,
        "name"             : string,
        "cod"              : int,
        "renamed"          : boolean,
        "status"           : string,
        "mapstate"         : int,
        "pbapstate"         : int,
        "hfstate"          : int,
        "autoconnectstate" : int
     }]
}
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
trusteddevices Yes object array Array of objects. See fields below. If no trusted devices, this is an empty array.
address No string Bluetooth device address containing hex digits for an IEEE standard MAC address, i.e., "00:0d:b5:38:c0:3f".
name No string Device name, e.g., "BT-GPS-38C03F"
cod No int Class of device -- indicates the device type and which types of services it supports.
renamed No boolean Indicates if user has modified device's name.
status No string connected|disconnected
mapstate No int Message Access (SMS) state - 1 (yes), 2 (no), or 255 (undefined). Indicates if the user has set the "Receive SMS" option to "ON".
pbapstate No int Phone Book Access state - 1 (yes), 2 (no), or 255 (undefined). Indicates if the user has set the "Receive Phone Calls" option to "ON".
hfstate No int Hands Free state, only for webOS tablet acting as headset - 1 (yes), 2 (no), or 255 (undefined).
autoconnectstate No int Only for webOS devices -- paired devices can receive the same phone calls or sms notifications if both have "Receive Phone Calls" (pbap), "Receive SMS" (map) and "Auto-Connect" all set to "ON". Note that these options are available when you select a paired device in the Bluetooth app. These devices will automatically connect when they come into each other's range. 1 (yes), 2 (no), or 255 (undefined).

Examples

Enyo

...
{
    name : "getDevices",
    kind : "PalmService",
    service : "palm://com.palm.bluetooth/gap/",
    method : "gettrusteddevices",
    onSuccess : "getDevicesFinished",
    onFailure : "getDevicesFail",
    onResponse : "gotResponse",
    subscribe : true
}
...     

getDevicesFinished : function(inSender, inResponse) {
    enyo.log("gettrusteddevices success, results=" + enyo.json.stringify(inResponse));
},
getDevicesFail : function(inSender, inResponse) {
    enyo.log("gettrusteddevices failure, results=" + enyo.json.stringify(inResponse));
},
getDevicesCall : function(inSender, inResponse)
{
    this.$.getDevices.call({});
}

Mojo

   this.controller.serviceRequest('palm://com.palm.bluetooth/gap', {
        method: 'gettrusteddevices',
        parameters: {},
         onSuccess : function (e){ Mojo.Log.info("gettrusteddevices success, results="+JSON.stringify(e)); },
         onFailure : function (e){ Mojo.Log.info("gettrusteddevices failure, results="+JSON.stringify(e)); }
    });

Success

gettrusteddevices success, results=
{
   "returnValue":true,
   "trusteddevices":[
      {
         "address":"70:1a:04:9c:20:9a",
         "name":"E64004CRBVL1",
         "cod":4063500,
         "renamed":true,
         "status":"disconnected",
         "mapstate":1,
         "pbapstate":255,
         "hfstate":1,
         "autoconnectstate":1
      }
   ]
}

SPP Access Methods

SPP (Serial Port Profile) is based on ETSI 07,10 and the RFCOMM protocol. It emulates a serial cable to provide a simple substitute for existing RS-232, including the familiar control signals.

The URI for SPP access is:

com.palm.bluetooth/spp

Methods


connect

Connect to an SPP server.

Syntax

{
    "address"    : string
}

Parameters

Parameter Required Type Description
address Yes string Bluetooth device address containing hex digits for an IEEE standard MAC address, i.e., "00:0d:b5:38:c0:3f".

Returns

{
    "returnValue"  : boolean,
    "errorCode"    : string,
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorCode No string Error code returned on failure.
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.bluetooth/spp/', {
    method: 'connect',
    parameters: { 
        "address" : "00:1d:fe:77:x3:a7"
    },
    onSuccess : function (e){ Mojo.Log.info("connect success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("connect failure, results="+JSON.stringify(e)); }   
});

disableserver

Disable an SPP server.

Syntax

{
    "servicename" : string
}

Parameters

Parameter Required Type Description
servicename Yes string Server name. Name used when enabling server.

Returns

{
    "returnValue"  : boolean,
    "errorCode"    : string,
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorCode No string Error code returned on failure.
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.bluetooth/spp/', {
    method: 'disableserver',
    parameters: {
          "servicename":"HPQA"
    },
    onSuccess : function (e){ Mojo.Log.info("disableserver success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("disableserver failure, results="+JSON.stringify(e)); }     
});

disconnect

Disconnect from an SPP peer.

Syntax

{
    "address"    : string
}

Parameters

Parameter Required Type Description
address Yes string Bluetooth device address containing hex digits for an IEEE standard MAC address, i.e., "00:0d:b5:38:c0:3f".

Returns

{
    "returnValue"  : boolean,
    "errorCode"    : string,
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorCode No string Error code returned on failure.
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.bluetooth/spp/', {
    method: 'disconnect',
    parameters: {
          "address":"70:1a:04:9c:20:9a"
    },
    onSuccess : function (e){ Mojo.Log.info("disconnect success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("disconnect failure, results="+JSON.stringify(e)); }    
});

enableserver

Make webOS device an SPP server with a specified service name.

Syntax

{
   "servicename" : string
}

Parameters

Parameter Required Type Description
servicename Yes string Service name, 128 characters maximum.

Returns

{
    "returnValue"  : boolean,
    "errorCode"    : string,
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorCode No string Error code returned on failure.
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.bluetooth/spp/', {
    method: 'enableserver',
    parameters: {"servicename":"HPQA"},
    onSuccess : function (e){ Mojo.Log.info("enableserver success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("enableserver failure, results="+JSON.stringify(e)); }      
});

Failure

{
    "returnValue":false,
    "errorCode":134217729,
    "errorText":"BtSppEnableServer: Error enabling server"
}

selectservice

Select a service from list of services received through notification.

Syntax

{
    "instanceId"  : int,
    "servicename" : string
}   

Parameters

Parameter Required Type Description
instanceId Yes integer Subscribed service identifier.
servicename Yes string Service name, returned from subscribenotifications.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.bluetooth/spp/', {
    method: 'selectservice',
    parameters: { 
                   "instanceId" : 23, 
                   "servicename":"HPQA"
    },
    onSuccess : function (e){ Mojo.Log.info("selectservice success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("selectservice failure, results="+JSON.stringify(e)); }     
});

Returns

{
    "returnValue"  : boolean,
    "errorCode"    : string,
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorCode No string Error code returned on failure.
errorText No string Error message returned on failure.


subscribenotifications

Subscribe to SPP notifications.

Syntax

{
    "subscribe" : boolean
}

Parameters

Parameter Required Type Description
subscribe Yes boolean Subscribe to Bluetooth SPP notifications flag.

Returns

{
    "returnValue"  : boolean,
    "errorCode"    : string,
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorCode No string Error code returned on failure.
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.bluetooth/spp/', {
    method: 'subscribenotifications',
    parameters: { "subscribe": true },
    onSuccess : function (e){ Mojo.Log.info("subscribenotifications success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("subscribenotifications failure, results="+JSON.stringify(e)); }   
});

Success

{"returnValue":true,"subscribed":true}

SPP Data Transfer Methods

The URI for Serial Port Profile Data Transfer is:

com.palm.service.bluetooth.spp

Methods


close

Close Bluetooth SPP communication channel.

Syntax

{
    "instanceId" : int
}   

Parameters

Parameter Required Type Description
instanceId Yes integer Subscribed service identifier.

Returns

{
    "returnValue"  : boolean,
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.service.bluetooth.spp', {
    method: 'close',
    parameters: { "instanceId" : 23},
    onSuccess : function (e){ Mojo.Log.info("close success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("close failure, results="+JSON.stringify(e)); }     
});

open

Opens a Bluetooth SPP port for communication.

Syntax

{
    "instanceId"  : int
}   

Parameters

Parameter Required Type Description
instanceId Yes integer Subscribed service identifier.

Returns

{
    "returnValue"  : boolean,
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.service.bluetooth.spp', {
    method: 'open',
    parameters: { "instanceId" : 23},
    onSuccess : function (e){ Mojo.Log.info("open success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("open failure, results="+JSON.stringify(e)); }      
});

read

Reads data from an SPP port.

Syntax

{
    "instanceId" : int,
    "dataLength" : int
}   

Parameters

Parameter Required Type Description
instanceId Yes integer Subscribed service identifier.
dataLength Yes integer Size of the buffer to be read.

Returns

{
    "returnValue"  : boolean,
    "data"         : string,
    "dataLength"   : int,       
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
data No string Data
dataLength No int Length of data
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.service.bluetooth.spp', {
    method: 'read',
    parameters: { 
                   "instanceId" : 23, 
                   "dataLength" : 128
    },
    onSuccess : function (e){ Mojo.Log.info("read success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("read failure, results="+JSON.stringify(e)); }      
});

write

Writes data to an SPP port.

Syntax

{
    "instanceId" : int,
    "data"       : string,
    "dataLength" : int
}   

Parameters

Parameter Required Type Description
instanceId Yes integer Subscribed service identifier.
data Yes string Data to write.
dataLength Yes integer Size of the buffer to be written.

Returns

{
    "returnValue"  : boolean,   
    "errorText"    : string
}       
Parameter Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorText No string Error message returned on failure.

Examples

Mojo

this.controller.serviceRequest('palm://com.palm.service.bluetooth.spp', {
    method: 'write',
    parameters: { 
                  "instanceId" : 23, 
                  "data"       : "lhasdflkasjhdflasjdhfaouweyroasdfasdfasdfasfdaswqguoyuilj,uiiaewfdas",
                  "dataLength" : 128},
    onSuccess : function (e){ Mojo.Log.info("write success, results="+JSON.stringify(e)); },
    onFailure : function (e){ Mojo.Log.info("write failure, results="+JSON.stringify(e)); }     
});