Rénovo X240

J'ai récupéré un ordinateur portable Lenovo ThinkPad X240 pour lui donner une seconde jeunesse1. Au départ, il s'agissait simplement de changer le clavier qui était défectueux depuis qu'il avait été aspergé d'une tasse de café. Et puis la loi de Murphy a frappé une deuxième fois cette machine.

La gamme des ordinateurs ThinkPad est très répandue en entreprise ce qui explique qu'on trouve aisément des pièces de rechange. Après avoir suivi les instructions de cet excellent tutoriel vidéo pour changer le clavier, je démarrais l'ordinateur déjà fier de ma réparation. Aussitôt, j'entendis un léger claquement – Plop – accompagné par l'odeur âcre d'un composant électronique qui venait de brûler. Le message d'erreur suivant s'affichait à l'écran : Fan error. Ça ne sentait pas bon…

Effectivement, le ventilateur ne tournait plus ce qui interrompait la séquence de démarrage. J'essayais alors une astuce trouvée sur Internet : lors du démarrage, je soufflais fortement à travers la sortie d'aération du ventilateur pour le mettre en mouvement et faire croire au BIOS que le ventilateur fonctionnait. L'ordinateur démarrait bien mais le ventilateur demeurait immobile sous Linux ; je décidais sagement d'éteindre la machine pour éviter que son processeur ne surchauffe.

Le lendemain, je démontais le ventilateur pour le tester séparément. Ne disposant pas d'une source de courant continu de 5 volts, j'en bricolais une en coupant un câble USB. En effet, entre le fil rouge et le fil noir, la tension est de 5 volts. Ainsi alimenté, le ventilateur brassait l'air à plein régime.

En observant avec plus d'attention la carte mère, je remarquais une tâche noire à côté du connecteur du ventilateur. Je tenais le coupable : un composant électronique avait bel et bien grillé.

Fusible grillé en amont du ventilateur

À ce stade, je ne connaissais ni la nature ni les caractéristiques du composant qui avait grillé. Heureusement, un collègue trouvait sur ce forum les schémas électroniques du Lenovo X2402. À la page 50 du document, se trouvait la réponse à ma question : le défunt composant était un fusible qui pouvait supporter un courant d'une intensité de 2 ampères. Il a eu très chaud !

Schéma du connecteur du ventilateur

J'ai la chance de travailler dans l'électronique grand public et d'avoir des collègues électroniciens qui savent souder des composants montés en surface. Ils sont très adroits parce que les composants montés en surface sont minuscules (à titre d'exemple le fusible mentionné mesure 1 mm × 0.5 mm). Il n'aura fallu que cinq minutes à l'un de mes collègues pour remplacer le regretté fusible par un fil, faute de disposer d'un remplaçant3. Voici le résultat :

Remplacement du fusible grillé par un fil

Et le patient dans tout ça ? Il se porte bien puisque c'est depuis le Rénovo X240 que j'écris ces lignes.


  1. Merci Guillaume. 

  2. Merci Rémi. 

  3. Merci Jean-Luc. 

Rusticity: convert an integer to an enum

I am learning how to program in Rust. Thinking in Rust is a delightful experience and the more I practice Rust the more I feel how it empowers developers to solve complex problems with confidence.

However, I sometimes get frustrated on my way to rusticity. For instance, when a programming task easily done in C or Python requires more work in Rust. This happened to me not so long ago when I had to convert an integer to an enum. Let's see how this is usually done in C and how this can be done in Rust.

Converting an integer to an enum in C

In C, the enumeration constants have the type int. Thus, an integer value can be directly assigned to an enum.

#include <stdio.h>

enum atomic_number {
    HYDROGEN = 1,
    HELIUM = 2,
    // ...
    IRON = 26,
};

int main(void)
{
    enum atomic_number element = 26;

    if (element == IRON) {
        printf("Beware of Rust!\n");
    }

    return 0;
}

While it is easy to assign an integer value to an enum, the C compiler performs no bounds checking. Nothing prevents us from assigning an impossible value to an atomic_number enum.

Converting an integer to an enum in Rust, the naïve way

Let's write an equivalent program in Rust:

enum AtomicNumber {
    HYDROGEN = 1,
    HELIUM = 2,
    // ...
    IRON = 26,
}

fn main() {
    let element: AtomicNumber = 26;
}

When we try to compile and run the program with cargo run, the Rust compiler reports a mismatched types error:

error[E0308]: mismatched types
 --> src/main.rs:9:34
  |
9 |     let element: AtomicNumber = 26;
  |                                 ^^ expected enum `AtomicNumber`, found integral variable
  |
  = note: expected type `AtomicNumber`
             found type `{integer}`

The compiler error clearly indicates that AtomicNumber and integer are two different types.

To explicitly convert an integer to our AtomicNumber enum, we can write a conversion function that takes an unsigned 32-bits integer as parameter and returns an AtomicNumber.

enum AtomicNumber {
    HYDROGEN = 1,
    HELIUM = 2,
    // ...
    IRON = 26,
}

impl AtomicNumber {
    fn from_u32(value: u32) -> AtomicNumber {
        match value {
            1 => AtomicNumber::HYDROGEN,
            2 => AtomicNumber::HELIUM,
            // ...
            26 => AtomicNumber::IRON,
            _ => panic!("Unknown value: {}", value),
        }
    }
}

fn main() {
    let element = AtomicNumber::from_u32(26);
}

The from_u32() function is an associated function of the AtomicNumber type because it is defined only in the context of this type and unlike a method does not take a first parameter named self.

There are several issues in from_u32():

  • When the given value does not match any variant in the enumeration, the execution is aborted with panic!().
  • The integer value for each enumeration variant is duplicated in the enumeration definition and in the conversion function. We must take care to use the same value in both locations.
  • If the enumeration contains a large number of variants, the conversion function becomes very long.

Since there are more than 100 atomic numbers, implementing a conversion function quickly becomes boring. There should be a better way.

Converting an integer to an enum in Rust with num::Derive

A more elegant solution is to use the FromPrimitive trait from the num crate coupled with syntax extensions from the num-derive crate.

extern crate num;
#[macro_use]
extern crate num_derive;

#[derive(FromPrimitive)]
enum AtomicNumber {
    HYDROGEN = 1,
    HELIUM = 2,
    // ...
    IRON = 26,
}

fn main() {
    let element = num::FromPrimitive::from_u32(26);
    match element {
        Some(AtomicNumber::IRON) => println!("Beware of Rust!"),
        Some(AtomicNumber) => {},
        None => println!("Unknown atomic number")
    }
}

The #[derive(FromPrimitive)] attribute instructs the Rust compiler to generate a basic implementation of the FromPrimitive trait for the AtomicNumber enumeration. Unlike our handwritten from_u32() function, the conversion function generated by the Rust compiler returns an Option which is either Some atomic number or None if the given integer does not match any known atomic number. This is much safer than calling panic!().

With the #[derive(FromPrimitive)] attribute our Rust program is nearly as concise as the equivalent program written in C with the bonus of being safer.

Harder, better, safer, rustier

While I had some hard time figuring how to convert an integer value to an enum variant in Rust, I feel reassured by its type safety and pleased with how its ecosystem of crates can simplify my work as a programmer.

Rust on the pont de Bir-Hakeim

Rust on the pont de Bir-Hakeim

Le paquet targetcli-fb intègre Debian

Depuis quelques mois, le paquet targetcli-fb qui permet de configurer une target iSCSI avec LIO fait partie de Debian Testing (la version en cours de développement de Debian 9 "Stretch").

L'intégration de targetcli-fb vient combler un manque dans Debian. En effet, aucun utilitaire n'est fourni dans l'actuelle Debian Stable (Debian 8 "Jessie") pour configurer une target iSCSI avec LIO.

Je participe à la maintenance du paquet targetcli-fb dans Debian avec deux contributeurs plus expérimentés : Christian Seiler et Ritesh Raj Sarraf. J'utilise Debian depuis de nombreuses années et c'est un juste retour des choses que de contribuer modestement (et librement) au projet.

L'iSCSI sous Linux étant un sujet rarement traité sur le web francophone, j'évoquerai comment s'en servir dans un futur article.

Time-lapse de fleurs de safran

Mi octobre, j'ai eu le plaisir d'assister à l'ouverture des fleurs de safran (Crocus sativus) dans le potager de mes parents. L'occasion était belle de fixer sur la pellicule carte SD les étapes de la floraison pour en faire un time-lapse.

Cette vidéo accélérée 1500 fois a été réalisée en prenant une image toutes les 5 minutes puis en générant une vidéo qui fait défiler 5 images par seconde.

Pour réaliser la vidéo, j'ai employé deux logiciels en ligne de commande : ImageMagick et ffmpeg. ImageMagick a permis de recadrer, redimensionner et légender chaque image tandis que ffmpeg a été utilisé pour combiner les images en une vidéo au format H.264.

Recadrage et redimensionnement

Au moment de la prise de vue, j'ai oublié de configurer mon appareil photo pour prendre des clichés aux dimensions de la vidéo finale : 1920×1080 pixels. J'ai donc enregistré des images dont les dimensions étaient trop grandes : 4608×3456 pixels (ratio 43). Il a fallu recadrer et réduire chaque image à sa dimension finale : 1920×1080 pixels (ratio 169).

Recadrage et redimensionnement

Les deux étapes de recadrage et de redimensionnement ont été réalisées par une seule commande convert en utilisant les options -crop et -resize :

$ convert -crop 3840x2160+0+1130 -resize 50% source.jpg destination.jpg

Cet appel à la commande convert recadre d'abord l'image aux dimensions 3840×2160 en décalant le cadre de 1130 pixels vers le bas (et 0 pixel vers la droite) puis divise ses dimensions par deux pour aboutir à une image de 1920×1080 pixels.

Extraction de l'heure de prise de vue et ajout de la légende

J'ai extrait la date et l'heure de la prise de vue pour chaque image avec le programme exiftool :

$ exiftool -DateTimeOriginal image.jpg
Date/Time Original              : 2016:10:17 08:37:09

Ensuite, j'ai utilisé la commande convert pour ajouter une undercolor box qui contient la légende.

Ajout d'un légende

$ convert source.jpg -pointsize 50 -font Inconsolata -fill white -undercolor '#00000080' -annotate +8+50 " Légende " destination.jpg

La légende est écrite en caractères blancs (-fill white) de 50 points de hauteur (-pointsize 50), dans une police à chasse fixe (-font Inconsolata). Un fond noir en semi transparence (-undercolor '#00000080') augmente la lisibilité.

Création de la vidéo au format H.264 à partir des images

La dernière étape a consisté à combiner les images en une vidéo avec ffmpeg.

$ ffmpeg -framerate 5/1 -i image-%03d.jpg -c:v libx264 -pix_fmt yuv420p -r 30 video.mp4

Les images défilent au rythme de cinq par seconde (-framerate 5/1) et le codec vidéo choisi est x264 pour coder un flux vidéo H.264 (-c:v libx264). J'ai du contraindre le pixel format avec -pix_fmt yuv420p parce que Firefox 45 considère que la vidéo est corrompue quand le pixel format par défaut (yuv422p) est employé.

Mise à jour des fréquences de la TNT pour VLC

Depuis le 5 avril 2016, la haute définition a été généralisée sur la TNT. Il faut donc faire un scan pour rechercher les chaînes. Sous Linux, on emploie la commande w_scan à cet effet :

$ w_scan -c FR -R0 -O0 > mes-chaines.conf

Malheureusement, je constate chez moi que la commande w_scan ne trouve aucune chaîne et affiche des erreurs qui ressemblent fort à celles décrites dans ce bug.

Pour contourner le problème, j'ai utilisé l'application Kaffeine qui identifie correctement les chaînes de la TNT lors d'une recherche. À partir des fréquences détectées par Kaffeine, j'ai écrit un fichier de configuration qui permet de regarder la TNT à Paris avec VLC, parce que je préfère VLC à Kaffeine. Le fichier de configuration pour VLC est le suivant : tnt-paris.conf (émetteur de la tour Eiffel).

Le fichier de configuration doit être donné en paramètre à VLC pour lire la TNT :

$ vlc tnt-paris.conf
L'émetteur de la tour Eiffel

Branchez une antenne plus grande pour mieux recevoir la TNT !
L'émetteur de la Tour Eiffel