Skip to content

Usage

object:Cf (Client Function)

CF (Client-function) object is a special purpose RPC | request-response implementation to build command and control applications. CF object exposes properties, functions and events for command and control server applications to send messages to devices and application using dataBridges library in **trust-safe manner **, build smart update configuration system and implement **trust-safe ** actions for remote and automated management.

CF REDUCES HUGE ENGINEERING TIME EFFORT REQUIRED TO DESIGN, BUILD AND MAINTAIN A ROBUST COMMAND-CONTROL INFRASTRUCTURE.

  • A client function(s) is a callback function exposed by the client library as a RPC (remote procedure call).
  • Server application (using dataBridges server library), can execute the CF function remotely.

Concepts

  • CF (client-function) simplifies the command and control type application design and maintenance.
  • iOT and large distributed system requires a standard, secured and compliant method to send reliable request-response communication to the managed devices from authenticated and authorized Command-and-Control server applications. dataBridges CF allows you you to expose device functions and capabilities in a easy, secured manner allowing only authoirized dataBridges server applications to communicate with the devices, remote applications.
  • Only server application using dataBridges server library + application key secret can execute CF functions exposed by remote devices.
  • The server application is called CALLER (the one executing cf.call() function)
  • The server application needs to know the sessionID of the device to which it needs to communicate.
  • The device application exposing command functions is called CALLEE. Only authenticated and authorized server application will be allowed to communicate with the device application for device / application management.

Properties

The following is the list of cf properties. These properties has to be set before dbridge.connect()

Property Description
enable (boolean) (default:false) If application wants to enable clientFunction functionality, this needs to be true else false.
functions (function) A client function(s) is a callback function exposed by the client library as a RPC (remote procedure call).

enable:

You need to enable cf in the connection property.

dbridge.cf.enable = true;
dbridge.cf.enable = true;
dbridge.cf.enable = True
dbridge.cf.enable = true;
dbridge.cf.enable = True
dbridge.cf.enable = True

functions:

Application can expose callback function(s) as Client function (special case RPC | Request-Response). Server application using dataBridges server library can remotely execute the client functions. Each function needs to be registered with the library as a client function (CF), using dbridge.cf.regfn()where you can link the functionName to ClientFunctionName.

  • The client application that exposes the client function is called a CALLEE.
  • The server application that executes the client function is called a CALLER.

Functions can be defined either inside the property callback function or anywhere in the scope of application. Below code exhibits both ways of exposing the function.

// function is exposed outside the property callback function, but in the scope of application.
function cfFunOutside (payload, response) {
    try {
        response.tracker = true;
        response.next('This is Houston');
        response.end('message received by Houston');
        response.exception('INVALID_PARAM', 'Wrong parameter'); 
    } catch(err) {
        console.log(err.source, err.code, err.message);
    }
}

dbridge.cf.functions = function () {
    // function is exposed inside the property callback function.
    function cfFunInside (payload, response) {
        try {
            response.tracker = true;
            response.next('This is Hassan');
            response.end('message received by Hassan');
            response.exception('INVALID_PARAM', 'Wrong parameter'); 
            console.log(response.id);
        } catch(err) {
            console.log(err.source, err.code, err.message);
        }
    }
    // binding of functions to be exposed by clientfunctions
    try {
        dbridge.cf.regfn("nasa", cfFunOutside);
        dbridge.cf.regfn("isro", cfFunInside);
    } catch(err) {
        console.log(err.source, err.code, err.message);
    }
}

// unbinding of function exposed by clientfunctions
dbridge.cf.unregfn("nasa", cfFunOutside);
// function is exposed outside the property callback function, but in the scope of application.
function cfFunOutside (payload, response) {
    try {
        response.tracker = true;
        response.next('This is Houston');
        response.end('message received by Houston');
        response.exception('INVALID_PARAM', 'Wrong parameter'); 
    } catch(err) {
        console.log(err.source, err.code, err.message);
    }
}

dbridge.cf.functions = function () {
    // function is exposed inside the property callback function.
    function cfFunInside (payload, response) {
        try {
            response.tracker = true;
            response.next('This is Hassan');
            response.end('message received by Hassan');
            response.exception('INVALID_PARAM', 'Wrong parameter'); 
            console.log(response.id);
        } catch(err) {
            console.log(err.source, err.code, err.message);
        }
    }
    // binding of functions to be exposed by clientfunctions
    try {
        dbridge.cf.regfn("nasa", cfFunOutside);
        dbridge.cf.regfn("isro", cfFunInside);
    } catch(err) {
        console.log(err.source, err.code, err.message);
    }
}

// unbinding of function exposed by clientfunctions
dbridge.cf.unregfn("nasa", cfFunOutside);
# function is exposed outside the property callback function, but in the scope of application.
async def cfFunOutside(inparameter, response):
    try:
        response.tracker = True
        upTime = {"uptime": "13:34:30 up 8 days,  3:10,  1 user,  load average: 0.03, 0.11, 0.21"};
        response.next('retrieving system uptime')
        response.end(json,dumps(upTime))
        response.exception('INVALID_PARAM', 'Wrong parameter') 
    except dBError as e:
        print(e.code, e.source, e.message) 

async def cfFunctionBinder():
    async def cfFunInside(inparameter, response):
        #// function is exposed inside the property callback function.
        response.tracker = True
        try:
            response.tracker = True
            uName = {"uname": "Linux analysis 2.6.32-696.30.1.el6.x86_64 #1 SMP Tue May 22 03:28:18 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux"};
            response.next('retrieving uName')
            response.end(json.dumps(uName))
            response.exception('INVALID_PARAM', 'Wrong parameter') 
        except dBError as e:
            print(e.code, e.source, e.message) 

    try:
        dbridge.cf.regfn("isro", cfFunInside)
        dbridge.cf.regfn("nasa", cfFunOutside)
    except dBError as e:
        print(e.code, e.source, e.message) 

dbridge.cf.functions = cfFunctionBinder
# unbinding of function exposed by rpc functions
dbridge.cf.unregfn("nasa", cfFunOutside)
// function is exposed outside the property callback function, but in the scope of application.
using dBridges.responseHandler;

async void cfFunOutside(object inparam, object response)
{
    try {
        CResponseHandler responsehandler = response as CResponseHandler;
        responsehandler.tracker = true;
        Dictionary<string , string> uName = new Dictionary<string , string>() {"uname", "Linux analysis 2.6.32-696.30.1.el6.x86_64 #1 SMP Tue May 22 03:28:18 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux"};

        responsehandler.next('retrieving uName');
        responsehandler.end(new JavaScriptSerializer().Serialize(uName));
        responsehandler.exception('INVALID_PARAM', 'Wrong parameter'); 
    } catch (dBError err) {
        Console.WriteLine("{0} ,  {1} , {2}" , err.source, err.code, err.message);
    }
}

async void cfFunctionBinder(object sender)
{
    try{
        dBridges.clientFunctions.cfclient cfclient = sender as dBridges.clientFunctions.cfclient;
        // function is exposed outside the property callback function, but in the scope of application.
        Action<object , object> ifunctionoutside = cfFunOutside;
        cfclient.regfn("nasa", ifunctionoutside);

        // function is exposed inside the property callback function.
        Action<object , object> ifunctioninside;
        cfclient.regfn("isro", ifunctioninside = (object inparam, object response) =>{
            try {
                CResponseHandler responsehandler = response as CResponseHandler;
                responsehandler.tracker = true;
                Dictionary<string , string> uName = new Dictionary<string , string>() {"uname", "Linux analysis 2.6.32-696.30.1.el6.x86_64 #1 SMP Tue May 22 03:28:18 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux"};

                responsehandler.next('retrieving uName');
                responsehandler.end(new JavaScriptSerializer().Serialize(uName));
                responsehandler.exception('INVALID_PARAM', 'Wrong parameter'); 
            } catch (dBError err) {
                Console.WriteLine("{0} ,  {1} , {2}" , err.source, err.code, err.message);
            }       
        });

    } catch (dBError err) {
        Console.WriteLine("{0} ,  {1} , {2}" , err.source, err.code, err.message);
    }

}

Action<object> icfFunctions = cfFunctionBinder;
dbridge.cf.functions = icfFunctions;
// unbinding of function exposed by clientfunctions
dbridge.cf.unregfn("nasa", cfFunOutside);
dbridge.cf.regfn("cfTestFunction", new callRecieved() {
    @Override
    public void onCall(Object parameters, Object response) {
        try {
            rpcResponse rpcresponse = (rpcResponse) response;
            rpcresponse.tracker = true;
            response.next('output start');
            response.end('output end');
            response.exception(statuscode, errormessage) ;
        }catch(dBError dberror){
            Log.d("Main", "exception :" +  dberror.code + "::" + dberror.source);
        }
    }
});

dbridge.cf.regfn("nasa", new callRecieved() {
    @Override
    public void onCall(Object parameters, Object response) {
        try {
            rpcResponse rpcresponse = (rpcResponse) response;
            rpcresponse.tracker = true;
            rpcresponse.next('This is Houston');
            rpcresponse.end('message received by Houston');
            rpcresponse.exception(statuscode, errormessage) ;
        }catch(dBError dberror){
            Log.d("Main", "exception :" +  dberror.code + "::" + dberror.source);
        }
    }
});


dbridge.cf.regfn("isro", new callRecieved() {
    @Override
    public void onCall(Object parameters, Object response) {
        try {
            rpcResponse rpcresponse = (rpcResponse) response;
            rpcresponse.tracker = true;
            rpcresponse.next('This is Hassan');
            rpcresponse.end('message received by Hassan');
            rpcresponse.exception(statuscode, errormessage) ;
        }catch(dBError dberror){
            Log.d("Main", "exception :" +  dberror.code + "::" + dberror.source);
        }
    }
});

//  unbinding of function exposed by clientfunctions
dbridge.cf.unregfn("nasa", callRecievedHandler)
dbridge.cf.regfn("nasa",{  (parameters: Any, response: Any) in
    do {
        rpcresponse:rpcResponse = response as? rpcResponse
        rpcresponse.tracker = true
        response.next('This is Houston');
        response.end('message received by Houston');
        response.exception(statuscode, errormessage) 
    } catch(dBError dberror) {
        Log.d("Main", "exception :" +  dberror.code + "::" + dberror.source)
    }
})

dbridge.cf.regfn("isro",{  (parameters: Any, response: Any) in
    do {
        rpcresponse:rpcResponse = response as? rpcResponse
        rpcresponse.tracker = true
        response.next('This is Hassan');
        response.end('message received by Hassan');
        response.exception(statuscode, errormessage) 
    } catch(dBError dberror) {
        Log.d("Main", "exception :" +  dberror.code + "::" + dberror.source)
    }
})

// unbinding of function exposed by clientfunctions
dbridge.cf.unregfn("nasa", callRecievedHandler)

Below are parameters of the callback function which is exposed to clientfunctions.

Parameter Description
payload (string) The inParameter for the clientFunction.
response (object) The library creates a response object unique for each client function call. The Response object has properties and function to return execution results of the function back to caller.
response: (object)
Properties/Function Description
tracker (boolean) This will enable response tracker, and event cf.response.tracker will be fired if any issue happens in sending back response to caller. Enable this property if your function needs a confirmation of response delivered to the caller.
id (string) (readonly) Each client function execution is assigned a unique ID by the library. when the response tracker is enabled, the application can bind to an event cf.response.tracker to get the delivery notification. The event will indicate the delivery notification linked to this ID. Client application will need to maintain this ID to track the delivery notification.
next (function) dataBridges CF (Special case RPC |request-response) supports mult-part response. Application can use response.next to send multi-part response to the caller.
end (function) response.end is to send the final response to the caller. Once end is called, the object is closed and no more response can be sent.
exception (function) Two parameter, return errorCode (string) ,errorMessage (string) is sent to caller. This will raise an exception at the caller library.
Exceptions:

Below exceptions are raised in the cf.regfn.

Source Code Description
DBLIB_CF_REGFN INVALID_FUNCTION_NAME Invalid Function name.
DBLIB_CF_REGFN INVALID_CALLBACK Callback is not a function or is not defined.

Below exceptions are raised on response object inside the registered function.

Source Code Description
DBLIB_CF_CALL NETWORK_DISCONNECTED Connection to dataBridges network is not active.
DBLIB_CF_CALL RESPONSE_OBJECT_CLOSED Return response object is closed. Thus the function is unable to respond back to the call.

resetqueue()

dbridgeObject resetqueue() . The dataBridges network maintains in-process CF function execution status. resetqueue() informs the dataBridges network that all in-process CF function execution will be dropped by the application and response to be invalidated. Resetqueue() use case is intended to be used by application in its self health status management. Sometime due to the application process flow, the application can identify situation where it would like to ease its load by resettiing the CF function execution queue by sending resetqueue() message to dataBridges network and than closing all in-process CF function execution.

try {
    dbridge.cf.resetqueue();
} catch(err) {
    console.log(err.source, err.code, err.message);
}
try {
    dbridge.cf.resetqueue();
} catch(err) {
    console.log(err.source, err.code, err.message);
}
try:
    await dbridge.cf.resetqueue();
except dBError as e:
    print(e.code, e.source, e.message)
try {
    dbridge.cf.resetqueue();
} catch (dBError err) {
    Console.WriteLine("{0} ,  {1} , {2}" , err.source, err.code, err.message);
}
try {
    dbridge.cf.resetqueue();
}catch(dBError dberror){
  Log.d("Main", "exception :" +  dberror.code + "::" + dberror.source);
}
do {
    dbridge.cf.resetqueue();
} catch {
    let db = error as?  dBError
    print(db?.ToString() ?? "unknown")
}
Exceptions:
Source Code Description
DBLIB_CF_CALL NETWORK_DISCONNECTED Connection to dataBridges network is not active.

System events for cf object

There are a number of events which are triggered internally by the library, but can also be of use elsewhere. Below are the list of all events triggered by the library.

Below syntax is same for all system events.

//  Binding to systemeven on dbridgeObject  
try {
    dbridge.cf.bind('eventName', (payload, metadata) => {
        console.log( payload, metadata);
    });
} catch(err) {
     console.log(err.source, err.code, err.message);
}
//  Binding to systemeven on dbridgeObject  
try {
    dbridge.cf.bind('eventName', (payload, metadata) => {
        console.log( payload, metadata);
    });
} catch(err) {
     console.log(err.source, err.code, err.message);
}
#  Binding to systemevent on dbridgeObject 
def eventFunction(payload,metadata):
   print(payload,metadata)

try:
    dbridge.cf.bind('eventName', eventFunction)
except dBError as e:
    print(e.code, e.source, e.message)
// Binding to systemevent on dbridgeObject 
try {
    Action<object , object> ifunction;
    dbridge.cf.bind('eventName', ifunction = (object payload, object response) =>{
        Console.WriteLine("{0} , {1} " , payload, response);
    });
} catch (dBError err) {
    Console.WriteLine("{0} ,  {1} , {2}" , err.source, err.code, err.message);
}   
//  Binding to systemevent on dbridgeObject   
dbridge.cf.bind("eventName" , new eventHandler() {
    @Override
    public void onEvent(Object message, metaData metadata) {
      Log.i("event: ", message);
      Log.i("event: ", metadata);
    }
});
//  Binding to systemevents on dbridgeObject 
do {
    dbridge.cf.bind('eventName', {  (message: Any, metadata: Any) in
        print("event :" , message)
        print("event :" , metadata)
    })
} catch {
    let db = error as?  dBError
    print(db?.ToString() ?? "unknown")
}

cf.response.tracker

Callback parameters
Return Values Description
payload (string) Tracker identifier. which is same as response.id
metadata (string) Refer below table.
Error Identifier Description
RE_12616 cf caller is disconnected from dataBridges network and hence cannot process response tracking.
RE_13151 cf caller is disconnected from dataBridges network and hence cannot process response tracking.
RE_30030 The cf client is disconnected from dataBridges network
RE_33635 The cf client is disconnected from dataBridges network

cf.callee.queue.exceeded

Callback parameters
payload: (dberror object)
{
    "source": "DBNET_CF_CALL" ,                 // (string) Error source
    "code": "ERR_CALLEE_QUEUE_EXCEEDED",        // (string) Error code  
    "message": ""                               // (string) Error message if applicable.
}
metadata:

null

dberror:

Source Code Description
DBNET_CF_CALL ERR_CALLEE_QUEUE_EXCEEDED No new cf calls are being routed by the dataBridges network to the application because the application's current cf processing queue has already exceeded.
Each application connection cannot exceed cf.queue.maximum. Refer to management console documentation for cf.queue.maximum details.