YARP
Yet Another Robot Platform
YARP ports from your browser

YARP ports process HTTP requests with a default interface suitable for viewing their status, receiving bottle-compatible messages, and writing bottle-compatible streams. This is not a general purpose web-server, or something you'd expose to the general public on the internet. HTTP service comes is implemented by the http carrier; for other carriers, see Configuring YARP Connections.

Index page

To form the URL for a yarp port /PORT, we need to know the IP address of the machine it lives on, and the (socket) port number it listens to. One way to get this information is with yarp name query -

yarp name query /PORT

For example, let's look at the YARP name server's port, by default called /root (or whatever "yarp namespace" reports). For me, that is reported to be here:

registration name /root ip 192.168.1.3 port 10000 type tcp

Then the URL we need to reach this port is:

http://192.168.1.3:10000

Visiting that address in a browser, I see something like this:

yarp port /root
(All ports)   (connections)   (help)   (read)
This is /root at tcp://192.168.1.3:10000
There are no outgoing connections
There is an input connection from web to /root using http

This is the index page for that port, and it reports information analogous to that given by yarp ping. You can view this page for any YARP port.

Sending data

You can send data to a port by appending w?data=... to its base URL. For example:

http://192.168.1.3:10000/w?data=list

For my case, that will send a bottle containing the string "list" to the name server, which will respond with a list of all ports.

Or, if I could send a vector of three floating point numbers 10.0, 30.0, and 40.0 to a port called /adder by finding its address and port number, then visiting:

http://.../w?data=10.0+30.0+40.0

The format of the data parameter is regular Bottle text format (the "+" symbol is URL encoding for the space character).

Receiving (low-bandwidth) data

Viewing data sent by a port is done by visiting:

http://.../r

This will sit and wait for messages and render them as Bottle text format. For example, doing:

yarpdev --device fakeMotor --name /motor

Gives a vector stream at port /motor/state:o. Finding its URL and then visiting "http://.../r" gives:

yarp port /motor/state:o
(All ports)   (connections)   (help)   (read)
Reading data from port...
0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0
...

Buffering behavior varies from browser to browser - YARP does its best to flush data in a timely fashion but you may have to try different browsers or browser settings to get good results.

Viewing images in a browser

Image streams can be viewed in the browser if the mjpeg carrier has been enabled.

For example, doing:

yarpdev --device fakeFrameGrabber --name /grabber --framerate 5

We can now view the /grabber port image output at the following URL:

http://.../?action=stream

and see the image in any browser that understands MJPEG streams (firefox and chrome for sure).

We can also visit:

http://.../r

as before, but that will give images in text format, which is slow and not very helpful...

For the record, the mjpeg carrier currently intercepts any URLs of the form "http://.../?ac". Other URLs are handled by the default http carrier.

Custom content

If you do succumb to the temptation to make a mini-webserver, YARP >= 2.3.15 will help you a little. Requests that don't match the patterns above are passed on to the port in bottle-compatible format; you may simply reply to them to generate a custom webpage. See the example web/web_test.cpp. Be aware that this is a new feature of YARP that is not yet nailed down, so you may need to change your code when using the next version of YARP.

/*
* Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
* All rights reserved.
*
* This software may be modified and distributed under the terms of the
* BSD-3-Clause license. See the accompanying LICENSE file for details.
*/
#include <yarp/os/all.h>
using namespace yarp::os;
class Responder : public PortReader {
public:
std::string getCss() {
return "\n\
body { background: black; color: white; } \n\
h1 { font-size: 300%; color: yellow; } \n\
div { padding-bottom: 10px; } \n\
";
}
virtual bool read(ConnectionReader& in) {
Bottle request, response;
if (!request.read(in)) return false;
printf("Request: %s\n", request.toString().c_str());
if (out==NULL) return true;
response.addString("web");
std::string code = request.get(0).asString();
if (code=="css") {
response.addString(getCss());
response.addString("mime");
response.addString("text/css");
return response.write(*out);
}
std::string prefix = "<html>\n<head>\n<title>YARP web test</title>\n";
prefix += "<link href=\"/css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n";
prefix += "</head>\n<body>\n";
if (code=="push") {
prefix += "<h1>Potato count</h1>\n";
prefix += "<div>(<a href='/test'>back</a>)</div>\n";
response.addString(prefix);
response.addString("stream");
response.addInt32(1);
return response.write(*out);
}
std::string postfix = "</body>\n</html>";
std::string txt = prefix;
txt += std::string("<h1>") + code + "</h1>\n";
txt += "<div>Is this working for you? <a href='/yes'>yes</a> <a href='/no'>no</a></div>\n";
if (!request.check("day")) {
txt += "<div>By the way, what day is it?</div>\n<form><input type='text' id='day' name='day' value='Sunday' /><input type='submit' value='tell me' /></form>\n";
} else {
txt += std::string("<div>So today is ") + request.find("day").asString() + ", is it? Hmm. I don't think I'm going to bother remembering that.</div>\n";
}
txt += "<div><a href='/push'>How many potatoes?</a> (streaming example)</div>\n";
txt += postfix;
response.addString(txt);
return response.write(*out);
}
};
int main(int argc, char *argv[]) {
Property options;
options.fromCommand(argc,argv);
std::string name = options.check("name",Value("/web")).asString();
int port_number = options.check("p",Value(0)).asInt32();
Port server;
Responder responder;
server.setReader(responder);
Contact contact(name);
if (port_number!=0) {
contact.setSocket("", "", port_number);
}
if (!server.open(contact)) return 1;
contact = server.where();
int at = 0;
while (true) {
if (at%10==0) {
printf("Server running, count at %d, visit: http://%s:%d/test\n",
at,
contact.getHost().c_str(),
contact.getPort());
}
Bottle push;
push.addString("web");
std::stringstream ss;
ss << at;
std::string div = std::string("<div>")+ss.str()+
" potatoes</div>";
push.addString(div);
server.write(push);
at++;
}
return 0;
}
yarp::os::Bottle
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:72
yarp::os::Bottle::toString
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:214
yarp::sig::file::read
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
Definition: ImageFile.cpp:656
all.h
main
int main(int argc, char *argv[])
Definition: yarpros.cpp:261
yarp::os::Port::open
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition: Port.cpp:82
yarp::os::Bottle::find
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Bottle.cpp:290
yarp::os::Port
Definition: Port.h:49
yarp::os::Bottle::check
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Bottle.cpp:280
yarp::os::Property::fromCommand
void fromCommand(int argc, char *argv[], bool skipFirst=true, bool wipe=true)
Interprets a list of command arguments as a list of properties.
Definition: Property.cpp:1057
yarp::os::PortReader
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
Definition: PortReader.h:27
yarp::os::Bottle::get
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
yarp::os::Bottle::write
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition: Bottle.cpp:233
yarp::os::ConnectionWriter
An interface for writing to a network connection.
Definition: ConnectionWriter.h:39
yarp::os::Value::asString
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
yarp::os::Bottle::addInt32
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:143
yarp::os::Property::check
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Property.cpp:1024
yarp::os::ConnectionReader::getWriter
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
yarp::os::Bottle::addString
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:173
yarp::os::Port::setReader
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition: Port.cpp:505
yarp::os::ConnectionReader
An interface for reading from a network connection.
Definition: ConnectionReader.h:39
yarp::os::Port::write
bool write(const PortWriter &writer, const PortWriter *callback=nullptr) const override
Write an object to the port.
Definition: Port.cpp:430
yarp::os
Definition: AbstractCarrier.h:17
yarp::os::Network
Definition: Network.h:785
yarp
Definition: environment.h:18
yarp::os::Port::where
Contact where() const override
Returns information about how this port can be reached.
Definition: Port.cpp:399
yarp::os::Bottle::read
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:243
yarp::os::Contact
Represents how to reach a part of a YARP network.
Definition: Contact.h:38
yarp::os::Value
A single value (typically within a Bottle).
Definition: Value.h:46
yarp::os::Time::delay
void delay(double seconds)
Wait for a certain number of seconds.
Definition: Time.cpp:114
yarp::os::Property
A class for storing options and configuration information.
Definition: Property.h:34