I have been writing mostly C and C++ in the last months, hacking away on LoRa and drones, but I had the pleasure of doing a week of JavaScript again, and I was reminded how much I love this weird, quirk and beautiful language. So today a write-up of some very useful patterns that show the power of JS.

Continue reading »

Flying a drone in your browser with WebBluetooth

There are tons of devices around us, and the number is only growing. And more and more of these devices come with connectivity. This brings new challenges: how can we discover devices around us, and how can we interact with them?

Ah! An empty meeting room. The moment you sit down however you’re being kicked out by someone who apparently ‘reserved’ the damn thing, and you’ll have to start your quest for some quiet working space all over again. Annoying. So when you’re finally used to first checking the calendar for the room, you’ll start to notice that there are people reserving rooms that they are not using at all!

As we see smart suitcases, connected plants, and egg management devices appear I was wondering why our meeting rooms are still so dumb. When companies are building ‘smart’ meeting rooms, they usually don’t get further than just hanging an iPad next to the entrance. It’s time to create a proper smart meeting room.

Continue reading »

Google selects appear.in to make WebRTC tutorial

Together with Google, we made a tutorial based on the challenges we have faced, to make it easy for other developers to get started with using WebRTC.

Neither Chrome nor Firefox quite conforms to the spec for WebRTC statistics, nor is the spec done evolving. I’ll try to document some of their peculiarities here and to update this post when changes arise.

###API

The spec says RTCPeerConnection.getStats takes a nullable MediaStreamTrack, a success callback, and a failure callback, in that order. The success callback is passed an RTCStatsReport which has a getter for accessing its various RTCStats by ID.

Chrome reverses the order of the first two parameters, and its success callback is passed a RTCStatsResponse whose result method returns a list of RTCStatReport objects. Chrome’s RTCStatsReport does not correspond to the spec’s type of the same name, but to its RTCStats; it is just a dictionary.

Firefox matches the spec; but the callbacks are optional, and if both callbacks are omitted then a Promise is returned. Presumably the spec will eventually prefer Promises as it already does for other methods.

The two APIs can be unified with the following code:

function getStats(pc, selector) {
	if (navigator.mozGetUserMedia) {
		return pc.getStats(selector);
	}
	return new Promise(function(resolve, reject) {
		pc.getStats(function(response) {
			var standardReport = {};
			response.result().forEach(function(report) {
				var standardStats = {
					id: report.id,
					type: report.type
				};
				report.names().forEach(function(name) {
					standardStats[name] = report.stat(name);
				});
				standardReport[standardStats.id] = standardStats;
			});
			resolve(standardReport);
		}, selector, reject);
	});
}

###Stats

Each RTCStats (or RTCStatsReport in Chrome) object is a dictionary with three default attributes: timestamp, type, and id; and various other attributes: some required, depending on type, and others that are implementation specific.

Firefox does not include timestamp.

The spec defines various stats report types. Instead of outboundrtp and inboundrtp, Chrome uses ssrc. The exact type can be inferred from the presence of attributes such as bytesSent vs bytesReceived.

The spec decrees that roundtriptime shall be defined on an RTPOutboundRTPStreamStats object. Google calls this googRtt. Firefox calls it mozRtt and puts it on the inbound stats rather than the outbound.