Skip to content
simen edited this page Mar 27, 2017 · 22 revisions

1. Overview

This module is a transportation with WebSocket protocol, which is used by the RPC interface of freebird framework. It provides methods to create RPC client and RPC server for real-time remote communications. The RPC server should be registered to freebird framework to be able to transmit freebird messages to RPC client (e.g., the web browser). And the RPC client is provided for webapp to be able to communicate with freebird.

Subsystems

The freebird framework has net, dev, and gad subsystems responsible for network, device, and gadget management, respectively. In brief, a network is formed with many devices, and each device may have some gadgets on it. A gadget is the real application in a manchine network.

Example

Let's take a wifi weather station in a machine network for example. The weather station is made up of temperature, humidity, and pm2.5 sensors, where each sensor is a gadget living on the WiFi-connected device. A device, such as Arduino(wifi-connected), ESP8266, MT7688, RaspberryPi or Beaglebone, is the carrier of applications(gadgets). Now we know, this weather station has 3 gadgets on it, but only has a single device in it.

Here is another example, we have a bluetooth low-energy (BLE) light switch in the network. This is a simple one-device-with-one-gadget machine, here we can say "There is only one gadget - a light switch - implemented on a TI CC2540 BLE SoC device."

Why subsystems?

The concept of net, dev, and gad subsystems in freebird framework well separates the machine management and application management from each other. This brings developers a more clear, convenient and flexible way in building up a IoT machine network.


2. Installation

$ npm install freebird-rpc --save


3. Usage

freebird-rpc exports its functionalities as an object that has two methods createServer() and createClient() on it.

  • Create a RPC server
var fbRpc = require('freebird-rpc'),
    http = require('http');

var httpServer = http.createServer();
httpServer.listen(3000);

var rpcServer = fbRpc.createServer(httpServer);
  • Create a RPC client
var fbRpc = require('freebird-rpc');

var rpcClient = fbRpc.createClient('ws://192.168.1.108:3000');

4. APIs and Events

.createServer(httpServer)

Create the websocket RPC server on top of a http server.

Arguments:

  1. httpServer (Object): A Node.js HTTP server.

Returns:

  • (Object): rpcServer

Example:

var http = require('http'),
    fbRpc = require('freebird-rpc');

var httpServer,
    rpcServer;

httpServer = http.createServer().listen(3000);
rpcServer = fbRpc.createServer(httpServer);




.createClient(addr[, options])

Create the websocket RPC client.

Arguments:

  1. addr (String): host address and port.
  2. options (Object): An optional object to set up the websocket client. Please refer to websocket official ws.md for more details about this options.

Returns:

  • (Object): rpcClient

Example:

var rpcClient = fbRpc.createClient('ws://192.168.1.108:3000');



Server Class

fbRpc.createServer() returns an instance of this class. The instance, which is denoted as rpcServer in this document, is essentially a WebSocket server for real-time bidirectional communications with WebSocket clients.


.send(msg, callback)

Send response message to the client with results of the client asking for.

Arguments:

  1. msg (Object): msg must at least have clientId and data fields, where clientId is used to identify the client you want to send the message to, and data is the message to transmit out. data must be an object shaped with Response Data Object definition, and it must be serialized to a JSON string when transmitting.
  2. callback (Function): function (err, bytes) { ... }. Get called after message send off. The argument bytes tells how many bytes were sent.

Returns:

  • (None)

Example:

var sendData = {
    __intf: 'RSP',
    subsys: 'net',
    seq: 5,
    id: null,
    cmd: 'getAllDevIds',
    status: 0,
    data: { ids: [ 1, 2, 3, 8, 12 ] }
};

sendData = JSON.stringify(sendData);

rpcServer.send({ clientId: 'client01', data: sendData }, function (err, bytes) {
    if (err)
        console.log(err);
    else
        console.log(bytes + ' bytes were sent');
});



.broadcast(msg, callback)

Broadcast the indication message to all clients.

Arguments:

  1. msg (Object): msg must has the data field. data is the message to transmit out which must be shaped with Indication Data Object definition, and it must be serialized to a JSON string when transmitting.
  2. callback (Function): function (err, bytes) { ... }. Get called after message send off. The argument bytes tells how many bytes were sent.

Returns:

  • (None)

Example:

var broadcastData = {
    __intf: 'IND',
    subsys: 'net',
    type: 'started',
    id: null,
    data: { netcore: 'freebird-netcore-ble' }
};

broadcastData = JSON.stringify(broadcastData);

rpcServer.broadcast({ data: broadcastData }, function (err, bytes) {
    if (err)
        console.log(err);
    else
        console.log(bytes + ' bytes were sent');
});




.on('message', function (msg) {})

The 'message' event is triggered when the server receives a request from the client.

Arguments of the listener

  1. msg (Object): msg contains clientId and data properties. clientId is to help the user determine which client sends the message, and data is the received message which will follow Request Data Object and be converted to a JSON string.

Example:

rpcServer.on('message', function (msg) {
    console.log(msg.data.toString());
});



Client Class

fbRpc.createClient() returns an instance of this class. The instance, which is denoted as rpcClient in this document, is essentially a WebSocket client for real-time bidirectional communications with WebSocket servers.


.send(subsys, cmd, args, callback)

Send the request message to the server for requesting something or asking the server to perform an operation.

Arguments:

  1. subSys (String): Only 3 types are accepted. They are 'net', 'dev', and 'gad' to denote which subsystem is this message referring to.
  2. cmd (String): Command identifier, which is simply the API name. It can be found in the Command Name field of the Request Data Model.
  3. args (Object): A value-object with command arguments. Please see section Request Data Model to learn more about the args.
  4. callback (Function): function (err, result) {}. Get called when the server respond to this client with results of the client asking for.
    • 'err' (Error): Error object.
    • 'result' (Object): result is an object of { status, data }, where status is a code defined by RSP Status Code and data is a response object shaped with the Response Data Model definition.

Returns:

  • (None)

Example:

rpcClient.send('net', 'getAllDevIds', { ncName: 'freebird-netcore-ble' }, function (err, result) {
    if (err) {
        console.log(err);
    } else {
        console.log(result);

        // result equal to 
        // {
        //     status: 0,
        //     data: {
        //         ids: [1, 5, 8, 15, 27]
        //     }
        // }
    }    
});




.on('open', function () {})

Fires when the connection is open and ready for communication.

Arguments of the listener

  • (None)

Example:

rpcClient.on('open', function () {
    // You can now communicate with the RPC server
});




.on('close', function (code, reason) {})

Fires when the connection is closed.

Arguments of the listener

  1. code (Number): code is a numeric value to indicate the status code explaining why the connection has been closed.
  2. reason (String): reason is a human-readable string explaining why the connection has been closed.

Example:

rpcClient.on('close', function (code, reason) {
    console.log('Connection is closed because the reason: ' + reason);
});




.on('ind', function (msg) {})

Fires when an indication received from the server.

Arguments of the listener

  1. msg (Object): A message object with fields 'subsys', 'type', 'id' and 'data'
    • subsys (String): Can be 'net', 'dev', or 'gad' to denote which subsystem is this indication coming from.
    • type (String): Indication types. Please see section Indication types for details.
    • id (Number): Id of the sender.
      • id is meaningless if subsys === 'net'.
      • id refers to device id if subsys === 'dev'.
      • id refers to gadget id if subsys === 'gad'
    • data (Object): Data along with the indication. Please see section Indication Data Model to learn more about the indication data format.

Example:

rpcClient.on('ind', function (msg) {
    console.log(msg);
});




REQ/RSP/IND Interfaces

In freebird, the web-Client and Server are communicating with each other through websocket along with a JSON message. The __intf field in the message can be 'REQ', 'RSP' or 'IND' to denote the interface.



Request Message

  • Direction: Client sends to Server to request something or to ask the server to perform an operation.

  • Interface: __intf = 'REQ'

  • Message keys: { __intf, subsys, seq, id, cmd, args }

    Property Type Description
    __intf String 'REQ'
    subsys String Only 3 types accepted. They are 'net', 'dev', and 'gad' to denote which subsystem is this message going to
    seq Number Sequence number of this REQ/RSP transaction
    id Number Id of the sender. id is meaningless if subsys === 'net'. id is device id if subsys === 'dev'. id is gadget id if subsys === 'gad'. It is noticed that id = 0 is reserved for the freebird web-Client and Server
    cmd String Command Identifier corresponding to the API name
    args Object A value-object that contains command arguments. Please see section Request Data Model to learn more about the args data object
  • Message Example:

    { 
        __intf: 'REQ',
        subsys: 'net',
        seq: 3,
        id: 0,
        cmd: 'getDevs',
        args: {
            ids: [ 2, 4, 18, 61 ]
        }
    }



Response Interface

  • Direction: Server responds to Client with the results of the client asking for.

  • Interface: __intf = 'RSP'

  • Message keys: { __intf, subsys, seq, id, cmd, status, data }

    Property Type Description
    __intf String 'RSP'
    subsys String Only 3 types accepted. They are 'net', 'dev', and 'gad' to denote which subsystem is this message coming from
    seq Number Sequence number of this REQ/RSP transaction
    id Number Id of the sender. id is meaningless if subsys === 'net'. id is device id if subsys === 'dev'. id is gadget id if subsys === 'gad'. It is noticed that id = 0 is reserved for the freebird web-Client and Server
    cmd String Command Identifier corresponding to the API name
    status Number Status code of the response
    data Depends Data along with the response. To learn more about the data format corresponding to each command, please see section Response Data Model.
  • Message Example:

    { 
        __intf: 'RSP',
        subsys: 'net',
        seq: 17,
        id: 0,
        cmd: 'getAllDevIds',
        status: 0,
        data: {
            ids: [ 2, 4, 18, 61 ]
        }
    }



Indication Interface

  • Direction: Server indicates Client

  • Interface: __intf = 'IND'

  • Message keys: { __intf, subsys, type, id, data }

    Property Type Description
    __intf String 'IND'
    subsys String Only 3 types accepted. They are 'net', 'dev', and 'gad' to denote which subsystem is this indication coming from
    type String There are few types of indication accepted, such as 'attrsChanged'. Please see section Indication types for details
    id Number Id of the sender. id is meaningless if subsys === 'net'. id is device id if subsys === 'dev'. id is gadget id if subsys === 'gad'
    data Depends Data along with the indication. Please see section Indication Data Model to learn more about the indication data format

  • Indication types:

    subsys Indication Type Description
    net 'error' Netcore error occurs
    net 'started' A netcore is started
    net 'stopped' A netcore is stopped
    net 'enabled' A netcore is enabled
    net 'disabled' A netcore is disabled
    net 'permitJoining' A netcore is now allowing devices to join the network
    net 'bannedDevIncoming' A banned device is trying to join the network
    net 'bannedGadIncoming' A banned gadget is trying to join the network
    net 'bannedDevReporting' A banned device is trying to report its attributes
    net 'bannedGadReporting' A banned gadget is trying to report its attributes
    dev 'error' Device error occurs
    dev 'devIncoming' A new device is incoming
    dev 'devLeaving' A device is leaving
    dev 'netChanged' Network information of a device has changed
    dev 'statusChanged' Status of a device has changed. The status can be 'online', 'sleep', 'offline', and 'unknown'
    dev 'propsChanged' Meta-property(ies) of a device has changed
    dev 'attrsChanged' Attribue(s) on a device has changed
    gad 'error' Gadget error occurs
    gad 'gadIncoming' A new gadget is incoming
    gad 'gadLeaving' A gadget is leaving
    gad 'panelChanged' Panel information of a gadget has changed
    gad 'propsChanged' Meta-property(ies) of a gadget has changed
    gad 'attrsChanged' Attribue(s) on a gadget has changed
    gad 'attrsReport' A report message of certain attribute(s) on a gadget
  • Message Example:

    { 
        __intf: 'IND',
        subsys: 'gad',
        type: 'attrsChanged',
        id: 147,            // sender of this indication is a gadget with id = 147
        data: {
            sensorValue: 24
        }
    }
Clone this wiki locally