Laurent Ellerbach

Ce blog est principalement destiné à publier des informations relatives à Microsoft, à ses technologies, aux outils Visual Studio et à ses versions Express notamment Visual Basic

  • Laurent Ellerbach

    J’ai hacké mon onduleur ou le reverse engineering de protocoles de communication (part 1)

    • 15 Comments

    C’est un titre un peu long mais bon, il exprime le fond de mon problème : j’ai acheté un onduleur (un Belkin) pour mettre sur mon serveur et un de mes PC à la maison. Par contre, faudra être un peu patient car il va y avoir plusieurs post sur le sujet.

    Le truc, c’est que l’application de gestion livrée avec est… comment dire… sans dire de gros mots… un peu vieillissante et inutilisable pour faire de l’administration. Une vieille appli au look de la fin des années 90, pas d’accès à distance, pas de SNMP, pas de page Web, bref rien :-(. Pour ne pas polémiquer, je préfère ne pas mettre de capture d’écran. Mais bon, pour les curieux, je vous les tiens à disposition…

    Du coup, je me suis lancé dans la recherche d’application un peu mieux. Au bout de quelques heures de recherche, quelques applications téléchargées et installées, je m’aperçois que tous les onduleurs ont un protocole de communication totalement différent. Les logiciels d’un constructeur ne fonctionnent qu’avec leur propre onduleur. Les applications sont d’ailleurs toutes très variées, seules les versions pro proposent du SNMP et quasi pas de soft qui permette d’avoir un état dans une page Web.

    Je me suis donc rabattu sur le service « Onduleur » de Windows (on le trouve dans « Gestion d’énergie » sauf sur les portables). Et là, pas mieux. Un service de base où mis à part si l’on possède un APC, il n’y a pas grand-chose. Visiblement n’importe quel onduleur possède des instructions minimums qui permettent de vérifier son état : sur secteur, sur batterie, batterie faible. Les possibilités sont très limitées : arrêter la machine et exécuter un programme. Point barre.

    Je suis donc parti sur l’écriture d’un programme en ligne de commande qui permette d’envoyer un mail en SMTP. Cela me permettra en cas de panne électrique d’être alerté par mail de la coupure de courant. Mieux que rien. Je me suis dit que ça allait me faire du bien, presque 2 ans et demi sans écrire une ligne de code. Ca va me dérouiller un peu.

    Côté outil, je pars donc sur Visual Basic Express 2005. Une solution parfaite pour m’y remettre. Parfaite car j’adore Visual Basic (je « parle » aussi C/C++,Java, Pascal, Fortran, C#, ADA et « baragouine un peu » en Eiffel, Python, PhP). Parfaite aussi pour les étudiants, les débutants et les passionnés : le produit est gratuit, permet de développer en .NET 2.0 et offre des possibilités de recherche super sympa (j’y reviendrais plus loin). Après 15 minutes de téléchargement (OK, j’ai une bonne ligne ADSL), l’installation se passe sans encombre. Je prends évidemment la librairie MSDN avec moi. Pas besoin de SQL Express pour mon besoin (pour l’instant). SQL Express est une base de données, basée sur SQL Server et gratuite. SQL Express est idéal pour les développements, les tests, une utilisation en production avec quelques utilisateurs simultanés.

    Evidemment, j’active mon Visual Basic Express 2005, qui permet d’avoir accès à de nombreux avantages :

    • Corbis Image Pack — Un assortiment de 250 images Corbis gratuites à inclure dans vos sites Web et vos applications
    • La suite IconBuffet Studio Edition Icon — Une collection de plus de 100 icônes IconBuffet.com, professionnelles et gratuites
    • Une variété de composants — Une sélection de composants à utiliser dans vos applications
    • Des livres électroniques et des articles — Des livres électroniques Microsoft Press complets ainsi que des articles intéressants pour les débutants, les amateurs, et les personnes essayant les outils de développement Microsoft pour la première fois.

    D’ailleurs en ce moment, il y a un jeu Activ'Express avec 20 lots à gagner chaque mois. Bref aucune excuse pour ne pas activer ses version de Visual Studio Express.

    Côté développement, je me dis que j’allais commencer par chercher dans l’aide. Toujours commencer par réfléchir avant de coder :-). D’ailleurs la bonne règle, c’est autant de temps à réfléchir qu’à coder. Un nouveau menu est présent « Communauté » et « Recherche dans les communautés ». A l’intérieur, on trouve des recherches sur des exemples. Je lance donc la recherche qui m’ouvre une nouvelle fenêtre, je tape « envoi mail smtp ». J’obtiens de nombreux résultats dont un très bien sur MSDN intitulé « Envoi de courrier, exemple » en ce qui concerne Microsoft et un autre très bien aussi sur le réseau Codes-Sources (superbement piloté par mon ami Nix) intitulé « VB.NET envoi de mail pas SMTP avec authentification ».

    Résultat : avec ces deux exemples, en moins de 10 minutes, j’avais fait mon programme. Très cool côté productivité, moins cool côté « me remettre à faire un peu de code ». Du coup, c’est là que me vient l’idée d’aller plus loin et de réécrire un logiciel qui permette de gérer mon onduleur ! Mon onduleur possède deux ports de communication : série et USB. Je me lance pour série, je connais bien…

    Cela me rappellera mon jeune temps de développeur. J’étais à l’époque étudiant à l’ENSAM (les Arts et Métiers). Je passais mon temps libre et mes vacances à travailler pour la société SAMx. Cet éditeur de logiciel est spécialisé dans les logiciels d’analyse scientifique. Leurs logiciels communiquent avec des microsondes et spectromètres électroniques. La plupart de ces appareils à l’époque ne communiquait qu’en port série et/ou parallèle. Je me souviens d’un développement où l’objectif était de récupérer des données (des images représentant des cartographies) depuis des PDP vers des PC (à l’époque en 1996 sous Windows 95). C’était l’époque des premiers ports parallèle EPP et ECP. La technologie n’était tellement pas sèche qu’il m’a fallut développer un dongle spécifique pour réussir à fonctionner avec l’ensemble des chipsets disponibles sur le marché. J’ai appris à cette époque à vraiment me servir d’un oscilloscope… Au final, la solution fonctionnait parfaitement avec un port série sur lequel les informations de commande étaient envoyées et un port parallèle sur lequel les informations étaient reçues. Pour les autres développements, je n’avais que rarement accès aux matériels (une microsonde, cela prend une pièce complète, SAMx n’en possédait pas, nous allions chez des clients faire les test) et je devait donc d’une part bien développer en respectant les protocoles de communication (documentés dans des superbes docs comme celles des standards) et d’autre part bien émuler les tests ! C’est à cette époque que la VT100 est devenue une de mes meilleure amie.

    De là, j’ai gardé de très bons restes. Restes que j’ai appliqués à mon onduleur. Et vous comprendrez le titre de ce post au prochain post :-)

     

  • Laurent Ellerbach

    J’ai hacké mon onduleur ou le reverse engineering de protocoles de communication (part 2)

    • 6 Comments

    Cette fois-ci, je vais rentrer plus dans le concret des quelques étapes clés à suivre pour déchiffrer le fonctionnement d’un protocole de communication. Pour ceux qui veulent suivre la genèse de l’article, allez voir le premier post.

    Je vais commencer par rappeler quelques principes de base quand on veut faire du reverse engineering. Loin de moi l’idée d’être exhaustif et de proposer une méthode infaillible et universelle. Ils sont juste basés sur le bon sens et des grands principes d’ingénierie. J’appliquerais ces principes sur mon exemple d’onduleur.

    La première étape consiste à se munir des bons outils : la documentation complète du vecteur d’information, des outils d’écoutes, des outils d’analyse et des outils de simulation. Pour un port série, c’est assez simple. C’est un des premiers ports à être apparu sur les ordinateurs. De base, il ne nécessite que 3 fils de base: une masse, une ligne de donnée montante et une ligne de données descendante. Certains montages peuvent nécessités d’autres lignes qui permettaient notamment, au début, de faire du contrôle de données.

    Alors pour commencer, qu’est-ce que RS232 ? Et bien, c’est une norme de communication série que l’on trouve RS232 à l’EIA/TIA et qui est identique aux normes CCITT V.24/V.28, X.20bis/X.21bis et ISO IS2110. Des mots bien compliqués pour l’appeler familièrement un « port série ». De bonnes explications en anglais sur Wikipedia. Pourquoi série ? Et bien tout simplement parce que les données sont transmises en série, les unes après les autres sur une seule ligne. La différence avec un port parallèle, c’est que sur le port parallèle, il faut un fil par bit (en général), et les données d’un mot sont transmises toutes en même temps. Le principe du port série est d’ailleurs réutilisé sur les ports SATA (contrôleurs de disques dur nouvel génération) qui remplace les ports PATA qui eux transmettaient les informations en parallèle. Le port USB est également un très bon exemple d’utilisation de transmission en série des informations. Chaque technologie présente ses avantages et ses inconvénients. Je ne rentrerais pas dans le détail ici car j’ai besoin d’espionner à un niveau plus haut dans les couches OSI que sur la couche de transport en tant que tel.

    Le port série se présente sous la forme de prises DB25 (25 broches), DB9 (9 broches) ou RJ45 (8 broches). Les plus courants sont DB9 (on les trouve sur les PC actuels). Les DB25 ne sont plus utilisés depuis pas mal d’années et on évite les RJ45 pour ne pas les confondre avec les prises réseaux. Côté physique, les 3 seuls chiffres à retenir sur une DB9, ce sont 2, 3 et 5. 5 est la masse. La câblage de base consiste donc à relier 2 appareils en mettant directement les broches 2 et 3 en liaison (ou très rarement 2-2 et 3-3) et relier entre elles les broches 5. Dans mon cas, un câble série était livré, je n’ai pas eu besoin de me prendre la tête avec du câblage. Cependant, cela peut s’avérer utile d’avoir 2 câbles tout prêts, un droit et un croisé (appelé câble null modem) pour faire ce type de manipulation. Les autres broches peuvent avoir leur importance suivant ce que l’on cherche à faire. Mais elles ne sont pas obligatoires. Tous les câblages sont disponibles dans la doc de Windows 2000 par exemple.

    Côté communication, le port série fonctionne avec :

    • un débit données, exprimé en baud : (150), 300, (600), 1 200, 2 400, (3 600), 4 800, 9 600, 19 200, 28 400, 38 400, 57 600, 115 200, entre parenthèse les débits possibles mais plus utilisés ou rarement utilisés. Avec les nouveaux chpsets, il est possible d’obtenir une plage plus large notamment entre 28,4 et 57,6 K baud.
    • un nombre de bit par mot 7 ou 8,
    • une parité : None (aucune), Odd (paire), Even (Impaire), Mark (marquée)
    • 1 ou 2 bits de stop

    Les informations sont codées du bit de point faible vers le bit de poids fort suivi du bit de parité (si pas none) et du ou des bits de stop. A priori, rien n’interdit les transmissions simultanées. Dans ce cas, il faut être sûr que les broches ready to send et ready do receive sont bien reliées les unes avec les autres.

    Pour pouvoir correctement espionner ce qui circule sur le port série, la première difficulté consiste donc à trouver la bon paramétrage. Ce n’est pas si facile car les possibilités sont nombreuses. Dans mon cas, je ne possède pas la documentation du protocole de communication, impossible donc de connaître les bonnes informations. Et rien n’est écrit sur le matériel. Pas d’information disponible.

    J’ai la « chance » d’avoir un logiciel qui communique déjà avec mon onduleur. La seule chose que je vais donc avoir besoin de faire, c’est de l’espionner pour obtenir ces informations. L’avantage d’être à ce niveau là, c’est que c’est du logiciel. Et comme on dit, en logiciel tout est possible . Donc, je pars m’équiper d’un outil d’écoute. J’en connais un très bien : PortMon. Il provient de Sysinternals. Un site avec de nombreux outils tous indispensables au bon développeur et administrateur réseau. Sysinternals vient d’ailleurs d’être racheté par Microsoft il y a quelques semaines. Mark Russinovich et Bryce Cogswell ont toujours été pour moi des idoles et ils vont certainement le rester longtemps. Le fonctionnement de PortMon est parfaitement documenté sur le site.

    PortMon permet d’écouter ce qui se passe sur un port série ou un port parallèle. Je lance donc PortMon, je paramètre l’utilisation du port pour l’ordinateur local et utilise le port COM1. Je lance ensuite l’outil de monitoring de l’onduleur et j’écoute. Et vous savez quoi ? Et bien, on trouve plein de choses intéressantes… La suite au prochain post.

     

  • Laurent Ellerbach

    J’ai hacké mon onduleur ou le reverse engineering de protocoles de communication (part 6)

    • 6 Comments

    Voici la suite des aventures de l’analyse du protocole de communication expliqué dans la quatrième partie. J’ai donc essayé à partir des commandes envoyées à l’onduleur de compléter ce que j’ai trouvé en écoutant la conversation entre l’application livrée avec l’onduleur et l’onduleur. J’ai donc utilisé l’application développée précédemment pour envoyer les commandes. Je notais le résultat de chaque commande. Ensuite, j’ai essayé à partir de l’application livrée avec et des informations renvoyées de déchiffrer les résultats. Avoir une application existante aide grandement, cela facilite la comparaison des résultats. Sinon, il faut essayer de deviner par tâtonnement. Moins drôle. Il me reste quelques zones d’incertitude cependant que je vais devoir approfondir. Pour les commandes que je n’avais pas (exemple S), j’ai tout simplement envoyé chaque lettre de l’alphabet et j’ai attendu le retour. La plupart du temps, c’est un écho, assez classique dans les protocoles. Quand rien ne revenait, j’analysais l’onduleur lui-même. Parfois rien ne se passait du tout (exemple envoi de la commande Q). Cela impliquait qu’il pouvait manquer une lettre/chiffre derrière ou que le mode était déjà enclenché (exemple commande C quand on est déjà en courant continue).

    Commande I

    Renvoie l’identifiant de l’onduleur : #BELKIN Master 1.00

    1 caractère # qui identifie le début de la chaîne

    16 caractères qui contiennent la marque de l’onduleur, ici BELKIN

    11 caractères qui contiennent le modèle de l’onduleur, ici Master

    11 caractères qui contiennent la version du firmware ici 1.00

    Commande S

    Arrête l’onduleur. Attention, si l’onduleur est alimenté en courant il se remet en marche automatiquement. Commande à utiliser donc de préférence lors d’une coupure de courant si besoin.

    Commande T

    Passe l’onduleur en mode batterie test pendant 10s.

    Commande C

    Repasse l’onduleur en mode alimentation par secteur. Utile lorsqu’on force l’onduleur à se mettre en mode batterie avec la commande TL ou T. Pas de différence visible avec la commande CT.

    Commande TL

    Passe l’onduleur en mode batterie.

    Commande CT

    Repasse l’onduleur en mode alimentation par secteur. Voir commande C.

    Commande Q1

    Renvoie un statut des tensions, fréquences, températures et charges : (238.0 237.0 236.0 024 50.0 13.9 32.0 00001000

    238.0 = Voltage d’alimentation = 238.0 V

    237.0 = Voltage tension de sortie primaire ( ?) = 237.0 V

    236.0 = Voltage tension de sortie secondaire ( ?) = 236.0 V

    024 = charge de l’onduleur en %

    50.0 = fréquence en Hertz

    13.9 = Charge de la batterie (?), reste à déterminer l’échelle, a priori 14.

    32.0 = température en °C

    00001000 = statut. 1 bit par info. Pas encore déterminé l’utilité de tous les bits. Tests à effectuer

    Commande F

    Renvoie un statut de la batterie : #230.0 2.2 12.00 50.0

    230.0 = Voltage de la sortie batterie

    2.2 = courant en ampère

    12.00 = tension de la batterie

    50.0 = Fréquence de sortie

    Je suis content de ce premier jet de résultat qu’il me reste à approfondir avec quelques tests complémentaires. Cela vade toute façon me permettre d’avancer rapidement dans l’écriture d’une classe de gestion de l’onduleur. A suivre au prochain post !

  • Laurent Ellerbach

    J’ai hacké mon onduleur ou le reverse engineering de protocoles de communication (part 8)

    • 4 Comments

    J’ai donc continuer de développer ma solution de gestion d’onduleur. J’ai profité de mon retour à la maison pour continuer les tests physiques sur mes onduleurs. Oui, j’ai bien dit mes onduleurs. En fait, j’en possède 3 du même modèle. Ce qui a aussi motivé l’écriture de ce service de gestion…

    La suite des tests m’a permis de compléter le protocole de communication et de déterminer à quoi servent la plupart des bits :

    00001000 = statut. 1 bit par info.

    b0b1b2b3b4b5b6b7

    • b0 = passe à 1 lorsqu’une panne de courant arrive, lorsque l’alimentation est coupée
    • b1 = passe à 1 lorsque la batterie est faible
    • b2 = ??? pas encore déterminé. Impossible en utilisation normale de le faire passer à 1. Il reste à 0.
    • b3 = ??? Idem
    • b4 = est à 1 en fonctionnement normal. Il indique que les sorties sont alimentées
    • b5= passe à 1 quand on est en mode test. Le mode test est déclenché par l’envoie de la commande T
    • b6 = ??? pas non plus réussit à déterminer à quoi ce bit sert
    • b7 = passe à 1 quand l’alimentation est sur batterie

    Cela m’a également permis d’étalonner les niveau de la batterie. Le niveau haut varie de 14 à 10,7. L’échelle de consommation est quasi linéaire.

    Côté code, j’ai décidé d’implémenter des événements. Ainsi, lorsqu’un de ces bits change, j’envoie l’événement correspondant. Cela permet de gérer avec de la souplesse ce qui peut arriver. Il faut d’abord dans le code déclarer les événements :

    'se déclenche lorsque le secteur est coupé, en général va avec l'événement FonctionnementBatterie

    Public Event ArretAlimSecteur()

    'se déclenche lorsque le secteur est remis (et qu'il était coupé)

    Public Event RetourAlimSecteur()

    'lorsque l'onduleur fonctionne sur batterie

    Public Event FonctionnementBatterie()

    'ou lorsqu'il fonctionne de nouveau normalement

    Public Event ArretFonctionnementBatterie()

    'Lorsque la batterie est faible

    Public Event BatterieFaible()

    'lorsque l'onduleur est arrêté

    Public Event OnduleurArrete()

    Puis, pour chaque bit, on vérifie si un changement d’état s’est passé. Ca donne cela :

    'position 0 = panne secteur

    Dim BoolTemp As Boolean

    ' récupère la valeur (0 ou 1) du bit 0 de la chaîne de 8 bits

    BoolTemp = Val(mc.Item(7).Value.Substring(0, 1))

    If BoolTemp <> myOnduleurPanneSecteur Then

    If BoolTemp Then

    RaiseEvent ArretAlimSecteur()

    Else

    RaiseEvent RetourAlimSecteur()

    End If

    myOnduleurPanneSecteur = BoolTemp

    End If

    Le principe est simple, il faut récupérer la valeur dans une variable temporaire. Puis on compare à la valeur actuelle. Si la valeur est la même, alors pas de changement d’état et on ne fait rien. Si les valeurs sont différentes, alors on regarde la valeur de la variable.

    Dans le cas où le bit est à 1, alors cela signifie que le courant a été coupé. On envoie donc l’événement ArretAlimSecteur. Dans le cas où il passe à 0, on peut signifier que le courant est revenu en envoyant l’événement RetourAlimSecteur. Le mot magic RaiseEvent permet d’envoyer l’événement.

    Ne pas oublier à la fin d’attribuer la nouvelle valeur à la variable privée stockant cette information.

    Côté du code qui intercepte les événements, ce n’est pas plus compliqué. Il faut déclarer une variable avec le mot clé WithEvents.

    Public WithEvents myOnduleur As New Onduleur

    On se retrouve ensuite avec une fonction de ce type qui permet d’intercepter l’événement et de le traiter :

    Private Sub myOnduleur_ArretAlimSecteur() Handles myOnduleur.ArretAlimSecteur

    'Faire quelque chose ici :-)

     

    End Sub

     

    S’il y a des paramètres à passer, cela se passe de la même façon. Il suffit de les décrire dans la définition puis de les envoyer ans le RaiseEvent et de les récupérer comme avec n’importe quel événement dans la fonction Handles.

    L’utilisation des événements est donc très simple. Un vrai bonheur.

    Avec cela, j’ai fini d’écrire ma classe de gestion de l’onduleur. Elle permet de se connecter à l’onduleur, de récupérer les informations, en cas de panne de courant ou autre, d’envoyer l’événement correspondant.

    Je récupère les données de façon régulière à l’aide d’un timer. Le fonctionnement d’un timer au prochain post…

     

  • Laurent Ellerbach

    Implementing a simple HTTP server in .NET Microframework

    • 4 Comments

    To follow my previous posts, I’ve started to implement a simple HTTP server in my netduino using .NET Microfamework. I have to admit it was quite easy as there is a HTTP Server example in the samples. I was very impressed that with no OS so no Windows, no Linux, no Mac or any DOS or whatever OS, you can do high level code, create a Web Server in about 2 hours. I haven’t seen something comparable using Java, native C or other languages. There may be ways but here, all the framework is designed to be able to handle any kind of networking, there is even multithreading. I’ll use multithreading in a future post to show how to handle periodic calls.

    As I would not use all the functions, I’ve started to simplify the code and kept only what I needed.

    So I just kept couple of functions:

    • public static void StartHttpServer()
    • internal static void RunServer(string prefix)
    • static private string GetPathFromURL(string URL)
    • private static void ProcessClientGetRequest(HttpListenerContext context)
    • static void SendFileOverHTTP(HttpListenerResponse response, string strFilePath)
    • class PrefixKeeper

    I will not used any post method, so I removed it from the code. I removed also the certificate part because I won’t use HTTPS and removed the secure part as I won’t also use it. It needs to clean a bit the code but nothing really too complicated.

    I wanted to use parameter in the URL. So have requests like http://siteweb/page.ext?param1=value1;param2=value2

    In order to do that, I’ve created a very simple class which associate on parameter and one value. Nothing really to comment here, it’s a very classic class. I let the set and get properties in this class as it may be use in read and write. Both parameters and values are string.

    public class Param
            {
                private string myName = "";
                private string myValue = "";
    
                public string Name
                {
                    get { return myName; }
                    set { myName = value; }
                }
    
                public string Value
                {
                    get { return myValue; }
                    set { myValue = value; }
                }
    
                public Param()
                {
                    myName = "";
                    myValue = "";
                }
            }

    In the sample, there is nothing to decrypt such a URL. So I’ll need to function to decrypt the URL and return a table with parameters and the associated values.

    As I want to have clean code (or as clean as possible Sourire), I’ve defined 3 chars constant for the various separators.

    const char ParamSeparator = ';';
    const char ParamStart = '?';
    const char ParamEqual = '=';

    private static Param[] decryptParam(String Parameters)
    {
        Param[] retParams = null;
        int i = Parameters.IndexOf(ParamStart);
        int j = i;
        int k;
        if ( i> 0) 
        {
            //look at the number of = and ;
            
            while ((i < Parameters.Length) || (i == -1))
            {
                j = Parameters.IndexOf(ParamEqual, i);
                if (j > i)
                {
                    //first param!
                    if (retParams == null)
                    {
                        retParams = new Param[1];
                        retParams[0] = new Param();
                    }
                    else
                    {
                        Param[] rettempParams = new Param[retParams.Length+1];
                        retParams.CopyTo(rettempParams, 0);
                        rettempParams[rettempParams.Length-1] = new Param();
                        retParams = new Param[rettempParams.Length];
                        rettempParams.CopyTo(retParams, 0);
                    }
                    k = Parameters.IndexOf(ParamSeparator, j);
                    retParams[retParams.Length - 1].Name = Parameters.Substring(i + 1, j - i - 1);
                    //case'est la fin et il n'y a rien
                    if (k == j)
                    {
                        retParams[retParams.Length - 1].Value = "";
                    } // cas normal
                    else if (k > j)
                    {
                        retParams[retParams.Length - 1].Value = Parameters.Substring(j + 1, k - j - 1);
                    } //c'est la fin
                    else
                    {
                        retParams[retParams.Length - 1].Value = Parameters.Substring(j + 1, Parameters.Length - j - 1);
                    }
                    if (k > 0)
                        i = Parameters.IndexOf(ParamSeparator, k);
                    else
                        i = Parameters.Length;
                }
            }
        }
        return retParams;
    }

    The code here is not very complex. It looks first at the start parameter. Here, it’s the question mark (? ParamStart) then it finds the separator equal mark (= ParamEqual) and it finished by the separator (; ParamSeparator). Couple of cases if we are at the end for example as there is usually no separator.

    I’m not sure it’s the smartes way to do it but it’s working, it’s pretty robust and it’s been working with many various URL and cases. I’ve chosen to return a table as it’s easy to implement and easy to use. It’s pretty simple in .NET Microframework.

    You just has to be careful as depending on the platform you are using the size of the tables are limited. In the case of netduino, it’s a maximum 1024 elements. That’s also the limit size for strings. No impact here as we can consider (never consider anything in code Sourire) that a URL will be less than 1024 parameters as the string used will of course of a maximum of 1024 characters.

    In order to have clean code, I’ve also define couple of parameters and page names in a read only class.

    public class ParamPage {
        public string year { get { return "year"; } }
        public string month { get { return "month"; } }
        public string day { get { return "day"; } }
        public string hour { get { return "hour"; } }
        public string minute { get { return "minute"; } }
        public string duration { get { return "duration"; } }
        public string spr { get { return "spr"; } }
        public string pageProgram { get { return "program.aspx"; } }
        public string pageListPrgm { get { return "listprg.aspx"; } }
        public string pageCalendar { get { return "calendar.aspx"; } }
        public string pageSprinkler { get { return "sprinkler.aspx"; } }
    }

    It defines all my parameters, name of the pages I’ll use. So in code, I’ll use this class to make sure I’ll always use the right element and don’t mix up my parameters. It will also be the same name use for all pages when needed.

    As you’ve seen, the decrypt parameter function return a string value. In your code, you may want to convert it to int, float, bool or other numeric values. .NET Microframework does not provide any convert class as the full framework. So you’ll to do it by hand Sourire Not quite hard and you’ll be able to keep this class for other development.

    public class Convert
     {
         public static bool ToFloat(string s, out float result)
         {
             bool success = true;
             int decimalDiv = 0;
             result = 0;
             try
             {
                 for (int i = 0; i < s.Length; i++)
                 {
                     if (s[i] == '.' && decimalDiv == 0)
                         decimalDiv = 1;
                     else if (s[i] < '0' || s[i] > '9')
                         success = false;
                     else
                     {
                         result = result * 10;
                         decimalDiv = decimalDiv * 10;
                         result += (int)(s[i] - '0');
                     }
                 }
                 result = (float)result / decimalDiv;
             }
             catch
             {
                 success = false;
             }
             return success;
         }
    
         public static bool ToInt(string s, out int result)
         {
             bool success = true;
             result = 0;
             try
             {
                 for (int i = 0; i < s.Length; i++)
                 {
                         result = result * 10;
                         result += (int)(s[i] - '0');
                 }
             }
             catch
             {
                 success = false;
             }
             return success;
         }
    
         public static bool ToBool(string s, out bool result)
         { 
             bool success = true;
             result = false;
             try
             {
                 if ((s == "1") || (s.ToLower() == "true"))
                     result = true;
             }
             catch
             {
                 success = false;
             }
             return success;
         }
     
     }

    The code is very simple too. I’ve prefer to handle in the class a try catch and return a success value. I feel more comfortable coding like that but if you want to make it more simpler and faster, just don’t use a try catch and handle it in a higher level. The conversion for int will return funky numbers if you don’t have only decimal in the string and same for float. I’m not looking first if all are numeric if the min and max values are correct. It’s just fast and easy way to convert.

    For the bool conversion, I’ve decided to only validate the true which can be represented as 1 or true. Anything else will just be false. So here false is anything but true.

    Now to use the decrypt function and associate couple of values, here is a complete example. with the request.RawUrl you can get the URL so a string like calendar.aspx?year=2011;month=9;spr=0

    HttpListenerRequest request = context.Request;
    HttpListenerResponse response = context.Response;
    // decode params
    string strParam = request.RawUrl;
    ParamPage MyParamPage = new ParamPage();
    int intMonth = -1;
    int intYear = -1;
    int intSprinkler = -1;
    Param[] Params = decryptParam(strParam);

    Here you’ll get Params as a table of 3 elements. First couple will be year and 2011, second month and 9 and third spr and 0. All as strings. Now you’ll have to convert those string into values and then use them in your code.

    if (Params !=null)
        for (int i = 0; i < Params.Length; i++)
        {
            //on cherche le paramètre strMonth
            int j = Params[i].Name.ToLower().IndexOf(MyParamPage.month);
            if (j == 0)
            {
                Convert.ToInt(Params[i].Value, out intMonth);
            }
            j = Params[i].Name.ToLower().IndexOf(MyParamPage.year);
            if (j == 0)
            {
                Convert.ToInt(Params[i].Value, out intYear);
            }
            j = Params[i].Name.ToLower().IndexOf(MyParamPage.spr);
            if (j == 0)
            {
                Convert.ToInt(Params[i].Value, out intSprinkler);
            }
        }

    At the end, you’ll get intMonth = 9, intYear = 2011 and intSprinkler = 0.

    Last but not least, to call a function with a name and parameters you’ll need to do it in the private static void ProcessClientGetRequest(HttpListenerContext context) function from the sample.

    HttpListenerRequest request = context.Request;
    HttpListenerResponse response = context.Response;
    
    ParamPage MyParamPage = new ParamPage();
    
    string strFilePath = GetPathFromURL(request.RawUrl);
    
    string strCalendar = "\\" + MyParamPage.pageCalendar;
    // if page calendar.aspx
     if (strFilePath.Length >= strCalendar.Length)
     {
         if (strFilePath.Substring(0, strCalendar.Length).ToLower() == strCalendar)
         {
             ProcessCalendar(context);
             return;
         }
     }

    So basically, the idea is to see if the name of the page is the one used at the beginning of the URL string. If yes, it calls a specific function and gives it the context object. From there, you can use the previous code to decode your URL and analyze your parameters.

    So to summarize, with couple of more functions, you are now able to pass parameters un a URL and decrypt them. For me, that’s what I wanted to do as it’s very easy to use to generate URL but also call specific URL in code. If you have better way to do all of this, just let me know, I’m just a marketing guy doing code Sourire

  • Laurent Ellerbach

    Lighting my Lego city using .NET Microframework

    • 4 Comments

    Now I have created a software to pilot sprinklers, I want to be able to pilot my Lego city and light it. I know my sprinkler project is not over as I still need to work on the hardware. I will do it over the winter and try to find someone to help me. This new project looks simpler for me as it will basically only be couple of led. So it can be directly plugged to the netduino board.

    I have quite a big Lego city as you can see in this picture with 2 trains, a modern city, an old city, an airport, couple of rail stations.

    For those who may not have guess, I’m a Lego fan, I have more than 650 official Lego sets from 1970+ to now. Not all are build, some are just used for spare parts to build other kind of constructions. And I have also hundreds of kilos of brick at home which allow me to build whatever I want. You can have a look at part of the collection here.

    Same as for the sprinkler project, the idea is to be able to switch some part on automatically, at night for example, and switch them on and off also manually. In order to reuse the work I’ve done, I will create a similar project with and http web server (like IIS or Apache running on Windows or Linux), dynamic pages (like ASP.NET, php or Java) with parameters. I’ve already develop a web server I will be able to reuse and the management for dynamic input.

    My idea this time is to be able to display a web page with pictures of the city and specific points on the pictures that will represent the light to switch on and off. clicking on them will change the color of the points and switch the light accordingly.

    In a longer term, I will try to pilot also the train lights and the rail switch. That will need a bit more electronic but is very easy to do in term of code. So probably that the code will exist before the electronic as for the sprinkler project. I will try also in this project to use the SD card to store the picture of the city and the points coordinate to be displayed. So a kind of setup file. I’ve already try to play with the SD card but with limited success. I don’t know from where the problem is coming from. I use couple of different cards and I always get errors but never the same. So I think the problem is coming from the hardware.

    So let see where this project will go Sourire

  • Laurent Ellerbach

    Creating an efficient HTTP Web Server for .NET Microframework (NETMF)

    • 4 Comments

    That’s not the first post I’m doing on incorporating a Web Server in .NET Microframework (NETMF). In some of my previous posts, I’ve explain how to do it using the existing .NET classes for this. And it is working very well!

    The main concerns I have is that I’m using a netduino board. This board is great, I love it. But there is a very limited amount of memory available and limited amount of space to store the programs. Total storage is 64Kb and what is left when the code is in is about 48K… So very little amount of memory. And the http .NET classes are great and use stream but they are intense in terms of memory and also the main http class is huge…

    So I had to find a solution and it was to redevelop a web server like IIS or Apache. OK, I can’t compare Sourire I just want a web server which handle GET answers and respond a simple web page. The other challenge I have is to be able to reuse the code I4ve already written for my Sprinkler, to pilot my Lego city and my Lego infrared receiver like my Lego trains…

    So I was searching for code to reuse on the Internet and found some code. So I did a mix of existing code and spend some time testing various solutions Sourire Most of the existing code is not really robust. It does fail if there is a network problem, if 2 requests arrive at the same time, etc. I’m not saying my code is perfect but it is working and working well for the last month with no problem at all.

    A web server is simple, it’s just a connection on a socket and a protocol of communication which is HTTP. It is also very simple as it is text based. What is interesting is to see all what you can do with such a simple protocol and such a simple markup language like HTML and some javascript.

    OK, so let start with what is necessary: a thread that will run all the time and handle socket requests. So we need also a socket. And a way to stop the thread.

     
    private bool cancel = false;
    private Thread serverThread = null;
    
    public WebServer(int port, int timeout)
    {
        this.Timeout = timeout;
        this.Port = port;
        this.serverThread = new Thread(StartServer);
        Debug.Print("Web server started on port " + port.ToString());
    }
    

    As you can see, it is quite simple, the WebServer object is initialize with a specific port and a timeout. By default, the http port is 80 but it can be anything. There is no limitation. And as it’s easy to implement, let make the code generic enough to be able to be use with different ports. And a new Thread is created to point on function StartServer. I will detail it later. I will explain also why we need a timeout later.

    Now we have this object initialize, let start the Webserver:

    public bool Start()
    {
        bool bStarted = true;
        // start server           
        try
        {
            cancel = false;
            serverThread.Start();
            Debug.Print("Started server in thread " + serverThread.GetHashCode().ToString());
        }
        catch
        {   //if there is a problem, maybe due to the fact we did not wait engouth
            cancel = true;
            bStarted = false;
        }
        return bStarted;
    }
    
    
    
    

    That is where the fun being! We start listening and initialize a variable we will use later to stop the server if needed. The catch can contain something to retry to start, here, it just return if it is started or not. At this stage, it should work with no problem as it is only a thread starting. But who knows Sourire

    private void StartServer()
    {
        using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            //set a receive Timeout to avoid too long connection 
            server.ReceiveTimeout = this.Timeout;
            server.Bind(new IPEndPoint(IPAddress.Any, this.Port));
            server.Listen(int.MaxValue);
            while (!cancel)
            {
                try
                {
    
                    using (Socket connection = server.Accept())
                    {
                        if (connection.Poll(-1, SelectMode.SelectRead))
                        {
                            // Create buffer and receive raw bytes.
                            byte[] bytes = new byte[connection.Available];
                            int count = connection.Receive(bytes);
                            Debug.Print("Request received from " 
    + connection.RemoteEndPoint.ToString() + " at " + DateTime.Now.ToString("dd MMM yyyy HH:mm:ss")); //stup some time for send timeout as 10s. //necessary to avoid any problem when multiple requests are done the same time. connection.SendTimeout = this.Timeout; ; // Convert to string, will include HTTP headers. string rawData = new string(Encoding.UTF8.GetChars(bytes)); string mURI; // Remove GET + Space // pull out uri and remove the first / if (rawData.Length > 5) { int uriStart = rawData.IndexOf(' ') + 2; mURI = rawData.Substring(uriStart, rawData.IndexOf(' ', uriStart) - uriStart); } else mURI = ""; // return a simple header string header = "HTTP/1.1 200 OK\r\nContent-Type: text/html
    ; charset=utf-8\r\nConnection: close\r\n\r\n"
    ; connection.Send(Encoding.UTF8.GetBytes(header), header.Length, SocketFlags.None); if (CommandReceived != null) CommandReceived(this, new WebServerEventArgs(connection, mURI)); } } } catch (Exception e) { //this may be due to a bad IP address Debug.Print(e.Message); } } } }

     

    This function will run all the time in a thread. It’s in an infinite loop which can be break by the cancel variable. First, we need to initialize the Socket. We will use IPv4 with a stream and the TCP protocol. No timeout to receive the request. The, you’ll have to bind this socket to a physical IP address. In our case, we will use all IP address on the port initialized before. Any IP address mean all addresses and in our case only 1 IP address as we do have only 1 Ethernet interface. We are using '”using” to make sure the server Socket will be closed and cleaned properly after usage.

    The way it is working is not too complicated. Remember that we’ve open a Socket named Server, setup it to listen to port 80. This is running in a separate thread in this thread. So in order to analyze the information returned when a connection is accepted (so when a Browser ask for a page), we need to create another Socket pointing to the same Socket, here “using (Socket connection = server.Accept())”. In this case “using” allow the code to clean in the “proper way” when the thread will be finished or then the loop end or when it goes back to the initial loop. It’s thread in thread and if you don’t close things correctly, it can quickly let lots of objects in the memory, objects which will be seen as alive by the garbage collector.

    When there are bytes ready to read with connection.Poll, we just read them. The request is transformed into a string. An http request look like “GET /folder/name.ext?param1=foo&param2=bar HTTP/1.1”. Areal life example looks more like this: "GET /folder/name.ext?param1=foo&param2=bar HTTP/1.1\r\nAccept: text/html, application/xhtml+xml, */*\r\nAccept-Language: fr-FR,fr;q=0.8,en-US;q=0.5,en;q=0.3\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)\r\nAccept-Encoding: gzip, deflate, peerdist\r\nHost: localhost:81\r\nConnection: Keep-Alive\r\nX-P2P-PeerDist: Version=1.1\r\nX-P2P-PeerDistEx: MinContentInformation=1.0, MaxContentInformation=1.0\r\n\r\n"

    For a normal, full web server like IIS or Apache, you’ll analyze all those parameters, and there are lots, see the W3C protocol here. For our usage, the only thing that interest us is the full URL. And it is located between the 2 first spaces. And we will extract the URL, remove the first ‘/’ as I will not use it in the rest of the code.

    Now, the next step is to start answering the request. When someone ask you something, it’s polite to answer Sourire Like for the request, the response need to have couple of header information. And as my usage is extremely simple, I will always consider that it is OK, I’m only delivering text content and that the connection can be closed. By the way, whatever you put there, HTTP is a disconnected protocol, so you should never consider that you are always connected! It’s an error and can drive you to very bad behaviors.

    connection.Send return the first part of the message and then I call an event to tell the creator of the WebServer object that something happened. I send of course the connection object so that the caller will be able to create an HTML page and answer and also the URL so that it can analyze it.

    Last but not least, the try and catch is extremely important. With Sockets a problem can quickly arrive due to a network problem. And I’ve seen it happening on the netduino for no reason. Just capturing the problem and not doing anything makes the web server working for months! Even if you loose the network, the catch will capture the problem and the server will continue to work up to the point the network will work again. The other reason to use it is because of the timeout. If something happen between the client and our webserver, after the timeout, you’ll get in this catch and you’ll start a new socket and the process will go back to something normal. It can happen and happened to me with very long HTML pages I was generating. When I was interrupting the creation and ask for a new page, the socket went into a kind of infinite loop waiting for a request. There should be a smart way to check is something goes well or not but it’s an easy way.

    public delegate void GetRequestHandler(object obj, WebServerEventArgs e);
    public class WebServerEventArgs: EventArgs
    {
        public WebServerEventArgs(Socket mresponse, string mrawURL)
        {
            this.response = mresponse;
            this.rawURL = mrawURL;
        }
        public Socket response { get; protected set;  }
        public string rawURL { get; protected set; }
    
    }
    
    public event GetRequestHandler CommandReceived;
    

    Right after the header is sent back, an event is raised. The arguments are simple here, we do send the Socket object and the URL. If you want to enrich the web server, you can add other elements like the header element rather than sending them right away, the browser requesting the page, the IP address or whatever you want! Again, simple and efficient there.

    Last but not least if you need to stop the Server, you’ll need a function to this and also to clean the code at the end:

    private bool Restart()
    {
        Stop();
        return Start();
    }
    
    public void Stop() { cancel = true; Thread.Sleep(100); serverThread.Suspend(); Debug.Print("Stoped server in thread "); }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            serverThread = null;
        }
    }
    

    Nothing too complex there, it’s just about pausing the thread (remember, there are other tread attached in it), closing the other thread leaving in the Server object and cleaning everything. I hope it’s the good code to let it clean Sourire But at the end of the day, my only interest is to let this server running all the time. So I don not really care if it will stop correctly!

    Now, to use the server, easy:

    private static WebServer server;
    
    // Start the HTTP Server
    
    WebServer server = new WebServer(80, 10000);
    server.CommandReceived += new WebServer.GetRequestHandler(ProcessClientGetRequest);
    // Start the server.
    server.Start();
    

    Declare a static WebServer if you want it to be unique. Technically, you can have multiple servers running on different port. In my case, no need for this. Then, it’s about creating the object, adding an event and starting the server!

    private static void ProcessClientGetRequest(object obj, WebServer.WebServerEventArgs e)
    

    And you are ready to do some treatment into this function. To return part of the answer, just use e.response.Send as for the header part and you’re done!

    To simplify the process, as it’s a function which you’ll have to call often, I’ve created a function to do this:

    public static string OutPutStream(Socket response, string strResponse)
    {
        byte[] messageBody = Encoding.UTF8.GetBytes(strResponse);
        response.Send(messageBody, 0, messageBody.Length, SocketFlags.None);
        //allow time to physically send the bits
        Thread.Sleep(10);
        return "";
    }
    

    This can be a function you add in your main code or can add in the Web Server code.

    Now you have a fully functional simple Web Server. You can read the previous article on how to handle parameters and analyzing them. The code to manage the parameter is now in the WebServer class.

    I’ll post the code in CodePlex so anyone will be able to use it as a helper.

    Enjoy this code Sourire Again, I’m just a marketing director doing some code. And it’s the code running in my sprinkler management system for the last month without any problem!

  • Laurent Ellerbach

    Using XMLHttpRequest to pilot a Lego train dynamically in HTML 5

    • 4 Comments

    It’s a long time I did not write a blog post. I was very busy and had no time to write and code anything in the last weeks. I still have a lot of work but I need an intellectual break for the evening. So I do not write this post from a plane but from an hotel room. In my past blog posts I’ve explained how to pilot any Lego Power System with a Netduino using .NET Microframework.

    In the HTTP Web server I’ve implemented, I command the train thru a URL with arguments. Those arguments are transformed into parameters which are given to a class. This class output a wave form into an infrared led amplified by a transistor. This is a simple and efficient way to command anything. I do the same for my sprinkler system.

    Now if you want to pilot in a web interface multiple trains, and click on buttons or pictures to get an action without opening a new web page or refreshing the page, you need to do some Scripting in your HTML page. I’m not a web developer, I don’t like Scripting languages as they are not strict enough to write correct code and imply too many errors. They drastically increase your development time! I truly prefer a good language like C#, VB or even Java and I can go up to C/C++ Sourire Now, if I want to avoid any problem, I can jump into Eiffel Sourire OK, I won’t go up to there, I’ll stay with java script in an HTML5 page.

    What I want is to call my command page in the background of the page and stay in the HTML page when I click on a button. There is a nice object in HTML which allow you to do that which is XMLHttpRequest. It is implemented in all decent browsers.

    Here is the code that I generate dynamically (I’ll show you the code later) and I’ll explain you how it works:

    <html xmlns="http://www.w3.org/1999/xhtml"><head>
    <title></title></head><body>
    <SCRIPT language="JavaScript">
    var xhr = new XMLHttpRequest();
    function btnclicked(boxMSG, cmdSend) {
        boxMSG.innerHTML = "Waiting";
        xhr.open('GET', 'singlepwm.aspx?' + cmdSend + '&sec=');
        xhr.send(null);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4)
            { boxMSG.innerHTML = xhr.responseText; } 
    };
    }
    </SCRIPT>
    <TABLE BORDER="0"><TR><TD>
    <FORM>Super train</TD><TD>
    <INPUT type="button" 
    onClick="btnclicked(document.getElementById('train0'),
    'pw=11&op=0&ch=254')" 
    value="<"></TD><TD>
    <INPUT type="button" 
    onClick="btnclicked(document.getElementById('train0'),
    'pw=8&op=0&ch=254')" value="Stop"></TD><TD>
    <INPUT type="button" 
    onClick="btnclicked(document.getElementById('train0'),
    'pw=5&op=0&ch=254')" value=">"></TD><TD>
    <span id='train0'></span></FORM></TD></TR>
    
    

    In the script part of the page, I have created a simple script. Those lines of code is what is necessary to do a synchronous call of an HTTP page and display the result in the page.

    I create an XMLHttpRequest object which I call xhr. The function call btnclicked takes 2 arguments. the first one is the element of the page I will put the results of the request. And the second one is the command (the parameters) to pass to the URL which will pilot the infrared led as explain previously.

    The function is very simple. First, I put “Waiting” in the element. Then I open the XMLHttpRequest object. I open it with GET and pass the overall URL.

    The request is done when the send function is called. It is a synchronous call, so it get to the onreadystatechange when it is finished.

    Here, when you read the documentation, the readyState 4 mean that everything went well and you have your data back. My function return “OK” when everything is OK and “Problem” if there is a problem.

    Now let have a look at the rest of the HTML page. I decided to create a form with button input. Each button input has a onClick event. This event can be linked to a script. So I will call the fucntion describe before and give a span element (here train0) and the URL. The URL is different depending if you want to train to go forward, backward or stop. And I put all this in a nice table top be able to have multiple trains.

    The page with 4 trains looks like this:

    image

    I’ve clicked on the forward button, “Wainting” is displayed in span. And as soon as the command will finish, it will either display OK or Problem. In my case, Problem will be displayed as in the Emulator, there is no SPI port!

    // Start HTML document
    strResp = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
    ; strResp += "<html xmlns=\"http://www.w3.org/1999/xhtml\">
    <head><title></title></head><body>"
    ; //creat the script part strResp += "<SCRIPT language=\"JavaScript\">"; strResp += "var xhr = new XMLHttpRequest(); function btnclicked(boxMSG, cmdSend)
    { boxMSG.innerHTML=\"Waiting\";"
    ; strResp += "xhr.open('GET', 'singlepwm.aspx?' + cmdSend + '&" + securityKey + "');"; strResp += "xhr.send(null); xhr.onreadystatechange = function()
    {if (xhr.readyState == 4) {boxMSG.innerHTML=xhr.responseText;}};}"
    ; strResp += "</SCRIPT>"; strResp = WebServer.OutPutStream(response, strResp); // Create one section for each train strResp += "<TABLE BORDER=\"0\">"; for (byte i = 0; i < myParamRail.NumberOfTrains; i++) { strResp += "<TR><TD><FORM>" + myParamRail.Trains[i].TrainName + "</TD>
    <TD><INPUT type=\"button\"
    onClick=\"btnclicked(document.getElementById('train"
    + i + "')
    ,'pw="
    + (16 - myParamRail.Trains[i].Speed); strResp += "&op="+ myParamRail.Trains[i].RedBlue + "&ch=" +
    (myParamRail.Trains[i].Channel - 1) + "')\" value=\"<\"></TD>"; strResp += "<TD><INPUT type=\"button\"
    onClick=\"btnclicked(document.getElementById('train"
    + i + "'),'pw=8"; strResp += "&op=" + myParamRail.Trains[i].RedBlue + "&ch=" +
    (myParamRail.Trains[i].Channel - 1) + "')\" value=\"Stop\"></TD>"; strResp += "<TD><INPUT type=\"button\"
    onClick=\"btnclicked(document.getElementById('train"
    + i + "'),
    'pw="
    + myParamRail.Trains[i].Speed; strResp += "&op=" + myParamRail.Trains[i].RedBlue + "&ch=" +
    (myParamRail.Trains[i].Channel - 1) + "')\" value=\">\"></TD>"; strResp += "<TD><span id='train" + i + "'></span></FORM></TD></TR>"; strResp = WebServer.OutPutStream(response, strResp); } strResp += "</TABLE><br><a href='all.aspx?" + securityKey +
    "'>Display all page</a>"; strResp += "</body></html>"; strResp = WebServer.OutPutStream(response, strResp);

    The code to generate the HMTL page is here. As you see it is manually generated. The table which contains the name of the train, the backward, stop and forward button is created totally dynamically. Each train may have a different speed and use different channels so the URL is generated dynamically.

    All this takes time to generate and to output in the Stream. So it’s much better to do it only 1 time and then call a simple and small function which will return just a bit of text.

    Last part, on the server header, you have to make sure you add “Cache-Control: no-cache” in the response header. If you don’t do it, only the first request will be send to the netduino board back. XMLHttpRequest will consider that the page will never expire. So I’ve modified the header code of my HTTP Server like this:

    string header = "HTTP/1.1 200 OK\r\nContent-Type: text/html; 
    charset=utf-8\r\nCache-Control: no-cache\r\nConnection:
    close\r\n\r\n"
    ; connection.Send(Encoding.UTF8.GetBytes(header), header.Length,
    SocketFlags.None);

    What is interesting there is that I can now pilot up to 8 Lego trains using this very simple interface and without having to refresh the page.

    And the excellent news is that it is working from my Windows Phone so it’s even cool to pilot your Lego train from your Windows Phone. I haven’t tested from an Android or iPhone but I’m quite sure it will work the same way. Remember that all the code is sitting in a very small hardware with no OS, just .NET Microframework! As always, do not hesitate to send me your comments Sourire

  • Laurent Ellerbach

    .NET Microframework on RaspberryPi (Part 1)

    • 4 Comments

    I’m a bit fan of .NET Microframework (NETMF). NETMF is an open source technology originally developed by Microsoft based on .NET. It directly run on metal, without any OS. All sources and portability kit are freely available On Codeplex: http://netmf.codeplex.com/.

    And as a fan of Embedded devices I had to buy this inexpensive RaspberryPi http://www.raspberrypi.org/. I bought the version second revision with the network adaptor. Advantage is clearly the price and having access to couple of GPIO like SPI,k i2c, PWM, serial and couple of other digital IO. Now it’s a slow device when using the user interface, there is no analog input or output, PWM is limited to only 1 hardware PWM and not really flexible for setting the frequencies. But overall, for the price, it’s Worth playing a bit with it.

    In term of environment, it runs under Linux, it was a very long time I did not had to setup and make a Linux working. I was just reminding couple of commands. And I’m far to be a Linux developer… so I’ve started to look at what to put that looks like C# or .NET on this board and more specifically .NET Microframework.

    I was disappointed to see that NETMF is not on the platform. But happy to see a good implementation of Mono http://www.mono-project.com/Main_Page. So at least I was able to run some .NET code on the Raspberry and take the advantage of the display if needed with Windows forms.

    So what for access like we do in NETMF to the GPIO? I started to search on the web for what is possible to do. And I found a first project RaspberryPi.Net: https://github.com/cypherkey/RaspberryPi.Net/. This project is using one library to access the BCM2835 chipset where the GPIO are managed. I found the last version of the library here: http://www.airspayce.com/mikem/bcm2835/

    And I just followed the steps explained on the RaspberryPi.Net project page. Here are the steps. Open an LXTerminal and type:

    sudo apt-get update

    sudo apt-get install xrdp

    this second one will allow you to access your Raspberry thru RDP Sourire So you can do remote desktop on your Raspberry as you do with any other Windows machine.

    sudo apt-get install mono-runtime

    this will install Mono and all what is needed to run a .NET program.

    sudo apt-get install git

    Very useful if you need to download Git projects. I’ll explain how to use it in the next part of this article as I’ve used it.

    Now we go thru the download of the BCM2835 library, the compilation, the installation:

    wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.25.tar.gz

    tar -zxvf bcm2835-1.25.tar.gz

    cd bcm2835-1.25

    ./configure

    make

    sudo make install

    cd src

    cc -shared bcm2835.o -o libbcm2835.so

    cd

    rm bcm2835-1.25.tar.gz

    Now, you have to copy the libbcm2835.so library with the executable you’ll produce at the end. And for the moment you’re done with the RaspberryPi.

    Go on Windows, download the code from https://github.com/cypherkey/RaspberryPi.Net/, open the project in Visual Studio, if like me you’re using the 2012 version, you may have to change the target to .Net Framework 4.0, change the pin you want to use to put a led, compile the project, put the exe and the so on a USB stick for example, or use any other way to copy it on your Rapsberry.

    image

    I’ve used GPIO 7 (pin 11 on the board), ground on pin 9, I put a Led and a 60 ohms resistor.

    Use this site as a reference to know which pin does what: http://elinux.org/Rpi_Low-level_peripherals. Very well done, with all the details.

    image

    On the Raspberry, run the following command line from the directory you’ve copied the exe and the so file:

    Sudo mono yourprogramm.exe

    of course, yourprogramm here represent the name of the program you’ve done. And in my case I made the link blinking.

    The way it’s working is quite simple. Like in a normal .Net program, you can import external DLL like the system ones. Here, you import the same way but of course not DLL but object. See the following example:

     

    [DllImport("libbcm2835.so", EntryPoint = "bcm2835_spi_transfernb")]
    static extern void bcm2835_spi_transfernb(
    [MarshalAs(UnmanagedType.LPArray)]byte[] tbuf, 
    [MarshalAs(UnmanagedType.LPArray)]byte[] rbuf, UInt32 len);
    

    In this case, it’s interesting as you’ll have to use the Marshaling. And you’ll have to do in a similar way for all the array, strings, pointers and anything what is not a very simple as byte, uint or other. Be also very careful on the length of the parameters, make sure you match them correctly.

    And I’ve quickly implemented a compatible class for Cpu.Pin, SPI, OutputPort and PWM by importing the various functions from the BCM2835 library.

    My main goal was to reuse the maximum of code from an SPI example piloting a 3.5$ Nokia 5110 LCD screen. I reused the code found on the Netduino wiki page: http://wiki.netduino.com/Nokia-5110-LCD.ashx?HL=nokia.

    I did it in couple of hours, exporting the definition from the NETMF code to a new project. As a result, I manage to make it work perfectly on my RaspberryPi!! Cool Sourire 

    image

    Now, I quickly found lots of limitation in the BCM2835 library I’ve used. PWM was not implemented, I found bugs in the SPI part, no support of interruptions, and others.

    So I’ve looked at another library and I found the WiringPi http://wiringpi.com/. This library was a bit more complete. Still not the perfect one but more complete. It does implement SPI, i2c, soft and hard PWM and interruption support for the digital IO. It does support also advanced implementations like the helpers we can find in NETMF.

    And from this points, I’ve used the NETMF portability kit with all the definitions, all the sources to make it as much compatible as possible with NETMF. See my next posts to find more about it and find the Codeplex project associated.

    Ultimately, I’d love to port the full NETMF on RaspberryPi but for this, I’ll need much more time than I have or other very motivated persons.

  • Laurent Ellerbach

    .NET Microframework (NETMF) Web Server source code available

    • 3 Comments

    So as I got lots of asks to get the code of my Web Server, I’ve decided to create a Codeplex project. You’ll find the source here: https://netmfwebserver.codeplex.com/

    It does include the following features:

    • Start, stop, Pause the Web Server
    • Creation of a Web Server on any port
    • Fully functional multithread Web Server supporting GET only
    • Downloading any file present on a SD (or any other physical storage)
    • A full function to get all the parameters of a URL

    Examples of usage can be found on this blog. Working to publish a fully functional example.

    Feedback welcome!

  • Laurent Ellerbach

    J’ai hacké mon onduleur ou le reverse engineering de protocoles de communication (part 3)

    • 3 Comments

    Pour faire suite aux deux premiers article sur le sujet, je vais rentrer un peu dans le dur de l’analyse du protocole de communication de mon onduleur. Pour mémoire, je me suis arrêté en disant que j’avais lancé PortMon et que j’avais vu plein de choses intéressantes. Voici donc les résultats :

    0    0.00004426    RupsMon.exe    IRP_MJ_CREATE    Serial0    SUCCESS    Options: Open     

    1    0.00000178    RupsMon.exe    IOCTL_SERIAL_SET_TIMEOUTS    Serial0    SUCCESS    RI:-1 RM:5 RC:80 WM:0 WC:0    

    2    0.00000091    RupsMon.exe    IOCTL_SERIAL_GET_BAUD_RATE    Serial0    SUCCESS        

    3    0.00000104    RupsMon.exe    IOCTL_SERIAL_GET_LINE_CONTROL    Serial0    SUCCESS        

    4    0.00000083    RupsMon.exe    IOCTL_SERIAL_GET_CHARS    Serial0    SUCCESS        

    5    0.00000100    RupsMon.exe    IOCTL_SERIAL_GET_HANDFLOW    Serial0    SUCCESS        

    6    0.00000087    RupsMon.exe    IOCTL_SERIAL_GET_BAUD_RATE    Serial0    SUCCESS        

    7    0.00000082    RupsMon.exe    IOCTL_SERIAL_GET_LINE_CONTROL    Serial0    SUCCESS        

    8    0.00000083    RupsMon.exe    IOCTL_SERIAL_GET_CHARS    Serial0    SUCCESS        

    9    0.00000089    RupsMon.exe    IOCTL_SERIAL_GET_HANDFLOW    Serial0    SUCCESS        

    10    0.00000689    RupsMon.exe    IOCTL_SERIAL_SET_BAUD_RATE    Serial0    SUCCESS    Rate: 2400    

    11    0.00000391    RupsMon.exe    IOCTL_SERIAL_SET_RTS    Serial0    SUCCESS        

    12    0.00000351    RupsMon.exe    IOCTL_SERIAL_SET_DTR    Serial0    SUCCESS        

    13    0.00000250    RupsMon.exe    IOCTL_SERIAL_SET_LINE_CONTROL    Serial0    SUCCESS    StopBits: 1 Parity: NONE WordLength: 8    

    14    0.00000124    RupsMon.exe    IOCTL_SERIAL_SET_CHAR    Serial0    SUCCESS    EOF:0 ERR:0 BRK:0 EVT:d XON:11 XOFF:13    

    15    0.00000238    RupsMon.exe    IOCTL_SERIAL_SET_HANDFLOW    Serial0    SUCCESS    Shake:1 Replace:40 XonLimit:2048 XoffLimit:512    

    16    0.00000225    RupsMon.exe    IOCTL_SERIAL_SET_WAIT_MASK    Serial0    SUCCESS    Mask: RXCHAR     

    17    0.00000260    RupsMon.exe    IOCTL_SERIAL_SET_WAIT_MASK    Serial0    SUCCESS    Mask: RXFLAG         

    Alors, comment lire ces résultats ? Et bien c’est simple, à l’ouverture du port série, PortMon intercepte les appels au port série. On y voit un IOCTL_SERIAL_SET_BAUD_RATE Serial0 SUCCESS Rate: 2400 qui nous indique que le port a été ouvert à 2400 baud. En lisant les quelques lignes qui suivent, on trouve les autres informations :

    • 1 bit de stop
    • Pas de parité
    • Un mot de 8 bits

    Nous avons donc la première information nécessaire pour communiquer avec l’onduleur. Nous avons eu pas mal de chance car il est possible que les appels ne passent pas en mode user et donc l’espionnage du port série avec un outil tel que PortMon ne fonctionne pas. C’est par exemple le cas du service Windows onduleur. Alors comment faire dans ces cas là ? Et bien, il faut ressortir l’oscilloscope. L’oscilloquoi ? L’oscilloscope. Un instrument qui permet d’analyser des signaux, le truc que l’on utilise en TP au collège. Le principe est simple, il suffit de brancher une des bornes de l’oscilloscope sur la masse et l’autre sur une des bornes de communication. Ensuite, il faut faire parler entre eux les appareils (dans notre cas l’ordinateur et l’onduleur) et capturer les signaux (les oscilloscopes modernes permettent tous de le faire). Ensuite, il suffit d’analyser la longueur d’un bit ou de plusieurs bits et d’en déduire la fréquence. Je vais expliquer comment faire un peu plus loin.

    A défaut d’avoir un onduleur, il est possible de capturer les signaux sur une carte son par exemple. Le montage est simple et fonctionne également. Il suffit pour cela de faire la même chose qu’avec l’oscilloscope (la masse de l’entrée micro sur la masse du port série et la borne 2 sur l’entrée gauche et la borne 3 sur l’entrée droite par exemple. Ensuite, il suffit d’enregistrer avec n’importe quel logiciel de capture de son ce qui passe sur le micro. Attention, il faut fixer le gain plutôt faible car 5 volts (tension de sortie du port série) est assez important. Normalement, pas de problème côté carte son mais bon, mieux vaut être prévoyant pour ne pas abîmer le matériel. Au pire, le signal « clipera » (saturera) mais ce n’est pas important dans notre cas, nous essayons seulement de capturer des bits donc des 0 et des 1. Peu importe le niveau de crête. L’analyse se passe de la même façon qu’avec l’oscilloscope. La période de plusieurs bits donne la fréquence. Pour la calculer, c’est simple, il faut juste connaître la fréquence d’échantillonnage (comme sur l’oscilloscope). Imaginons que l’on capture un signal à 44KHz, la période est donc de 2,3 10^-5 secondes. Avec un logiciel permettant de zoomer suffisamment, sur le signal acquis, il est possible de calculer la période du signal. Imaginons que nous ayons 18 points entre deux crêtes, cela nous donne donc une période de 4,09 10^-4 secondes et donc une fréquence de 2440 Hz (rappel, fréquence en Hertz = 1 / période en seconde). Et donc on retombe facilement sur 2400 Hz. Evidemment, la vrai vie, c’est un petit peu plus compliqué que cette théorie. En général, on est obligé de prendre plusieurs bits, de prier pour que les bits ne soient pas doublés (ça peut arrive avec beaucoup de malchance) car sinon la fréquence est multipliée par deux.

    Avec un peu d’expérience, on y arrive assez facilement. Avec cette méthode, une fois la fréquence déterminée, il est possible de déterminer la parité (il faut plusieurs mots différents pour être sûr), le nombre de bits de stop et aussi la longueur d’un mot. Ca peut prendre un peu de temps et il faut faire dialoguer les appareils entre eux pas mal de fois pour être sûr de ne pas se tromper. Et c’est là que la norme complète aide beaucoup :-) J’ai eu à faire ce type de manipulation, lorsque je développait l’application de récupération d’information du PDP. C’était sur le port parallèle. Croyez-moi, ça forme :-) Une bonne expérience que l’on devrait faire faire à tous les étudiants en TP d’informatique/électronique. En plus, les tests après permettent de valider les informations trouvées par cette expérience.

    Maintenant, j’ai toutes les informations nécessaires pour me connecter à l’onduleur, il me faut maintenant déterminer son protocole pour pouvoir dialoguer avec lui. La suite au prochain post !

  • Laurent Ellerbach

    EXCLUSIVITE - Windows Home Server : le serveur clé en main et simple de la maison !

    • 3 Comments

    Nous venons d'annoncer au CES (Consumer Electronics Show) une nouvelle version de la famille Windows Server. Il s'agit de Windows Home Server, nom de code Q (Quattro). Et comme son nom l'indique, cette version est dédiée à créer un serveur personnel à la maison.

    Son utilisation est ultra simple. Il suffit de brancher et le reste s'effectue de façon quasi automatique. Il back-up notamment en heure creuse l'ensemble des données des PC de la maison et permet une restauration rapide en cas de problème. Il se back-up d'ailleurs lui-même :-). J'ai eu l'occasion de "jouer" un peu avec cette version et le résultat, même dans les versions très préliminaires est positivement surprenant.

    Voici d'ailleurs un prototype de Windows Home Server. De quoi passer la barrière du WAF (Women Acceptation Factor) :-)

    Une vidéo explicative sur : http://www.on10.net/Blogs/jesse/windows-home-server-will-live-in-your-closet-simplify-your-life/

    Un site en développement en partenariat avec HP et AMD qui traite exclusivement de Windows Home Server : http://www.stopdigitalamnesia.com/

    L'annonce presse officielle sur : http://www.microsoft.com/presspass/press/2007/jan07/01-07CES2007PR.mspx

    Evidemment, une recherche sur Live donne aussi de bonnes infos : http://search.live.com/results.aspx?q=%22windows+home+server%22

     

  • Laurent Ellerbach

    J’ai hacké mon onduleur ou le reverse engineering de protocoles de communication (part 4)

    • 2 Comments

    Me voici donc au quatrième épisode. Pour suivre les épisodes précédents, c’est ici pour le premier, ici pour le second et ici pour le troisième. Pour rappel, j’ai donc réussi à obtenir les informations nécessaires à l’ouverture du port série. J’en ai profité pour donner quelques explications qui permettent avec différentes méthode d’obtenir ces informations. Même si l’exemple est basé sur un port série, cela fonctionne avec à peu près n’importe quel type de protocole. Le principe de base reste le même.

    Je tiens quand même à apporter quelques précisions si vous utilisez un procédé d’acquisition discret tel que la carte son. Dans l’exemple que j’ai donné, je suis parti sur une acquisition à 44,1 KHz (ce qui correspond à ce que la plupart des cartes d’acquisition audio fond en standard). Il ne faut pas oublier le théorème de Nyquist – Shanon qui stipule que la fréquence maximale que l’on peut acquérir est égale à la moitié de la fréquence d’acquisition. Donc si l’on acquière à 44,1 KHz, cela donne donc une fréquence maximale de 22,05 KHz. En effet, il faut au moins 2 points dans une période pour déterminer la fréquence d’un sinus pur. Si l’on utilise une carte son, avec cette fréquence d’acquisition, cela permet de calculer jusqu’à 19 600 baud. Au-delà, il faut donc acquérir avec une fréquence plus importante (si la carte le permet) ou vraiment utiliser un oscilloscope.

    Aller, je gardais une autre solution pour ce post : utiliser un port parallèle qui permet d’acquérir avec une fréquence suffisamment importante pour aller jusqu’à 115 KHz /2 soit 57,5 KHz. Le montage n’est pas plus compliqué et il faut écrire à la main le bout de soft qui permet de faire cela. Quand j’étais étudiant (il y a bien longtemps maintenant…), nous nous amusions à faire des chenillards et autres affichages loufoques à base de port parallèle. Un port très sympathique qui a inspiré la plupart des affichages LCD de façade…

    Bon, revenons-en au code. J’ai promis à Benjamin (qui est dans mon équipe) que je publierais un peu code. Alors, Benj, chose promise, chose due :-) Je vais donc publier un morceau de code qui permet de se connecter à l’onduleur, de lui envoyer du texte et de récupérer ce qui en revient. Ce code est basé sur un projet (How-to Using the Comm Port) de GotDotNet. Il permet aux utilisateurs du framework 1.0 et 1.1 de bénéficier d’une classe super bien faite pour accéder aux ports séries. Ca me rappelle celle que j’avais dû faire et que j’utilisais à l’époque en C++. De base dans le framework 2.0, il y a tout ce qu’il faut avec la classe SerialPort, elle aussi bien faite. Je suis parti du projet de GotDotNet car je l’ai trouvé très rapidement et qu’il y avait du code pour m’inspirer. Donc, benj, ouvre les yeux, voici mon code :

    ' BtnSendOnduleur est un bouton :-)

    Private Sub BtnSendOnduleur_Click(ByVal sender As System.Object, ByVal e As

    System.EventArgs) Handles BtnSendOnduleur.Click

    ' Les Ports, c’est comme les fichiers, dès qu’on s’en sert, faut les try catch.

    Try

    m_CommPort.Open(1, 2400, 8, Rs232.DataParity.Parity_None, Rs232.DataStopBit.StopBit_1, 64)

    ' TxtSendOnduleur est une boîte de texte, texte à envoyer à l’onduleur

    m_CommPort.Write(Encoding.ASCII.GetBytes(TxtSendOnduleur.Text & Chr(13)))

    'Une pose quand on ouvre un port, ça fait toujours du bien

    System.Threading.Thread.Sleep(200)

    Application.DoEvents()

    ' Try pour la récupération des données.

    Try

    ' Je lit une donnée et toutes celles qui suivent. Quand le retour est -1, c’est timeout, donc, en principe, plus de données à lire

    While (m_CommPort.Read(1) <> -1)

    ' txtStatus est une boîte de texte qui permet de mettre le résultat de la lecture du port.

    txtStatus.Text = txtStatus.Text + Chr(m_CommPort.InputStream(0))

    End While

     

    m_CommPort.Close()

    Return

    Catch exc As Exception

    ' Rien à lire ou un problème

    m_CommPort.Close()

    Return

    End Try

    Catch exc As Exception

    ' Impossible d’ouvrir le port

    MsgBox("Port pas ouvert.", MsgBoxStyle.OkOnly, Me.Text)

    Return

    End Try

    End Sub

    Maintenant que tu as vu le code, je vais expliquer à quoi il me sert. Revenons sur l’exercice que j’ai fait avec PortMon. Voici la suite de ce que j’ai récupéré pas la suite :

    28    0.00002172    RupsMon.exe    IRP_MJ_WRITE    Serial0    SUCCESS    Length 2: F.    

    29    0.11777290    RupsMon.exe    IOCTL_SERIAL_WAIT_ON_MASK    Serial0    SUCCESS        

    30    0.00445378    RupsMon.exe    IRP_MJ_WRITE    Serial0    SUCCESS    Length 3: Q1.    

    31    0.00000703    RupsMon.exe    IOCTL_SERIAL_GET_COMMSTATUS    Serial0    SUCCESS        

    32    0.00000273    RupsMon.exe    IOCTL_SERIAL_GET_COMMSTATUS    Serial0    SUCCESS        

    33    0.00000576    RupsMon.exe    IRP_MJ_READ    Serial0    SUCCESS    Length 22: #230.0 2.2 12.00 50.0.    

    34    2.09370086    RupsMon.exe    IOCTL_SERIAL_WAIT_ON_MASK    Serial0    SUCCESS        

    35    0.00000559    RupsMon.exe    IOCTL_SERIAL_PURGE    Serial0    SUCCESS    Purge: TXCLEAR     

    36    0.00002896    RupsMon.exe    IRP_MJ_WRITE    Serial0    SUCCESS    Length 3: Q1.    

    37    0.00000333    RupsMon.exe    IOCTL_SERIAL_WAIT_ON_MASK    Serial0    INVALID PARAMETER        

    38    0.00000359    RupsMon.exe    IOCTL_SERIAL_GET_COMMSTATUS    Serial0    SUCCESS        

    39    0.00000191    RupsMon.exe    IOCTL_SERIAL_GET_COMMSTATUS    Serial0    SUCCESS        

    40    0.00000388    RupsMon.exe    IRP_MJ_READ    Serial0    SUCCESS    Length 47: (239.0 239.0 239.0 022 50.0 13.9 32.0 00001000.    

    41    0.00002742    RupsMon.exe    IRP_MJ_WRITE    Serial0    SUCCESS    Length 2: F.    

    42    0.11799550    RupsMon.exe    IOCTL_SERIAL_WAIT_ON_MASK    Serial0    SUCCESS        

    43    0.00000374    RupsMon.exe    IOCTL_SERIAL_GET_COMMSTATUS    Serial0    SUCCESS        

    44    0.00000183    RupsMon.exe    IOCTL_SERIAL_GET_COMMSTATUS    Serial0    SUCCESS        

    45    0.00000380    RupsMon.exe    IRP_MJ_READ    Serial0    SUCCESS    Length 22: #230.0 2.2 12.00 50.0.    

    46    0.00011600    RupsMon.exe    IRP_MJ_WRITE    Serial0    SUCCESS    Length 3: Q1.    

    47    0.22647997    RupsMon.exe    IOCTL_SERIAL_WAIT_ON_MASK    Serial0    SUCCESS        

    48    0.00000381    RupsMon.exe    IOCTL_SERIAL_GET_COMMSTATUS    Serial0    SUCCESS        

    49    0.00000182    RupsMon.exe    IOCTL_SERIAL_GET_COMMSTATUS    Serial0    SUCCESS        

    50    0.00000407    RupsMon.exe    IRP_MJ_READ    Serial0    SUCCESS    Length 47: (239.0 239.0 239.0 022 50.0 13.9 32.0 00001000.    

    En gros, quand la commande F ou Q1 est envoyée, il y a un retour. Pour définir ce que le point représente, j’ai fait une acquisition en binaire. Cela donne pour Q1 : IRP_MJ_WRITE    Serial0    SUCCESS    Length 3: 51 31 0D

    0D = 13 en décimal, ce qui correspond au caractère « entrée ». Très classique dans le cas de communication avec des appareils en port série. D’où dans le code, TxtSendOnduleur.Text & Chr(13) qui permet d’envoyer du texte (F ou Q1 pour faire les premiers tests) avec le caractère « entrée ». Mon programme permet donc d’envoyer une commande, de récupérer le résultat et de l’afficher dans une boîte de texte. A noter que j’ai fait ce code uniquement pour me dérouiller. Inutile dans mon cas, j’aurais pu utiliser le bon vieux terminal Windows qui fait exactement la même chose (en mieux). J’ai écrit ce code, toujours dans l’optique de me dérouiller. De toute façon, ce n’est pas perdu, j’aurais besoin d’en écrire et à peu près le même pour mon application finale. Je reviendrais sur cet excellent outil qu’est le Terminal Windows et qui m’a presque fait oublier ma VT100

    A noter qu’avec VB 2005, pour ouvrir un port, on peut utiliser l’excellente classe My en faisant un Dim MonPort As System.IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort("COM1", 2400, IO.Ports.Parity.None, 8, IO.Ports.StopBits.One). Ensuite, la classe SerialPort permet d’envoyer et récupérer des données. Je l’utiliserais dans mon application finale.

    Du coup, cette application, m’a permit d’envoyer diverses commandes et de voir la réaction de l’onduleur et le retour qu’il a pu m’en faire. Cela m’a permit de déterminer (quasiment) toutes les commandes disponibles et donc de déterminer quel est le langage entre l’onduleur et le PC. La suite au prochaine numéro…

  • Laurent Ellerbach

    IDEES ou comment aider les start-up

    • 2 Comments

    Microsoft France a lancé un programme de soutient aux start-up l'année dernière. Ce programme se nomme IDEES et parrainait l'année dernière 25 start-up. Ce nombre va doubler cette année pour atteindre 50. La liste des start-up et les détails de l'aide apporté sont disponibles sur le site.

    La campagne actuelle est d'ailleurs très sympa :

    On imagine une nouvelle entreprise, de nouveaux potentiels

    L'aide à l'innovation ne s'arrête pas là puisque début 2005, Microsoft a ouvert, dans ses locaux parisiens du VIIème arrondissement, un centre technologique de pointe (le MTC – Microsoft Technology Center) permettant de travailler main dans la main avec partenaires et grands clients, ainsi qu'avec des éditeurs de logiciels indépendants. Ces derniers peuvent y tester leurs applications dans différents environnements matériels et logiciels, accéder aux ressources techniques de Microsoft et bénéficier d'une aide à l'architecture afin d'accélérer leurs développements logiciels. Pour tout contact avec le MTC : mtcparis@microsoft.com

    Toujours dans le but de contribuer à l'économie local et à l'innovation en France, cette année vient d'être inauguré un laboratoire de recherche commun entre Microsoft et l'INRIA. Plus d'infos sur cette page.

  • Laurent Ellerbach

    Imagine Cup 2008 se d&#233;roulera &#224; Paris en 2008 !!!

    • 2 Comments

    Et oui, Paris sera la capitale du monde mondial en 2008. Mieux que les JO, la finale d'Imagine Cup, la grande compétition des nouvelles technologies à destination des étudiants se déroulera à Paris. (cf http://www.imaginecup.fr pour ceux qui ne connaissent pas encore).

    L'annonce a été faite hier soir au premier étage de la Tour Eiffel par Jean-Philippe Courtois, Président de Microsoft International et Senior Vice Président de Microsoft Corp !

    La soirée a aussi été l'occasion d'annoncer les gagnants de la catégorie "conception logicielle".

    L’ISEN Toulon se qualifie pour la grande finale coréenne L’événement a permis aux équipes d’étudiants sélectionnées de présenter leurs projets. A l’issu des délibérations, le Jury a déclaré l’équipe constituée de Bastien Ingweiller, Nathalie Pettier, Johanna Piou, Charles Hétier de l’ISEN Toulon, vainqueur de cette finale française. Leur solution est tout simplement exceptionnelle et permet à des étudiants handicapés d'apprendre ou de réapprendre.

    Enfin, Régis Hanol, serial habitué de la catégorie Project Hoshimi et serial finaliste (déjà 2 finales internationnales) a gagné la catégorie française ! Il a clairement d'excellentes chances d'arriver dans les 6 premiers internationnaux. 

    Le communiqué de presse en français est dispo sur :

    http://www.microsoft.com/france/CP/2007/6/2007060701_a146.mspx

    Tout le monde en parle déjà (et encore, ce ne sont que quelques liens) :

    http://www.01net.com/article-actualites/paris-accueillera-limagine-cup-2008-un-concours-technologique-high-tech-reuters.-01net.html

    http://codor.blogs.com/intro/2007/06/imagine_cup_200.html

    http://potinblog.typepad.com/potin_blog/2007/06/imagine_cup_200.html

    http://quoideneufaujourdhui.spaces.live.com/Blog/cns!42006D96A523B059!378.entry

    http://groquikman.free.fr/live/?p=239

    http://benjamingauthey.com/PermaLink,guid,28b49bc5-16f4-4ee7-988f-38d6f5d066f8.aspx

    http://blogs.developpeur.org/kangoo/archive/2007/06/06/Imagine-Cup-2008-Cocorico-Ca-se-passera-en-France.aspx

    http://groquikman.free.fr/live/?p=239

    http://www.lemonde.fr/web/depeches/0,14-0,39-31191441@7-37,0.html

    http://www.infos-du-net.com/actualite/10787-Imagine-Cup-Microsoft.html

    http://www.infos-du-net.com/actualite/10787-Imagine-Cup-Microsoft.html

    http://www.afjv.com/press0706/070607_imagine_cup_2008.htm

    http://sevanno.free.fr/wordpress/

    http://jmgall.typepad.com/weblog/2007/06/post_6.html

    http://www.neteco.com/74815-microsoft-france-accueillera-prochaine-imagine-cup.html

    http://www.jbouteiller.net/Imagine-Cup-sur-la-Tour-Eiffel_a535.html

    http://thibautlegendre.com/informatique/mieux-que-les-jo-limagine-cup.htm

    http://test1.wananow.net/2007/06/07/paris-accueillera-limagine-cup-2008-un-concours-technologique-reuters/

     

  • Laurent Ellerbach

    Quiksilver : du Silverlight qui déchire :-)

    • 2 Comments

    Quiksilver en partenariat avec Microsoft a développé un super player pour suivre la compétition Quiksilver Pro France.

    Ca se passe ici : http://premium.quiksilverlive.com/

    Au menu :

    • les lives quand il y a des vagues, là, y'en n'a pas :-(
    • les replays de toutes les meilleurs vagues
    • les scores
    • les stats
    • la possibilité de noter des vagues
    • une gallerie de photo
    • le tout en HD pour ceux qui veullent !
    • et quelques bonus en plus :-)

    Faut vraiment aller voir pour se donner une idée de ce que l'on peut faire avec Silverlight.

  • Laurent Ellerbach

    La CNJE : Révélateur d'esprit d'entreprise a un blog

    • 2 Comments

    Voilà maintenant plus de 4 ans que Microsoft est partenaire de la Confédération  Nationale des Juniors Entreprises (CNJE). La CNJE est une association qui regroupe toutes les Junior Entreprises (JE) de France. Une JE, c'est une association d'étudiants à but pédagogique qui fonctionne comme une entreprise et propose du service (du vrai) aux entreprises à tarif étudiants.

    Je fais parti des personnes qui sont à l'origine de la signature de ce partenariat. Je suis intéressé par tout ce qui touche à l'aide que l'on peut apporter aux entrepreneurs et aux jeunes pour leur donner envie d'entreprendre.

    Et j'en viens donc au sujet de ce post qui est l'ouverture d'un blog sur l'esprit d'entreprendre animé par les membres de la CNJE :

    http://blog.junior-entreprises.com/

    Je vais l'ajouter à mes flux !

  • Laurent Ellerbach

    Fréquence MSDN, vous connaissez ?

    • 2 Comments

    C'est un nouveau concept que nous lançons. Une émission de radio diffusée en live avec roundtalbe (donc plutôt de la TV avec vision 360° du plateau) à partir du 10 octobre.

    L'objectif est de pouvoir revenir sur l'actialité des quelques semaines passées, décortiquer des annonces et aussi répondre à vos questions en direct. Vous pourrez en effet poser des questions en direct.

    Nous vous réservons également quelques surprises et un peu de fun :-)

    Nous avons prévu 1 heure pour la première émission. Si le concept plait, alors on remettra ça avec d'autres émissions.

    Pour s'inscrire, c'est là que ça passe :

    http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032354930&Culture=fr-FR

  • Laurent Ellerbach

    IIS rattrape Apache comme serveur Web

    • 2 Comments

    Ca faisait déjà un moment qu’IIS progressait et cela continue. La source est l’étude Netcraft qui fait référence depuis plus de 10 ans sur le marché des serveurs Web.

    “This continues the strong gains seen last month, a rate of over 5% monthly growth, with MySpace, Microsoft Live.com, and Google's Blogger each gained over 1 million sites this month. Benefitting from the gains at MySpace and Microsoft Live, Microsoft-IIS now hosts over 50 million sites.”

    Le graphique est d’ailleurs intéressant à suivre : Market Share for Top Servers Across All Domains August 1995 - October 2007clip_image002

    Source : http://news.netcraft.com/archives/2007/10/11/october_2007_web_server_survey.html

  • Laurent Ellerbach

    Adding Bluetooth support to a NETMF board (.NET Microframework)

    • 2 Comments

    I recently bought a very cheap Bluetooth adaptor for my Netduino. I wanted to test how easy/hard it is to support Bluetooth. I see lots of advantages with Bluetooth for a near field communication like piloting easily a robot with a Phone without the need of other network or Infrared. Also Bluetooth is a secured communication with a peering.

    So I bought this cheap Bluetooth adaptor for $8.20. It does expose itself to the world with a serial port on one side and as a normal Bluetooth device on the other side. Communication is supported with a serial port from one side to the other. On a PC, Phone or whatever device, it creates a serial port. So communication is basically very transparent and assimilated to a serial port from end to end.

    JY-MCU Arduino Bluetooth Wireless Serial Port ModuleJY-MCU Arduino Bluetooth Wireless Serial Port Module

    When I received it, I was impatient to test it. First step was to peer it with a PC. I looked at the documentation and found the default name for this device was “linvor” and found out the passkey was 1234. After cabling it with 3.3V (my board support 3.3V to 12V alimentation) and the ground, and approximately 1 minutes, I peered it!

    New step was to write a bit of code to test all this. I decided to do a very basic echo program. So whatever it will receive, it will send it back to the calling program. On the netduino board, I’ll use the COM1 (pins D0 and D1). I found also in less than 1 minute that the default configuration was 9600 bauds, 8 bits, no parity and 1 bit stop. So I wrote this very simple code for the test, very hard to do more basic than that:

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using Microsoft.SPOT;
    using Microsoft.SPOT.Hardware;
    using SecretLabs.NETMF.Hardware;
    using SecretLabs.NETMF.Hardware.Netduino;
    using System.Text; 
    using System.IO.Ports;   
    
    namespace Bluetooth
    {
        public class Program
        {
            static SerialPort serial;
            public static void Main()
            {
                // initialize the serial port for COM1 (pins D0 and D1)             
                serial = new SerialPort(SerialPorts.COM1, 9600, Parity.None, 8, StopBits.One);             
                // open the serial-port, so we can send and receive data             
                serial.Open();             
                // add an event-handler for handling incoming data             
                serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);       
                //wait until the end of the Universe :-)
                
                Thread.Sleep(Timeout.Infinite);         
            }            
            static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)         
            {             
                // create a single byte array             
                byte[] bytes = new byte[1];                
                // as long as there is data waiting to be read             
                while (serial.BytesToRead > 0)             
                {                 
                    // read a single byte                 
                    serial.Read(bytes, 0, bytes.Length);                 
                    // send the same byte back                 
                    serial.Write(bytes, 0, bytes.Length);             
                }         
            }       
            
        }
    }
    

    I launch a simple serial port program like the old Hyper terminal on the PC where I peered the Bluetooth device and ran the test. Good surprise, I selected the port created on my PC (was port 6), open the port. The Bluetooth device went from a red blinking led to a always on led showing the device was correctly peered. Sounds good so far! So I typed “bonjour” and send it. instantly I get the “bonjour” back.

    So cool it’s working! I wanted to know more about the cheap and what can be setup, changes like the name of the device, the pin, the baud rate, etc. I used my preferred search engine Bing and quickly found out that it’s possible to change lots of things by sending couple of AT command. Those commands were used at the old age of modems Sourire It just remembered me that!

    Even if there are lots of cheap existing like the one I bought, most support exactly the same commands. I found a good documentation there. It’s not the same cheap and the AT commands are a bit different but I quickly found out that most were working. So I’ve decided to test if it was working. All what you have to do is send the commands when the device is not peered. You can do it either with a USB to serial FTDI cheap or directly from the board. I did it directly from the Netduino by modifying  a bit the code to send the commands. I found the most interesting commands were the following:

    • AT+NAMEnewname\r\n to change the device name, you get an answer
    • AT+PINxxxx\r\n to change the pin code, default is 1234
    • AT+BAUDx\r\n where X goes from 1 to 8 (1 = 1200 to 8 = 115200) to change the baud rate

     

    I send couple of commands to test and it worked just perfectly Sourire So I renamed the device to LaurelleBT instead of linvor. As the device was already peered, Windows did not had to reinstall drivers or cut the communication, it was just about changing the displayed name:

    image 

    So that’s it! In 5 minutes I had a working Bluetooth module on my board. I was positively surprised and I’ll buy more for sure! Next step it to mount it on a robot and pilot it from a Windows Phone or Windows 8 device.

  • Laurent Ellerbach

    Web Server and CSS files in NETMF (.NET Microframework)

    • 2 Comments

    It’s been a long time I did not write anything on my blog. Not that I haven’t developed anything but just because I did not take the time to write proper articles. I’ve continue to add features to my Lego city by piloting the trains but also the switches. And I’ll try to write articles to explain how to do that for all the features.

    But I will start with the modification of my Web Server to support CSS file. I did couple of demonstration of my development and each time I show the interface people were telling to me I need to work with a designer. And that’s what I finally did Sourire I worked with Michel Rousseau who is designer at Microsoft in the French team. And I gave him a challenge: “Design this simple web page without changing the code too much and keep it less than couple of K without any image”. Michel is used to design Windows 8 and Windows Phone apps but not very very simple page like the one I had.

    And he has done an excellent job! Here is the view before and after:

    imageimage

    Now I had to implement this in my code. As the brief was to have minimal effect on the code, I was expecting to implement this quickly. Reality was a bit different. It took me a bit more time than expected for the following reasons:

    • I had to implement in my basic web server a function to be able to download a file (the CSS one)
    • To read and download a file from an SD, you have to do it by chunk as the buffer size is limited (in the case of my Netduino 1024 bit)
    • Modify the main code to care about downloaded file and also add the lines of code to support CSS
    • But the main issue was that I’ve discovered that to be able to have a CSS file, you need to have the specific type “text/css”. This is to avoid cross domain fishing and other hacking

    So let see how to implement this step by step. So let start with the reading part of the file and how to send it. As explained in the last point, a CSS file has to have the correct mime type in the header. In fact, Internet Explorer and most of the other browsers such as Chrome and Firefox does not need the mime type to determine what kind of fire you are downloading. They do it with the mime type and/or with the extension. Most of the time, it’s just with the extension and reading the header of the file. But for security reason, it’s better if you have to determine correctly the type matching with the extension and the header of the file. And for CSS, it is forced like this to reinforce the security in Internet Explorer 8, 9 and 10.

    So as I had to implement this feature for CSS, I made a simple function to support some types I’ll use in other creation:

            public static void SendFileOverHTTP(Socket response, string strFilePath)
            {
                string ContentType = "text/html";
                //determine the type of file for the http header
                if (strFilePath.IndexOf(".cs") != -1 ||
                    strFilePath.IndexOf(".txt") != -1 ||
                    strFilePath.IndexOf(".csproj") != -1
                )
                {
                    ContentType = "text/plain";
                }
    
                if (strFilePath.IndexOf(".jpg") != -1 ||
                    strFilePath.IndexOf(".bmp") != -1 ||
                    strFilePath.IndexOf(".jpeg") != -1
                  )
                {
                    ContentType = "image";
                }
    
                if (strFilePath.IndexOf(".htm") != -1 ||
                    strFilePath.IndexOf(".html") != -1
                  )
                {
                    ContentType = "text/html";
                }
    
                if (strFilePath.IndexOf(".mp3") != -1)
                {
                    ContentType = "audio/mpeg";
                }
                if (strFilePath.IndexOf(".css") != -1)
                {
                    ContentType = "text/css";
                }
    
                string strResp = "HTTP/1.1 200 OK\r\nContent-Type: "
     + ContentType + "; charset=UTF-8\r\nCache-Control: 
    no-cache\r\nConnection: close\r\n\r\n";
                OutPutStream(response, strResp);

     

    So very simple and straight forward code. I do determine the extension of the file I want to read and create a ContentType variable with the right format. Then I build the HTTP header and send the header. Very simple, efficient and straight forward code. We are doing Embedded code, it’s not the code I would do in a normal development of a real web server. But it does the job there!

    Next step is reading the file and outputting it to the Socket. And I do this in the same function, right after this first part:

                FileStream fileToServe = null;
                try
                {
                    fileToServe = new FileStream(strFilePath, 
    FileMode.Open, FileAccess.Read);
                    long fileLength = fileToServe.Length;
                    // Now loops sending all the data.
    
                    byte[] buf = new byte[MAX_BUFF];
                    for (long bytesSent = 0; bytesSent < fileLength; )
                    {
                        // Determines amount of data left.
                        long bytesToRead = fileLength - bytesSent;
                        bytesToRead = bytesToRead < MAX_BUFF ? bytesToRead : MAX_BUFF;
                        // Reads the data.
                        fileToServe.Read(buf, 0, (int)bytesToRead);
                        // Writes data to browser
                        response.Send(buf, 0, (int)bytesToRead, SocketFlags.None);
    
                        System.Threading.Thread.Sleep(100);
                        // Updates bytes read.
                        bytesSent += bytesToRead;
                    }
                    fileToServe.Close();
                }
                catch (Exception e)
                {
                    if (fileToServe != null)
                    {
                        fileToServe.Close();
                    }
                    throw e;
                }
    
            }

    First step is to create a FileStream and create the Stream with the path of the file and read the length of the file. MAX_BUFF = 1024 and is the maximum size of a buffer. It depends on the .NET Microframework Platform. And we will start a loop to read part of the file and send it.

    The System.Threading.Thread.Sleep(100) is necessary to allow some time for the system and other tasks. If you don’t put it and have other tasks, the risk is that the memory will get full very quickly and you’ll block all the code.

    In my Web Server I have an event raised when an HTTP request is done. Here is an example of code you can place in your handling function to manage on one side the files to be downloaded from the SD and on the other side a page you’ll generate dynamically like in ASP, ASP.NET, PHP or any other dynamic language:

                //PageCSS
                if (strFilePath.Length >= pageCSS.Length)
                {
                    if (strFilePath.Substring(0, pageCSS.Length).ToLower() == pageCSS)
                    {
                        string strDefaultDir = "";
                        if (Microsoft.SPOT.Hardware.SystemInfo.IsEmulator)
                            strDefaultDir = "WINFS";
                        else
                            strDefaultDir = "SD";
                        WebServer.SendFileOverHTTP(response, strDefaultDir + "\\" + pageCSS);
                        return;
                    }
                }
                //HTTP header
                strResp = "HTTP/1.1 200 OK\r\nContent-Type: text/html; 
    charset=utf-8\r\nCache-Control: no-cache\r\nConnection: close\r\n\r\n";
                strResp = WebServer.OutPutStream(response, strResp);
    
                // Page util
                if (strFilePath.Length >= pageUtil.Length)
                {
                    if (strFilePath.Substring(0, pageUtil.Length).ToLower() == pageUtil)
                    {
                        ProcessUtil(response, strFilePath);
                        return;
                    }
                }

    Here PageCSS = the file name of the file you are looking for (including the path if in sub directory) so something like “page.css” and pageUtil = name of a page you will generate dynamically (including the path subdirectory) so something like “util.aspx”

    strFilePath = full URL including the parameters so something like “util.apsx?bd=3;tc=4”

    so code looks for the name of the page in the URL and brunch it to a either the SendFileOverHTTP function we’ve just look at or another function in the case of a dynamic page.

    You’ll note also that the is a case in the file part as the default directory is not the same if you are in the emulator or on a real board. The path depend also from the Platform. In the case of my Netduino, it’s CD. For emulator, it’s always WINFS.

    And please do all your file reading brunching before the HTTP header part. As for files, the header is already send out. Which is not the case for the dynamic generated page. As you can send whatever you want including images, text, binary files and you’ll need to set it up correctly.

    Now, lets have a look at the CSS file:

    @charset "utf-8";
    /* CSS Document */
    
    body {
        font-family: "Lucida Console", Monaco, monospace;
        font-size: 16px;
        color: #09C;
        text-align: center;
        margin-left: 0px;
        margin-top: 0px;
        margin-right: 0px;
        margin-bottom: 0px;
    }
    
    a {
        font-family: "Lucida Console", Monaco, monospace;
        font-size: 14px;
        color: #09F;
    }
    td {
        font-family: Arial, Helvetica, sans-serif;
        color: #004262;
        font-size: 14px;
    }
    input {
        font-family: "Lucida Console", Monaco, monospace;
        font-size: 16px;
        color: #09F;
        background-color: #FFF;
        -webkit-transition: all 0s linear 0s;
        -moz-transition: all 0s linear 0s;
        -ms-transition: all 0s linear 0s;
        -o-transition: all 0s linear 0s;
        transition: all 0s linear 0s;
        border: 1px none #FFF;
    }
    
    h1 {
        font-family: Arial, Helvetica, sans-serif;
        color: #FFF;
        background-color: #006699;
        font-size: 24px;
        border: thick solid #006699;
    }
    td {
        font-family: Arial, Helvetica, sans-serif;
        text-align: left;
        font-size: 16px;
    }
    footer {
        color: #09C;
    }
    input:hover {
        background-color: #09F;
        color: #FFF;
    }
    input:active {
        background-color: #003;
    }
    

    As you can see, it is very simple CSS that Michel did. It is just over righting the normal styles with colors and fonts. Nothing really complex but complicated to do something nice in only few lines of code! Well done Michel Sourire

    Now implementation in the rest of the code and all the pages is quite straight forward and simple, here is an example:

    // Start HTML document
    strResp += "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" 
    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
    strResp += "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>Gestion des trains</title>";
    //this is the css to make it nice :-)
    strResp += "<link href=\"" + pageCSS + "?" + securityKey + "\" rel=\"stylesheet\" type=\"text/css\" />";
    strResp += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/></head><body>";
    strResp += "<meta http-equiv=\"Cache-control\" content=\"no-cache\"/>";
    strResp = WebServer.OutPutStream(response, strResp);

    The HTML page is build and the CSS page is added with a parameter (a security key). And this line including the CSS is the only line I have to add to go from the original design to the nice new one!

    So that’s it for this part. I’ll try to find some time to write additional examples.

  • Laurent Ellerbach

    Using netduino and .NET Microframework to pilot any Lego Power Function thru Infrared (part 1)

    • 2 Comments

    I’m part of FREELUG, the French Enthusiast Lego User Group. And in this group, there are lots of discussions on Lego of course. In one of the thread someone ask the question if it was possible to pilot an Lego train using the new Power Function with a PC. The need is during expo, it makes it easier to run trains, stop them in a programmatic way.

    image

    I did a quick answer on the list saying that it can be quite easy if the protocol was not too complex and the IR technology used was close to RC5 from Philips. A small oscillator behind a serial or parallel port would do the trick. Philo, one of the FREELUG member answer me with a link to the protocol. And also tell me it should not be as easy as I was thinking. And he was more than right! No real way to make this work with a simple serial or parallel port on a PC. The protocol is more complex and need quite a bit of work to implement. I’ll come later on the first explanation on how to do it.

    So I decided to see if it was possible to implement this on netduino using .NET Microframework. this board has lots of IO, analogic and digital, do implement busses like I2C but also SPI. As any project, I started my project with my friend Bing. And start searching for similar projects. And I found Mario Vernari who I’ve mentioned in my previous post who was doing something similar. And we’ve exchange couple of emails to find a good way to implement an Infrared emitter using .NET Microframework. We will create the wave form in a buffer and then send it thru the MOSI port of an SPI port linked to the infrared led. So I will use the ideas and implementation Mario explain in his blog to pilot the Lego Power Function.

    I let go thru Mario article to get the basics of the IR protocol in general. And I will focus here on the specific Lego implementation and of course the specific code to make it work.

    Reading the 14 pages of the Lego protocol, we learn that the IR signals are using 38 kHz cycles. An IR Mark is 6 on and off signals as shown in the next picture

    image

    Each message will start and stop with a Start/Stop bit. This bit is 6 IR Mark and 39 pauses. So if I represent it in a binary way it will be:

    101010101010000000000000000000000000000000000000000000000000000000000000000000000000000000

    As Mario described in his post, we will use ushort to create the wave length. So in this case it will looks like

    0xFF00 0xFF00 0xFF00 0XFF00 0xFF00 0xFF00 and 39 times 0x0000

    Reality is a bit different as when using MOSI on a SPI to output a signal it is always a 1 for couple of µ seconds. So the right value to use is 0xFE00

    The low bit is working the same way, it is 6 IR Mark and 10 cycles of pause, the high one 6 IR Mark and 21 cycles of pause.

    So if I want to send the binary value 10011 I will send 6 IR Marks, 21 pauses, 6 IR Marks, 10 pauses, 6 IR Marks, 10 pauses, 6 IR Marks, 21 pauses, 6 IR Marks, 21 pauses. And I will create a ushort buffer which will contains 6 times 0xFE00, 21 times 0x0000, 6 times 0xFE00, 10 times 0x0000, 6 times 0xFE00, 10 times 0x0000, 6 times 0xFE00, 21 times 0x0000, 6 times 0xFE00, 21 times 0x0000

    All this make the Lego protocol complex compare to the RC5 and other similar protocols where the Low bit and high bits are usually the same size, the IR Mark is just inverted and the pause same size as the IR Mark.

    Now let have a look at the protocol itself.

    image

    The protocol start and stop with our Start/Stop bit describe up in the article. And then have 4 nibble. One nibble is a 4 bit data. The last nibble is used to to a check sum and is called LRC LLLL = 0xF xor Nibble 1 xor Nibble 2 xor Nibble 3.

    There are 4 channels possible going from 1 to 4 represented as CC from 0 to 3.

    a is not used in this protocol for the moment and kept for a future implementation. So it has to be set to 0.

    E is 0 for most modes except one specific mode (PWM)

    Toggle is an interesting one. The value has to change each time a new command is sent. So if the first time you send a command on a specific Channel (let say 1), it is 0, the next command send on Channel 1 will have to set Toggle as 1.

    The Power Function have different modes available (MMM):

    000 Not used in PF RC Receiver
    001 Combo direct (timeout)
    010 Single pin continuous (no timeout)
    011 Single pin timeout
    1xx Single output

    To know which mode is doing what, just refer to the protocol. I will detail the Combo direct (timeout) mode as an example for the rest of the article. It is easy to understand how it is working. The others are not much more complex and the logic is the same.

    image

    Mode (MMM) here is 001. Channel (CC) will vary form 0 to 3 depending which channel you want to pilot. So here, the Data nibble is split into 2 parts BB and AA. The documentation give this:

    B output BB,, called Red in all receivers

    00xx Float output B
    01xx Forward on output B
    10xx Backward on output B
    11xx Brake output B

    A output AA, called Blue in all receivers

    xx00 Float output A
    xx01 Forward on output A
    xx10 Backward on output A
    xx11 Brake output A

    And an interesting information is that Toggle bit is not verified on receiver. So if you don’t want to implement it, it’s possible.

    So it’s time to write some code Sourire Let start with couple of enums to facilitate the usage:

    //mode public enum LegoMode {
        COMBO_DIRECT_MODE = 0x1,
        SINGLE_PIN_CONTINUOUS = 0x2,
        SINGLE_PIN_TIMEOUT = 0x3,
        SINGLE_OUTPUT = 0x4
    };
    
    //speed public enum LegoSpeed {
        RED_FLT = 0x0,
        RED_FWD = 0x1,
        RED_REV = 0x2,
        RED_BRK = 0x3,
        BLUE_FLT = 0x0,
        BLUE_FWD = 0x4,
        BLUE_REV = 0x8,
        BLUE_BRK = 0xC
    };
    
    //channel public enum LegoChannel {
        CH1 = 0x0,
        CH2 = 0x1,
        CH3 = 0x2,
        CH4 = 0x3
    };
    

    The LegoMode one will be used to setup the mode (MMM), the LegoSpeed for the AA and BB output and the LegoChannel to select the Channel.

    private uint[] toggle = new uint[] { 0, 0, 0, 0 };
    
    public void ComboMode(LegoSpeed blue_speed, LegoSpeed red_speed, LegoChannel channel)
    {
        uint nib1, nib2, nib3, nib4;
    
        //set nibs nib1 = toggle[(uint)channel] | (uint)channel;
        //nib1 = (uint)channel; nib2 = (uint)LegoMode.COMBO_DIRECT_MODE;
        nib3 = (uint)blue_speed | (uint)red_speed;
        nib4 = 0xf ^ nib1 ^ nib2 ^ nib3;
    
        sendMessage((ushort)nib1, (ushort)nib2, (ushort)nib3, (ushort)nib4, (uint)channel);
    }
    

    I have defined a toggle table which will contain the value of the toggling. The function ComboModo takes as argument, the channel and the AA and BB parameters.

    The code is quite straight forward, I build the 4 nibbles like in the description.

    nib1 contains the Toggle plus escape (0) plus the channel. Toggle is not mandatory in this one but I’ve implemented to show you how to do it. and the values the Toggle will take will be in binary 1000 or 0000 so 8 or 0 in decimal.

    nb2 is E (which is 0) and the Mode (MMM) which is 1 in our case.

    nib3 combine AA and BB to select the Blue and Red orders.

    nib4 is the check sum.

    And then I call a function called sendMessage. I’ve build all the modes the same way, implementing simply the protocol.

    Now, let have a look at the sendMessage function:

    private void sendMessage(ushort nib1, ushort nib2, ushort nib3, ushort nib4, uint channel)
    {
        ushort code = (ushort)((nib1 << 12) | (nib2 << 8) | (nib3 << 4) | nib4);
        for (uint i = 0; i < 6; i++)
        {
            message_pause(channel, i);
    
            spi_send(code);
        }
        if (toggle[(int)channel] == 0)
            toggle[(int)channel] = 8;
        else toggle[(int)channel] = 0;
    
    }
    

    4 nibbles of 4 bits is 16 bits so a ushort. And I’m building this ushort simply with all the nibbles. OK, the protocol is a bit more complex than only sending 1 time a command. Each command has to be sent 5 times. What make the protocol not easy is that you have to wait different amount of time depending on the channel and the number of time you’ve already send a command! That is the job of the message_pause function. The spi_send send the code Sourire. The rest is about toggling the toggle bit of the channel.

    That’s it for today. In the next blog post, I’ll continue to go more in the details, show the implementation of the missing functions. And when I’ll finish to explain all the protocol code, I’ll go a bit further with a way to remotely using a web page or equivalent send commands to the netduino board which will send the IR command. And if I have more time, I will also implement sensors to detect if a train or a vehicle is on a specific place. This will be extremely easy as I’ve already explain how to use sensors like this.

  • Laurent Ellerbach

    Using netduino and .NET Microframework to pilot any Lego Power Function thru Infrared (part 2)

    • 2 Comments

    In a previous post, I’ve started to describe the Lego Power Function protocol and how I’ve implemented it on a netduino board using .NET Microframework. My work is based on ideas and implementation Mario explain in his blog. We’ve exchange couple of emails to make both our projects work Sourire

    To continue where I stopped, The message_pause function is like this:

     

    private void message_pause(uint channel, uint count)
    {
    
        int a = 0;
        // delay for first message
        // (4 - Ch) * Tm
        if (count == 0)
            a = 4 - (int)channel + 1;
        // next 2 messages
        // 5 * Tm
        else if (count == 1 || count == 2)
            a = 5;
        // last 2 messages
        // (6+2*Ch) * Tm
        else if (count == 3 || count == 4)
            a = 5 + ((int)channel + 1) * 2;
    
        // Tm = 16 ms (in theory 13.7 ms)
        System.Threading.Thread.Sleep(a * 16);
    

    It is a bit more comprehensive if you look at this picture. Each dot represent a signal sent. and each space the time you have to wait.

    image_thumb[10]

    The Lego protocol says you have to wait 16 ms minimum between 2 messages as it is the max size of a message. How did they arrive to this magic number?

    Back to our protocol, we know that the frequency is 38KHz, that the structure of a message starts and stop with a start/stop bit which is composed by 6 pulses IR and 39 pauses. A low bit is a 6 IR pulse and 10 pauses, a high bit a 6 IR pulse and 21 pauses. So we can do a ^simple table like this to have the length in µ seconds and the length in ushort:

    Type Total
    start µs           1 184  
    start ushort                 45  
    stop µs           1 184  
    stop ushort                 45  
    low µs              421  
    low ushort                 16  
    hight µs              711  
    hight ushort                 27  

    And we can also have the view of the full size of a message. The minimum size (if all bits are low) and the maximum one (if all bits are high):

      Total Start Toggle Escape C C a M M M D D D D L L L L stop
    Min size µs 9104 1184 421 421 421 421 421 421 421 421 421 421 421 421 421 421 421 421 1184
    Min size ushort 346 45 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 45
    Max size µs 13744 1184 711 711 711 711 711 711 711 711 711 711 711 711 711 711 711 711 1184
    Max size ushort 522 45 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 45

    So if you do the sum, you can see that the maximum length is 13 744 µ seconds which is 13.744 mili seconds and not 16ms as Lego describe. But lets take the Lego recommendation there. As you can see also the maximum length of a message is 522 ushort. And that’s the perfect transition to have a look at the spi_send function:

    private void spi_send(ushort code)
    {
        try
        {
            ushort[] tosend = new ushort[522]; // 522 is the max size of the message to be send
            ushort x = 0x8000;
            int i = 0;
    
            //Start bit
            i = FillStartStop(tosend, i);
    
            //encoding the 2 codes
            while (x != 0)
            {
                if ((code & x) != 0)
                    i = FillHigh(tosend, i);
                else
                    i = FillLow(tosend, i);
                x >>= 1;  //next bit
            }
            //stop bit
            i = FillStartStop(tosend, i);
            MySerial.Write(tosend);
        }
        catch (Exception e)
        {
            Debug.Print("error spi send: " + e.Message);
        }
    
    }
    
    

    The code starts with the creation of a ushort buffer of 522 elements. It is the max size of a message. The I create a short “x” (ok, I’m not creative for this little increment, but any developer has to use some crappy small names time to time Sourire). I will use it as a mask to see what is the value to send.

    There are now 3 functions called here: FillStartStop, FillHigh and FillLow. They are like this:

    private int FillStartStop(ushort[] uBuff, int iStart)
    {
        //Bit Start/stop = 6 x IR + 39 x ZE
        int inc;
        int i = iStart;
        //startstop bit
        for (inc = 0; inc < 6; inc++)
        {
            uBuff[i] = _high;
            i++;
        }
        for (inc = 0; inc < 39; inc++)
        {
            uBuff[i] = _low;
            i++;
        }
        return i;
    }
    
    private int FillHigh(ushort[] uBuff, int iStart)
    {
        //Bit high = 6 x IR + 21 x ZE
        int inc;
        int i = iStart;
        //High bit
        for (inc = 0; inc < 6; inc++)
        {
            uBuff[i] = _high;
            i++;
        }
        for (inc = 0; inc < 21; inc++)
        {
            uBuff[i] = _low;
            i++;
        }
        return i;
    }
    
    private int FillLow(ushort[] uBuff, int iStart)
    {
        //Bit low = 6 x IR + 10 x ZE
        int inc;
        int i = iStart;
        //Low bit
        for (inc = 0; inc < 6; inc++)
        {
            uBuff[i] = _high;
            i++;
        }
        for (inc = 0; inc < 10; inc++)
        {
            uBuff[i] = _low;
            i++;
        }
        return i;
    }
    

    Those functions take the buffer as an input and where to fill it. And then depending if it is a start/stop, low or high bit will fill the buffer correctly. For example, the low bit is 6 times IR pulses (_high = 0xFE00) and 10 times pauses (_low = 0x0000). And it return the new start position.

    Back to the spi_send function, after calling a first time the FillStartStop, the while loop use the “x” variable as a mask, call FillHigh if it is a high bit and FillLow if it is a low bit. And I change the mask for each bit. High bits have to be send first.

    while (x != 0)
    {
        if ((code & x) != 0)
            i = FillHigh(tosend, i);
        else
            i = FillLow(tosend, i);
        x >>= 1;  //next bit
    }
    

    When all the bits are transformed and the waveform is created, the signal is sent with MySerial.Write(tosend);

    The MySerail object is an SPI object:

    private SPI MySerial;
    

    Initialization is done like this:

    try
    {
        //Frequency is 38KHz in the protocol
        float t_carrier = 1 / 38.0f;
        //Reality is that there is a 2us difference in the output as there is always a 2us bit on on SPI using MOSI
        float t_ushort = t_carrier - 2e-3f;
        //Calulate the outpout frenquency. Here = 16/(1/38 -2^-3) = 658KHz
        uint freq = (uint)(16.0f / t_ushort);
    
        SPI.Configuration Device1 = new SPI.Configuration(
        Pins.GPIO_NONE, // SS-pin
        true,             // SS-pin active state
        0,                 // The setup time for the SS port
        0,                 // The hold time for the SS port
        true,              // The idle state of the clock
        true,             // The sampling clock edge
        freq,              // The SPI clock rate in KHz
        SPI_Devices.SPI1);   // The used SPI bus (refers to a MOSI MISO and SCLK pinset)
    
        MySerial = new SPI(Device1);
    
    }
    catch (Exception e)
    {
        Debug.Print("Error: " + e.Message);
    }
    

    Details on on the math can be found in Mario article. This is a very precise math, the tolerance for the Lego protocol is about 30%. The official document gives the following range value:

    Low bit range 316 - 526 us
    High bit range 526 – 947 us
    Start/stop bit range 947 – 1579 us

    That said, it is better to be in the right domain, make it work better.

    So we’ve seen how to create the waveform, send it over the MOSI output. Now, let see how to use all this in a very simple way.

        public class Program
        {
            public static void Main()
            {
                LegoInfrared myLego = new LegoInfrared();
                for (int i = 0; i < 10; i++)
                {
                    myLego.ComboMode(LegoInfrared.LegoSpeed.BLUE_FWD, LegoInfrared.LegoSpeed.RED_FWD, LegoInfrared.LegoChannel.CH1);
                    System.Threading.Thread.Sleep(1000);
                }
            }
    
        }
        public class LegoInfrared
    

    The LegoInfrared class does contains all the functions and enums I’ve explained. Here the usage is extremely simple. I create an object like this and call 10 times a forward command for both the Blue and Red output on channel 1. I wait 1 second and do it again. And the good news is that it is really working. I’m of course using the electronic schema that Mario proposed.

    If you are interested in the full source code of the full protocol, just let me a comment.

    More to come to show how to pilot it thru a web server and how to use it from another program. And again, depending of my inspiration, we will go a bit further and use sensors to raise events and be a bit smarter. Stay tune Sourire. If you want to implement other protocols like RC5, you can directly go to Mario blog and use his code. If you have a more complex protocol like the Lego one, you’ll be able to reuse most of the implementation I’ve done. Let me know if you want the full code.

  • Laurent Ellerbach

    Using one temperature sensor with I2C protocol and .NET Micro framework on netduino board

    • 2 Comments

    I wanted to play with a temperature sensor. And when the time came to choose one, I was amaze to see how many of those sensor exists. Some were simple resistor like the light sensor I used in one of my previous example, some were more like transistors, and couple integrated more advanced features. And I choose a TC74 from Microchip as it includes an I2C communication protocol and was extremely cheap (less than 1€ for the cheap). And they were sold by 2 so I get 2 of them Sourire My main idea was to be able to get the temperature of both of them.

    So I started to understand how I2C was working. The basic idea is simple: you have a clock going from the master (the netduino board in my case) to slaves (the TC74) and a line with data which is bidirectional. So the master can speak to the slave and the slave to the master.

    Good explanation on how this bus works in details in Wikipedia for example. The main difficulty with this protocol is to understand that you are sending information and can continue to send or receive some depending on what you’ve asked. But I’ll explain this later. Every device has an address on the bus and will respond when this address is send on the bus. That’s the ACK below.

    This table is coming from the TC74 documentation and explain how to write, read and receive a byte from the TC74.

    image

    There are simple commands and more complex one. The more complex one are usually accessing registers to setup and tweak a bit the device. In the case of the TC74, the register can be read and write. But it’s extremely simple as there are only 2 registers. One to see if a temperature is ready to read and one to put the device in standby mode or read if it is standby.

    image

    And the associated value to the register is simple also. D[7] is the high bit and D[0] the lowest one.

    image

    Then the read function return the temperature in a sbyte according the to table bellow:

    image

    Last but not least, here is how to connect the pins:

    image

    You don’t have to forget to put a resistor between the SDA and SCL lines like in the schema here. I used 10KΩ resistors and it’s working perfectly. I need to run more tests to see how long the cables cans be. I guess that if I need long cables, I’ll need to lower the value of this resistor.

    That’s it for the hardware part. Now, on the soft part, I started to search using bing and found couple of good articles to explain how to use I2C. This first one gives you an overall example and this second one a class to be used with multiples slaves. What I liked with the second one is that it’s easy to use it with multiples slaves. And in the future, I may want to add other sensors like a barometer and humidity sensor using I2C. Or even create my own I2C sensor as there are existing chip to be the interface.

    On top of this code, I’ve implemented a class called TC74 which implement all features of this sensor and calling the I2C class. So the overall code is quite simple.

    namespace TC74
    {
        //Command Code Function
        //RTR 00h Read Temperature (TEMP)
        //RWCR 01h Read/Write Configuration
        //(CONFIG)
        public enum TC74Command: byte
        {
            ReadTemperature = 0x00,
            ReadWriteRegister = 0x01
        };
        
        public enum TC74Config: byte
        {
            READY = 0x40,
            STANDBY = 0x80
        };
        /// <summary>
        /// This is an I2C temperature sensor.
        /// </summary>
        public class TC74Device
        {
            private I2CDevice.Configuration _slaveConfig;
            private const int TransactionTimeout = 3000; // ms
            private const byte ClockRateKHz = 100;
            public byte Address { get; private set; }
    
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="address">I2C device address 
    of the TC74 temperature sensor
    </param> public TC74Device(byte address) { Address = address; _slaveConfig = new I2CDevice.Configuration(address,
    ClockRateKHz); } public sbyte ReadTemperature() { // write register address I2CBus.GetInstance().Write(_slaveConfig, new byte[]
    { (byte)TC74Command.ReadTemperature }, TransactionTimeout); // get the byte result byte[] data = new byte[1]; I2CBus.GetInstance().Read(_slaveConfig, data,
    TransactionTimeout); //force the convertion to a signed byte return (sbyte)data[0]; } public byte ReadRegister() { // get the Register byte[] data = new byte[1]; I2CBus.GetInstance().ReadRegister(_slaveConfig,
    (byte)TC74Command.ReadWriteRegister, data, TransactionTimeout); return data[0]; } public void Init() { byte[] data = new byte[2] { (byte)TC74Command.ReadWriteRegister, 0x00 }; I2CBus.GetInstance().Write(_slaveConfig, data, TransactionTimeout); I2CBus.GetInstance().Write(_slaveConfig, new byte[]
    { (byte)TC74Command.ReadTemperature }, TransactionTimeout); } public bool IsReady() { bool bready = false; byte ret = ReadRegister(); if ((ret | (byte)TC74Config.READY) == (byte)TC74Config.READY) bready = true; return bready; } public void Standby(bool stdby) { byte[] data = new byte[2] { (byte)TC74Command.ReadWriteRegister, 0x00 }; if (stdby) data[1] = (byte)TC74Config.STANDBY; I2CBus.GetInstance().Write(_slaveConfig, data, TransactionTimeout); } } }

    Starting with the constructor, the address need to be stored. This address is b1001101 (0x4D) as I have a TC74A5-5.0VCT. We will use it later in a sample code. And this device works very well at 100KHz.

    Then the function Init is there to initialize the device. First it write in the internal register the value 0 to make sure it is not in standby mode. And then it write ReadTemperature to make sure we’ll be able to read the temperature.

    The register function read the register and return the byte value.

    The IsReady function read the register to check if the device is ready. It is only ready when power is up for enough time and before shut down. It is also not ready when the device is on standby mode.

    Standby set or unset the standby mode. It write in the register the STANDBY value which is 0x80 (b10000000).

    So pretty straight forward code and simple as well.

    public static void Main()
    {
        TC74Device MyTC74 = new TC74Device(0x4D); //0x4D
        byte MyData;
        sbyte MyTemp;
        Thread.Sleep(1000); 
    MyTC74.Init(); while (MyTC74.IsReady()) { MyTemp = MyTC74.ReadTemperature(); Debug.Print("Temperature :" + MyTemp); MyData = MyTC74.ReadRegister(); Debug.Print("Register :" + MyData); Thread.Sleep(1000); //MyTC74.Standby(true); } }

    The basic example to use this sensor is also quite easy. The device is initialized with the 0x4D address. Then the device is initialized. And the temperature and register are ready every second, if you want to test the Standby function, just unhide the last line, it will put the device in the standby mode and the device won’t be ready so the code will return.

    If you’ve done something wrong, exception will be raised and your code will stop.

    Now that’s how to pilot one sensor. The question is what can be done to read 2 identical sensors with the same address? I did it Sourire and it will be the topic of the next post. Stay tune!

  • Laurent Ellerbach

    Apprendre .NET avec la Saga .NET

    • 2 Comments

    Mieux que Dalas, la Saga .NET, réalisée par Pascal Belaud, va vous permettre de vous mettre à .NET. C’est un cursus de cours de 10 épisodes complets avec des vidéos, les codes sources associés et de quoi refaire les exercices.

    Ce que j’aime particulièrement chez Pascal, c’est sa pédagogie, les explications qu’il donne sont toujours claires et les exemples parlent bien.

    image

    La série sera complétée par d’autres épisodes si nous en avons la demande. Aussi, n’hésitez pas à réagir en m’envoyant un mail ou dans les commentaires.

    Ca se passe ici : http://www.microsoft.com/france/vision/saga-dot-net/

Page 1 of 5 (122 items) 12345