A telepresence robot - Enhancements

In this article, I'm going to describe architecture enhancements for the
control system of the WebRTC-controlled telepresence robot I built a few
months ago, presented in a previous
article.

The four-wheel base of the telepresence robot

Since I did not manage to have a satisfying
WebRTC support directly in a native Android
app, I previously settled for a
hack
where the smartphone of the Telebot uses two different connections to
the signaling channel: one to receive user control in the Android app,
and one to handle the WebRTC session in the browser.

This was bad for two reasons:

The robot can enter an incoherent state if one connection is closed
and not the other.

User control commands do not benefit from WebRTC, instead they travel
through the server, adding latency and jitter.

The idea for the new architecture is to have the Android app run a small
HTTP server in background that can accept motor control commands and
send them to the Bluetooth device. We will send users commands on an
RTCDataChannel and forward them to this small HTTP server with
JavaScript in the browser.

General schematic of the enhanced architecture

Let's put together a tiny single-threaded HTTP server for our Android
app. For the sake of simplicity, requests and responses content will
be formatted as JSON. I know the implementation is only partial, but
it is totally sufficient and standard-compliant for our limited needs.

We are now able to send requests containing control commands from the
JavaScript code!

[...]// Local control APIvarlocalControlUrl="http://127.0.0.1:11698/control";// Send control to local APIfunctionlocalControl(left,right){varxhr=newXMLHttpRequest();xhr.open("POST",localControlUrl,true);xhr.setRequestHeader('Content-Type','application/json');xhr.send(JSON.stringify({"left":left,"right":right}));}

This assumes that resources on 127.0.0.1 are not considered mixed
content,
even if accessed over HTTP from an HTTPS page. The W3C
specification is strangely not
clear about that, but it seems to me this is the right behaviour, since
you can't get a TLS X.509 certificate for localhost. Chromium allows
access,
anyway.

The last step is to set up the RTCDataChannel. The user side opens
it, and the robot side accepts it: