Blog

  • Evolution du HomeLab

    V2: Ajout d’un NUC n100

    Je fais enfin évoluer mon HomeLab depuis sa 1ère installation partagée ici.

    J’avais donc un NAS maison, à base de hp proliant microserver gen8, sur lequel je faisais tourner Proxmox avec par dessus OMC et Plex. Depuis 6 mois, j’avais ajouté pour test une VM Home Assistant. Forcément, je suis conquis, et j’abandonne donc mon domogik (qui tournait sur un rpi). Au passage j’abandonne aussi toutes mes bidouilles domotique à base d’arduino pour du zigbee…. A un moment faut des choses plug and play :-). Pour revenir sur le proliant, depuis l’ajout de la VM Home Assitant, j’avais régulièrement la VM Plex qui tombait, et vice et versa… Bref avec son Intel Celeron G1610T Dual Core cadencé à 2,3Ghz, on est un peu juste pour tout ça.

    J’ai donc suivi le mouvement en cours en ce moment dans le monde de la domotique/HomeLab. L’achat d’un nuc N100. De mon côté je suis parti sur ce BMAX. Pourquoi ? Le N100 est préférable au N95, plus performant, notamment au niveau video ce qui me permettra de faire tourner frigate à côté de Home Assistant pour la vidéo surveillance. De plus je me suis dis qu’il y aurait surement un truc à faire pour le transcoding de Plex avec ce type de serveur… j’ai donc migré mes VMs HA et Plex dessus. Le N100 étant très peu énergivore, ca va me permettre à terme de couper plus souvent le HP Proliant, qui devient un simple NAS (media). Ce dernier est plus énergivore…. On passe donc sur un intel de 12ème génération avec 4 coeurs @ 3,4Ghz… tout en consommant moins :-).

    V2.1: Ouverture vers l’extérieur

    Afin de pouvoir relier mon echo dot (alexa) à home assitant, j’ai ouvert une porte de l’extérieur vers HA. J’ai opté pour la solution Nginx Proxy Manager (d’autres possibilités s’offraient à moi, je reviendrais dessus dans un prochain article). Je l’ai donc ajouté sur le NUC. Tout ce qui arrive de l’extérieur passe donc par lui.

    A venir

    Afin d’avoir une approche DevOps qui me tient à cœur (j’en ai déjà parlé dans mes différents tutos), je vais tenter d’automatiser plus les prochaines étapes. Des articles de vulgarisation vont donc arriver sur le blog.

  • Gérer les maj de Proxmox (community)

    Si vous avez installé « simplement » proxmox comme dans mon précédant article, vous de vez donc avoir une sérier d’erreur visible dans les logs, visible à chaque connexion :

    Le détail de l’erreur nous montre qu’on n’est pas autorisé à contacter les repos « entreprise » de proxmox.

    Si on va voir le détail de nos repos, on voit qu’on a 2 repos « entreprise » de défini. On voit aussi ce beau warning « The enterprise repository is enabled, but there is no active subscription!’ On a donc un repo entreprise pour pve itself, et aussi pour ceph.

    Activation des mises à jour via des repos gratuits

    Depuis l’écran des repositories, on va donc cliquer sur le bouton « Add » afin d’ajouter nos repos. Il faut prendre les repos sans abonnement « No-Subscription ».

    Il s’agit du dépôt recommandé pour les tests et l’utilisation hors production. Ses paquets ne sont pas aussi lourdement testés et validés que le référentiel d’entreprise prêt pour la production. Vous n’avez pas besoin d’une clé d’abonnement pour accéder à ce référentiel.

    Ne vous inquiétes pas, il y a tout de même un processus de validation sur les mises à jours présentes, du style: Test Interne -> No-Subscription -> Enterprise. Les repos sont donc stables. Proxmox se dédouane juste en cas de problème :-). (Après on peut très bien faire nos mises à jour en décalé pour éviter toute surprise)

    Nos dépôts sont donc maintenant présent sur l’interface.

    Désactiver les dépôts entreprise.

    Sur chacun des dépôts entreprise, on clique dessus et on sélectionne désactivé. En effet, ils nous servent à rien et autant éviter l’erreur dans les logs.

    Test de détection de mise à jour

    En retournant dans le menu « Updates » on va faire un « Refresh » des paquets disponibles. On va bien voir apparaitre les mises à jours de Debian ET aussi celle de proxmox et ceph. Well done !

  • Plex sur Debian11

    Article sous forme de note, de mon installation de plex sur debian 11. J’ai tenté d’être 100% ligne de commande dans l’optique de pouvoir automatiser en Ansible cette installation par la suite.

    Voici les articles que j’ai suivi et qui m’ont dépanné lors de cette installation :

    https://www.linuxcapable.com/how-to-install-plex-media-server-on-debian-11-bullseye/
    https://www.linuxuprising.com/2021/01/apt-key-is-deprecated-how-to-add.html

    Il faut d’abord de loguer en ssh via l’utilisateur défini lors de l’installation et passer en root ensuite

    $ su -
    $ apt install gnupg
    $ echo deb [signed-by=/usr/share/keyrings/plex-archive-keyring.gpg] https://downloads.plex.tv/repo/deb public main | tee /etc/apt/sources.list.d/plexmediaserver.list
    $ wget -O- https://downloads.plex.tv/plex-keys/PlexSign.key | gpg --dearmor | tee /usr/share/keyrings/plex-archive-keyring.gpg
    $ apt update
    $ apt install plexmediaserver

    Et pour le NFS

    $ mkdir -p /mnt/nfs/movies
    $ echo '192.168.0.xxx:/movies /mnt/nfs/movies  nfs      defaults    0       0' >> /etc/fstab
    $ mkdir /mnt/nfs/tvshows
    $ echo '192.168.0.xxx:/tvshows /mnt/nfs/tvshows  nfs      defaults    0       0' >> /etc/fstab
    $ mount /mnt/nfs/movies
    $ mount /mnt/nfs/tvshows

    Puis la fin de la config de plex . Ici ca devient plus difficilement scriptable ?
    Il faut en effet se rendre sur un lien local pour relier le serveur à votre compte: http://ip:32400/web

    Enfin on peut passer à l’installation du plugin WebTools. Dans l’UI Plex les plugins ne sont plus officiellement supportés, mais c’est seulement en surface. J’ai donc suivi ce tuto: https://github.com/ukdtom/WebTools.bundle/wiki/Install

    $ apt install unzip
    $ wget https://github.com/ukdtom/WebTools.bundle/releases/download/3.0.0/WebTools.bundle.zip
    $ unzip WebTools.bundle.zip
    $ cp -R WebTools.bundle /var/lib/plexmediaserver/Library/Application\ Support/Plex\ Media\ Server/Plug-ins/WebTools.bundle
    $ chown -R plex:plex /var/lib/plexmediaserver/Library/Application\ Support/Plex\ Media\ Server/Plug-ins/

    A ce moment en vous rendant sur l’interface web de plex, au niveau des réglages de votre serveur plex, vous devez voir un logo WebTools en vous rendant dans la section Gérer > Extensions.

    En cliquant sur la roue crantée, il est alors possible de configurer Webtools, comme indiqué ici.

    Par défault, webtools est disponible sur le port 3340: http://ip:33400

  • Installation de Proxmox/OpenMediaVault

    Pourquoi ?

    Le crash d’un de mes disques de mon NAS m’a obligé à repenser un peu/beaucoup mon infra personnel. Et je suis tombé sur pas mal de posts qui m’ont donné envie d’appliquer un peu plus de sécurité sur mon infra perso (à l’image de ce que je pourrai faire professionnellement pour un client… c’est pas toujours le cordonnier qui doit être le plus ma chaussé !).

    Bref point de départ, on va aller au plus simple en attendant l’arrivée progressive du Matos pour sécurisé les datas. Seul chose qu’on va donc mettre en place par rapport à avant : virtualisation d’OpenMediaVault + vérification périodique des disques durs. On va aborder le 1er point dans ce post. Alors pourquoi virtualiser OMV ? Car si ce dernier commence à déconner (c’était le cas de ma dernière install qui était plus très stable), c’est plus simple d’en réinstaller un en //. Plus simple d’avoir des backup de la vm de dispo aussi. Et enfin ca ma me permettre de mettre en place d’autres VM pour gérer plus proprement mon réseau… Et l’envie de découvrir Proxmox est grand aussi (professionnellement of course , je côtois plus VmWare….)

    Installation de Proxmox

    Pas grand chose à dire ici, la documentation officielle est assez clair sur le sujet. J’ai donc créer une clé usb bootable à partir de l’ISO officielle, voir Préparation du média d’installation. Ensuite j’ai répondu aux différentes questions de l’installation en restant simple : https://pve.proxmox.com/wiki/Installation.

    Et voilà la chose est installée.

    Ajout d’un user « simple »

    L’utilisateur de départ est l’utilisateur root du système. On va donc prendre une bonne habitude de sécurité en ajoutant un user linux « normal » (sans droit sudo) et en ajoutant ensuite ce user sur proxmox. On va donc depuis la connexion ssh faire les commandes suivantes (tirés de la partie user management de la doc officielle)

    $ adduser proxmox
    $ pveum group add admin -comment "System Administrators"
    $ pveum acl modify / -group admin -role Administrator
    $ pveum user modify proxmox@pam -group admin

    Hormis la création du user linux (via adduser) tout le reste aurait pu également être réalisé par l’IHM de proxmox (j’ai pas envie de vous faire peur direct). C’est la force de proxmox d’avoir toutes les actions également scriptable.

    • Ajout du group dans Datacenter > Permissions > Groups
    • Ajout des droits au groupe depuis Datacenter > Permissions
    • Ajout du User au groupe depuos Datacenter > Permissions > Users

    Retrait de la demande d’abonnement

    Vous avez surement vu ce popup de demande de subscription à chaque fois que vous vous connectez à l’interface web. Il existe une petite astuce qui permet d’enlever ce popup. Merci à John pour le tuyau.

    Depuis la cnx ssh, changez de répertoire: cd /usr/share/javascript/proxmox-widget-toolkit

    Faire une copie du fichier que nous allons modifier: cp proxmoxlib.js proxmoxlib.js.bak

    Editer le fichier: nano proxmoxlib.js

    Trouver la ligne avec le code suivant (Ctrl+W dans nano et recherchez « No valid subscription »):
    Ext.Msg.show({
    title: gettext('No valid subscription'),

    Remplacer Ext.Msg.show par void
    void({ //Ext.Msg.show({
    title: gettext('No valid subscription'),

    Redémarre le service web de proxmox: systemctl restart pveproxy.service

    Pour voir le résultat, n’oubliez pas de vider le cache de votre navigateur si besoin.

    Déploiement d’OpenMediaVault

    Récupération de l’image d’installation

    On va télécharger la dernière version sur le site : OpenMediaVault.

    Bien entendu au passage on va vérifier le checksum, ca mange pas de pain.

    2 façon de faire se présente à nous :

    • Geek Attitude: directement en ssh sur le server:
    $ cd /var/lib/vz/template/iso
    $ wget https://sourceforge.net/projects/openmediavault/files/5.6.13/openmediavault_5.6.13-amd64.iso
    $ openssl dgst -sha256 openmediavault_5.6.13-amd64.iso
    $ curl -L https://sourceforge.net/projects/openmediavault/files/5.6.13/openmediavault_5.6.13-amd64.iso.sha256
    • Ou en mode, je profite de l’outil que je viens d’installer, bref depuis l’ihm de proxmox (en gros proxmox va taper les commandes pour nous comme un grand). Ici on met donc les infos suivantes :
      • URL: https://sourceforge.net/projects/openmediavault/files/5.6.13/openmediavault_5.6.13-amd64.iso
      • Fine name: openmediavault_5.6.13-amd64.iso
      • Mode Advanced:
        • Hash Algorithm: SHA-256
        • Checksum: on le copie/colle depuis le fichier https://sourceforge.net/projects/openmediavault/files/5.6.13/openmediavault_5.6.13-amd64.iso.sha256

    Création de la VM

    On clique donc sur le bouton « Create VM » (en haut à droite)

    On va lui donner un petit nom depuis l’onglet General (on laisse les autres valeurs par défault, l’id est généré, et on a qu’un seul noeud…)

    Dans l’onglet suivant « OS », on va sélectionner l’ISO ajouté un peu plus haut.

    Dans l’onglet « System », on change rien:

    Pour le disque dur, il sera localisé sur « local-lvm », et on va mettre la valeur minimale requise par OMV (si besoin on pourra toujours augmenter plus tard).

    Point de vue CPU, là aussi OMV n’en réclame pas trop (il faudra voir à l’usage si plex suit par contre). On va donc laisser un seul coeur de CPU. Là aussi, si besoin, on repassera.

    Même remarque pour la RAM. La minimum requis est de 1Go, mais plex on vaudra surement plus… On va partir sur 2 pour le moment.

    On se termine avec l’onglet Network où on ne change rien, et on finit avec la confirmation finale où on relit toute notre configuration et on peut enfin appuyer sur « Finish » pour créer la VM.

    Installation d’OpenMediaVault

    Maintenant que la VM est prête (hormis la question stockage qu’on abordera plus bas), il est temp de cliquer sur start pour lancer notre VM et donc l’installation présente sur l’ISO. Il nous suffira donc de suivre simplement les différentes étapes de l’installation d’OMV en se rendant dans la Console (pour voir l’écran de la VM….)

    Après le choix des langues qui se fait assez simplement, on nous demande le nom du host, je suis resté simple, et j’ai mis OMV (même nom donné à la VM plus haut).

    Pour le nom du domaine, je vais laisser le .lan proposé.

    Ensuite on arrive sur un écran nous demandant de créer un mot de passe pour l’utilisateur root. Cet utilisateur n’est pas utilisée pour l’interface web d’OMV, il est seulement utilisé pour accéder à la machine depuis la ligne de commande.

    Aucune question sur le disque de destination, en effet pour le moment seul le disque principal de la VM (le disque OS) est visible par l’installation. On va s’occuper de ce point plus bas.

    L’installation est donc en cours….

    A la suite de ce 1er 100% atteint, on va vous poser quelques questions afin de configurer le gestionnaire de dépôt de paquet. Les choix par default sont normalement les bons.

    Enfin on nous demande où on veut mettre le système de démarrage GRUB, dans mon cas, pas trop de choix, il y a qu’un seul disque, donc qu’une seule possibilité de proposée

    On arrive ensuite enfin sur l’étape « Fin de l’installation », cela sent bon !

    On peut profiter de ce message pour démonter l’ISO d’installation. Ce n’est pas obligatoire, en effet l’ordre du boot fait qu’on aurait tout de même démarrer sur le disque dur.

    Pour démonter l’ISO, on se rend dans l’onglet Hardware de la VM, on sélectionne la ligne CD/DVD Drive (ide2), on clique alors sur le bouton EDIT.

    On clique alors sur « Do not use any media » dans la boite de dialogue qui s’ouvre, et qu’on va refermer en appuyant sur « OK ».

    Enfin n’oublions pas de retourner dans la console pour valider le redémarrage post installation.

    A la fin du boot il peut être intéressant de récupérer l’adresse ip attribué à notre OMV. Comme on peut le voir, cette dernière n’est pas encore accessible depuis le « Summary » de la VM. « No Guest Agent configured ». On va remédier à ça un peu plus bas.

    On va donc utiliser la bonne vieille méthode, on retourne sous la console, on se logue dans la console d’OMV avec le compte root crée plus haut, et on tape ip a :

    Et donc…. on voit bien que le site d’OpenMediavault est disponible sur cet ip.

    A ce stade avant toute chose, je vais faire une image à froid (vm éteinte). J’expliquerais dans un prochain article l’utilité de la chose. Ceci est réalisé en faisant un clic droit sur la VM, et en cliquant sur « Convert to template ». Ensuite on pourra recréer une VM depuis ce template (en mode Full Clone) pour continuer notre travail. En gros ce template me permet d’avoir une image de base d’une installation fraiche, disponible sans passer par tout le processus d’installation manuel (questions….). On voit bien que si on voulait automatiser tout ce process d’installation de mon infra, cette étape manuelle d’installation d’OMV présente un frein.

    Installation de l’agent client

    On l’avait vu un peu plus haut, l’ip de la vm n’était pas disponible depuis l’interface proxmox, car on avait un « No guest agent confgured ». On va remédier à ça en s’appuyant sur la documentation officielle: Qemu-guest-agent.

    On va donc d’abord installer l’agent dans le système. On le fait donc depuis la console de la vm ou depuis un connexion ssh. La commande à taper est donc apt-get install qemu-gest-agent (on est sur une base debian).

    Ensuite il nous suffit d’activer le lien avec cet agent depuis les options de la vm sous proxmox

    On fait alors un shutdown de la VM (depuis sa ligne de commande) et on la redémarre….. et magie :

    Le lien entre proxmox et l’agent est donc opérationnel. Cela permet notamment de faire des shutdown (depuis proxmox) plus propre et aussi de freezer le système de fichier lors de backup.

    Ajout des disques durs (en mode brute)

    Mon objectif est de rendre opérationnelle rapidement la chose avant surement de futur aménagement/migration. Bref j’ai donc fait le choix d’installer les disque dur media en mode pass through vers OMV. De cette manière ces diqques durs resteront exploitables sur d’autres machines (simple ext4). Le but à moyen terme sera de passer sur un montage ZFS avec 3 disques identiques. Bref rien envie de virtualiser quoi que ce soit pour le moment, seul OMV a besoin de gérer et accéder ses disques.

    On va donc s’insiprer encore une fois de la documentation officielle. Cette fois-ci on va être obligé de passer par de le ligne de commande sur le serveur proxmox (via ssh ou le shell dispo depuis l’interface web).

    Chaque disque va être configuré par son id, en effet son nommage de type devide (/dev/sda) peut changer ce qui nous ammènrait des ennuis…. Chaque id est disponible facilement via l’IHM de proxmox, au niveau du PVE > Disk.

    Ces mêmes id sont retrouvables dans le file system au niveau du répertoire /dev/disk/by-id/. On retrouve d’ailleurs aussi via la commande ls -l les noms actuellement mis sur chacune des partitions. Cela peut nous aider aussi à retrouver qui est qui.

    Example: je veux passer en pass-through mon Disque de 3To. On voit depuis Proxmox (1ère image) que son Serial est WD-WCAWZ2254019. Son /dev par id est donc /dev/disk/by-id/ata-WDC_WD30EZRX-00MMMB0_WD-WCAWZ2254019. Pour ajouter le disque à notre VM on va donc taper :
    qqm set 101 -scsi1 /dev/disk/by-id/ata-WDC_WD30EZRX-00MMMB0_WD-WCAWZ2254019
    où 101 est l’id de notre VM, scsci1 le numéro de port virtuel auquel le disque va être attaché sur la VM.
    Attention cette commande doit être tapée avec l’utilisateur root.

    En regardant la partie hardware de la VM depuis l’IHM de proxmox, on voit que le disque dur a bien été ajouté.

    Il faudra alors redémarrer la VM pour que OMV voit ce nouveau disque dur. Avant cela, je vais ajouter également les autres disques durs que je veux faire apparaitre en faisant bien attention à chaque fois d’incrémenter le port virtuel scsci.

    On reboot la vm depuis l’ihm proxmox qui arrive à la faire proprement depuis qu’on a ajouté le guest client :-).

    On peut donc se loguer depuis l’IHM d’OpenMediVault (pour rappel le login/pwd initial est admin/openmediavault).
    Au niveau du Stocakge>Disques, on voit bien mes 4 disques : le disque virtuel système (l’OS) de 4 Go et les 3 disques que j’ai définie en pass-through.

    Au niveau des systèmes de fichiers, mes partitions ext4 existantes sont bien détectés. On voit qu’actuellement, seul la partition système est montée.

    La configuration classique d’OMV va pour voir avoir lieu !

  • Ajouter du texte dans une DataGridViewCheckBoxCell

    Tout d’abord expliquons pour j’ai ce besoin. Pour un projet (pro) une colonne de mon DataGrid affiche en information textuelle, une valeur numérique modifiable. Oui mais voilà sous certaines conditions, certaines lignes de cette colonne ne peuvent avoir que 0 ou 1 comme valeur numérique. En m’abonnant à l’évènement DataBindingComplete, j’ai donc modifié à la volée ces cellules en cellule avec une case à cocher (DataGridViewCheckBoxCell). Bien entendu, je trouvais cela un peu moins parlant. Une ligne avec une valeur numérique pouvait être suivie d’une case à cocher dans la même colonne. A la base, l’idée de la case à cocher, c’était surtout pour aider au changement de la valeur. Pourquoi donc éditer ce texte si on ne peut que mettre un 1 ou 0 ? Pour rendre plus claire cette colonne, j’ai donc eu l’idée de faire apparaître ce 1 ou ce 0 à côté de la case à cocher.

    Bien entendu cet objet n’existe pas de base dans le framework. Comme je sais qu’il ne faut pas réinventer la roue, je suis parti sur le net à la conquête de la chose. Et j’ai trouvé quelque chose, mais qui ne correspondait pas exactement à mes besoins… forcément ! Mais cette source d’inspiration m’a été forte utile.

    L’inspiration

    Extending The DataGridViewCheckBoxCell To Include Text

    Dans cet article l’auteur veut faire la même chose, mais pas pour le même besoin. Au final, comme le montre sa capture finale,  il semble vouloir avoir une liste de choix dans une ligne. Pour faire simple, le texte mis à coté de la case à cocher est un simple texte statique. Sa solution semble donc réellement utile que dans le cas d’une liste de choix.

    Je vais tout de même me baser sur sa solution du moins en point de départ, car au final, j’ai pas mal modifié (perfectionné ?) certains points.
    Dans la suite, mes commentaires seront donc beaucoup basé sur son exemple.

    Ma solution

    Tout comme Murray, je vais donc avoir besoin de définir 2 classes : DataGridViewCheckBoxTextColumn et DataGridViewCheckBoxTextCell. En effet, pour avoir une solution générique, la définition de la colonne correspondante est à faire. Ces 2 classes étendront donc respectivement les classes DataGridViewCheckBoxColumn et DataGridViewCheckBoxCell.

    DataGridViewCheckBoxTextCell

    Tout comme Muray, on peut commencer par définir cette classe. C’est très simple, on modifie juste le template de la cellule par défaut et le tour est joué.

    using System;
    using System.Windows.Forms;
    
    namespace Kerlink.Windows.Forms
    {
        public class DataGridViewCheckBoxTextColumn : DataGridViewCheckBoxColumn
        {
            public DataGridViewCheckBoxTextColumn()
            {
                this.CellTemplate = new DataGridViewCheckBoxTextCell();
            }
        }
    }

    DataGridViewCheckTextCell

    Voilà le gros du travail. Contrairement à Murray, je ne vais pas commencer par ajouter des propriétés à cette classe. Tout comme lui, j’ai envie de faire quelque chose de générique, j »ajouterais donc des propriétés au fur et à mesure que si cela est réellement nécessaire. Je vais tenter d’utiliser au maximum ce qui est déjà définie dans mon objet de base, la classe DataGridViewCheckBoxCell. Bref, ici je n’ajoute donc pas les propriétés Enabled, Text, Color et Font définie par Murray. Notre classe est donc déjà bien différente dans sa définition de base :

    public class DataGridViewCheckAndTextCell : DataGridViewCheckBoxCell
    {
        public DataGridViewCheckAndTextCell()
        {}
    }

    Passons donc directement à la deuxième action proposée par Murray : surcharger la méthode DataGridViewCheckBoxCell.Paint(). Nous allons donc en premier lieu appelé la méthode mère (qui fait ce qu’elle aura à faire, cela ne nous regarde pas) puis ajouter notre mixture locale. Voilà la bête, qui est bien différent de celle de Murray, plus courte et plus basée sur les propriétés existantes de la classe. De plus le placement du texte sera un peu plus propre (je trouve), c’est à dire correctement aligner (verticalement) avec les autres cellules de texte, contrairement au résultat de la solution de Murray. Sans plus tarder, le code :

    protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
    {
        // Call the base method (which must draw the checkbox)
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
    
        // Get the actual content Area (area where the checkbox must be)
        System.Drawing.Rectangle contentBounds = this.GetContentBounds(rowIndex);
    
        // Get Area Where String Must be Added (at 2px on the right of the checkbox)
        System.Drawing.Rectangle stringArea = new System.Drawing.Rectangle();
        stringArea.X = cellBounds.X + contentBounds.Right + 2;
        stringArea.Y = cellBounds.Y + contentBounds.Top;
        stringArea.Height = contentBounds.Height;
        stringArea.Width = cellBounds.Width - contentBounds.Right - 2 - 2;
    
        // Convert DataGridViewContentAlignment to StringFormat
        System.Drawing.StringFormat format = cellStyle.Alignment.ToStringFormat();
    
        // Draw the cell value inside the computed area
        graphics.DrawString(this.Value.ToString(), cellStyle.Font, new System.Drawing.SolidBrush(cellStyle.ForeColor), stringArea, format);
    }

    Ce qu’on fait est donc très simple. Contrairement à Murray, pas besoin de redessiner la checkbox. On a pas de notion de checkbox Enabled: ici, ce n’est pas une liste de choix. On va donc directement dessiner notre texte. On va donc passer tout sa partie de vérification des propriétés et d’initialisation de variable. On commence directement à définir notre espace où le texte doit être dessiner, et non pas un point de départ comme Muray. La définition d’une zone nous aidera pour l’alignement du texte dans cette dernière.
    On récupère donc la zone occupée par le contenu actuel : contentBounds via l’appel à GetContentBounds. On peut alors définir notre rectangle qui se situera à 2 pixel à droite du contenu actuel, de même hauteur que le contenu actuel, et de longueur maximum, c’est à dire ce qui reste de disponible dans la cellule en gardant une marge de 2 pixels sur sa droite.

    A ce stade, afin de dessiner le texte, il nous manque certains paramètre par rapport à Murray : le texte, la police et sa couleur. Comme précisé plus haut, je vais utiliser les paramètres déjà définies dans la classe ! Il suffit de les trouver… Ainsi, pour le texte, on utilisera donc la valeur actuelle associé à notre DataGridViewCheckBox. En effet dans mon cas, cette valeur est soit le chiffre 1 ou 0. Pour la police, rien ne sert d’ajouter une propriété, le paramètre cellSyle (de type DataGridViewCellStyle) de la méthode Paint contient déjà cette information. En effet, toute DataGridViewCell a une telle propriété. De même pour la couleur.

    Pour finir, par rapport à Murray, on dessine notre texte dans une surface. Cela nous permet donc d’aligner horizontalement et verticalement ce texte dans cette surface. La méthode DrawString utilise le type StringFormat pour se faire. Une propriété d’alignement existe déjà dans notre style de cellule, mais elle est de type DataGridViewContentAlignement. Une petite méthode d’extension (ou une méthode statique si vous êtes en .net2) et le tour est joué.

    On est donc en mesure de dessiner notre texte via l’appel à DrawString de l’objet graphics.

    Pour information, ci joint le code du convertisseur de type :

    public static class DataGridViewContentAlignmentHelper
    {
        public static System.Drawing.StringFormat ToStringFormat(this DataGridViewContentAlignment alignement)
        {
            System.Drawing.StringFormat format = new System.Drawing.StringFormat();
    
            // Set the Vertical Alignement (could transform enum in string and test value ?)
            switch (alignement)
            {
                case DataGridViewContentAlignment.BottomCenter:
                case DataGridViewContentAlignment.BottomLeft:
                case DataGridViewContentAlignment.BottomRight:
                    format.LineAlignment = System.Drawing.StringAlignment.Far;
                    break;
    
                case DataGridViewContentAlignment.MiddleCenter:
                case DataGridViewContentAlignment.MiddleLeft:
                case DataGridViewContentAlignment.MiddleRight:
                case DataGridViewContentAlignment.NotSet:
                    format.LineAlignment = System.Drawing.StringAlignment.Center;
                    break;
    
                case DataGridViewContentAlignment.TopCenter:
                case DataGridViewContentAlignment.TopLeft:
                case DataGridViewContentAlignment.TopRight:
                    format.LineAlignment = System.Drawing.StringAlignment.Near;
                    break;
            }
    
            // Set the Horizontal Alignement (could transform enum in string and test value ?)
            switch (alignement)
            {
                case DataGridViewContentAlignment.BottomCenter:
                case DataGridViewContentAlignment.MiddleCenter:
                case DataGridViewContentAlignment.TopCenter:
                    format.Alignment = System.Drawing.StringAlignment.Center;
                    break;
    
                case DataGridViewContentAlignment.BottomLeft:
                case DataGridViewContentAlignment.MiddleLeft:
                case DataGridViewContentAlignment.TopLeft:
                    format.Alignment = System.Drawing.StringAlignment.Near;
                    break;
    
                case DataGridViewContentAlignment.BottomRight:
                case DataGridViewContentAlignment.MiddleRight:
                case DataGridViewContentAlignment.NotSet:
                case DataGridViewContentAlignment.TopRight:
                    format.Alignment = System.Drawing.StringAlignment.Far;
                    break;
            }
    
            return format;
        }
    }

    1er essai

    Contrairement à Murray on a pas fini. Certes la colonne est disponible depuis le designer. Certes on voit la magie apparaitre. Mais comme on pouvait s’y attendre, il manque tout le côté dynamique. On a beau cocher ou décocher, pas de changement du texte associé.

    La première question à se poser, c’est comment fait donc une DataGridViewCheckBoxCell pour changer sa valeur quand celle-ci n’est pas un simple boolean ?

    On cherche, et la réponse est à porté de main ou plutôt à portée de 2 propriétés :

    • TrueValue : Obtient ou définit la valeur sous-jacente correspondant à une valeur de cellule true.
    • FalseValue :  Obtient ou définit la valeur sous-jacente correspondant à une valeur de cellule false.

    Du même acabits, on a aussi la IndeterminateValue.

    Une fois la databinding en place, on peut donc aussi préciser comment notre checkbox met à jour sa donnée. Ce code est donc du côté du client de notre classe. Dans mon cas, je devrais préciser une TrueValue à 1 et une FalseValue à 0. A noter que ce client peut le définir via les même propriétés disponible au niveau de la DataGridViewCheckBoxColumn.

    2ème essai

    La mise à jour a lieu certes. Mais celle ci n’opère que quand on sort du mode édition de la cellule (en cliquant sur une autre). On abouti là sur une grosse limite des CheckBox cell qui semble connue. En effet le chemin habituel google -> stackoverflow m’a fait aboutir sur cette solution.

    Contexte Dynamique

    Il faut donc s’abonner à l’événement CurrentCellDirtyStateChanged du DataGridView pour forcer la validation du changement en cours.

    Oui, mais voilà la propriété interne DataGridView  n’est pas disponible lors de la construction de notre classe. Pour récupérer son instance, on va donc surcharger la méthode protégée OnDataGridViewChanged.

    Passons donc au code :

    private DataGridView _previousDataGridView = null;
    // get datagridview instance to can subribe to CurrentCellDirtyStateChanged event.
    protected override void OnDataGridViewChanged()
    {
        base.OnDataGridViewChanged();
    
        if (this.DataGridView != _previousDataGridView)
        {
            if (_previousDataGridView != null)
            {
                // unsubscribe from previous DataGridView
                _previousDataGridView.CurrentCellDirtyStateChanged -= DataGridView_CurrentCellDirtyStateChanged;
            }
    
            if (this.DataGridView != null)
            {
                   // subscribe to new related DataGridView
                   this.DataGridView.CurrentCellDirtyStateChanged += new EventHandler(DataGridView_CurrentCellDirtyStateChanged);
            }
        }
    }
    
    // Force the databound property update (for this checkbox) as soon as the check box is checked/unchecked (default is after the CellLeave event)
    void DataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        // we can't use this.DataGridView : it can be null in this context !
        DataGridView dgv = sender as DataGridView;
    
        // Always directly commit the uncommited changes of the current cell.
        if ((dgv.CurrentCell == this) && (dgv.IsCurrentCellDirty))
        {
            dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }

    Voilà pas grand chose à ajouter pour expliquer. Au niveau de OnDataGridViewChanged, j’ai fait ça propre : je me désinscris de l’ancien pour m’inscrire sur le nouveau. Je sais pas si un changement est possible, mais en tout cas, cette méthode peut être appelé alors que this.DataGridView est nul en début d’exécution. Bref, j’ai préférais assurer le coup.

    Enfin dans le traitement de l’évènement CurrentCellDirtyStateChanged, on applique la solution trouvée. Seul remarque, on ne peut pas utiliser this.DataGridView ici. Bref, soit on récupére la DataGridView via le sender (ce que j’ai fait), ou on pourrait aussi utiliser notre variable locale _previousDataGridView.

    3ème essai

    C’est parfait. On clique, la valeur change directement. Good job.

    Au final

    Ces petites recherches ont été intéressantes. Comme d’habitude on prend des bouts de solution à droite à gauche pour faire ce qu’on veut. On pourrait imaginer une classe un peu plus générique s’adaptant aussi bien au besoin de Murray ou au miens (changement de comportement via une Propriété ?). Enfin, en réfléchissant à ça, je me demande aussi si cela reste toujours une bonne idée de partir de DataGridViewCheckBoxCell. En héritant de DataGridViewCell, on aura pas mal de chose à refaire (tout ce qui définie la checkbox) mais au moins on serait pas obligé d’utiliser des astuces pour réussir à se rendre compte du changement d’état de la CheckBox. En la gérant totallement on pourrait dire en revoir à l’évènement CurrentCellDirtyChanged. Un évènement lié à notre CheckBox serait directement utilisé… Voilà une autre solution envisageable.

     

  • Arduino, avr-gcc et avrdude

    Arduino.
    On ne le présente plus.
    C’est à la fois un package hardware et un package software. Il permet donc aux bidouilleurs de se mettre facilement au monde de l’embarqué, via un langage de programmation (processing) légèrement adapté.

    Oui, mais voilà, quand vous êtes déjà habitué par ce monde (aussi bien soft que hard), vous êtes vite un peu dépité par l’ide d’arduino. Vous avez envie de profiter du côté hardware de ce monde (cela reste des cartes d’évaluation, prototypage très bon marché)… Mais cela ne vous gène pas de garder votre bon vieux C… De garder votre éditeur préféré… Votre makefile maison qui automisera tout. Bref avoir un environnement de développement plus efficace, plus ouvert (plus technique). Avec aucun bout de soft caché.

     

    Bref, en gros, pour moi personnellement ça donne, « bref c beau on vient d’inventer l’arduino en 2005, mais je serais pas contre d’utiliser (directement) ce bon vieil avr-libc avec son compilo et ces lib, tout comme en 2001 avec mon AT90S8515. (souvenir d’un bout de code permettant de lire un disque dur…). Après tout pourquoi s’enfermer dans le monde arduino ? Le but du prototypage et de pouvoir aussi compiler directement ensuite sur une cible différente ?

    J’ai ajouté « directement » car au final l’IDE arduino s’appui sur cette chaine pour la compilation. Elle amène juste une surcouche fine au langage C (processing),  et des librairies supplémentaires pour des accès plus facile à certains périphériques (uart, spi) voir composant (shields) extérieurs (ex: ethernet).

    First Step : Compilation

    Ce premier article trouvé sur le net, partant du même constat, aborde ce sujet, avec les premiers arduino en cible (atmega8/168).
    Il cible avant tout le monde linux et m’a permis de re-trouver LA bonne page d’aide de l’avr-libc expliquant les étapes pour compiler un programme (qui reste après tout les étapes usuelles et classiques d’une compilation, bref un tuto qui s’adresse plus à ceux qui découvre ce processus).

    Ici, on peut donc voir comment générer ça à la mano, et le makefile nécessaire pour automatiser tout ça.

    Il faut savoir que l’avr-libc est disponible sous Windows via le package WinAvr. Ce dernier est d’ailleurs inclus dans le package arduino (et d’ailleurs semble plus à jour que le package officiel).  Dans la suite de ce tuto, on va donc faire avec tout ce qui provient du package arduino (ici dans sa version 1.0), installé sous D:\arduino-1.0.  Bref on retrouve donc le package winavr (updaté) sous D:\arduino-1.0\hardware\tools\avr. Et donc tous les compilos et autre sont dans le sous-répertoire bin. (structure linux classique ici).

    On va garder l’exemple fourni par notre tuto qui est l’équivalent d’un des exemples de base d’Arduino, le clignotement d’une Led.
    Voici donc le fichier blink.c :

    #include 
    #include 
    
    int main (void)
    {
      unsigned char counter;
      /* set PORTB for output*/
      DDRB = 0xFF;
    
      while (1)
      {
          /* set PORTB.2 high */
          PORTB = 0xFF;
    
          /* wait (10 * 120000) cycles = wait 1200000 cycles */
          counter = 0;
          while (counter != 50)
          {
    	  /* wait (30000 x 4) cycles = wait 120000 cycles */
    	  _delay_loop_2(30000);
    	  counter++;
          }
    
          /* set PORTB.2 low */
          PORTB = 0x00;
    
          /* wait (10 * 120000) cycles = wait 1200000 cycles */
          counter = 0;
          while (counter != 50)
          {
    	  /* wait (30000 x 4) cycles = wait 120000 cycles */
    	  _delay_loop_2(30000);
    	  counter++;
          }
      }
      return 1;
    }

    Et donc les commandes à la mano de compilation provenant de la page de win-avr :

    D:\arduino-1.0\hardware\tools\avr\bin\avr-gcc -g -Os -mmcu=atmega2560 -c blink.c
    D:\arduino-1.0\hardware\tools\avr\bin\avr-gcc -g -mmcu=atmega2560 -o blink.elf blink.o
    D:\arduino-1.0\hardware\tools\avr\bin\avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex

    Pour automaiser tout ça, voici une version un peu plus clean du makefile que celui proposé par le tuto d’avr-libc. C’est le genre de makefile générique que j’utilise. Bien qui celui-ci soit modifié (simplifié) pour l’occasion (en effet habitullement, j’ai un sous-répertoire différent pour tout ce qui est source, header et .o). Avec ce genre de makefile, on peut avoir un makefile global simple (qui définie les variables utilisateurs, conceptuelles) qui inclus ce dernier plus générique. De plus j’ai jouté une variable TOOLSDIR pour nous éviter de modifier le PATH pour le moment.

    # GENERIC MAKEFILE EXAMPLE FOR AVR GCC
    
    # ================ Project name
    PROJECT_NAME=blink
    
    # ================ Working directory
    WORKDIR=.
    TOOLSDIR=D:\Projets\Hardware\Arduino\IDE\arduino-1.0\hardware\tools\avr\bin\\
    
    # ================ Compilation Tools
    COMMAND_PREFIX=avr-
    MCU_TARGET=atmega2560
    
    CC=$(TOOLSDIR)$(COMMAND_PREFIX)gcc
    OBJCOPY=$(TOOLSDIR)$(COMMAND_PREFIX)objcopy
    OBJDUMP=$(TOOLSDIR)$(COMMAND_PREFIX)objdump
    
    # ================ Common compilation flags
    DEBUG=-g -Wall
    OPTIM=-O2
    DEFS=
    
    CFLAGS+=$(DEBUG) \
    		$(OPTIM) \
    		-mmcu=$(MCU_TARGET) \
    		$(DEFS)
    
    # ================ Libs & link FIle
    LIBS=
    LINKER_FLAGS=
    
    # Default sources are all sources of sources directory
    SOURCES = $(wildcard $(WORKDIR)/*.c)
    OBJECTS = $(SOURCES:.c=.o)
    
    # ================ Main targets
    
    all: $(PROJECT_NAME).elf lst text
    
    $(PROJECT_NAME).elf: $(OBJECTS)
    		$(CC) $(CFLAGS) -o $@ $(OBJECTS) $(LIBS) $(LINKER_FLAGS)
    
    $(OBJECTS): $(WORKDIR)/%.o : $(WORKDIR)/%.c
    		@echo BUILDING $@
    		$(CC) -c $(CFLAGS) $< -o $@	
    
    clean:
    		rm -rf *.o $(PROJECT_NAME).elf
    		rm -rf *.lst *.map
    
    lst:  $(PROJECT_NAME).lst
    
    %.lst: %.elf
    		$(OBJDUMP) -h -S $< > $@
    
    # Rules for building the .text rom images
    
    text: hex
    
    hex:$(PROJECT_NAME).hex
    
    %.hex: %.elf
    		$(OBJCOPY) -j .text -j .data -O ihex $< $@

    Second Step : Upload

    Alors là, on va devoir s’écarte de notre principal première source d’information.
    On a donc bien deux façon de charger notre programme dans l’arduino:

    • En gardant le bootloader « arduino » originale
    • Sans le bootloader, avec un programmeteur « classique »

    Pour ce deuxième cas, on va passer le coup du port parallèle cité dans notre premier tuto :-) Le monde évolue…. Et on va tout simplement passer ce second cas. En effet, dans ce cas il faut utiliser le connecteur officiel de programmation ICSP présent sur l’arduino. Il vous faut aussi un programmateur compatible, et donc la procédure à suivre sera différente selon ce dernier.

    Ici, on va se focaliser à rester un peu dans le monde arduino, en profitant de ce bootloader, qui apporte quand même une fonctionalié intéressante en mode proto/test. De plus personellement, j’ai bien un programmateur isp qui traine (depuis 2001…) mais je n’ai plus de foutu port paralléle sur mon pc… Et donc tant que je ne ma passe pas du bootloader (ou tant que je le modifie pas), je n’en ai pas réellement besoin.

    Donc en gros « Comment qu’on fait pour downloader de la même manière que l’Arduino IDE en ligne de commande ? »

    Et c’est là que ma 2ème grosse source d’inspiration arrive. En effet, mon arduino mega 2560 n’a plus le FTDI au niveau de son usb… je suis donc bien loin de notre premier tuto utilisé pour la compilation. C’est donc un atmega8u2 à la place. Ce dernier est donc une sorte de passerelle entre l’usb et le mode de programmation offert par le bootloader. Il est piloté suivant le protocol officiel stk500. (comme certains autres programmateur du commerce, qui sont alors un bridge entre le stk500 et le port de programmation isp de l’atmel).
    Ok, oui vous avez compris, avec l’arduino pas besoin de programmateur, car en gros, ce dernier est déjà dessus….  (ca reste vraiment une carte de prototypage). Enfin, en passant par ce dernier, on sait donc qu’on ne met pas en péril la zone dédié au bootloader.

    Au final, j’ai eu pas mal de problème, croyant que sa solution ne marchait pas, tout ça pour refaire exactement la même démarche que lui ! Cela m’aura au moins permis de savoir où trouver les traces d’exécution de l’IDE d’arduino. Et au final, la bonne solution est en commentaire de notre 2ème tuto.

    J’ai donc d’abord lancé une compilation/upload depuis l’IDE officiel, en activant les traces d’upload afin de voir la ligne de commande.

    Pour info voilà comment activer les traces :

        

    C’est également possible de le faire directement depuis le fichier de preferences ( http://arduino.cc/forum/index.php?topic=95254.0).Il est dans ce cas préférable de modifier le fichier spécifique à l’utilisateur (sous windows C:\Documents and Settings\<USER>\Application Data\Arduino)  et pas celui du répertoire arduino (arduino-1.0\lib).
    Une vue sur ce fichier (utilisateur) permet de voir, toutes les options réellement disponibles. 2 options vont d’ailleurs me mettre la puce à l’oreil pour la suite: console.error.file=stderr.txt & console.output.file=stdout.txt.

    En effet, une fois les traces activées, on n’a pas le temps de voir la ligne de commande tracée pour l’upload, d’autres traces suivent, et la fenêtre trace de l’IDE d’arduino n’offre pas un historique assez important (tu vois bien qu’il faut se défaire de cet IDE !). On se dit, il doit bien avoir un fichier… en plus certaines options ont l’air de le préciser !

    Après où sont-ils ? => http://forums.adafruit.com/viewtopic.php?f=25&t=23271#p121783.
    Ok , ils sont donc ici : C:\Documents and Settings\<USER>\Local Settings\Temp\console*******.tmp
    Suffit de trouver le dernier répertoire généré et vous aurez accès aux 2 fichier de traces de toute une session de l’IDE.

    On a donc dans le stdout.txt:

    Binary sketch size: 1602 bytes (of a 258048 byte maximum)
    D:\arduino-1.0\hardware/tools/avr/bin/avrdude -CD:\arduino-1.0\hardware/tools/avr/etc/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P\\.\COM3 -b115200 -D -Uflash:w:C:\DOCUME~1\Fabien\LOCALS~1\Temp\build8342149431938943132.tmp\Blink.cpp.hex:i

    Et dans le stderr.txt, les traces qui suivent :

    avrdude: Version 5.11, compiled on Sep  2 2011 at 19:38:36
    Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
    Copyright (c) 2007-2009 Joerg Wunsch
    System wide configuration file is "D:\arduino-1.0\hardware/tools/avr/etc/avrdude.conf"
    Using Port                    : \\.\COM3
    Using Programmer              : stk500v2
    Overriding Baud Rate          : 115200
    avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
    avrdude: Recv: . [1b]
    ......

    En retentant à la main, la ligne de commande détectée, on a les même traces mais un foireux Timeout à la place du premier Recv !!!
    Au passage contrairement au tuto, on voit bien que la différence ne vient pas d’avrdude, c’est la version 5.11 qui est maintenant livré avec la package Arduino. Ce n’est donc plus une version spécifique Arduino.

    En continuant de survoler le tuto et ces commentaires, voici les tentatives suivantes :

    • Essai en spécifiant un programmer de type « arduino » => même constat
    • Essai en plaçant en reset la board (via le bouton) jusqu’au moment où on lance la ligne de commande : Eureka ! En effet c’est ok. Par contre, c’est pas super top automatique ton truc ?
    • Heureusement qu’un commentaire du tuto nous résout tout ça. Il faut utiliser un programmateur de type wiring. C’est totalement accepté par l’avrdude 5.11 livré par le package arduino.

    C’est quand même étrange qu’on soit obligé de changer le type de programmateur par rapport à la ligne de commande faite par l’IDE arduino… C’est comme ci l’IDE arduino faisait un reset caché de la board avant de lancer avrdude.

    AU final :

    D:\arduino-1.0\hardware/tools/avr/bin/avrdude -CD:\arduino-1.0\hardware/tools/avr/etc/avrdude.conf -v -v -v -v -patmega2560 -cwiring -P\\.\COM3 -b115200 -D -Uflash:w:D:\Example\Blink.hex:i

    On pourra bien entendu enlenver tous les « -v » qui sont içi pour être en mode trace (full). Enfin pourquoi pas ajouter une option dans le makefile pour ajouter ça (bien que cette ligne de commande pourra devrait normalement pouvoir également être associé directement à un bouton dans votre IDE).

    Dans le makefile on pourrait ajouter :

    download : $(PROJECT_NAME).hex
    		$(TOOLSDIR)avrdude -CD:\arduino-1.0\hardware/tools/avr/etc/avrdude.conf -patmega2560 -cwiring -P\\.\COM3 -b115200 -D -Uflash:w:$(PROJECT_NAME).hex:i

    Ce qui nous donne dans la console DOS :

    D:\Example>D:\arduino-1.0\hardware\tools\avr\utils\bin\make.exe download
    D:\arduino-1.0\hardware\tools\avr\bin\\avrdude -CD:\arduino-1.0\hardware\tools\avr\etc\avrdude.conf -p
    atmega2560 -cwiring -P\\.\COM3 -b115200 -D -Uflash:w:blink.hex:i
    
    avrdude: AVR device initialized and ready to accept instructions
    
    Reading | ################################################## | 100% 0.02s
    
    avrdude: Device signature = 0x1e9801
    avrdude: reading input file "blink.hex"
    avrdude: writing flash (348 bytes):
    
    Writing | ################################################## | 100% 0.06s
    
    avrdude: 348 bytes of flash written
    avrdude: verifying flash memory against blink.hex:
    avrdude: load data flash data from input file blink.hex:
    avrdude: input file blink.hex contains 348 bytes
    avrdude: reading on-chip flash data:
    
    Reading | ################################################## | 100% 0.05s
    
    avrdude: verifying ...
    avrdude: 348 bytes of flash verified
    
    avrdude: safemode: Fuses OK
    
    avrdude done.  Thank you.
    
    D:\Example>

    Se passer de l’install de l’IDE officiel ?

    On a bien vue que pour le moment, j’ai tout fait via les packages installés avec l’IDE d’arduino. J’ai parlé aussi de légère différence (mise à jour) par rapport à l’installer simple de WinAvr. Regardons ce qu’il en est réellement.

    Le dernier package officiel de WinAvr date de Janvier 2010. C’est pas top comme impression pour le moment. Par default, il install donc tout sous C:\WinAVR-20100110. Personnellement, je n’ai pas demander à l’installer de ma changer le PATH. On verra ça ensuite.

    On va donc retrouver le même genre de contenu sous C:\WinAVR-20100110 que sous D:\arduino-1.0\hardware\tools\avr.
    D’ailleurs dans les 2 est présent le fichier qui permet de désinstaller WinAvr. On voit bien que le package arduino contient bien un gros copier/coller de l’install faire par WinAvr. Il aurait au moins pu enlever cet exécutable spécifique à la désinstallation de WinAvr !  On peut noter que d’un côté on a WinAVR-20100110-uninstall.exe et chez arduino WinAVR-20081205-uninstall.exe. Cette version 20081205 est également précisé dans le WinAVR-user-manual.txt.

    Ok donc arduino est basé sur la release 20081205 de WinAvr. Cela à l’air d’un pauvre copier coller (en gardant le désinstaller !) Mais on a bien vu qu’il contenait un avrdude tout neuf, le 5.11 qui est sortie le 27 Aout 2011 !!! Le répertoire livré par Arduino a donc bien était modifié.

    Pour une meilleur comparaison, on pourrait même ce baser sur cette release de WinAvr, elle est toujours dispo (merci google) : http://en.sourceforge.jp/projects/sfnet_winavr/downloads/WinAVR/20081205/WinAVR-20081205-install.exe/

    Me voilà donc avec un 3ème winavr (toujours pas de PATH modifié, on commence à comprendre pourquoi) sous C:\WinAVR-20081205.

    4111 fichier comparés plus tard (entre WinAVR-20081205 et sa version Arduino) on arrive à très peu de différence : WinAVR-20081205 vs arduino-1.0

    Les 3 principales :

    • avrdude.exe -> Qui l’aurait cru !
    • eeprom.h (pourtant aucune différence dans le copyright ;  les 3 différences sont bien annotées et semble concerner le 2560)
    • Enfin, avrdude.conf qui change aussi d’emplacement. Originalement dans bin il passe dans etc. Vous savez c’est celui qu’on passe en ligne de commande à avrdude plus haut. Les différences doivent venir de la différence de version d’avrdude.

    Tout le reste, c’est du fichier en plus du côté arduino.  C’est le contenu de tout le répertoire pn au final. Des fichiers xml, scheme et clips… Je sais pas trop à qui à quoi ça sert…. Surement pas à winavr en tout cas.

    Ce qu’on peut constater :

    C’est que déjà, winavr n’est plus mise à jour depuis 2010, mais en plus le outils utilisés par le package arduino sont ceux de winavr version 2008 ! On faisant une comparaison de winavr 2008 vs 2010 on voit bien que tout a évolué, tous les fichiers sont différents. EN regardant le manuel, on sait qu’on est passé de gcc 4.3.2 à 4.3.3, d’avr-libc 1.6.4 à 1.6.7, d’avrdude 5.5 au 5.8, d’avarice 2.7 au 2.9 de simulAVR 0.1.2.5 au 0.9… Il y a également d’autres petits outiles en plus…. A la fin il était donc précisait que c’était la dernière version de win-avr bien et que bien entendu tous les projets englobés continué à vivre (la version 2010 est donc elle aussi en retard….).

    On peut donc se dire que c’est dommage que la team arduino n’en est pas profité pour faire un gros update de ce package. Bien entendu, le problème ne doit pas se poser dans le monde linux.. vu que ce sont des outils développés pour ce monde. Il nous manque juste une mise à  jour de leur compilation dans l’environnement Windows. (via MinGw ou Cygwin).

    AU sujet de la différence du fichier eeprom.h, on peut juste voir que dans la version d’avr-libc 1.6.7 (fourni par le dernier winavr), il a bien évolué. Je pense donc que le patch arduino spécifique au 2560 n’est plus nécessaire.

    Au passage, en prenant la dernière version d’avrdude, qui est la 5.11.1, on se rend compte qu’on retrouve bien l’avrdude.conf fourni par le package arduino. PAr contre c’est un package source…  Le 5.11 avait un problème avec les FTDI pour la programmation.  Bien entendu on peut soit tenter de compiler ca en environnement windows, soit compter sur la magie du web : google -> avrfreaks -> helix.air.net.au :: AVRDUDE (par contre personellement j’ai des problèmes à l’exécuter…. la version fourni par le package arduino me suffisant (pas de programateur avec un ftdi) , je vais pas chercher plus loin)

    ==> C’est bon on a gagné.

    On se rend donc bien compte que chaque package a évolué depuis winavr 2010. Par exemple, en allant sur le site avr-libc on voit qu’on est en 1.8. Pour être à jour facilement, le plus simple est encore de travailler (ou du moins compiler) depuis linux. Si vous voulez pas quitter windows, une machine virtuelle est le tour est joué. J’ai pour ma part un linux très light (ubuntu-mini sans graphique, juste une console, pour des problèmes de pc un peu vieux) . Bref, en y installant tous les outils nécessaire, pas de problème.

    $ apt-get install gcc-avr avr-libc avrdude

    J’ai tenté ça dans ma machine virtuelle (ubuntu-mini), cela m’installe une libc plus récente (1.7.1-2), gcc-avr beaucoup plus récent (4.5.3-2), les binutils-avr en 2.20.1-2, et par contre un avrdude en 5.10-3. Ce dernier point est dommage, il me semble que seul le 5.11 marche dans notre cas. (m’enfin ca reste une marchine virtuelle, je peu softer depuis windows aussi).

    Pour faire simple sous windows, soit on peut faire confiance à mon tuto en se basant sur les outils délivrés par la package arduino, soit on se met un peu plus à jour en utilisant les outils délivré par WinAvr-20100110, auquel on lui met la dernière version d’avrdude (l’exe et le .conf) délivré par le package arduino.

    Utiliser WinAvr uniquement

    J’ai fait le test sur mon makefile, j’ai changé la ligne

    TOOLSDIR=D:\Projets\Hardware\Arduino\IDE\arduino-1.0\hardware\tools\avr\bin\\

    en

    TOOLSDIR=C:\WinAVR-20100110\bin\\

    La compilation a réussi. Le binaire passe de 995 octets à 946 octets.

    Ensuite, le download (via le makefile) :

    D:\Example>C:\WinAVR-20100110\utils\bin\make.exe download
    C:\WinAVR-20100110\bin\\avrdude -CD:\Projets\Hardware\Arduino\IDE\arduino-1.0\hardware\tools\avr\etc\avrdude.conf -patmega2560 -cwiring -P\\.\COM3 -b115200 -D -Uflash:w:blink.hex:i
    error at D:\Projets\Hardware\Arduino\IDE\arduino-1.0\hardware\tools\avr\etc\avrd
    ude.conf:332 unrecognized character: "w"
    make: *** [download] Error 1
    

    On s’y attendait…
    On va donc copier l’avrdude.exe d’Arduino dans C:\WinAVR-20100110\bin, pareil pour le avrdude.conf (dans le répertoire arduino-1.0\hardware\tools\avr\etc et on le met dans C:\WinAVR-20100110\bin). Au passage, on peut modifier la ligne de commande de download. Plus besoin de préciser où se trouve le .conf, car il est dans le même répertoire. On re-lance. C’est OK !