Introducing FrameRain

I have been working on different projects since the beginning of the year. Today, I want to introduce FrameRain: a way to manage favourite videos from Youtube. The idea came out, after thinking that it would be great to have a place to store videos you prefer without the need of an account. Today, I’m happy to « open source » this project, as decided at the beginning. It is licensed under MIT.

I’ve built FrameRain using Node.js and Express for the server. Data persistence uses MongoDB. These are the only requirements to run FrameRain. Configuration can be found in the file config.json, but there are only a few things in it for now. FrameRain stores the miniature of each video, so that it does not rely on Youtube to display it.

It is possible to add some video to a playlist to watch them one after another. FrameRain uses youtube embedded player to prevent the need to go on youtube.com. Unfortunately, it doesn’t prevent youtube from tracking you. Moreover, I’m not satisfied with the way I implemented the player. It is working, but it will be hard to add another platform like vimeo or dailymotion using this implementation.

I should also consider password encryption. Among other things, an initial idea was to be able to manage playlist of videos, like for example, a music playlist, trailer playlist, funny playlist, … I’m planning to add it later.

This was a really fun project. I learned a lot about how to use Mongo and Mongoose. I will now work back on my other project which aimed at playing flac files in the browser. So, if you have any comments about FrameRain, don’t hesitate to contact me.

ArduiTemp: Temperature, Arduino, LOLShield

ArduiTempYesterday, an idea just jumped in my mind. I was thinking about using my arduino and my LOLShield to display the local temperature. I tried to figure out how to achieve this the whole day. So I imagined a simple program. First, it will need to find the weather of a given city by requesting an url. Then, parse the information to extract temperature and finally, generate the code to turn on the right leds. The hackaton could begin.

I started digging the problem of compiling my code without any IDE, I found some Makefile but didn’t manage to make them work correctly. There was always something wrong. Finally, I discovered Ino, installed it et tested it with a sample code for the LOLShield. It compiled, uploaded the code: it worked well. I then search for a correct weather API with up to date data. I tested some and found wundergroud API, which corresponded to my need.

I then wrote the program I imagined during the day. I hadn’t encounter any specific problem during this step. I used NodeJs and request to perform retrieve data from the API and generate the code to compile for the arduino.

You can find this quick project on my github account under the name ArduiTemp. It was rewarding managing to produce a working solution in a small amount of time. Even though, I did not manage to use a simple Makefile, it would be interesting to write a correct Makefile from scratch. I think Ino source code could be helpful to achieve this.

Ghost: Un « nouvel » outil de publication

Je suis tombé par hasard il y a plusieurs semaines sur une campagne Kickstarter visant à financer le développement d’une nouvelle plateforme de blog nommée Ghost. Le design mit en avant est alléchant. Ghost prévoit en effet de présenter le contenu de manière simple et claire.

Côté fonctionnalités, la possibilité d’écrire ses articles en utilisant le langage de mise en forme Markdown a retenu mon attention. Langage déjà présent par exemple sur Github, pour la mise en forme des Pull Request notamment. Le dashboard semble également prometteur car il devrait permettre de visualiser, entre autre, des informations concernant le trafic du site. En effet, cette fonction de statistique me manque un peu sur WordPress (bien qu’il soit possible de l’ajouter par ailleurs, aucune des solutions que j’ai pu envisager ne m’a pour l’instant convaincu) et je me contente pour le moment des logs apache si besoin. Autre point intéressant, la compatibilité annoncée avec tous les types de supports: ordinateurs, smartphones et tablettes.

Côté techno, le tout repose sur NodeJs et Express, que j’affectionne tout particulièrement. Un package NPM est également prévu, annonçant un déploiement aisé. Enfin, Ghost sera publié sous licence MIT.

Ce projet a été financé à 785% au terme d’une campagne Kickstarter fin mai 2013. Le développement est maintenant en cours, avec une première publication des sources sur Github prévue pour la rentrée (Septembre 2013). Peu d’informations sur l’avancement des choses pour l’instant, mais gageons que nous aurons plus d’informations d’ici la fin du mois.

J’attends donc avec impatience de pouvoir tester la bête et pourquoi pas, contribuer lorsque le code sera rendu public. Les grandes inconnues restent pour moi la gestion des images et des galeries, ainsi que la possibilité d’avoir des pages statiques. Fonctionnalités que j’apprécie sur WordPress. Alors Ghost: évolution, révolution ou simple outil parmi d’autre? A suivre donc…

Map projection: Convert Lambert II into Longitude/Latitude

Last week, I faced an interesting problem. I was given a file containing the geographical position of various antennas around Disneyland Paris. The idea was to display them on a map: Open Street Map or Google Maps or whatever. Fine. In order to place the antenna on the map, I must use their coordinates in terms of latitude and longitude. But all coordinates are expressed in Lambert II. So I had to convert Lambert II into Longitude/Latitude.

I searched for formula, read articles and finally found the library Proj4Js which aim is to transform point coordinates from one coordinate system to another. I searched a little more and found node-proj4js a NodeJs port of Proj4Js. What’s next?

I found out that Lambert II conversion is not available by default. You had to add its specification in the Proj4Js format, which is pretty easy when you discover how to do it. First, you need to know the EPSG reference number of the coordinate system. Lambert II EPSG number is 27572. With this number, go to the website http://spatialreference.org/ref/ and search for your coordinate system using its reference number or its name. For example, the link for Lambert II is http://spatialreference.org/ref/epsg/27572/.

Once you find it, there is a link for the specification in the Proj4Js format: http://spatialreference.org/ref/epsg/27572/proj4js/. Now, just copy and paste the code in proj4js/lib/defs under the name EPSG27572 for Lambert II. I’m now able to convert Lambert II to Longitude/Latitude system. Let’s see how to do it!

I’m adding Proj4Js and initializing source and destination coordinate system:

var Proj4js = require("proj4js");
var source = new Proj4js.Proj('EPSG:27572'); //Lambert II
var destination = new Proj4js.Proj('EPSG:4326'); //Longitude/Latitude

Next, we need to create the source point to be used by Proj4Js:

var xLambertII = 589987;
var yLambertII = 2424591;
var point = new Proj4js.Point([xLambertII, yLambertII]);

Finally, convert from Lambert II to Longitude/Latitude et print new coordinates:

var latLon = Proj4js.transform(source, destination, point);
console.log('X: ' + latLon.x + ' Y: ' + latLon.y);

Let’s finish this article with a picture about map projections from the well-known xkcd website.

Request: noproxy configuration

Like with npm and for the same reasons, it would be a great idea to have a noproxy configuration in request.
So here is the pull request!

if(self.noproxy) {
  if(typeof self.noproxy == 'string') {
    if(self.noproxy.search(self.uri.hostname) !== -1) {
      delete self.proxy
    }
  }
}

Really simple. If the hostname is in the noproxy string, we delete the proxy parameter so that it won’t be used.

And the test which validate the modification:

/*
** Test noproxy configuration.
**
** We create a server and a proxy.
** Server listens on localhost:80.
** Proxy listens on localhost:8080.
** The proxy redirects all requests to /proxy on the server.
** On the server, /proxy sends "proxy" .
** When server is directly requested, it answers with "noproxy" .
**
**
** So we perform 2 tests, both with proxy equal to "http://localhost:8080".
** -A test is performed with noproxy equal to "null". In this case,
** the server responds with "proxy" because the proxy is used.
** -In the other test, noproxy equal "localhost, example.com".
** Since localhost is part of noproxy, request is made directly
** to the server and proxy is ignored.
*/

var assert = require("assert")
  , http = require('http')
  , request = require('../main.js')
  //We create a server and a proxy.
  , server = http.createServer(function(req, res){
      res.statusCode = 200
      if(req.url == '/proxy') {
        res.end('proxy')
      } else {
        res.end('noproxy')
      }
    })
  , proxy = http.createServer(function (req, res) {
      res.statusCode = 200
      var url = 'http://localhost:80/proxy'
      var x = request(url)
      req.pipe(x)
      x.pipe(res)
    })
    ;

//Launch server and proxy
var initialize = function (cb) {
  server.listen(80, 'localhost', function () {
    proxy.listen(8080, 'localhost', cb)
  })
}

//Tests
initialize(function () {
  //Checking the route for server and proxy
  request.get("http://localhost:80/test", function (err, res, body) {
    assert.equal(res.statusCode, 200)
    request.get("http://localhost:80/proxy", function (err, res2, body) {
      assert.equal(res2.statusCode, 200)
      request.get("http://localhost:8080/test", function (err, res3, body) {
        assert.equal(res3.statusCode, 200)
        makeNoProxyTest(function () {
          makeProxyTest(function () {
            closeServer(server)
            closeServer(proxy)
          })
        })
      })
    })
  })
})

//Request with noproxy
var makeNoProxyTest = function (cb) {
  request ({
    url: 'http://localhost:80/test',
    proxy: 'http://localhost:8080',
    noproxy: 'localhost, example.com'
  }, function (err, res, body) {
    assert.equal(body, 'noproxy')
    cb()
  })
}

//Request with proxy
var makeProxyTest = function (cb) {
  request ({
    url: 'http://localhost:80/test',
    proxy: 'http://localhost:8080',
    noproxy: 'null'
  }, function (err, res, body) {
    assert.equal(body, 'proxy')
    cb()
  })
}

var closeServer = function (s) {
  s.close()
}