/yarp.js

JavaScript bindings for YARP!

Primary LanguageJavaScriptGNU Lesser General Public License v3.0LGPL-3.0

yarp.js

DOI

A JavaScript set of bindings for YARP.

Introduction

This library has been developed with the idea of bringing YARP to any device without heavy code dependencies (It just needs an Internet Browser!). The idea is to have a server in charge of directly interacting with the YARP C++ layer (and the rest of the YARP network) while clients are completely implementation and hardware independent. Indeed, code is shipped by the server to all clients via websockets (in particular the Socket.io Node module), without the need to install anything on the client machine (a part the Browser of course).

The library is based on node.js which can be natively integrated with external C++ code via Node addons.

Tested OS: yarp.js has been tested on OSX and Ubuntu. This goes for the server side. The client side goes on any machine with a version of Google Chrome or Firefox installed.

Installation

Client dependencies (on any device on your network):

Server dependencies:

Note:

  • Please make sure that your Node version is = 20.13.1. This repository hasn't been tested with newer Node versions. It is easier to handle Node.js versions through the Node version manager (NVM). Refer to Reinstall npm with a node version manager for further details.
  • Linux. If you installed Node.js from the package manager, it could happen that the command node is not in your path, but rather nodejs is. To this end, run $> sudo ln -s /usr/bin/nodejs /usr/bin/node.

Once you have all dependencies installed, go to the folder where you have cloned this repository and run:

$> sudo npm install

The npm install script defined in ./package.json runs ./node_modules/cmake-js/bin/cmake-js on its own.

Optional: although the command sudo npm install installs the node dependencies locally, it needs administrative permissions. If you want to avoid this (and just use npm install), follow the official npm guide. This is not required to use yarp.js though.

Examples

We have prepared a series of tutorials and examples on how to use yarp.js. To get things started, go here to find the instruction to write and run a minimalistic node server that uses yarp.js. A website will be locally served on your network, showcasing the following demo applications:

Server

In this section we descirbe how to use yarp.js on the server side.

Port Communication

Ports are a key component to YARP. In this section we are going to see how yarp.js allows us to use YARP ports from JavaScript (in a Node environment).

Throughout we will assume that a yarp server is running on our network (if it's not your case, just run $> yarp server in a shell). You can find the example described in this section in the script examples/port_basics.js.

From the folder where you have cloned this repository run $> node to enter in the interactive Node.js interface. Then run:

var yarp = require('./yarp');

The first command loads the yarp.js module that will allow us to use YARP from JS. The second command is necessary to register the current session on the YARP network. We can finally create and open a port:

var port = new yarp.Port('bottle');
port.open('/yarpjs/example');

You should receive a message from YARP saying something like: yarp: Port /yarpjs/example active at tcp://some.ip:address At the time being yarp.js can open buffered ports for YARP bottles and images.

Writing on a Port

Let's write something from our port!

var bottle = new yarp.Bottle();
bottle.fromString('This is a Bottle');

port.write(bottle);

So, if someone is listening to our port (e.g. run in a different shell $> yarp read ... /yarpjs/example), she will receive a YARP Bottle containing the string 'This is a Bottle'. Note: you can create more complex YARP Bottles with the standard YARP sintax (e.g. bottle.fromString('(This is) (a Bottle)') creates a bottle with two bottles inside, containing respectively the strings 'This is' and 'a Bottle'.

Reading from a Port

Let's set up the callback for when a message is sent from another port to /yarpjs/example:

port.onRead(function(msg){
    console.log('Message received: ' + msg.toString());
});

This way, whenever a message arrives, it is printed on screen. You can try it out by going on another bash and type:

$> yarp write ... /yarpjs/example
>> Hello yarp.js!

On the shell where you run yarp.js you should be able to see the message: Message received: Hello "yarp.js!"

Note: The onRead method of a yarp port takes in input a callback. Everytime the port reads something on the network the callback is called with that objects as message msg.

RPC Communication

You can also set the RPC behavior for your port. For instance

port.onRPC(function(msg){
    console.log(msg.toString());

    var bottle = new yarp.Bottle();
    bottle.fromString('Reply (' + msg.toString() + ')');

    port.reply(bottle);
});

You can try this behavior by running in another shell $> yarp rpc /yarpjs/example and then typing a message. You should receive a reply Reply (<your message>).Note: the onRPC callback behave exactly like the onRead. Howevere it assumes that the method reply will be eventuallycalled. As a good practice we suggest to always put the reply command inside the onRPC callback.

Client (Browser)

This section describes how a yarp.js server communicates with the browser. This section is in alpha and it is likely to be subject to changes

Note yarp.js uses the websocket library Socket.io to exchange messages between server and the browser. However, the node.js wrapper and the browser communication are completely decoupled, so you can implement your own communication protocol.

Setup for the Server

To setup the server side create a js file for your server, e.g. server.js. The minimal code to run the server is

// Basic required node plugins to start the http server and socket.io
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

// yarp.js
var yarp = require('../yarp');  // <-- the path to yarp.js in the folder where you cloned this repo.
yarp.browserCommunicator(io);   // <-- The service handling communication with the browser.

// The Express.js routing to your index file (change it to your desired homepage, e.g. index.html)
app.get('/', function(req, res){
  res.sendFile('index.html',{ root : __dirname});
});

/*
    Your code here
*/

// Run the server on locahlhost:3000
http.listen(3000, function(){
  console.log('listening on *:3000');
});

This is enough to have a yarp.js server up and running and ready to communicate with the browser.

Note that we use Express.js since it is used in Socket.io.

Setup for the Browser

To use yarp.js on your browser simply include the following library in your html file (e.g. index.html)

<script src="/socket.io/socket.io.js"></script>
<script src="/yarp.js"></script>

Then, within a script tag

var socket = io();  // for socket io
yarp.init(socket); // to initialize the yarp.js wrapper with socket.io

Note. In order to start working with ports, yarp.js needs to be initialized with socket io. This means that all the code related to yarp.js (e.g. opening/closing ports, writing from ports or set up onRead callbacks must be included in

yarp.onInit(function() {

    // open ports
    // onRead callbacks

}

Port Communication

A browser cannot directly open a yarp port, but has to ask the server to open one. Therefore, in a nutshell, the communication between the YARP network and a browser works as follows: Suppose the server has a port open, let's say /myport. The Browser asks the server (via websockets) to registers to that port. If the port does not exist the server opens one for the browser. From that moment on, any message read from /myport is forwarded (via websockets) to the browser. The same works the other way around for the browsers to send messages on a YARP port.

Opening/Closing Ports

To register the browser to a YARP port

var port = new Port(port_type); // port_type default: 'bottle'
port.open(port_name);

If the port does not exist, the server opens one. Note that port.open returns a bool (true if the port was opened false otherwise). If the browser has already a port opened with that name, it does not open a new one and returns false.

You can close the port with port.close(), however note that since multiple clients could be connected to the same server.

Reading/Writing

Reading from a port is analogous to server side: you can pass a callback function that is invoked whenever a yarp port is read (on the server) to the port we are registered to. For instance

port.onRead(function(message){console.log(message);});

Writing is analogous: port.write(message). For instance if you want to send a vector (automatically transformed to a YARP Bottle over the nework):

port.write([1,2,3]);

Handling Connections

You can also (ask the server to) connect YARP ports with

yarp.Network.connect('/writing/port:o','/reading/port:i');

and disconnect them with yarp.Network.disconnect('/writing/port:o','/reading/port:i');

License

Material included in yarp.js is released under the terms of the LGPLv3.