Twister's blog

Aller au contenu | Aller au menu | Aller à la recherche

mercredi, mars 19 2014

Callbacks

Cela fait déjà une bonne dizaine de fois que je peste pour la même chose sur mon projet actuel : le chaînage des traitements dans tous les sens avec des fils de partout. Un schema très récurrent est "j'ai besoin de faire quelque chose après un traitement générique qui tourne dans un thread, mais cette chose dépend de paramètres qui ne sont jamais les mêmes suivant de où j'appelle mon traitement. Bon bah je vais rajouter pleins de paramètres à la méthode de mon traitement et me les traîner sur toute ma stack pour pouvoir faire ce qu'il faut à la fin". NOON ! Il faut arrêter les conneries. Si vous avez un traitement qui fonctionne gardez le comme ça, ATOMIQUE. Si les traitements qui suivent sont différents en fonction des appelants utilisez des Callbacks !

Un petit (mauvais) exemple :

public class Treatment {
    public static void doMyTreatment(int value1, int value2, int parameter1, int parameter2) {
        new Thread(new Runnable() {
            public void run() {
                /// DO a realy long treatment...
                /// very long...
                int res = value1 + value2;

                if (parameter1 == 0) {
                    doSomthg();
                } else if (parameter1 == 1) {
                    if (parameter2 == 0){
                        goSomewhere();
                } else {
                        cook();
                }
            }
        } 
    }
}

public class Caller1 {
    public void call() {
        Treatment.doMyTreatment(1, 2, 0, 0);
    }
}

public class Caller2 {
    public void call() {
        Treatment.doMyTreatment(1, 2, 1, 1);
    }
}

Ici vous avez les paramètres 1 et 2 qui vont influencer le "quoi" faire après le traitement des valeurs 1 et 2... C'est mal, ça va vite devenir une grosse pelote de laine au fil des ajouts de fonctionnalités. Alors que si vous aviez fait :

public class Treatment {
    public static void doMyTreatment(int value1, int value2, Runnable callback) {
        new Thread(new Runnable() {
            public void run() {
                /// DO a realy long treatment...
                /// very long...
                int res = value1 + value2;

                callback.run();
            }
        } 
    }
}

public class Caller1 {
    public void call() {
        Treatment.doMyTreatment(1, 2, new Runnable() {
            public void run() {
                StaticClass.doSomthg();
            }
        }
    }
}

public class Caller2 {
    public void call() {
        Treatment.doMyTreatment(1, 2, new Runnable() {
            public void run() {
                StaticClass.cook();
            }
        }
    }
}

C'est quand même plus propre. Bon là j'utilise de simples Runnable en callbacks, du coup je n'ai pas possibilité de passé des paramètres à ma méthode run mais ce n'est pas compliqué de définir votre interface perso à la place de Runnable.

Autre point, vous pouvez remplacer la callback par une List pour être capable de chaîner plusieurs traitements.

Et voilà...

dimanche, octobre 6 2013

Vera & Secure SSR-302

Je me suis récemment lancé dans la domotique. Pour commencé j'ai acquis une Vera Lite, un actionneur Secure SSR-302 et un switch Fibaro chez Delta Domotique (que je recommande au passage).

Mise à part de gros problèmes d'ergonomie sur la Vera, tout se passait plutôt pas mal jusqu'à ce que je réalise que la chaudière passe sa vie à s'éteindre. Au bout de quelques allumages je constate qu'elle s'éteint dans l'heure qui suit son allumage. Depuis son installation, le boitier SSR-302 a toujours clignoté en orange, ce qui veut dire qu'il est en fail-safe, j'avoue que comme ça avait l'air de marché je ne m'étais pas trop creusé (:p). Bref finalement, le froid arrivant et la chaudière ne marchant pas si bien que ça, j'ai creusé. Il se trouve que SSR-302 coupe tout une heure après le dernier signal reçu à cause du fameux mode fail-safe (comme quoi j'aurais du creuser tout de suite :p). Ainsi si le contrôleur tombe en rade, au lieu de laisser tout allumer sans contrôle, le SSR-302 coupe tout. Pas si bête à mon sens, mais galère à gérer... En effet lorsque l'on a le thermostat qui va bien c'est lui qui se charge d'envoyer le signal... Malheureusement je m'étais dis que ce serait pour plus tard (ça m'avait déjà couté assez cher :p).

Finalement ma mésaventure tombe plutôt bien puisque ça me démangeait depuis le début de regarder ce que l'on pouvait faire avec la Vera. Du coup ni une ni deux j'ai pris mon notepad et j'ai fais mon premier script LUUP qui se charge d'envoyer un signal au SSR-302 toutes les 45 minutes. Pour ce faire il faut commencer par créer une scène programmée pour s’exécuter toutes les 45 minutes. Cette scène ne fera rien d'autre que d'envoyer un signal d'allumage au SSR-302 s'il est déjà allumé. Pour cela quelques lignes suffisent :

local deviceNo = 13
local SSID = "urn:upnp-org:serviceId:HVAC_UserOperatingMode1"
local actualMode = luup.variable_get(SSID, "ModeTarget", deviceNo )

if (actualMode == "HeatOn") then
    luup.call_action(SSID,
                 "SetModeTarget", {NewModeTarget = "HeatOn"},
                 deviceNo )
end

return true
Et voilà, il vous suffit de remplacer le deviceNo par le numéro de device de votre SSR-302 et le tour est joué!

vendredi, août 2 2013

Lecteur RSS [suite]

Après la mort de Google Reader je pensais avoir trouvé plusieurs remplaçants dont un qui me convenait vraiment : The old reader. Malheureusement suite à un crash majeur de leurs serveurs ils ont décidé de jeter l'éponge et de passer à un mode de site privé pour quelques élus... Résultat je me re-retrouve au point de départ, plus rien pour lire mes flux. Sur les lecteurs existant qu'il me reste il y a donc :

  • Feedly buggant toujours pas mal et étant un poil lourd de temps en temps
  • Newsblur, payant à partir de 64 flux.

N'ayant que 50 flux, je partait donc sur Newsblur. Tout se passa bien pendant une semaine. Mais qu'elle ne fut pas ma surprise de découvrir ce matin une nouvelle limitation à Newsblur : on ne peut plus afficher que 8 articles non lus par flux en version gratuite ! Exit donc Newsblur.

J'ai donc décidé de redonner leur chance au petits lecteurs RSS installable sur un serveur. J'ai commencé par essayer d'installer Newsblur (oui c'est possible puisque le code est sur GitHub). Mais ce truc est une vrai usine à gaz ! Impossible de l'installer facilement... Poubelle!

Finalement après avoir réessayé tout ce qui trainait j'ai fini par installer Tiny-Tiny-RSS qui a en plus sa propre interface Android! Je vais donc voir ce que ça donne à terme, en espérant ne plus avoir à bouger de si tôt :p.

Pour ceux qui le voudrait mon install est ici : http://rss.perriot.fr/. Si vous voulez un compte n'hésitez pas à me faire signe.


mercredi, juillet 24 2013

Lire le contenu de fichiers dans un fichier zip en JAVA

Je viens de tomber sur un problème bête en Java, j'ai une application client/serveur avec un client qui envoie régulièrement des fichiers de logs au serveur sous forme de fichier ZIP. Le serveur doit décompresser les fichiers afin de la analyser pour en tirer des statistiques. Ce qui m'embêtait dans ce développement c'est qu'il faut dézipper les fichiers avant de pouvoir les analyser et que ce "dézippage" pourrait éventuellement laisser trainer des fichiers temporaires quelque part sur le serveur. Il me fallait donc une autre solution. J'en voyais 2 :

  • soit concatener les fichiers de logs en un seul fichier qu'il aurait suffit de gzipper pour pouvoir le lire avec un GZIPInputStream côté serveur.
  • soit permettre au serveur de lire de manière transparente les données de tous les fichiers contenus dans le zip.
La première solution aurait impliqué de faire des modifications sur le client qui utilise un système déjà existant (et standard pour notre application) pour envoyer ses fichiers ZIP, donc pas top. La seconde pose problème parce que le JDK ne fournit qu'un ZipInputStream qui permet de lire le Zip fichier par fichier, il faut en effet faire un appel à ZipInputStream.getNextEntry() entre chaque fichier pour passer à la suite. Comme l'ordre de lecture des fichiers n'a pas d'importance je décidais de faire un petit wrapper au stream afin qu'il soit capable de passer tout seul d'un fichier à l'autre. Et voilà le travail :

public static Reader acquireReader(File file) throws IOException {
       if (file.getName().endsWith(".zip")) {
           final ZipInputStream zis = new ZipInputStream(new FileInputStream(file));
           return new InputStreamReader(zis) {
               @Override
               public int read(char cbuf, int offset, int length) throws IOException {
                   int read = super.read(cbuf, offset, length);
                   if (read < length) {
                       if (read == -1) {
                           read = 0;
                       }
                       zis.getNextEntry();
                       read += super.read(cbuf, offset + read, length - read);
                   }
                   return read;
               }

               @Override
               public int read() throws IOException {
                   int c = super.read();
                   if (c == -1) {
                       zis.getNextEntry();
                       c = super.read();
                   }
                   return c;
               }
           };
       }
       return new FileReader(file);
   }

Comme vous pouvez le voire c'est relativement bateau :).


vendredi, juin 28 2013

Google Reader [RIP]

Vous le savez forcément, Google Reader tirera le rideau le 1er juillet 2013. C'est une page de l'histoire d'Internet qui se tourne. En effet depuis son lancement en 2005 aucun autre Reader n'aura jamais attiré autant de monde. Aucun autre n'est aussi simple, efficace et ne met à jour les flux aussi rapidement que Google Reader.

Depuis l'annonce faite par Google je me suis intéressé de près à tout ce que je pouvais trouver comme remplaçant. Que ce soit une application à installer sur un serveur ou un service clé en main en ligne je n'ai pas encore trouvé chaussure à mon pied. QUOI! me direz vous, et bien oui, je suis chiant et exigeant. Je veux tout comme Google Reader, tout de suite, et malheureusement ça n'existe pas.

Cependant, depuis quelques mois beaucoup de sociétés se sont mise en tête de devenir le nouveau Google Reader. Pas étonnant vus la masse d'utilisateur qui vont se retrouver sans foyer au 1er juillet il y a là un marché à conquérir. Ainsi durant les mois de mai et de juin nous avons vu de tout nouveaux reader apparaître, d'ancien évoluer rapidement, d'autre crouler sous la charge induite par tous ces nouveaux utilisateurs...

Au cours de ces derniers moi j'ai donc moi aussi fait le tour de ce qu'il existait. Je ne vous ferais pas ici un résumé complet de mes pérégrinations. Vous, comme moi, n'en avons pas le temps. Je vais donc aller droit au but :

Après 2 mois de tests divers et variés il en ressort 3 concurrents sérieux :

Et voici maintenant juste un résumé des pour/contre :

Feedly :

Pour Contre
  • Joli
  • Application Android (un peu difficile à appréhender au début, mais une fois habitué elle n'est pas si mal)
  • Mise à jour des flux relativement rapide
  • Beaucoup de vue différentes possible
  • Ne sait pas compter correctement le nombre de posts
  • Ne marque pas correctement les posts lus lors du scroll si le layout est 'serré'
  • Ne sauvegarde pas le layout par flux
  • Digg reader (beta fermée) :

    Pour Contre
  • Simple
  • (et oui c'est tout :))
  • Ne se met pas toujours à jour (sûrement des pbs sur les serveurs d'aggregation)
  • Ne sauvegarde pas le layout par flux
  • Pas d'application Android
  • Ne permet pas de caché les articles non lus
  • The Old Reader

    Pour Contre
  • Simple
  • Sauvegarde le layout par flux
  • Les flux sont mis à jour relativement rapidement
  • Pas d'application Android
  • Voilà pour un résumé rapide. Pour le moment mon choix se porte sur The Old Reader qui est le plus proche de Google Reader.

    Digg Reader est pour le moment très (trop) basique mais je pense qu'il vaut le coup de le surveiller.


    - page 1 de 34