diff --git a/config.js.example b/config.js.example index af0fbac..6258a6d 100644 --- a/config.js.example +++ b/config.js.example @@ -1,12 +1,27 @@ var config = { - keyboard: 'azerty', plugins: [ "video-png" // Display the video feed as static pngs (work in every browser) //, "video-stream" // Display the video as a native h264 stream decoded in JS , "hud" // Display the artificial horizon, altimeter, compass, etc. , "battery" // Display a simple battery widget in the header bar , "pilot" // Pilot the drone with the keyboard - ] + , "blackbox" // Experimental: Records all mision data (navData, raw video, PaVE headers, etc.) + //, "replay" // Experimental: Replay the data recorded by the blackbox + ], + + // Config for pilot plugin + keyboard: 'azerty', + + // Config for blackbox plugin. Path is an existing folder where to store mission data + // Each new mission will have its own timestamped folder. + blackbox: { + path: "/tmp" + }, + + // Config for replay plugin. Path points to a specific mission folder to be replayed. + replay: { + path: "/tmp/2013-06-03_09-10-33/" + } }; module.exports = config; diff --git a/package.json b/package.json index 09e4669..eb963b0 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,9 @@ "ejs": "~0.8.3", "socket.io": "~0.9.4", "dronestream": "git+ssh://git@github.com:eschnou/node-dronestream.git#master", - "dateformat": "~1.0.6-1.2.3" + "dateformat": "~1.0.6-1.2.3", + "line-reader": "~0.2.3", + "buffered-reader": "~1.0.1" }, "author": "Laurent Eschenauer ", "contributors": [ diff --git a/plugins/replay/index.js b/plugins/replay/index.js new file mode 100644 index 0000000..0834faf --- /dev/null +++ b/plugins/replay/index.js @@ -0,0 +1,64 @@ +var fs = require('fs'); +var df = require('dateformat'); +var util = require('util'); +var path = require('path'); +var timers = require('timers'); +var lineReader = require('line-reader'); +var reader = require ("buffered-reader"); +var config, client,video, navReader, vidReader, rawVideo; + +var BinaryReader = reader.BinaryReader; + +var NAV_INTERVAL = 1000/15; // Navdata sent 15/s in demo mode +var VIDEO_INTERVAL = 1000/30; // 30 fps + +function replay(name, deps) { + config = deps.config; + client = deps.client; + video = client.getVideoStream(); + + // Open the navdata file for line-by-line read + var self = this; + var navPath = path.join(config.replay.path, 'navdata.txt'); + lineReader.open(navPath, function(reader) { + navReader = reader; + }); + + // Open the video headers stream + var headerPath = path.join(config.replay.path, 'paveHeaders.txt'); + lineReader.open(headerPath, function(reader) { + vidReader = reader; + }); + + // Open the video raw stream + var videoPath = path.join(config.replay.path, 'video.h264'); + rawVideo = new BinaryReader(videoPath); + + // Schedule timer to simulate nav data emit + timers.setInterval(emitNav, NAV_INTERVAL); + timers.setInterval(emitVideo, VIDEO_INTERVAL); +} + +function emitNav() { + if (navReader && navReader.hasNextLine()) { + navReader.nextLine(function(data) { + client.emit('navdata', JSON.parse(data)); + }); + } +} + +function emitVideo() { + if (vidReader && vidReader.hasNextLine()) { + vidReader.nextLine(function(data) { + var frame = JSON.parse(data); + if (rawVideo !== null) { + rawVideo.read(frame.payload_size, function (error, bytes, bytesRead) { + if (error) throw error; + video.emit('data', bytes); + }); + } + }); + } +} + +module.exports = replay;